Chromium Code Reviews| 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 |