OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "remoting/test/host_list_fetcher.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/run_loop.h" |
| 10 #include "base/strings/stringprintf.h" |
| 11 #include "net/url_request/test_url_fetcher_factory.h" |
| 12 #include "remoting/test/host_info.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // Used as a HostListCallback for testing. |
| 18 void OnHostlistRetrieved( |
| 19 base::Closure done_closure, |
| 20 std::vector<remoting::test::HostInfo>* hostlist, |
| 21 const std::vector<remoting::test::HostInfo>& retrieved_hostlist) { |
| 22 *hostlist = retrieved_hostlist; |
| 23 |
| 24 done_closure.Run(); |
| 25 } |
| 26 |
| 27 const char kAccessTokenValue[] = "test_access_token_value"; |
| 28 const char kHostListReadyResponse[] = |
| 29 "{" |
| 30 " \"data\":{" |
| 31 " \"kind\":\"chromoting#hostList\"," |
| 32 " \"items\":[" |
| 33 " {" |
| 34 " \"tokenUrlPatterns\":[" |
| 35 " \"tokenUrlPattern_1A\"," |
| 36 " \"tokenUrlPattern_1B\"," |
| 37 " \"tokenUrlPattern_1C\"" |
| 38 " ]," |
| 39 " \"kind\":\"chromoting#host\"," |
| 40 " \"hostId\":\"test_host_id_1\"," |
| 41 " \"hostName\":\"test_host_name_1\"," |
| 42 " \"publicKey\":\"test_public_key_1\"," |
| 43 " \"jabberId\":\"test_jabber_id_1\"," |
| 44 " \"createdTime\":\"test_created_time_1\"," |
| 45 " \"updatedTime\":\"test_updated_time_1\"," |
| 46 " \"status\":\"ONLINE\"," |
| 47 " \"hostOfflineReason\":\"\"," |
| 48 " \"hostVersion\":\"test_host_version_1\"" |
| 49 " }," |
| 50 " {" |
| 51 " \"kind\":\"chromoting#host\"," |
| 52 " \"hostId\":\"test_host_id_2\"," |
| 53 " \"hostName\":\"test_host_name_2\"," |
| 54 " \"publicKey\":\"test_public_key_2\"," |
| 55 " \"jabberId\":\"test_jabber_id_2\"," |
| 56 " \"createdTime\":\"test_created_time_2\"," |
| 57 " \"updatedTime\":\"test_updated_time_2\"," |
| 58 " \"status\":\"OFFLINE\"," |
| 59 " \"hostOfflineReason\":\"test_host_offline_reason_2\"," |
| 60 " \"hostVersion\":\"test_host_version_2\"" |
| 61 " }" |
| 62 " ]" |
| 63 " }" |
| 64 "}"; |
| 65 const char kHostListMissingParametersResponse[] = |
| 66 "{" |
| 67 " \"data\":{" |
| 68 " \"kind\":\"chromoting#hostList\"," |
| 69 " \"items\":[" |
| 70 " {" |
| 71 " \"tokenUrlPatterns\":[" |
| 72 " \"tokenUrlPattern_1A\"," |
| 73 " \"tokenUrlPattern_1B\"," |
| 74 " \"tokenUrlPattern_1C\"" |
| 75 " ]," |
| 76 " \"kind\":\"chromoting#host\"," |
| 77 " \"hostId\":\"test_host_id_1\"," |
| 78 " \"hostName\":\"test_host_name_1\"," |
| 79 " \"publicKey\":\"test_public_key_1\"," |
| 80 " \"createdTime\":\"test_created_time_1\"," |
| 81 " \"updatedTime\":\"test_updated_time_1\"," |
| 82 " \"status\":\"OFFLINE\"," |
| 83 " \"hostOfflineReason\":\"\"," |
| 84 " \"hostVersion\":\"test_host_version_1\"" |
| 85 " }," |
| 86 " {" |
| 87 " \"kind\":\"chromoting#host\"," |
| 88 " \"hostName\":\"test_host_name_2\"," |
| 89 " \"publicKey\":\"test_public_key_2\"," |
| 90 " \"jabberId\":\"test_jabber_id_2\"," |
| 91 " \"createdTime\":\"test_created_time_2\"," |
| 92 " \"updatedTime\":\"test_updated_time_2\"," |
| 93 " \"status\":\"ONLINE\"," |
| 94 " \"hostOfflineReason\":\"\"," |
| 95 " \"hostVersion\":\"test_host_version_2\"" |
| 96 " }," |
| 97 " {" |
| 98 " \"kind\":\"chromoting#host\"," |
| 99 " \"hostId\":\"test_host_id_3\"," |
| 100 " \"publicKey\":\"test_public_key_3\"," |
| 101 " \"jabberId\":\"test_jabber_id_3\"," |
| 102 " \"createdTime\":\"test_created_time_3\"," |
| 103 " \"updatedTime\":\"test_updated_time_3\"," |
| 104 " \"status\":\"ONLINE\"," |
| 105 " \"hostOfflineReason\":\"\"," |
| 106 " \"hostVersion\":\"test_host_version_3\"" |
| 107 " }," |
| 108 " {" |
| 109 " \"kind\":\"chromoting#host\"," |
| 110 " \"hostId\":\"test_host_id_4\"," |
| 111 " \"hostName\":\"test_host_name_4\"," |
| 112 " \"jabberId\":\"test_jabber_id_4\"," |
| 113 " \"createdTime\":\"test_created_time_4\"," |
| 114 " \"updatedTime\":\"test_updated_time_4\"," |
| 115 " \"status\":\"ONLINE\"," |
| 116 " \"hostOfflineReason\":\"\"," |
| 117 " \"hostVersion\":\"test_host_version_4\"" |
| 118 " }," |
| 119 " {" |
| 120 " \"kind\":\"chromoting#host\"," |
| 121 " \"hostId\":\"test_host_id_5\"," |
| 122 " \"hostName\":\"test_host_name_5\"," |
| 123 " \"publicKey\":\"test_public_key_5\"," |
| 124 " \"jabberId\":\"test_jabber_id_5\"," |
| 125 " \"createdTime\":\"test_created_time_5\"," |
| 126 " \"updatedTime\":\"test_updated_time_5\"," |
| 127 " \"status\":\"OFFLINE\"," |
| 128 " \"hostVersion\":\"test_host_version_5\"" |
| 129 " }" |
| 130 " ]" |
| 131 " }" |
| 132 "}"; |
| 133 const char kHostListEmptyTokenUrlPatternsResponse[] = |
| 134 "{" |
| 135 " \"data\":{" |
| 136 " \"kind\":\"chromoting#hostList\"," |
| 137 " \"items\":[" |
| 138 " {" |
| 139 " \"tokenUrlPatterns\":[" |
| 140 " ]," |
| 141 " \"kind\":\"chromoting#host\"," |
| 142 " \"hostId\":\"test_host_id_1\"," |
| 143 " \"hostName\":\"test_host_name_1\"," |
| 144 " \"publicKey\":\"test_public_key_1\"," |
| 145 " \"jabberId\":\"test_jabber_id_1\"," |
| 146 " \"createdTime\":\"test_created_time_1\"," |
| 147 " \"updatedTime\":\"test_updated_time_1\"," |
| 148 " \"status\":\"ONLINE\"," |
| 149 " \"hostOfflineReason\":\"\"," |
| 150 " \"hostVersion\":\"test_host_version_1\"" |
| 151 " }" |
| 152 " ]" |
| 153 " }" |
| 154 "}"; |
| 155 const char kHostListEmptyItemsResponse[] = |
| 156 "{" |
| 157 " \"data\":{" |
| 158 " \"kind\":\"chromoting#hostList\"," |
| 159 " \"items\":[" |
| 160 " ]" |
| 161 " }" |
| 162 "}"; |
| 163 const char kHostListEmptyResponse[] = "{}"; |
| 164 |
| 165 const unsigned int kExpectedEmptyPatternsHostListSize = 1; |
| 166 const unsigned int kExpectedHostListSize = 2; |
| 167 const unsigned int kExpectedPatternsSize = 3; |
| 168 |
| 169 } // namespace |
| 170 |
| 171 namespace remoting { |
| 172 namespace test { |
| 173 |
| 174 // Provides base functionality for the HostListFetcher Tests below. |
| 175 // The FakeURLFetcherFactory allows us to override the response data and payload |
| 176 // for specified URLs. We use this to stub out network calls made by the |
| 177 // HostListFetcher. This fixture also creates an IO MessageLoop |
| 178 // for use by the HostListFetcher. |
| 179 class HostListFetcherTest : public ::testing::Test { |
| 180 public: |
| 181 HostListFetcherTest() : url_fetcher_factory_(nullptr) {} |
| 182 ~HostListFetcherTest() override {} |
| 183 |
| 184 protected: |
| 185 // testing::Test interface. |
| 186 void SetUp() override; |
| 187 |
| 188 // Sets the HTTP status and data returned for a specified URL. |
| 189 void SetFakeResponse(const GURL& url, |
| 190 const std::string& data, |
| 191 net::HttpStatusCode code, |
| 192 net::URLRequestStatus::Status status); |
| 193 |
| 194 private: |
| 195 net::FakeURLFetcherFactory url_fetcher_factory_; |
| 196 scoped_ptr<base::MessageLoopForIO> message_loop_; |
| 197 |
| 198 DISALLOW_COPY_AND_ASSIGN(HostListFetcherTest); |
| 199 }; |
| 200 |
| 201 void HostListFetcherTest::SetUp() { |
| 202 DCHECK(!message_loop_); |
| 203 message_loop_.reset(new base::MessageLoopForIO); |
| 204 |
| 205 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 206 kHostListEmptyResponse, net::HTTP_NOT_FOUND, |
| 207 net::URLRequestStatus::FAILED); |
| 208 } |
| 209 |
| 210 void HostListFetcherTest::SetFakeResponse( |
| 211 const GURL& url, |
| 212 const std::string& data, |
| 213 net::HttpStatusCode code, |
| 214 net::URLRequestStatus::Status status) { |
| 215 url_fetcher_factory_.SetFakeResponse(url, data, code, status); |
| 216 } |
| 217 |
| 218 TEST_F(HostListFetcherTest, RetrieveHostListFromProd) { |
| 219 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 220 kHostListReadyResponse, net::HTTP_OK, |
| 221 net::URLRequestStatus::SUCCESS); |
| 222 |
| 223 std::vector<HostInfo> hostlist; |
| 224 |
| 225 base::RunLoop run_loop; |
| 226 HostListFetcher::HostlistCallback host_list_callback = |
| 227 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 228 |
| 229 HostListFetcher host_list_fetcher; |
| 230 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 231 |
| 232 run_loop.Run(); |
| 233 |
| 234 EXPECT_EQ(hostlist.size(), kExpectedHostListSize); |
| 235 |
| 236 HostInfo online_host_info = hostlist.at(0); |
| 237 EXPECT_EQ(online_host_info.token_url_patterns.size(), kExpectedPatternsSize); |
| 238 EXPECT_FALSE(online_host_info.host_id.empty()); |
| 239 EXPECT_FALSE(online_host_info.host_jid.empty()); |
| 240 EXPECT_FALSE(online_host_info.host_name.empty()); |
| 241 EXPECT_EQ(online_host_info.status, HostStatus::kHostStatusOnline); |
| 242 EXPECT_TRUE(online_host_info.offline_reason.empty()); |
| 243 EXPECT_FALSE(online_host_info.public_key.empty()); |
| 244 |
| 245 HostInfo offline_host_info = hostlist.at(1); |
| 246 EXPECT_TRUE(offline_host_info.token_url_patterns.empty()); |
| 247 EXPECT_FALSE(offline_host_info.host_id.empty()); |
| 248 EXPECT_FALSE(offline_host_info.host_jid.empty()); |
| 249 EXPECT_FALSE(offline_host_info.host_name.empty()); |
| 250 EXPECT_EQ(offline_host_info.status, HostStatus::kHostStatusOffline); |
| 251 EXPECT_FALSE(offline_host_info.offline_reason.empty()); |
| 252 EXPECT_FALSE(offline_host_info.public_key.empty()); |
| 253 } |
| 254 |
| 255 TEST_F(HostListFetcherTest, RetrieveHostListWithEmptyPatterns) { |
| 256 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 257 kHostListEmptyTokenUrlPatternsResponse, net::HTTP_OK, |
| 258 net::URLRequestStatus::SUCCESS); |
| 259 |
| 260 std::vector<HostInfo> hostlist; |
| 261 |
| 262 base::RunLoop run_loop; |
| 263 HostListFetcher::HostlistCallback host_list_callback = |
| 264 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 265 |
| 266 HostListFetcher host_list_fetcher; |
| 267 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 268 |
| 269 run_loop.Run(); |
| 270 |
| 271 EXPECT_EQ(hostlist.size(), kExpectedEmptyPatternsHostListSize); |
| 272 |
| 273 // While this is unlikely to happen, empty token url patterns are handled. |
| 274 HostInfo online_host_info = hostlist.at(0); |
| 275 EXPECT_TRUE(online_host_info.token_url_patterns.empty()); |
| 276 EXPECT_FALSE(online_host_info.host_id.empty()); |
| 277 EXPECT_FALSE(online_host_info.host_jid.empty()); |
| 278 EXPECT_FALSE(online_host_info.host_name.empty()); |
| 279 EXPECT_EQ(online_host_info.status, HostStatus::kHostStatusOnline); |
| 280 EXPECT_TRUE(online_host_info.offline_reason.empty()); |
| 281 EXPECT_FALSE(online_host_info.public_key.empty()); |
| 282 } |
| 283 |
| 284 TEST_F(HostListFetcherTest, |
| 285 RetrieveHostListMissingParametersResponse) { |
| 286 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 287 kHostListMissingParametersResponse, net::HTTP_OK, |
| 288 net::URLRequestStatus::SUCCESS); |
| 289 |
| 290 std::vector<HostInfo> hostlist; |
| 291 |
| 292 base::RunLoop run_loop; |
| 293 HostListFetcher::HostlistCallback host_list_callback = |
| 294 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 295 |
| 296 HostListFetcher host_list_fetcher; |
| 297 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 298 run_loop.Run(); |
| 299 |
| 300 EXPECT_EQ(hostlist.size(), kExpectedHostListSize); |
| 301 |
| 302 HostInfo no_jid_host_info = hostlist.at(0); |
| 303 EXPECT_EQ(no_jid_host_info.token_url_patterns.size(), kExpectedPatternsSize); |
| 304 EXPECT_FALSE(no_jid_host_info.host_id.empty()); |
| 305 EXPECT_TRUE(no_jid_host_info.host_jid.empty()); |
| 306 EXPECT_FALSE(no_jid_host_info.host_name.empty()); |
| 307 EXPECT_EQ(no_jid_host_info.status, HostStatus::kHostStatusOffline); |
| 308 EXPECT_TRUE(no_jid_host_info.offline_reason.empty()); |
| 309 EXPECT_FALSE(no_jid_host_info.public_key.empty()); |
| 310 |
| 311 HostInfo no_offline_reason_host_info = hostlist.at(1); |
| 312 EXPECT_TRUE(no_offline_reason_host_info.token_url_patterns.empty()); |
| 313 EXPECT_FALSE(no_offline_reason_host_info.host_id.empty()); |
| 314 EXPECT_FALSE(no_offline_reason_host_info.host_jid.empty()); |
| 315 EXPECT_FALSE(no_offline_reason_host_info.host_name.empty()); |
| 316 EXPECT_EQ(no_offline_reason_host_info.status, HostStatus::kHostStatusOffline); |
| 317 EXPECT_TRUE(no_offline_reason_host_info.offline_reason.empty()); |
| 318 EXPECT_FALSE(no_offline_reason_host_info.public_key.empty()); |
| 319 } |
| 320 |
| 321 |
| 322 TEST_F(HostListFetcherTest, RetrieveHostListNetworkError) { |
| 323 base::RunLoop run_loop; |
| 324 |
| 325 std::vector<HostInfo> hostlist; |
| 326 |
| 327 HostListFetcher::HostlistCallback host_list_callback = |
| 328 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 329 |
| 330 HostListFetcher host_list_fetcher; |
| 331 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 332 run_loop.Run(); |
| 333 |
| 334 // If there was a network error retrieving the host list, then the host list |
| 335 // should be empty. |
| 336 EXPECT_TRUE(hostlist.empty()); |
| 337 } |
| 338 |
| 339 TEST_F(HostListFetcherTest, RetrieveHostListEmptyItemsResponse) { |
| 340 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 341 kHostListEmptyItemsResponse, net::HTTP_OK, |
| 342 net::URLRequestStatus::SUCCESS); |
| 343 |
| 344 base::RunLoop run_loop; |
| 345 |
| 346 std::vector<HostInfo> hostlist; |
| 347 |
| 348 HostListFetcher::HostlistCallback host_list_callback = |
| 349 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 350 |
| 351 HostListFetcher host_list_fetcher; |
| 352 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 353 run_loop.Run(); |
| 354 |
| 355 // If we received an empty items response, then host list should be empty. |
| 356 EXPECT_TRUE(hostlist.empty()); |
| 357 } |
| 358 |
| 359 TEST_F(HostListFetcherTest, RetrieveHostListEmptyResponse) { |
| 360 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 361 kHostListEmptyResponse, net::HTTP_OK, |
| 362 net::URLRequestStatus::SUCCESS); |
| 363 |
| 364 base::RunLoop run_loop; |
| 365 |
| 366 std::vector<HostInfo> hostlist; |
| 367 |
| 368 HostListFetcher::HostlistCallback host_list_callback = |
| 369 base::Bind(&OnHostlistRetrieved, run_loop.QuitClosure(), &hostlist); |
| 370 |
| 371 HostListFetcher host_list_fetcher; |
| 372 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, host_list_callback); |
| 373 run_loop.Run(); |
| 374 |
| 375 // If we received an empty response, then host list should be empty. |
| 376 EXPECT_TRUE(hostlist.empty()); |
| 377 } |
| 378 |
| 379 TEST_F(HostListFetcherTest, MultipleRetrieveHostListRequests) { |
| 380 // First, we will retrieve a valid response from the directory service. |
| 381 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 382 kHostListReadyResponse, net::HTTP_OK, |
| 383 net::URLRequestStatus::SUCCESS); |
| 384 |
| 385 std::vector<HostInfo> ready_hostlist; |
| 386 |
| 387 base::RunLoop ready_run_loop; |
| 388 HostListFetcher::HostlistCallback ready_host_list_callback = |
| 389 base::Bind(&OnHostlistRetrieved, |
| 390 ready_run_loop.QuitClosure(), |
| 391 &ready_hostlist); |
| 392 |
| 393 HostListFetcher host_list_fetcher; |
| 394 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, |
| 395 ready_host_list_callback); |
| 396 |
| 397 ready_run_loop.Run(); |
| 398 |
| 399 EXPECT_EQ(ready_hostlist.size(), kExpectedHostListSize); |
| 400 |
| 401 HostInfo online_host_info = ready_hostlist.at(0); |
| 402 EXPECT_EQ(online_host_info.token_url_patterns.size(), kExpectedPatternsSize); |
| 403 EXPECT_FALSE(online_host_info.host_id.empty()); |
| 404 EXPECT_FALSE(online_host_info.host_jid.empty()); |
| 405 EXPECT_FALSE(online_host_info.host_name.empty()); |
| 406 EXPECT_EQ(online_host_info.status, HostStatus::kHostStatusOnline); |
| 407 EXPECT_TRUE(online_host_info.offline_reason.empty()); |
| 408 EXPECT_FALSE(online_host_info.public_key.empty()); |
| 409 |
| 410 HostInfo offline_host_info = ready_hostlist.at(1); |
| 411 EXPECT_TRUE(offline_host_info.token_url_patterns.empty()); |
| 412 EXPECT_FALSE(offline_host_info.host_id.empty()); |
| 413 EXPECT_FALSE(offline_host_info.host_jid.empty()); |
| 414 EXPECT_FALSE(offline_host_info.host_name.empty()); |
| 415 EXPECT_EQ(offline_host_info.status, HostStatus::kHostStatusOffline); |
| 416 EXPECT_FALSE(offline_host_info.offline_reason.empty()); |
| 417 EXPECT_FALSE(offline_host_info.public_key.empty()); |
| 418 |
| 419 // Next, we will retrieve an empty items response from the directory service. |
| 420 SetFakeResponse(GURL(kHostListProdRequestUrl), |
| 421 kHostListEmptyItemsResponse, net::HTTP_OK, |
| 422 net::URLRequestStatus::SUCCESS); |
| 423 |
| 424 std::vector<HostInfo> empty_items_hostlist; |
| 425 |
| 426 base::RunLoop empty_items_run_loop; |
| 427 |
| 428 HostListFetcher::HostlistCallback empty_host_list_callback = |
| 429 base::Bind(&OnHostlistRetrieved, |
| 430 empty_items_run_loop.QuitClosure(), |
| 431 &empty_items_hostlist); |
| 432 |
| 433 // Re-use the same host_list_fetcher. |
| 434 host_list_fetcher.RetrieveHostlist(kAccessTokenValue, |
| 435 empty_host_list_callback); |
| 436 |
| 437 empty_items_run_loop.Run(); |
| 438 |
| 439 // If we received an empty items response, then host list should be empty. |
| 440 EXPECT_TRUE(empty_items_hostlist.empty()); |
| 441 } |
| 442 |
| 443 } // namespace test |
| 444 } // namespace remoting |
OLD | NEW |