1ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved.
2ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Use of this source code is governed by a BSD-style license that can be
3ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// found in the LICENSE file.
4ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
5fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
6fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
7ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
8ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <functional>
9ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <map>
10ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <queue>
113845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo#include <set>
12ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <utility>
13ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <vector>
14ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
15106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo#include <base/location.h>
16ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/test/simple_test_clock.h>
17ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/time/time.h>
18ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
199ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/brillo_export.h>
209ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/message_loops/message_loop.h>
21ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
229ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
23ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
24ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// The FakeMessageLoop implements a message loop that doesn't block or wait for
25ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// time based tasks to be ready. The tasks are executed in the order they should
26ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// be executed in a real message loop implementation, but the time is advanced
27ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// to the time when the first task should be executed instead of blocking.
28ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// To keep a consistent notion of time for other classes, FakeMessageLoop
29ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// optionally updates a SimpleTestClock instance when it needs to advance the
30ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// clock.
31ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// This message loop implementation is useful for unittests.
329ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkoclass BRILLO_EXPORT FakeMessageLoop : public MessageLoop {
33ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo public:
34ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Create a FakeMessageLoop optionally using a SimpleTestClock to update the
35ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // time when Run() or RunOnce(true) are called and should block.
36ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  explicit FakeMessageLoop(base::SimpleTestClock* clock);
37ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  ~FakeMessageLoop() override = default;
38ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
393845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  TaskId PostDelayedTask(const tracked_objects::Location& from_here,
40a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                         const base::Closure& task,
413845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                         base::TimeDelta delay) override;
42106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  using MessageLoop::PostDelayedTask;
433845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
443845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                             int fd,
453845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                             WatchMode mode,
463845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                             bool persistent,
47a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                             const base::Closure& task) override;
483845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  using MessageLoop::WatchFileDescriptor;
49ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  bool CancelTask(TaskId task_id) override;
50ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  bool RunOnce(bool may_block) override;
51ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
52ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // FakeMessageLoop methods:
53ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
543845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // Pretend, for the purpose of the FakeMessageLoop watching for file
553845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // descriptors, that the file descriptor |fd| readiness to perform the
563845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // operation described by |mode| is |ready|. Initially, no file descriptor
573845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // is ready for any operation.
583845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  void SetFileDescriptorReadiness(int fd, WatchMode mode, bool ready);
593845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
60ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Return whether there are peding tasks. Useful to check that no
61ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // callbacks were leaked.
62ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  bool PendingTasks();
63ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
64ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo private:
653845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  struct ScheduledTask {
663845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    tracked_objects::Location location;
673845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    bool persistent;
683845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    base::Closure callback;
693845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  };
703845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
713845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // The sparse list of scheduled pending callbacks.
723845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  std::map<MessageLoop::TaskId, ScheduledTask> tasks_;
733845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
74ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Using std::greater<> for the priority_queue means that the top() of the
75ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // queue is the lowest (earliest) time, and for the same time, the smallest
76ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // TaskId. This determines the order in which the tasks will be fired.
77ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  std::priority_queue<
78ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo      std::pair<base::Time, MessageLoop::TaskId>,
79ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo      std::vector<std::pair<base::Time, MessageLoop::TaskId>>,
80ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo      std::greater<std::pair<base::Time, MessageLoop::TaskId>>> fire_order_;
813845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
823845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // The bag of watched (fd, mode) pair associated with the TaskId that's
833845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // watching them.
843845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  std::multimap<std::pair<int, WatchMode>, MessageLoop::TaskId> fds_watched_;
853845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
863845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // The set of (fd, mode) pairs that are faked as ready.
873845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  std::set<std::pair<int, WatchMode>> fds_ready_;
88ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
89ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  base::SimpleTestClock* test_clock_ = nullptr;
90ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  base::Time current_time_ = base::Time::FromDoubleT(1246996800.);
91ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
92ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  MessageLoop::TaskId last_id_ = kTaskIdNull;
93ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
94ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  DISALLOW_COPY_AND_ASSIGN(FakeMessageLoop);
95ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo};
96ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
979ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
98ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
99fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
100