Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(692)

Side by Side Diff: chrome/browser/extensions/api/feedback_private/feedback_private_api_chromeos_unittest.cc

Issue 2840103002: Add new API function: feedbackPrivate.readLogSource (Closed)
Patch Set: Add proper ifdefs for non-CrOS platforms Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
6
7 #include "base/json/json_writer.h"
8 #include "base/macros.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/test/simple_test_tick_clock.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/api/feedback_private/log_source_resource.h"
13 #include "chrome/browser/extensions/api/feedback_private/single_log_source_facto ry.h"
14 #include "chrome/browser/extensions/extension_api_unittest.h"
15 #include "extensions/browser/api_test_utils.h"
16
17 namespace extensions {
18
19 namespace {
20
21 using api::feedback_private::ReadLogSourceResult;
22 using api::feedback_private::ReadLogSourceParams;
23 using base::TimeDelta;
24 using system_logs::SingleLogSource;
25 using system_logs::SystemLogsResponse;
26 using SupportedSource = system_logs::SingleLogSource::SupportedSource;
27
28 std::unique_ptr<KeyedService> ApiResourceManagerTestFactory(
29 content::BrowserContext* context) {
30 return base::MakeUnique<ApiResourceManager<LogSourceResource>>(context);
31 }
32
33 // Converts |params| to a string containing a JSON dictionary within an argument
34 // list.
35 std::string ParamsToJSON(const ReadLogSourceParams& params) {
36 base::ListValue params_value;
37 params_value.Append(params.ToValue());
38 std::string params_json_string;
39 EXPECT_TRUE(base::JSONWriter::Write(params_value, &params_json_string));
40
41 return params_json_string;
42 }
43
44 // A dummy SingleLogSource that does not require real system logs to be
45 // available during testing.
46 class TestSingleLogSource : public SingleLogSource {
47 public:
48 explicit TestSingleLogSource(SupportedSource type)
49 : SingleLogSource(type), call_count_(0) {}
50
51 ~TestSingleLogSource() override = default;
52
53 // Fetch() will return a single different string each time, in the following
54 // sequence: "a", "bb", "ccc", until a string of 26 z's. Will never return an
55 // empty result.
56 void Fetch(const system_logs::SysLogsSourceCallback& callback) override {
57 int count_modulus = call_count_ % kNumCharsToIterate;
58 std::string result(count_modulus + 1, kInitialChar + count_modulus);
59 ASSERT_GT(result.size(), 0U);
60 ++call_count_;
61
62 SystemLogsResponse* result_map = new SystemLogsResponse;
63 result_map->emplace("", result);
64
65 // Do not directly pass the result to the callback, because that's not how
66 // log sources actually work. Instead, simulate the asynchronous operation
67 // of a SingleLogSource by invoking the callback separately.
68 base::ThreadTaskRunnerHandle::Get()->PostTask(
69 FROM_HERE, base::Bind(callback, base::Owned(result_map)));
70 }
71
72 // Instantiates a new instance of this class. Does not retain ownership. Used
73 // to create a Callback that can be used to override the default behavior of
74 // SingleLogSourceFactory.
75 static std::unique_ptr<SingleLogSource> Create(SupportedSource type) {
76 return base::MakeUnique<TestSingleLogSource>(type);
77 }
78
79 private:
80 // Iterate over the whole lowercase alphabet, starting from 'a'.
81 const int kNumCharsToIterate = 26;
82 const char kInitialChar = 'a';
83
84 // Keep track of how many times Fetch() has been called, in order to determine
85 // its behavior each time.
86 int call_count_;
87
88 DISALLOW_COPY_AND_ASSIGN(TestSingleLogSource);
89 };
90
91 } // namespace
92
93 class FeedbackPrivateApiUnittest : public ExtensionApiUnittest {
94 public:
95 FeedbackPrivateApiUnittest()
96 : create_callback_(base::Bind(&TestSingleLogSource::Create)) {}
97 ~FeedbackPrivateApiUnittest() override {}
98
99 void SetUp() override {
100 ExtensionApiUnittest::SetUp();
101
102 // The ApiResourceManager used for LogSourceResource is destroyed every time
103 // a unit test finishes, during TearDown(). There is no way to re-create it
104 // normally. The below code forces it to be re-created during SetUp(), so
105 // that there is always a valid ApiResourceManager<LogSourceResource> when
106 // subsequent unit tests are running.
107 ApiResourceManager<LogSourceResource>::GetFactoryInstance()
108 ->SetTestingFactoryAndUse(profile(), ApiResourceManagerTestFactory);
109
110 SingleLogSourceFactory::SetForTesting(&create_callback_);
111 }
112
113 void TearDown() override {
114 SingleLogSourceFactory::SetForTesting(nullptr);
115 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(nullptr);
116
117 FeedbackPrivateAPI::GetFactoryInstance()
118 ->Get(profile())
119 ->GetLogSourceAccessManager()
120 ->SetTickClockForTesting(nullptr);
121
122 ExtensionApiUnittest::TearDown();
123 }
124
125 // Runs the feedbackPrivate.readLogSource() function. See API function
126 // definition for argument descriptions.
127 //
128 // The API function is expected to complete successfully. For running the
129 // function with an expectation of an error result, call
130 // RunReadLogSourceFunctionWithError().
131 //
132 // Note that the second argument of the result is a list of strings, but the
133 // test class TestSingleLogSource always returns a list containing a single
134 // string. To simplify things, the single string result will be returned in
135 // |*result_string|, while the reader ID is returned in |*result_reader_id|.
136 testing::AssertionResult RunReadLogSourceFunction(
137 const ReadLogSourceParams& params,
138 int* result_reader_id,
139 std::string* result_string) {
140 scoped_refptr<FeedbackPrivateReadLogSourceFunction> function =
141 new FeedbackPrivateReadLogSourceFunction;
142
143 std::unique_ptr<base::Value> result_value =
144 RunFunctionAndReturnValue(function.get(), ParamsToJSON(params));
145 if (!result_value)
146 return testing::AssertionFailure() << "No result";
147
148 ReadLogSourceResult result;
149 if (!ReadLogSourceResult::Populate(*result_value, &result)) {
150 return testing::AssertionFailure()
151 << "Unable to parse a valid result from " << *result_value;
152 }
153
154 if (result.log_lines.size() != 1) {
155 return testing::AssertionFailure()
156 << "Expected |log_lines| to contain 1 string, actual number: "
157 << result.log_lines.size();
158 }
159
160 *result_reader_id = result.reader_id;
161 *result_string = result.log_lines[0];
162
163 return testing::AssertionSuccess();
164 }
165
166 // Similar to RunReadLogSourceFunction(), but expects to return an error.
167 // Returns a string containing the error message. Does not return any result
168 // from the API function.
169 std::string RunReadLogSourceFunctionWithError(
170 const ReadLogSourceParams& params) {
171 scoped_refptr<FeedbackPrivateReadLogSourceFunction> function =
172 new FeedbackPrivateReadLogSourceFunction;
173
174 return RunFunctionAndReturnError(function.get(), ParamsToJSON(params));
175 }
176
177 private:
178 // Passed to SingleLogSourceFactory so that the API can create an instance of
179 // TestSingleLogSource for testing.
180 SingleLogSourceFactory::CreateCallback create_callback_;
181
182 DISALLOW_COPY_AND_ASSIGN(FeedbackPrivateApiUnittest);
183 };
184
185 TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceInvalidId) {
186 const TimeDelta timeout(TimeDelta::FromMilliseconds(0));
187 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
188
189 ReadLogSourceParams params;
190 params.source = api::feedback_private::LOG_SOURCE_MESSAGES;
191 params.incremental = true;
192 params.reader_id.reset(new int(9999));
193
194 EXPECT_NE("", RunReadLogSourceFunctionWithError(params));
195 }
196
197 TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceNonIncremental) {
198 const TimeDelta timeout(TimeDelta::FromMilliseconds(0));
199 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
200
201 ReadLogSourceParams params;
202 params.source = api::feedback_private::LOG_SOURCE_MESSAGES;
203 params.incremental = false;
204
205 // Test multiple non-incremental reads.
206 int result_reader_id = -1;
207 std::string result_string;
208 EXPECT_TRUE(
209 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
210 EXPECT_EQ(0, result_reader_id);
211 EXPECT_EQ("a", result_string);
212
213 result_reader_id = -1;
214 result_string.clear();
215 EXPECT_TRUE(
216 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
217 EXPECT_EQ(0, result_reader_id);
218 EXPECT_EQ("a", result_string);
219
220 result_reader_id = -1;
221 result_string.clear();
222 EXPECT_TRUE(
223 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
224 EXPECT_EQ(0, result_reader_id);
225 EXPECT_EQ("a", result_string);
226 }
227
228 TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceIncremental) {
229 const TimeDelta timeout(TimeDelta::FromMilliseconds(0));
230 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
231
232 ReadLogSourceParams params;
233 params.source = api::feedback_private::LOG_SOURCE_MESSAGES;
234 params.incremental = true;
235
236 int result_reader_id = 0;
237 std::string result_string;
238 EXPECT_TRUE(
239 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
240 EXPECT_GT(result_reader_id, 0);
241 EXPECT_EQ("a", result_string);
242 params.reader_id.reset(new int(result_reader_id));
243
244 EXPECT_TRUE(
245 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
246 EXPECT_EQ(*params.reader_id, result_reader_id);
247 EXPECT_EQ("bb", result_string);
248
249 EXPECT_TRUE(
250 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
251 EXPECT_EQ(*params.reader_id, result_reader_id);
252 EXPECT_EQ("ccc", result_string);
253
254 // End the incremental read.
255 params.incremental = false;
256 EXPECT_TRUE(
257 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
258 EXPECT_EQ(0, result_reader_id);
259 EXPECT_EQ("dddd", result_string);
260
261 // The log source will no longer be valid if we try to read it.
262 params.incremental = true;
263 EXPECT_NE("", RunReadLogSourceFunctionWithError(params));
264 }
265
266 TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceMultipleSources) {
267 const TimeDelta timeout(TimeDelta::FromMilliseconds(0));
268 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
269
270 int result_reader_id = 0;
271 std::string result_string;
272
273 // Attempt to open LOG_SOURCE_MESSAGES twice.
274 ReadLogSourceParams params_1st_read;
275 params_1st_read.source = api::feedback_private::LOG_SOURCE_MESSAGES;
276 params_1st_read.incremental = true;
277 EXPECT_TRUE(RunReadLogSourceFunction(params_1st_read, &result_reader_id,
278 &result_string));
279 EXPECT_GT(result_reader_id, 0);
280 // Store the reader ID back into the params to set up for the next call.
281 params_1st_read.reader_id = base::MakeUnique<int>(result_reader_id);
282
283 // Cannot create a second reader from the same log source.
284 ReadLogSourceParams params_1st_read_repeated;
285 params_1st_read_repeated.source = api::feedback_private::LOG_SOURCE_MESSAGES;
286 params_1st_read_repeated.incremental = true;
287 EXPECT_NE("", RunReadLogSourceFunctionWithError(params_1st_read_repeated));
288
289 // Attempt to open LOG_SOURCE_UI_LATEST twice.
290 ReadLogSourceParams params_2nd_read;
291 params_2nd_read.source = api::feedback_private::LOG_SOURCE_UILATEST;
292 params_2nd_read.incremental = true;
293 result_reader_id = -1;
294 EXPECT_TRUE(RunReadLogSourceFunction(params_2nd_read, &result_reader_id,
295 &result_string));
296 EXPECT_GT(result_reader_id, 0);
297 EXPECT_NE(*params_1st_read.reader_id, result_reader_id);
298 // Store the reader ID back into the params to set up for the next call.
299 params_2nd_read.reader_id = base::MakeUnique<int>(result_reader_id);
300
301 // Cannot create a second reader from the same log source.
302 ReadLogSourceParams params_2nd_read_repeated;
303 params_2nd_read_repeated.source = api::feedback_private::LOG_SOURCE_UILATEST;
304 params_2nd_read_repeated.incremental = true;
305 EXPECT_NE("", RunReadLogSourceFunctionWithError(params_2nd_read_repeated));
306
307 // Close the two open log source readers, and make sure new ones can be
308 // opened.
309 params_1st_read.incremental = false;
310 result_reader_id = -1;
311 EXPECT_TRUE(RunReadLogSourceFunction(params_1st_read, &result_reader_id,
312 &result_string));
313 EXPECT_EQ(0, result_reader_id);
314
315 params_2nd_read.incremental = false;
316 result_reader_id = -1;
317 EXPECT_TRUE(RunReadLogSourceFunction(params_2nd_read, &result_reader_id,
318 &result_string));
319 EXPECT_EQ(0, result_reader_id);
320
321 EXPECT_TRUE(RunReadLogSourceFunction(params_1st_read_repeated,
322 &result_reader_id, &result_string));
323 EXPECT_GT(result_reader_id, 0);
324 const int new_read_result_reader_id = result_reader_id;
325
326 EXPECT_TRUE(RunReadLogSourceFunction(params_2nd_read_repeated,
327 &result_reader_id, &result_string));
328 EXPECT_GT(result_reader_id, 0);
329 EXPECT_NE(new_read_result_reader_id, result_reader_id);
330 }
331
332 TEST_F(FeedbackPrivateApiUnittest, ReadLogSourceWithAccessTimeouts) {
333 const TimeDelta timeout(TimeDelta::FromMilliseconds(100));
334 LogSourceAccessManager::SetRateLimitingTimeoutForTesting(&timeout);
335
336 base::SimpleTestTickClock* test_clock = new base::SimpleTestTickClock;
337 FeedbackPrivateAPI::GetFactoryInstance()
338 ->Get(profile())
339 ->GetLogSourceAccessManager()
340 ->SetTickClockForTesting(std::unique_ptr<base::TickClock>(test_clock));
341
342 ReadLogSourceParams params;
343 params.source = api::feedback_private::LOG_SOURCE_MESSAGES;
344 params.incremental = true;
345 int result_reader_id = 0;
346 std::string result_string;
347
348 // |test_clock| must start out at something other than 0, which is interpreted
349 // as an invalid value.
350 test_clock->Advance(TimeDelta::FromMilliseconds(100));
351
352 EXPECT_TRUE(
353 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
354 EXPECT_EQ(1, result_reader_id);
355 params.reader_id.reset(new int(result_reader_id));
356
357 // Immediately perform another read. This is not allowed. (empty result)
358 EXPECT_FALSE(
359 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
360
361 // Advance to t=120, but it will not be allowed. (empty result)
362 test_clock->Advance(TimeDelta::FromMilliseconds(20));
363 EXPECT_FALSE(
364 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
365
366 // Advance to t=150, but still not allowed.
367 test_clock->Advance(TimeDelta::FromMilliseconds(30));
368 EXPECT_FALSE(
369 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
370
371 // Advance to t=199, but still not allowed. (empty result)
372 test_clock->Advance(TimeDelta::FromMilliseconds(49));
373 EXPECT_FALSE(
374 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
375
376 // Advance to t=210, annd the access is finally allowed.
377 test_clock->Advance(TimeDelta::FromMilliseconds(11));
378 EXPECT_TRUE(
379 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
380
381 // Advance to t=309, but it will not be allowed. (empty result)
382 test_clock->Advance(TimeDelta::FromMilliseconds(99));
383 EXPECT_FALSE(
384 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
385
386 // Another read is finally allowed at t=310.
387 test_clock->Advance(TimeDelta::FromMilliseconds(1));
388 EXPECT_TRUE(
389 RunReadLogSourceFunction(params, &result_reader_id, &result_string));
390 }
391
392 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698