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