OLD | NEW |
---|---|
(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/media/router/discovery/dial/device_description_service. h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "base/test/mock_callback.h" | |
9 #include "chrome/browser/media/router/discovery/dial/device_description_fetcher. h" | |
10 #include "chrome/browser/media/router/discovery/dial/dial_device_data.h" | |
11 #include "chrome/browser/media/router/discovery/dial/parsed_dial_device_descript ion.h" | |
12 #include "chrome/browser/media/router/discovery/dial/safe_dial_device_descriptio n_parser.h" | |
13 #include "chrome/test/base/testing_profile.h" | |
14 #include "content/public/test/test_browser_thread_bundle.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 using ::testing::_; | |
19 using ::testing::Return; | |
20 using ::testing::SaveArg; | |
21 | |
22 namespace media_router { | |
23 | |
24 class TestSafeDialDeviceDescriptionParser | |
25 : public SafeDialDeviceDescriptionParser { | |
26 public: | |
27 void Start(const std::string& xml_text, | |
imcheng
2017/04/25 01:40:12
Do you intend to mock out this method?
zhaobin
2017/04/26 18:50:04
Done.
| |
28 const DeviceDescriptionCallback& callback) override {} | |
29 }; | |
30 | |
31 class TestDeviceDescriptionService : public DeviceDescriptionService { | |
32 public: | |
33 TestDeviceDescriptionService( | |
34 const DeviceDescriptionParseSuccessCallback& success_cb, | |
35 const DeviceDescriptionParseErrorCallback& error_cb) | |
36 : DeviceDescriptionService(success_cb, error_cb) {} | |
37 | |
38 MOCK_METHOD0(CreateSafeParser, SafeDialDeviceDescriptionParser*()); | |
39 }; | |
40 | |
41 class DeviceDescriptionServiceTest : public ::testing::Test { | |
42 public: | |
43 DeviceDescriptionServiceTest() | |
44 : device_description_service_(mock_success_cb_.Get(), | |
45 mock_error_cb_.Get()), | |
46 fetcher_map_( | |
47 device_description_service_.device_description_fetcher_map_), | |
48 description_map_(device_description_service_.description_map_), | |
49 thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} | |
50 | |
51 TestDeviceDescriptionService* device_description_service() { | |
52 return &device_description_service_; | |
53 } | |
54 | |
55 // Create Test Data | |
mark a. foltz
2017/04/25 21:06:26
These static methods to create test data could go
zhaobin
2017/04/26 18:50:04
Done.
| |
56 static DialDeviceData CreateDialDeviceData(int num) { | |
57 DialDeviceData device_data( | |
58 base::StringPrintf("Device id %d", num), | |
59 GURL(base::StringPrintf("http://192.168.1.%d/dd.xml", num)), | |
60 base::Time::Now()); | |
61 device_data.set_label(base::StringPrintf("Device label %d", num)); | |
62 return device_data; | |
63 } | |
64 | |
65 static DialDeviceDescriptionData CreateDialDeviceDescriptionData(int num) { | |
66 return DialDeviceDescriptionData( | |
67 "", GURL(base::StringPrintf("http://192.168.1.%d/apps", num))); | |
68 } | |
69 | |
70 static chrome::mojom::DialDeviceDescriptionPtr CreateDialDeviceDescriptionPtr( | |
71 int num) { | |
72 chrome::mojom::DialDeviceDescriptionPtr description_ptr = | |
73 chrome::mojom::DialDeviceDescription::New(); | |
74 description_ptr->friendly_name = | |
75 base::StringPrintf("Friendly name %d", num); | |
76 description_ptr->model_name = base::StringPrintf("Model name %d", num); | |
77 description_ptr->unique_id = base::StringPrintf("Unique ID %d", num); | |
78 return description_ptr; | |
79 } | |
80 | |
81 static ParsedDialDeviceDescription CreateParsedDialDeviceDescription( | |
82 int num) { | |
83 ParsedDialDeviceDescription description_data; | |
84 description_data.app_url = | |
85 GURL(base::StringPrintf("http://192.168.1.%d/apps", num)); | |
86 description_data.friendly_name = | |
87 base::StringPrintf("Friendly name %d", num); | |
88 description_data.model_name = base::StringPrintf("Model name %d", num); | |
89 description_data.unique_id = base::StringPrintf("Unique ID %d", num); | |
90 return description_data; | |
91 } | |
92 | |
93 void AddToCache(const std::string& device_label, | |
94 const ParsedDialDeviceDescription& description_data, | |
95 bool expired) { | |
96 DeviceDescriptionService::CacheEntry cache_entry; | |
97 cache_entry.expire_time = base::Time::Now(); | |
98 if (!expired) | |
99 cache_entry.expire_time += base::TimeDelta::FromHours(12); | |
100 cache_entry.description_data = description_data; | |
101 description_map_[device_label] = cache_entry; | |
102 } | |
103 | |
104 void OnDeviceDescriptionFetchComplete(int num) { | |
105 if (!device_description_service_.parser_) { | |
106 device_description_service_.parser_ = | |
107 base::MakeUnique<TestSafeDialDeviceDescriptionParser>(); | |
108 } | |
109 | |
110 auto device_data = CreateDialDeviceData(num); | |
111 auto description_response_data = CreateDialDeviceDescriptionData(num); | |
112 auto parsed_description_data = CreateParsedDialDeviceDescription(num); | |
113 | |
114 EXPECT_CALL(mock_success_cb_, Run(device_data, parsed_description_data)); | |
115 | |
116 device_description_service_.OnDeviceDescriptionFetchComplete( | |
117 device_data, description_response_data); | |
118 device_description_service_.OnParsedDeviceDescription( | |
119 device_data, description_response_data.app_url, | |
120 CreateDialDeviceDescriptionPtr(num)); | |
121 } | |
122 | |
123 void TestOnParsedDeviceDescription( | |
124 chrome::mojom::DialDeviceDescriptionPtr description_ptr, | |
125 const std::string& error_message) { | |
126 GURL app_url("http://192.168.1.1/apps"); | |
127 auto device_data = CreateDialDeviceData(1); | |
128 auto description_data = CreateParsedDialDeviceDescription(1); | |
129 | |
130 if (!error_message.empty()) { | |
131 EXPECT_CALL(mock_error_cb_, Run(device_data, error_message)); | |
132 } else { | |
133 EXPECT_CALL(mock_success_cb_, Run(device_data, description_data)); | |
134 } | |
135 device_description_service()->OnParsedDeviceDescription( | |
136 device_data, app_url, std::move(description_ptr)); | |
137 } | |
138 | |
139 protected: | |
140 base::MockCallback< | |
141 DeviceDescriptionService::DeviceDescriptionParseSuccessCallback> | |
142 mock_success_cb_; | |
143 base::MockCallback< | |
144 DeviceDescriptionService::DeviceDescriptionParseErrorCallback> | |
145 mock_error_cb_; | |
146 | |
147 TestDeviceDescriptionService device_description_service_; | |
148 std::map<std::string, std::unique_ptr<DeviceDescriptionFetcher>>& | |
149 fetcher_map_; | |
150 std::map<std::string, DeviceDescriptionService::CacheEntry>& description_map_; | |
151 | |
152 const content::TestBrowserThreadBundle thread_bundle_; | |
153 TestingProfile profile_; | |
154 }; | |
155 | |
156 TEST_F(DeviceDescriptionServiceTest, TestGetDeviceDescriptionFromCache) { | |
157 auto device_data = CreateDialDeviceData(1); | |
158 auto description_data = CreateParsedDialDeviceDescription(1); | |
159 EXPECT_CALL(mock_success_cb_, Run(device_data, description_data)); | |
160 | |
161 AddToCache(device_data.label(), description_data, false /* expired */); | |
162 | |
163 std::vector<DialDeviceData> devices = {device_data}; | |
164 device_description_service()->GetDeviceDescriptions(devices, nullptr); | |
165 } | |
166 | |
167 TEST_F(DeviceDescriptionServiceTest, TestGetDeviceDescriptionFetchURL) { | |
168 DialDeviceData device_data = CreateDialDeviceData(1); | |
169 std::vector<DialDeviceData> devices = {device_data}; | |
170 | |
171 // Create Fetcher | |
172 EXPECT_TRUE(fetcher_map_.empty()); | |
173 device_description_service()->GetDeviceDescriptions( | |
174 devices, profile_.GetRequestContext()); | |
175 EXPECT_EQ(size_t(1), fetcher_map_.size()); | |
176 | |
177 // Remove fetcher and create safe parser | |
178 OnDeviceDescriptionFetchComplete(1); | |
179 } | |
180 | |
181 TEST_F(DeviceDescriptionServiceTest, TestGetDeviceDescriptionFetchURLError) { | |
182 DialDeviceData device_data = CreateDialDeviceData(1); | |
183 std::vector<DialDeviceData> devices; | |
184 devices.push_back(device_data); | |
185 | |
186 // Create Fetcher | |
187 EXPECT_TRUE(fetcher_map_.empty()); | |
188 device_description_service()->GetDeviceDescriptions( | |
189 devices, profile_.GetRequestContext()); | |
190 EXPECT_EQ(size_t(1), fetcher_map_.size()); | |
191 | |
192 EXPECT_CALL(mock_error_cb_, Run(device_data, "")); | |
193 | |
194 device_description_service()->OnDeviceDescriptionFetchError(device_data, ""); | |
195 EXPECT_TRUE(fetcher_map_.empty()); | |
196 } | |
197 | |
198 TEST_F(DeviceDescriptionServiceTest, | |
199 TestGetDeviceDescriptionRemoveOutDatedFetchers) { | |
200 DialDeviceData device_data_1 = CreateDialDeviceData(1); | |
201 DialDeviceData device_data_2 = CreateDialDeviceData(2); | |
202 DialDeviceData device_data_3 = CreateDialDeviceData(3); | |
203 | |
204 std::vector<DialDeviceData> devices; | |
205 devices.push_back(device_data_1); | |
206 devices.push_back(device_data_2); | |
207 | |
208 // insert fetchers | |
209 device_description_service()->GetDeviceDescriptions( | |
210 devices, profile_.GetRequestContext()); | |
211 | |
212 // Keep fetchers no exist in current device list and remove fetchers with | |
213 // different description url. | |
214 GURL new_url_2 = GURL("http://example.com"); | |
215 device_data_2.set_device_description_url(new_url_2); | |
216 | |
217 devices.clear(); | |
218 devices.push_back(device_data_2); | |
219 devices.push_back(device_data_3); | |
220 device_description_service()->GetDeviceDescriptions( | |
221 devices, profile_.GetRequestContext()); | |
222 | |
223 EXPECT_EQ(size_t(3), fetcher_map_.size()); | |
224 | |
225 auto* description_fetcher = fetcher_map_[device_data_2.label()].get(); | |
226 EXPECT_EQ(new_url_2, description_fetcher->device_description_url()); | |
227 | |
228 EXPECT_CALL(mock_error_cb_, Run(_, _)).Times(3); | |
229 device_description_service()->OnDeviceDescriptionFetchError(device_data_1, | |
230 ""); | |
231 device_description_service()->OnDeviceDescriptionFetchError(device_data_2, | |
mark a. foltz
2017/04/25 21:06:26
Is this asserting that the original fetcher for |d
zhaobin
2017/04/26 18:50:04
No, |device_data_2| will fail quietly without any
| |
232 ""); | |
233 device_description_service()->OnDeviceDescriptionFetchError(device_data_3, | |
234 ""); | |
235 } | |
236 | |
237 TEST_F(DeviceDescriptionServiceTest, TestCleanUpCacheEntries) { | |
238 DialDeviceData device_data_1 = CreateDialDeviceData(1); | |
239 DialDeviceData device_data_2 = CreateDialDeviceData(2); | |
240 DialDeviceData device_data_3 = CreateDialDeviceData(3); | |
241 | |
242 AddToCache(device_data_1.label(), ParsedDialDeviceDescription(), | |
243 true /* expired */); | |
244 AddToCache(device_data_2.label(), ParsedDialDeviceDescription(), | |
245 true /* expired */); | |
246 AddToCache(device_data_3.label(), ParsedDialDeviceDescription(), | |
247 false /* expired */); | |
248 | |
249 device_description_service_.CleanUpCacheEntries(); | |
250 EXPECT_EQ(size_t(1), description_map_.size()); | |
mark a. foltz
2017/04/25 21:06:26
Nit: Check that device 3 specifically is not remov
zhaobin
2017/04/26 18:50:04
Done.
| |
251 | |
252 AddToCache(device_data_3.label(), ParsedDialDeviceDescription(), | |
253 true /* expired*/); | |
254 device_description_service_.CleanUpCacheEntries(); | |
255 EXPECT_TRUE(description_map_.empty()); | |
256 } | |
257 | |
258 TEST_F(DeviceDescriptionServiceTest, TestOnParsedDeviceDescription) { | |
259 GURL app_url("http://192.168.1.1/apps"); | |
260 DialDeviceData device_data = CreateDialDeviceData(1); | |
261 | |
262 // null_ptr | |
263 std::string error_message = "Failed to parse device description xml"; | |
264 TestOnParsedDeviceDescription(nullptr, error_message); | |
265 | |
266 // Empty field | |
267 error_message = "Failed to process fetch result"; | |
268 TestOnParsedDeviceDescription(chrome::mojom::DialDeviceDescription::New(), | |
269 error_message); | |
270 | |
271 // Valid device description ptr and put in cache | |
272 auto description_ptr = CreateDialDeviceDescriptionPtr(1); | |
273 TestOnParsedDeviceDescription(std::move(description_ptr), ""); | |
274 EXPECT_EQ(size_t(1), description_map_.size()); | |
275 | |
276 // Valid device description ptr and skip cache. | |
277 size_t cache_num = 256; | |
278 for (size_t i = 0; i < cache_num; i++) { | |
279 AddToCache(std::to_string(i), ParsedDialDeviceDescription(), | |
280 false /* expired */); | |
281 } | |
282 | |
283 EXPECT_EQ(size_t(cache_num + 1), description_map_.size()); | |
284 description_ptr = CreateDialDeviceDescriptionPtr(1); | |
285 TestOnParsedDeviceDescription(std::move(description_ptr), ""); | |
286 EXPECT_EQ(size_t(cache_num + 1), description_map_.size()); | |
287 } | |
288 | |
289 TEST_F(DeviceDescriptionServiceTest, TestSafeParserProperlyCreated) { | |
290 DialDeviceData device_data_1 = CreateDialDeviceData(1); | |
291 DialDeviceData device_data_2 = CreateDialDeviceData(2); | |
292 DialDeviceData device_data_3 = CreateDialDeviceData(3); | |
293 | |
294 std::vector<DialDeviceData> devices = {device_data_1, device_data_2, | |
295 device_data_3}; | |
296 | |
297 // insert fetchers | |
298 device_description_service()->GetDeviceDescriptions( | |
299 devices, profile_.GetRequestContext()); | |
300 | |
301 EXPECT_FALSE(device_description_service()->parser_); | |
302 OnDeviceDescriptionFetchComplete(1); | |
303 | |
304 EXPECT_TRUE(device_description_service()->parser_); | |
305 OnDeviceDescriptionFetchComplete(2); | |
306 OnDeviceDescriptionFetchComplete(3); | |
307 | |
308 EXPECT_FALSE(device_description_service()->parser_); | |
309 } | |
310 | |
311 } // namespace media_router | |
OLD | NEW |