url_checker_unittest.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright 2014 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/safe_search_api/url_checker.h"
  5. #include <stddef.h>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/test/task_environment.h"
  13. #include "components/safe_search_api/fake_url_checker_client.h"
  14. #include "testing/gmock/include/gmock/gmock.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #include "url/gurl.h"
  17. using testing::_;
  18. namespace safe_search_api {
  19. namespace {
  20. constexpr size_t kCacheSize = 2;
  21. const char* kURLs[] = {
  22. "http://www.randomsite1.com", "http://www.randomsite2.com",
  23. "http://www.randomsite3.com", "http://www.randomsite4.com",
  24. "http://www.randomsite5.com", "http://www.randomsite6.com",
  25. "http://www.randomsite7.com", "http://www.randomsite8.com",
  26. "http://www.randomsite9.com",
  27. };
  28. ClientClassification ToAPIClassification(Classification classification,
  29. bool uncertain) {
  30. if (uncertain) {
  31. return ClientClassification::kUnknown;
  32. }
  33. switch (classification) {
  34. case Classification::SAFE:
  35. return ClientClassification::kAllowed;
  36. case Classification::UNSAFE:
  37. return ClientClassification::kRestricted;
  38. }
  39. }
  40. } // namespace
  41. class SafeSearchURLCheckerTest : public testing::Test {
  42. public:
  43. SafeSearchURLCheckerTest() : next_url_(0) {
  44. std::unique_ptr<FakeURLCheckerClient> fake_client =
  45. std::make_unique<FakeURLCheckerClient>();
  46. fake_client_ = fake_client.get();
  47. checker_ = std::make_unique<URLChecker>(std::move(fake_client), kCacheSize);
  48. }
  49. MOCK_METHOD3(OnCheckDone,
  50. void(const GURL& url,
  51. Classification classification,
  52. bool uncertain));
  53. protected:
  54. GURL GetNewURL() {
  55. CHECK(next_url_ < std::size(kURLs));
  56. return GURL(kURLs[next_url_++]);
  57. }
  58. // Returns true if the result was returned synchronously (cache hit).
  59. bool CheckURL(const GURL& url) {
  60. bool cached = checker_->CheckURL(
  61. url, base::BindOnce(&SafeSearchURLCheckerTest::OnCheckDone,
  62. base::Unretained(this)));
  63. return cached;
  64. }
  65. bool SendResponse(const GURL& url,
  66. Classification classification,
  67. bool uncertain) {
  68. bool result = CheckURL(url);
  69. fake_client_->RunCallback(ToAPIClassification(classification, uncertain));
  70. return result;
  71. }
  72. size_t next_url_;
  73. raw_ptr<FakeURLCheckerClient> fake_client_;
  74. std::unique_ptr<URLChecker> checker_;
  75. base::test::SingleThreadTaskEnvironment task_environment_;
  76. };
  77. TEST_F(SafeSearchURLCheckerTest, Simple) {
  78. {
  79. GURL url(GetNewURL());
  80. EXPECT_CALL(*this, OnCheckDone(url, Classification::SAFE, false));
  81. ASSERT_FALSE(SendResponse(url, Classification::SAFE, false));
  82. }
  83. {
  84. GURL url(GetNewURL());
  85. EXPECT_CALL(*this, OnCheckDone(url, Classification::UNSAFE, false));
  86. ASSERT_FALSE(SendResponse(url, Classification::UNSAFE, false));
  87. }
  88. {
  89. GURL url(GetNewURL());
  90. EXPECT_CALL(*this, OnCheckDone(url, Classification::SAFE, true));
  91. ASSERT_FALSE(SendResponse(url, Classification::SAFE, true));
  92. }
  93. }
  94. TEST_F(SafeSearchURLCheckerTest, Cache) {
  95. // One more URL than fit in the cache.
  96. ASSERT_EQ(2u, kCacheSize);
  97. GURL url1(GetNewURL());
  98. GURL url2(GetNewURL());
  99. GURL url3(GetNewURL());
  100. // Populate the cache.
  101. EXPECT_CALL(*this, OnCheckDone(url1, Classification::SAFE, false));
  102. ASSERT_FALSE(SendResponse(url1, Classification::SAFE, false));
  103. EXPECT_CALL(*this, OnCheckDone(url2, Classification::SAFE, false));
  104. ASSERT_FALSE(SendResponse(url2, Classification::SAFE, false));
  105. // Now we should get results synchronously, without a request to the api.
  106. EXPECT_CALL(*this, OnCheckDone(url2, Classification::SAFE, false));
  107. ASSERT_TRUE(CheckURL(url2));
  108. EXPECT_CALL(*this, OnCheckDone(url1, Classification::SAFE, false));
  109. ASSERT_TRUE(CheckURL(url1));
  110. // Now |url2| is the LRU and should be evicted on the next check.
  111. EXPECT_CALL(*this, OnCheckDone(url3, Classification::SAFE, false));
  112. ASSERT_FALSE(SendResponse(url3, Classification::SAFE, false));
  113. EXPECT_CALL(*this, OnCheckDone(url2, Classification::SAFE, false));
  114. ASSERT_FALSE(SendResponse(url2, Classification::SAFE, false));
  115. }
  116. TEST_F(SafeSearchURLCheckerTest, CoalesceRequestsToSameURL) {
  117. GURL url(GetNewURL());
  118. // Start two checks for the same URL.
  119. ASSERT_FALSE(CheckURL(url));
  120. ASSERT_FALSE(CheckURL(url));
  121. // A single response should answer both of those checks
  122. EXPECT_CALL(*this, OnCheckDone(url, Classification::SAFE, false)).Times(2);
  123. fake_client_->RunCallback(ToAPIClassification(Classification::SAFE, false));
  124. }
  125. TEST_F(SafeSearchURLCheckerTest, CacheTimeout) {
  126. GURL url(GetNewURL());
  127. checker_->SetCacheTimeoutForTesting(base::Seconds(0));
  128. EXPECT_CALL(*this, OnCheckDone(url, Classification::SAFE, false));
  129. ASSERT_FALSE(SendResponse(url, Classification::SAFE, false));
  130. // Since the cache timeout is zero, the cache entry should be invalidated
  131. // immediately.
  132. EXPECT_CALL(*this, OnCheckDone(url, Classification::UNSAFE, false));
  133. ASSERT_FALSE(SendResponse(url, Classification::UNSAFE, false));
  134. }
  135. TEST_F(SafeSearchURLCheckerTest, DestroyURLCheckerBeforeCallback) {
  136. GURL url(GetNewURL());
  137. EXPECT_CALL(*this, OnCheckDone(_, _, _)).Times(0);
  138. // Start a URL check.
  139. ASSERT_FALSE(CheckURL(url));
  140. fake_client_->RunCallbackAsync(
  141. ToAPIClassification(Classification::SAFE, false));
  142. // Reset the URLChecker before the callback occurs.
  143. checker_.reset();
  144. // The callback should now be invalid.
  145. task_environment_.RunUntilIdle();
  146. }
  147. } // namespace safe_search_api