1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
6 #define LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
7 
8 #include <functional>
9 #include <map>
10 #include <queue>
11 #include <set>
12 #include <utility>
13 #include <vector>
14 
15 #include <base/location.h>
16 #include <base/test/simple_test_clock.h>
17 #include <base/time/time.h>
18 
19 #include <brillo/brillo_export.h>
20 #include <brillo/message_loops/message_loop.h>
21 
22 namespace brillo {
23 
24 // The FakeMessageLoop implements a message loop that doesn't block or wait for
25 // time based tasks to be ready. The tasks are executed in the order they should
26 // be executed in a real message loop implementation, but the time is advanced
27 // to the time when the first task should be executed instead of blocking.
28 // To keep a consistent notion of time for other classes, FakeMessageLoop
29 // optionally updates a SimpleTestClock instance when it needs to advance the
30 // clock.
31 // This message loop implementation is useful for unittests.
32 class BRILLO_EXPORT FakeMessageLoop : public MessageLoop {
33  public:
34   // Create a FakeMessageLoop optionally using a SimpleTestClock to update the
35   // time when Run() or RunOnce(true) are called and should block.
36   explicit FakeMessageLoop(base::SimpleTestClock* clock);
37   ~FakeMessageLoop() override = default;
38 
39   TaskId PostDelayedTask(const tracked_objects::Location& from_here,
40                          const base::Closure& task,
41                          base::TimeDelta delay) override;
42   using MessageLoop::PostDelayedTask;
43   TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
44                              int fd,
45                              WatchMode mode,
46                              bool persistent,
47                              const base::Closure& task) override;
48   using MessageLoop::WatchFileDescriptor;
49   bool CancelTask(TaskId task_id) override;
50   bool RunOnce(bool may_block) override;
51 
52   // FakeMessageLoop methods:
53 
54   // Pretend, for the purpose of the FakeMessageLoop watching for file
55   // descriptors, that the file descriptor |fd| readiness to perform the
56   // operation described by |mode| is |ready|. Initially, no file descriptor
57   // is ready for any operation.
58   void SetFileDescriptorReadiness(int fd, WatchMode mode, bool ready);
59 
60   // Return whether there are peding tasks. Useful to check that no
61   // callbacks were leaked.
62   bool PendingTasks();
63 
64  private:
65   struct ScheduledTask {
66     tracked_objects::Location location;
67     bool persistent;
68     base::Closure callback;
69   };
70 
71   // The sparse list of scheduled pending callbacks.
72   std::map<MessageLoop::TaskId, ScheduledTask> tasks_;
73 
74   // Using std::greater<> for the priority_queue means that the top() of the
75   // queue is the lowest (earliest) time, and for the same time, the smallest
76   // TaskId. This determines the order in which the tasks will be fired.
77   std::priority_queue<
78       std::pair<base::Time, MessageLoop::TaskId>,
79       std::vector<std::pair<base::Time, MessageLoop::TaskId>>,
80       std::greater<std::pair<base::Time, MessageLoop::TaskId>>> fire_order_;
81 
82   // The bag of watched (fd, mode) pair associated with the TaskId that's
83   // watching them.
84   std::multimap<std::pair<int, WatchMode>, MessageLoop::TaskId> fds_watched_;
85 
86   // The set of (fd, mode) pairs that are faked as ready.
87   std::set<std::pair<int, WatchMode>> fds_ready_;
88 
89   base::SimpleTestClock* test_clock_ = nullptr;
90   base::Time current_time_ = base::Time::FromDoubleT(1246996800.);
91 
92   MessageLoop::TaskId last_id_ = kTaskIdNull;
93 
94   DISALLOW_COPY_AND_ASSIGN(FakeMessageLoop);
95 };
96 
97 }  // namespace brillo
98 
99 #endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_FAKE_MESSAGE_LOOP_H_
100