pub(crate) async fn run(self, sealer: SequencerSealer) {
        assert!(!self.actions.is_empty(), "Test scenario can't be empty");

        let batch_executor = TestBatchExecutorBuilder::new(&self);
        let (stop_sender, stop_receiver) = watch::channel(false);
        let (io, output_handler) = TestIO::new(stop_sender, self);
        let state_keeper = ZkSyncStateKeeper::new(
            Box::new(io),
            Box::new(batch_executor),
            output_handler,
            Arc::new(sealer),
            Arc::new(MockReadStorageFactory),
            None,
        );
        let sk_thread = tokio::spawn(state_keeper.run(stop_receiver));

        // We must assume that *theoretically* state keeper may ignore the stop request from IO once scenario is
        // completed, so we spawn it in a separate thread to not get test stuck.
        let hard_timeout = Duration::from_secs(60);
        let poll_interval = Duration::from_millis(50);
        let start = Instant::now();
        while start.elapsed() <= hard_timeout {
            if sk_thread.is_finished() {
                sk_thread
                    .await
                    .unwrap_or_else(|_| panic!("State keeper thread panicked"))
                    .unwrap();
                return;
            }
            tokio::time::sleep(poll_interval).await;
        }
        panic!("State keeper test did not exit until the hard timeout, probably it got stuck");
    }
Launches the test.
Provided `SealManager` is expected to be externally configured to adhere the written scenario logic.
core/node/state_keeper/src/testonly/test_batch_executor.rs