11
11
12
12
module AutomatedTestRunner (Example , getGenesisConfig , loadNKeys , doUpdate , onStartup , on , getScript , runScript , NodeType (.. ), startNode ) where
13
13
14
+ import Brick hiding (on )
15
+ import Brick.BChan
16
+ import BrickUI
17
+ import BrickUITypes
18
+ import Control.Concurrent
19
+ import Control.Concurrent.Async.Lifted.Safe
20
+ import Control.Exception (throw )
21
+ import Control.Lens (to )
22
+ import Control.Monad.STM (orElse )
23
+ import Data.Constraint (Dict (Dict ))
24
+ import Data.Default (Default (def ))
25
+ import Data.Ix (range )
14
26
import Data.List ((!!) )
27
+ import Data.Reflection (Given , given , give )
15
28
import Data.Version (showVersion )
16
29
import Options.Applicative (Parser , execParser , footerDoc , fullDesc , header , help , helper , info , infoOption , long , progDesc )
17
30
import Paths_cardano_sl (version )
18
31
import Pos.Client.KeyStorage (getSecretKeysPlain , addSecretKey )
19
32
import Pos.Crypto (emptyPassphrase , hash , hashHexF , withSafeSigners , noPassEncrypt )
33
+ import Pos.DB.BlockIndex (getTipHeader )
20
34
import Pos.Util.CompileInfo (CompileTimeInfo (ctiGitRevision ), HasCompileInfo , compileInfo , withCompileInfo )
21
35
import Prelude (show )
22
36
import Text.PrettyPrint.ANSI.Leijen (Doc )
23
37
import Universum hiding (when , show , on , state )
24
- import Control.Lens (to )
25
- import Pos.DB.BlockIndex (getTipHeader )
26
38
import qualified Pos.Client.CLI as CLI
27
39
import Pos.Launcher (HasConfigurations , NodeParams (npBehaviorConfig , npUserSecret , npNetworkConfig ),
28
40
NodeResources , WalletConfiguration ,
29
41
bracketNodeResources , loggerBracket ,
30
42
runNode , runRealMode , withConfigurations , InitModeContext )
31
- import Control.Exception (throw )
32
- import Data.Constraint (Dict (Dict ))
33
- import Data.Default (Default (def ))
34
- import Data.Reflection (Given , given , give )
35
43
import Formatting (int , sformat , (%) , Format )
36
- import PocMode ( AuxxContext ( AuxxContext , acRealModeContext ), AuxxMode , realModeToAuxx )
44
+ import Graphics.Vty ( mkVty , defaultConfig , defAttr )
37
45
import Ntp.Client (NtpConfiguration )
46
+ import PocMode (AuxxContext (AuxxContext , acRealModeContext ), AuxxMode , realModeToAuxx )
47
+ import Pos.Chain.Block (LastKnownHeaderTag )
38
48
import Pos.Chain.Genesis as Genesis (Config (configGeneratedSecrets , configProtocolMagic ), configEpochSlots )
39
49
import Pos.Chain.Txp (TxpConfiguration )
40
50
import Pos.Chain.Update (UpdateData , SystemTag , mkUpdateProposalWSign , BlockVersion , SoftwareVersion , BlockVersionModifier , updateConfiguration )
41
51
import Pos.Client.Update.Network (submitUpdateProposal )
42
52
import Pos.Core (LocalSlotIndex , SlotId (SlotId , siEpoch , siSlot ), mkLocalSlotIndex , EpochIndex (EpochIndex ), SlotCount , getEpochIndex , getSlotIndex , difficultyL , getChainDifficulty , getBlockCount , getEpochOrSlot )
43
53
import Pos.DB.DB (initNodeDBs )
44
54
import Pos.DB.Txp (txpGlobalSettings )
45
- import Pos.Infra.DHT.Real.Param (KademliaParams )
46
55
import Pos.Infra.Diffusion.Types (Diffusion , hoistDiffusion )
47
56
import Pos.Infra.Network.Types (NetworkConfig (ncTopology , ncEnqueuePolicy , ncDequeuePolicy , ncFailurePolicy ), Topology (TopologyAuxx ), topologyDequeuePolicy , topologyEnqueuePolicy , topologyFailurePolicy , NodeId )
57
+ import Pos.Infra.Shutdown (triggerShutdown )
48
58
import Pos.Infra.Slotting.Util (onNewSlot , defaultOnNewSlotParams )
49
59
import Pos.Util (logException , lensOf )
50
- import Control.Monad.STM (orElse )
51
60
import Pos.Util.UserSecret (usVss , readUserSecret , usPrimKey , usKeys )
52
61
import Pos.Util.Wlog (LoggerName )
53
62
import Pos.WorkMode (RealMode , EmptyMempoolExt )
54
63
import qualified Data.HashMap.Strict as HM
55
64
import qualified Data.Map as Map
56
65
import qualified Data.Text as T
57
- import Data.Ix (range )
58
- import Control.Concurrent.Async.Lifted.Safe
59
- import Brick hiding (on )
60
- import Brick.BChan
61
- import Graphics.Vty (mkVty , defaultConfig , defAttr )
62
- import Control.Concurrent
63
- import Pos.Chain.Block (LastKnownHeaderTag )
64
- import BrickUI
65
66
66
67
class TestScript a where
67
68
getScript :: a -> Script
@@ -85,9 +86,7 @@ data Script = Script
85
86
, startupActions :: [ SlotTrigger ]
86
87
} deriving (Show , Generic )
87
88
88
- data SlotTrigger = SlotTrigger
89
- { stAction :: Dict HasConfigurations -> Diffusion AuxxMode -> AuxxMode ()
90
- }
89
+ data SlotTrigger = SlotTrigger (Dict HasConfigurations -> Diffusion AuxxMode -> AuxxMode () )
91
90
92
91
instance Show SlotTrigger where
93
92
show _ = " IO ()"
@@ -105,6 +104,7 @@ instance HasEpochSlots => TestScript (Example a) where
105
104
instance TestScript Script where
106
105
getScript = identity
107
106
107
+ data NodeHandle = NodeHandle (Async () )
108
108
109
109
data EpochSlots = EpochSlots { epochSlots :: SlotCount , config :: Config }
110
110
type HasEpochSlots = Given EpochSlots
@@ -142,42 +142,49 @@ getScriptRunnerOptions = execParser programInfo
142
142
loggerName :: LoggerName
143
143
loggerName = " script-runner"
144
144
145
- thing :: (TestScript a , HasCompileInfo ) => ScriptRunnerOptions -> ( HasEpochSlots => IO a ) -> BChan CustomEvent -> IO ()
146
- thing opts@ ScriptRunnerOptions {.. } scriptGetter eventChan = do
145
+ thing :: (TestScript a , HasCompileInfo ) => ScriptRunnerOptions -> InputParams a -> IO ()
146
+ thing opts@ ScriptRunnerOptions {.. } inputParams = do
147
147
let
148
148
conf = CLI. configurationOptions (CLI. commonArgs cArgs)
149
149
cArgs@ CLI. CommonNodeArgs {.. } = srCommonNodeArgs
150
- withConfigurations Nothing cnaDumpGenesisDataPath cnaDumpConfiguration conf (runWithConfig opts scriptGetter eventChan )
150
+ withConfigurations Nothing cnaDumpGenesisDataPath cnaDumpConfiguration conf (runWithConfig opts inputParams )
151
151
152
- runWithConfig :: (TestScript a , HasCompileInfo , HasConfigurations ) => ScriptRunnerOptions -> (HasEpochSlots => IO a ) -> BChan CustomEvent -> Genesis. Config -> WalletConfiguration -> TxpConfiguration -> NtpConfiguration -> IO ()
153
- runWithConfig ScriptRunnerOptions {.. } scriptGetter eventChan genesisConfig _walletConfig txpConfig _ntpConfig = do
152
+ maybeAddPeers :: [NodeId ] -> NodeParams -> NodeParams
153
+ maybeAddPeers [] params = params
154
+ maybeAddPeers peers nodeParams = nodeParams { npNetworkConfig = (npNetworkConfig nodeParams) { ncTopology = TopologyAuxx peers } }
155
+
156
+ addQueuePolicies :: NodeParams -> NodeParams
157
+ addQueuePolicies nodeParams = do
158
+ let
159
+ topology = ncTopology $ npNetworkConfig nodeParams
160
+ nodeParams { npNetworkConfig = (npNetworkConfig nodeParams)
161
+ { ncEnqueuePolicy = topologyEnqueuePolicy topology
162
+ , ncDequeuePolicy = topologyDequeuePolicy topology
163
+ , ncFailurePolicy = topologyFailurePolicy topology
164
+ }
165
+ }
166
+
167
+ runWithConfig :: (TestScript a , HasCompileInfo , HasConfigurations ) => ScriptRunnerOptions -> InputParams a -> Genesis. Config -> WalletConfiguration -> TxpConfiguration -> NtpConfiguration -> IO ()
168
+ runWithConfig ScriptRunnerOptions {.. } inputParams genesisConfig _walletConfig txpConfig _ntpConfig = do
154
169
let
155
170
cArgs@ CLI. CommonNodeArgs {.. } = srCommonNodeArgs
156
- nArgs =
157
- CLI. NodeArgs {behaviorConfigPath = Nothing }
171
+ nArgs = CLI. NodeArgs {behaviorConfigPath = Nothing }
158
172
(nodeParams', _mSscParams) <- CLI. getNodeParams loggerName cArgs nArgs (configGeneratedSecrets genesisConfig)
159
173
let
160
- topology :: Topology KademliaParams
161
- topology = TopologyAuxx srPeers
162
- nodeParams = nodeParams' {
163
- npNetworkConfig = (npNetworkConfig nodeParams')
164
- { ncTopology = topology
165
- , ncEnqueuePolicy = topologyEnqueuePolicy topology
166
- , ncDequeuePolicy = topologyDequeuePolicy topology
167
- , ncFailurePolicy = topologyFailurePolicy topology
168
- }
169
- }
174
+ nodeParams = addQueuePolicies $ maybeAddPeers srPeers $ nodeParams'
170
175
epochSlots = configEpochSlots genesisConfig
171
176
vssSK = fromMaybe (error " no user secret given" ) (npUserSecret nodeParams ^. usVss)
172
177
sscParams = CLI. gtSscParams cArgs vssSK (npBehaviorConfig nodeParams)
173
178
thing1 = txpGlobalSettings genesisConfig txpConfig
174
179
thing2 :: ReaderT InitModeContext IO ()
175
180
thing2 = initNodeDBs genesisConfig
176
- script <- liftIO $ withEpochSlots epochSlots genesisConfig scriptGetter
177
- bracketNodeResources genesisConfig nodeParams sscParams thing1 thing2 (thing3 genesisConfig txpConfig script eventChan)
181
+ script <- liftIO $ withEpochSlots epochSlots genesisConfig (ipScriptGetter inputParams)
182
+ let
183
+ inputParams' = InputParams2 (ipEventChan inputParams) (ipReplyChan inputParams) script
184
+ bracketNodeResources genesisConfig nodeParams sscParams thing1 thing2 (thing3 genesisConfig txpConfig inputParams')
178
185
179
- thing3 :: (TestScript a , HasCompileInfo , HasConfigurations ) => Config -> TxpConfiguration -> a -> BChan CustomEvent -> NodeResources () -> IO ()
180
- thing3 genesisConfig txpConfig script eventChan nr = do
186
+ thing3 :: (TestScript a , HasCompileInfo , HasConfigurations ) => Config -> TxpConfiguration -> InputParams2 a -> NodeResources () -> IO ()
187
+ thing3 genesisConfig txpConfig inputParams nr = do
181
188
let
182
189
toRealMode :: AuxxMode a -> RealMode EmptyMempoolExt a
183
190
toRealMode auxxAction = do
@@ -188,15 +195,24 @@ thing3 genesisConfig txpConfig script eventChan nr = do
188
195
thing5 :: Diffusion AuxxMode -> AuxxMode ()
189
196
thing5 = runNode genesisConfig txpConfig nr thing4
190
197
thing4 :: [ (Text , Diffusion AuxxMode -> AuxxMode () ) ]
191
- thing4 = workers genesisConfig script eventChan
198
+ thing4 = workers genesisConfig inputParams
192
199
runRealMode updateConfiguration genesisConfig txpConfig nr thing2
193
200
194
- workers :: (HasConfigurations , TestScript a ) => Genesis. Config -> a -> BChan CustomEvent -> [ (Text , Diffusion AuxxMode -> AuxxMode () ) ]
195
- workers genesisConfig script eventChan =
196
- [ ( T. pack " worker1" , worker1 genesisConfig script eventChan)
197
- , ( " worker2" , worker2 eventChan)
201
+ workers :: (HasConfigurations , TestScript a ) => Genesis. Config -> InputParams2 a -> [ (Text , Diffusion AuxxMode -> AuxxMode () ) ]
202
+ workers genesisConfig InputParams2 {ip2EventChan,ip2Script,ip2ReplyChan} =
203
+ [ ( T. pack " worker1" , worker1 genesisConfig ip2Script ip2EventChan)
204
+ , ( " worker2" , worker2 ip2EventChan)
205
+ , ( " brick reply worker" , brickReplyWorker ip2ReplyChan)
198
206
]
199
207
208
+ brickReplyWorker :: HasConfigurations => BChan Reply -> Diffusion AuxxMode -> AuxxMode ()
209
+ brickReplyWorker replyChan diffusion = do
210
+ reply <- liftIO $ readBChan replyChan
211
+ case reply of
212
+ TriggerShutdown -> do
213
+ triggerShutdown
214
+ brickReplyWorker replyChan diffusion
215
+
200
216
worker2 :: HasConfigurations => BChan CustomEvent -> Diffusion AuxxMode -> AuxxMode ()
201
217
worker2 eventChan diffusion = do
202
218
localTip <- getTipHeader
@@ -208,7 +224,7 @@ worker2 eventChan diffusion = do
208
224
f (Just v) = Just $ getBlockCount v
209
225
f Nothing = Nothing
210
226
liftIO $ do
211
- writeBChan eventChan $ NodeInfoEvent (getBlockCount localHeight) (getEpochOrSlot localTip) (f globalHeight)
227
+ writeBChan eventChan $ CENodeInfo $ NodeInfo (getBlockCount localHeight) (getEpochOrSlot localTip) (f globalHeight)
212
228
threadDelay 100000
213
229
worker2 eventChan diffusion
214
230
@@ -217,8 +233,7 @@ worker1 genesisConfig script eventChan diffusion = do
217
233
let
218
234
handler :: SlotId -> AuxxMode ()
219
235
handler slotid = do
220
- liftIO $ writeBChan eventChan $ SlotStart (getEpochIndex $ siEpoch slotid) (getSlotIndex $ siSlot slotid)
221
- print slotid
236
+ liftIO $ writeBChan eventChan $ CESlotStart $ SlotStart (getEpochIndex $ siEpoch slotid) (getSlotIndex $ siSlot slotid)
222
237
case Map. lookup slotid (slotTriggers realScript) of
223
238
Just (SlotTrigger act) -> runAction act
224
239
Nothing -> pure ()
@@ -235,37 +250,53 @@ worker1 genesisConfig script eventChan diffusion = do
235
250
pure ()
236
251
realWorker `catch` errhandler @ SomeException
237
252
253
+ data TestScript a => InputParams a = InputParams
254
+ { ipEventChan :: BChan CustomEvent
255
+ , ipReplyChan :: BChan Reply
256
+ , ipScriptGetter :: HasEpochSlots => IO a
257
+ }
258
+ data TestScript a => InputParams2 a = InputParams2
259
+ { ip2EventChan :: BChan CustomEvent
260
+ , ip2ReplyChan :: BChan Reply
261
+ , ip2Script :: a
262
+ }
263
+
238
264
runScript :: TestScript a => (HasEpochSlots => IO a ) -> IO ()
239
265
runScript scriptGetter = withCompileInfo $ do
240
- (eventChan, asyncUi) <- runUI
266
+ (eventChan, replyChan, asyncUi) <- runUI
241
267
opts <- getScriptRunnerOptions
242
268
let
269
+ inputParams = InputParams eventChan replyChan scriptGetter
243
270
loggingParams = CLI. loggingParams loggerName (srCommonNodeArgs opts)
244
271
loggerBracket " script-runner" loggingParams . logException " script-runner" $ do
245
- thing opts scriptGetter eventChan
272
+ thing opts inputParams
246
273
pure ()
247
274
liftIO $ writeBChan eventChan QuitEvent
248
275
finalState <- wait asyncUi
249
- print finalState
276
+ -- print finalState
277
+ pure ()
250
278
251
- runUI :: IO (BChan CustomEvent , Async AppState )
279
+ runUI :: IO (BChan CustomEvent , BChan Reply , Async AppState )
252
280
runUI = do
253
281
eventChan <- newBChan 10
282
+ replyChan <- newBChan 10
254
283
let
255
284
app = App
256
285
{ appDraw = ui
257
- , appChooseCursor = \ _ _ -> Nothing
286
+ , appChooseCursor = showFirstCursor
258
287
, appHandleEvent = handleEvent
259
288
, appStartEvent = \ x -> pure x
260
289
, appAttrMap = const $ attrMap defAttr []
261
290
}
262
291
state :: AppState
263
- state = AppState 0 Nothing " " Nothing
292
+ state = AppState 0 Nothing " " Nothing replyChan
264
293
go :: IO AppState
265
294
go = do
266
- customMain (mkVty defaultConfig) (Just eventChan) app state
295
+ finalState <- customMain (mkVty defaultConfig) (Just eventChan) app state
296
+ writeBChan replyChan TriggerShutdown
297
+ pure finalState
267
298
brick <- async go
268
- pure (eventChan, brick)
299
+ pure (eventChan, replyChan, brick)
269
300
270
301
getGenesisConfig :: Example Config
271
302
getGenesisConfig = do
@@ -356,14 +387,14 @@ loadNKeys n = do
356
387
addSecretKey $ noPassEncrypt primSk
357
388
mapM_ loadKey (range (0 ,n - 1 ))
358
389
359
- data NodeHandle = NodeHandle
360
-
361
390
startNode :: NodeType -> IO NodeHandle
362
391
startNode (Core idx) = do
363
392
let
364
- params = [ " --configuration-file" , " ../lib/configuration.yaml"
393
+ _params = [ " --configuration-file" , " ../lib/configuration.yaml"
365
394
, " --system-start" , " 1543100429"
366
395
, " --db-path" , " poc-state/core" <> (show idx) <> " -db"
367
396
, " --keyfile" , " poc-state/secret" <> (show idx) <> " .key"
368
397
]
369
- pure undefined
398
+ later <- async $ do
399
+ pure ()
400
+ pure $ NodeHandle later
0 commit comments