| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #pragma once |
| |
| #include <lib/async-testutils/test_loop_dispatcher.h> |
| |
| #include <fbl/unique_ptr.h> |
| #include <fbl/vector.h> |
| #include <lib/async/dispatcher.h> |
| |
| namespace async { |
| |
| // A minimal, abstract message loop interface. |
| class LoopInterface { |
| public: |
| virtual ~LoopInterface() = default; |
| virtual async_dispatcher_t* dispatcher() = 0; |
| }; |
| |
| // A message loop with a fake clock, to be controlled within a test setting. |
| class TestLoop { |
| public: |
| // Constructs a TestLoop with a seed from the environment, or a random |
| // seed if absent. |
| TestLoop(); |
| // If state is nonzero, constructs a TestLoop with the given seed. |
| // Otherwise, uses a seed from the environment or a random seed. |
| TestLoop(uint32_t state); |
| ~TestLoop(); |
| |
| // Returns the test loop's asynchronous dispatcher. |
| async_dispatcher_t* dispatcher(); |
| |
| // Returns a loop interface simulating the starting up of a new message |
| // loop. The lifetime of the 'loop' is tied to the returned interface. |
| // Each successive calls to this method corresponds to a new loop. |
| fbl::unique_ptr<LoopInterface> StartNewLoop(); |
| |
| // Returns the current fake clock time. |
| zx::time Now() const; |
| |
| // Quits the message loop. If called while running, it will immediately |
| // exit and dispatch no further tasks or waits; if called before running, |
| // then next call to run will immediately exit. Further calls to run will |
| // dispatch as usual. |
| void Quit(); |
| |
| // Advances the fake clock time by the smallest possible amount. |
| // This doesn't run the loop. |
| void AdvanceTimeByEpsilon(); |
| |
| // Dispatches all waits and all tasks with deadlines up until |deadline|, |
| // progressively advancing the fake clock. |
| // Returns true iff any tasks or waits were invoked during the run. |
| bool RunUntil(zx::time deadline); |
| |
| // Dispatches all waits and all tasks with deadlines up until |duration| |
| // from the the current time, progressively advancing the fake clock. |
| // Returns true iff any tasks or waits were invoked during the run. |
| bool RunFor(zx::duration duration); |
| |
| // Dispatches all waits and all tasks with deadlines up until the current |
| // time, progressively advancing the fake clock. |
| // Returns true iff any tasks or waits were invoked during the run. |
| bool RunUntilIdle(); |
| |
| // The initial value of the state of the TestLoop. |
| uint32_t initial_state() { return initial_state_; } |
| |
| private: |
| // An implementation of LoopInterface. |
| class TestLoopInterface; |
| |
| // A TimeKeeper implementation that manages the test loop's fake clock time |
| // and fake timers. |
| class TestLoopTimeKeeper; |
| |
| // Whether there are any due tasks or waits across |dispatchers_|. |
| bool HasPendingWork(); |
| |
| // Returns the next due task time across |dispatchers_|. |
| zx::time GetNextTaskDueTime() const; |
| |
| fbl::unique_ptr<TestLoopTimeKeeper> time_keeper_; |
| |
| // Encapsulation of the async_dispatcher_t dispatch methods. |
| fbl::Vector<fbl::unique_ptr<TestLoopDispatcher>> dispatchers_; |
| |
| // The seed of a pseudo-random number used to determinisitically determine the |
| // dispatching order across |dispatchers_|. |
| uint32_t initial_state_; |
| // The current state of the pseudo-random generator. |
| uint32_t state_; |
| |
| // Quit state of the loop. |
| bool has_quit_ = false; |
| // Whether the loop is currently running. |
| bool is_running_ = false; |
| }; |
| |
| } // namespace async |