ukm_url_recorder_unittest.mm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2018 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. #include "components/ukm/ios/ukm_url_recorder.h"
  5. #include "base/bind.h"
  6. #import "base/test/ios/wait_util.h"
  7. #include "components/ukm/test_ukm_recorder.h"
  8. #import "ios/web/public/navigation/navigation_manager.h"
  9. #import "ios/web/public/test/web_test_with_web_state.h"
  10. #import "ios/web/public/web_state.h"
  11. #include "net/test/embedded_test_server/embedded_test_server.h"
  12. #include "net/test/embedded_test_server/http_request.h"
  13. #include "net/test/embedded_test_server/http_response.h"
  14. #include "services/metrics/public/cpp/ukm_source.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. #include "url/gurl.h"
  17. #if !defined(__has_feature) || !__has_feature(objc_arc)
  18. #error "This file requires ARC support."
  19. #endif
  20. namespace {
  21. std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
  22. const net::test_server::HttpRequest& request) {
  23. if (request.GetURL().path() == "/title1.html") {
  24. auto result = std::make_unique<net::test_server::BasicHttpResponse>();
  25. result->set_content_type("text/html");
  26. result->set_content("<html><head></head><body>NoTitle</body></html>");
  27. return std::move(result);
  28. }
  29. if (request.GetURL().path() == "/page_with_iframe.html") {
  30. auto result = std::make_unique<net::test_server::BasicHttpResponse>();
  31. result->set_content_type("text/html");
  32. result->set_content(
  33. "<html><head></head><body><iframe src=\"title1.html\"></body></html>");
  34. return std::move(result);
  35. }
  36. if (request.GetURL().path() == "/download") {
  37. auto result = std::make_unique<net::test_server::BasicHttpResponse>();
  38. result->set_content_type("application/vnd.test");
  39. result->set_content("TestDownloadContent");
  40. return std::move(result);
  41. }
  42. if (request.GetURL().path() == "/redirect") {
  43. auto result = std::make_unique<net::test_server::BasicHttpResponse>();
  44. result->set_code(net::HTTP_MOVED_PERMANENTLY);
  45. result->AddCustomHeader("Location", "/title1.html");
  46. return std::move(result);
  47. }
  48. return nullptr;
  49. }
  50. } // namespace
  51. class UkmUrlRecorderTest : public web::WebTestWithWebState {
  52. protected:
  53. UkmUrlRecorderTest() {
  54. server_.RegisterDefaultHandler(base::BindRepeating(&HandleRequest));
  55. }
  56. void SetUp() override {
  57. web::WebTestWithWebState::SetUp();
  58. ASSERT_TRUE(server_.Start());
  59. ukm::InitializeSourceUrlRecorderForWebState(web_state());
  60. }
  61. bool LoadUrlAndWait(const GURL& url) {
  62. web::NavigationManager::WebLoadParams params(url);
  63. web_state()->GetNavigationManager()->LoadURLWithParams(params);
  64. return base::test::ios::WaitUntilConditionOrTimeout(
  65. base::test::ios::kWaitForPageLoadTimeout, ^{
  66. return !web_state()->IsLoading();
  67. });
  68. }
  69. testing::AssertionResult RecordedUrl(
  70. ukm::SourceId source_id,
  71. GURL expected_url,
  72. absl::optional<GURL> expected_initial_url) {
  73. auto* source = test_ukm_recorder_.GetSourceForSourceId(source_id);
  74. if (!source)
  75. return testing::AssertionFailure() << "No URL recorded";
  76. if (source->url() != expected_url)
  77. return testing::AssertionFailure()
  78. << "Url was " << source->url() << ", expected: " << expected_url;
  79. absl::optional<GURL> initial_url;
  80. if (source->urls().size() > 1u)
  81. initial_url = source->urls().front();
  82. if (expected_initial_url != initial_url) {
  83. return testing::AssertionFailure()
  84. << "Initial Url was " << initial_url.value_or(GURL())
  85. << ", expected: " << expected_initial_url.value_or(GURL());
  86. }
  87. return testing::AssertionSuccess();
  88. }
  89. testing::AssertionResult DidNotRecordUrl(GURL url) {
  90. const auto& sources = test_ukm_recorder_.GetSources();
  91. for (const auto& kv : sources) {
  92. if (kv.second->url() == url)
  93. return testing::AssertionFailure()
  94. << "Url " << url << " was recorded with SourceId: " << kv.first;
  95. if (kv.second->url() == url)
  96. return testing::AssertionFailure()
  97. << "Url " << url
  98. << " was recorded as an initial URL with SourceId: " << kv.first;
  99. }
  100. return testing::AssertionSuccess();
  101. }
  102. protected:
  103. net::EmbeddedTestServer server_;
  104. ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
  105. };
  106. // Tests that URLs get recorded for pages visited.
  107. TEST_F(UkmUrlRecorderTest, Basic) {
  108. GURL url = server_.GetURL("/title1.html");
  109. EXPECT_TRUE(LoadUrlAndWait(url));
  110. ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state());
  111. EXPECT_TRUE(RecordedUrl(source_id, url, absl::nullopt));
  112. }
  113. // Tests that subframe URLs do not get recorded.
  114. TEST_F(UkmUrlRecorderTest, IgnoreUrlInSubframe) {
  115. GURL main_url = server_.GetURL("/page_with_iframe.html");
  116. GURL subframe_url = server_.GetURL("/title1.html");
  117. EXPECT_TRUE(LoadUrlAndWait(main_url));
  118. ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state());
  119. EXPECT_TRUE(RecordedUrl(source_id, main_url, absl::nullopt));
  120. EXPECT_TRUE(DidNotRecordUrl(subframe_url));
  121. }
  122. // Tests that download URLs do not get recorded.
  123. TEST_F(UkmUrlRecorderTest, IgnoreDownloadUrl) {
  124. GURL url = server_.GetURL("/download");
  125. EXPECT_TRUE(LoadUrlAndWait(url));
  126. EXPECT_TRUE(DidNotRecordUrl(url));
  127. }
  128. // Tests that redirected URLs record initial and final URL.
  129. TEST_F(UkmUrlRecorderTest, InitialUrl) {
  130. GURL redirect_url = server_.GetURL("/redirect");
  131. GURL target_url = server_.GetURL("/title1.html");
  132. EXPECT_TRUE(LoadUrlAndWait(redirect_url));
  133. ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state());
  134. EXPECT_TRUE(RecordedUrl(source_id, target_url, redirect_url));
  135. }