OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium 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 CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_ | |
6 #define CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_ | |
7 | |
8 #include <queue> | |
9 #include <vector> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "base/callback.h" | |
13 #include "base/compiler_specific.h" | |
14 #include "base/memory/linked_ptr.h" | |
15 #include "base/memory/weak_ptr.h" | |
16 #include "chrome/browser/policy/delayed_work_scheduler.h" | |
17 | |
18 // Utilities for testing users of DelayedWorkScheduler. There are no | |
19 // thread-safety guarantees for the classes in this file. They expect to | |
20 // only be called from the UI thread and issue callbacks on that very same | |
21 // thread. | |
22 // | |
23 // Usage examples: | |
24 // | |
25 // Making CloudPolicyController and/or DeviceTokenFetcher run without real-time | |
26 // delays in tests: | |
27 // | |
28 // DeviceTokenFetcher fetcher(..., new DummyDelayedWorkScheduler); | |
29 // | |
30 // Running CloudPolicyController and/or DeviceTokenFetcher in a simulated | |
31 // environment, in which the time of any of their actions can be recorded, | |
32 // but without having to wait for the real-time delays: | |
33 // | |
34 // EventLogger logger; | |
35 // DeviceTokenFetcher fetcher(..., new LoggingEventScheduler(&logger)); | |
36 // CloudPolicyController controller(..., new LoggingEventScheduler(&logger)); | |
37 // | |
38 // Start the policy subsystem, and use logger.RegisterEvent() in case of | |
39 // any interesting events. The time of all these events will be recorded | |
40 // by |logger|. After that, the results can be extracted easily: | |
41 // | |
42 // std::vector<int64> logged_events; | |
43 // logger.Swap(&logged_events); | |
44 // | |
45 // Each element of |logged_events| corresponds to a logger event, and stores | |
46 // the virtual time when it was logged. Events are in ascending order. | |
47 | |
48 namespace policy { | |
49 | |
50 // Helper class for LoggingWorkScheduler. It essentially emulates a real | |
51 // message loop. All the submitted tasks are run with zero delay, but the | |
52 // order in which they would run with delays is preserved. | |
53 // All the task posting requests of the schedulers will be channeled through | |
54 // a common instance of EventLogger. This makes sure, that this instance can | |
55 // keep track of time in the simulation and record logged events with correct | |
56 // timestamps. | |
57 class EventLogger { | |
58 public: | |
59 EventLogger(); | |
60 ~EventLogger(); | |
61 | |
62 // Post a task to be executed |delay| milliseconds from now. The task can be | |
63 // cancelled later by calling Reset() on the callback. | |
64 void PostDelayedWork(linked_ptr<base::Closure> callback, int64 delay); | |
65 | |
66 // Register a new event that happened now according to the internal clock. | |
67 void RegisterEvent(); | |
68 | |
69 // Swap out the internal list of events. | |
70 void Swap(std::vector<int64>* events); | |
71 | |
72 // Counts the events in a sorted integer array that are >= |start| but | |
73 // < |start| + |length|. | |
74 static int CountEvents(const std::vector<int64>& events, | |
75 int64 start, int64 length); | |
76 | |
77 private: | |
78 class Task; | |
79 | |
80 // Updates |current_time_| and triggers the next scheduled task. This method | |
81 // is run repeatedly on the main message loop until there are scheduled | |
82 // tasks. | |
83 void Step(); | |
84 | |
85 // Stores the list of scheduled tasks with their respective delays and | |
86 // schedulers. | |
87 std::priority_queue<Task> scheduled_tasks_; | |
88 | |
89 // Machinery to put a call to |Step| at the end of the message loop. | |
90 bool step_pending_; | |
91 base::WeakPtrFactory<EventLogger> weak_ptr_factory_; | |
92 | |
93 // Ascending list of observation-times of the logged events. | |
94 std::vector<int64> events_; | |
95 // The current time of the simulated system. | |
96 int64 current_time_; | |
97 // The total number of tasks scheduled so far. | |
98 int64 task_counter_; | |
99 | |
100 DISALLOW_COPY_AND_ASSIGN(EventLogger); | |
101 }; | |
102 | |
103 // Issues delayed tasks with zero effective delay, but posts them through | |
104 // an EventLogger, to make it possible to log events and reconstruct their | |
105 // execution time. | |
106 class LoggingWorkScheduler : public DelayedWorkScheduler { | |
107 public: | |
108 // An EventLogger may be shared by more than one schedulers, therefore | |
109 // no ownership is taken. | |
110 explicit LoggingWorkScheduler(EventLogger* logger); | |
111 virtual ~LoggingWorkScheduler(); | |
112 | |
113 virtual void PostDelayedWork(const base::Closure& callback, int64 delay) | |
114 OVERRIDE; | |
115 virtual void CancelDelayedWork() OVERRIDE; | |
116 | |
117 private: | |
118 EventLogger* logger_; | |
119 linked_ptr<base::Closure> callback_; | |
120 | |
121 DISALLOW_COPY_AND_ASSIGN(LoggingWorkScheduler); | |
122 }; | |
123 | |
124 // This implementation of DelayedWorkScheduler always schedules the tasks | |
125 // with zero delay. | |
126 class DummyWorkScheduler : public DelayedWorkScheduler { | |
127 public: | |
128 DummyWorkScheduler(); | |
129 virtual ~DummyWorkScheduler(); | |
130 | |
131 virtual void PostDelayedWork(const base::Closure& callback, int64 delay) | |
132 OVERRIDE; | |
133 | |
134 private: | |
135 DISALLOW_COPY_AND_ASSIGN(DummyWorkScheduler); | |
136 }; | |
137 | |
138 } // namespace policy | |
139 | |
140 #endif // CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_ | |
OLD | NEW |