system_dns_config_change_notifier_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Copyright 2019 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 "net/dns/system_dns_config_change_notifier.h"
  5. #include <utility>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/run_loop.h"
  10. #include "base/task/task_traits.h"
  11. #include "base/task/thread_pool.h"
  12. #include "net/base/ip_address.h"
  13. #include "net/base/ip_endpoint.h"
  14. #include "net/dns/dns_hosts.h"
  15. #include "net/dns/test_dns_config_service.h"
  16. #include "net/test/test_with_task_environment.h"
  17. #include "testing/gmock/include/gmock/gmock.h"
  18. #include "testing/gtest/include/gtest/gtest.h"
  19. namespace net {
  20. namespace {
  21. const std::vector<IPEndPoint> kNameservers = {
  22. IPEndPoint(IPAddress(1, 2, 3, 4), 95)};
  23. const std::vector<IPEndPoint> kNameservers2 = {
  24. IPEndPoint(IPAddress(2, 3, 4, 5), 195)};
  25. const DnsConfig kConfig(kNameservers);
  26. const DnsConfig kConfig2(kNameservers2);
  27. } // namespace
  28. class SystemDnsConfigChangeNotifierTest : public TestWithTaskEnvironment {
  29. public:
  30. // Set up a change notifier, owned on a dedicated blockable task runner, with
  31. // a faked underlying DnsConfigService.
  32. SystemDnsConfigChangeNotifierTest()
  33. : notifier_task_runner_(
  34. base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})) {
  35. auto test_service = std::make_unique<TestDnsConfigService>();
  36. notifier_task_runner_->PostTask(
  37. FROM_HERE,
  38. base::BindOnce(&TestDnsConfigService::OnHostsRead,
  39. base::Unretained(test_service.get()), DnsHosts()));
  40. test_config_service_ = test_service.get();
  41. notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
  42. notifier_task_runner_, std::move(test_service));
  43. }
  44. protected:
  45. // Test observer implementation that records all notifications received in a
  46. // vector, and also validates that all notifications are received on the
  47. // expected sequence.
  48. class TestObserver : public SystemDnsConfigChangeNotifier::Observer {
  49. public:
  50. void OnSystemDnsConfigChanged(absl::optional<DnsConfig> config) override {
  51. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  52. configs_received_.push_back(std::move(config));
  53. DCHECK_GT(notifications_remaining_, 0);
  54. if (--notifications_remaining_ == 0)
  55. run_loop_->Quit();
  56. }
  57. void WaitForNotification() { WaitForNotifications(1); }
  58. void WaitForNotifications(int num_notifications) {
  59. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  60. notifications_remaining_ = num_notifications;
  61. run_loop_->Run();
  62. run_loop_ = std::make_unique<base::RunLoop>();
  63. }
  64. void ExpectNoMoreNotifications() {
  65. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  66. configs_received_.clear();
  67. base::RunLoop().RunUntilIdle();
  68. EXPECT_TRUE(configs_received_.empty());
  69. }
  70. std::vector<absl::optional<DnsConfig>>& configs_received() {
  71. return configs_received_;
  72. }
  73. private:
  74. int notifications_remaining_ = 0;
  75. std::unique_ptr<base::RunLoop> run_loop_ =
  76. std::make_unique<base::RunLoop>();
  77. std::vector<absl::optional<DnsConfig>> configs_received_;
  78. SEQUENCE_CHECKER(sequence_checker_);
  79. };
  80. // Load a config and wait for it to be received by the notifier.
  81. void LoadConfig(const DnsConfig& config, bool already_loaded = false) {
  82. TestObserver observer;
  83. notifier_->AddObserver(&observer);
  84. // If |notifier_| already has a config loaded, |observer| will first get a
  85. // notification for that initial config.
  86. if (already_loaded)
  87. observer.WaitForNotification();
  88. notifier_task_runner_->PostTask(
  89. FROM_HERE,
  90. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  91. base::Unretained(test_config_service_), config));
  92. observer.WaitForNotification();
  93. notifier_->RemoveObserver(&observer);
  94. }
  95. scoped_refptr<base::SequencedTaskRunner> notifier_task_runner_;
  96. std::unique_ptr<SystemDnsConfigChangeNotifier> notifier_;
  97. // Owned by |notifier_|.
  98. raw_ptr<TestDnsConfigService> test_config_service_;
  99. };
  100. TEST_F(SystemDnsConfigChangeNotifierTest, ReceiveNotification) {
  101. TestObserver observer;
  102. notifier_->AddObserver(&observer);
  103. notifier_task_runner_->PostTask(
  104. FROM_HERE,
  105. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  106. base::Unretained(test_config_service_), kConfig));
  107. observer.WaitForNotification();
  108. EXPECT_THAT(observer.configs_received(),
  109. testing::ElementsAre(testing::Optional(kConfig)));
  110. observer.ExpectNoMoreNotifications();
  111. notifier_->RemoveObserver(&observer);
  112. }
  113. TEST_F(SystemDnsConfigChangeNotifierTest, ReceiveNotification_Multiple) {
  114. TestObserver observer;
  115. notifier_->AddObserver(&observer);
  116. notifier_task_runner_->PostTask(
  117. FROM_HERE,
  118. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  119. base::Unretained(test_config_service_), kConfig));
  120. notifier_task_runner_->PostTask(
  121. FROM_HERE,
  122. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  123. base::Unretained(test_config_service_), kConfig2));
  124. observer.WaitForNotifications(2);
  125. EXPECT_THAT(observer.configs_received(),
  126. testing::ElementsAre(testing::Optional(kConfig),
  127. testing::Optional(kConfig2)));
  128. observer.ExpectNoMoreNotifications();
  129. notifier_->RemoveObserver(&observer);
  130. }
  131. // If the notifier already has a config loaded, a new observer should receive an
  132. // initial notification for that config.
  133. TEST_F(SystemDnsConfigChangeNotifierTest, ReceiveInitialNotification) {
  134. LoadConfig(kConfig);
  135. TestObserver observer;
  136. notifier_->AddObserver(&observer);
  137. observer.WaitForNotification();
  138. EXPECT_THAT(observer.configs_received(),
  139. testing::ElementsAre(testing::Optional(kConfig)));
  140. observer.ExpectNoMoreNotifications();
  141. notifier_->RemoveObserver(&observer);
  142. }
  143. // If multiple configs have been read before adding an Observer, should notify
  144. // it only of the most recent.
  145. TEST_F(SystemDnsConfigChangeNotifierTest, ReceiveInitialNotification_Multiple) {
  146. LoadConfig(kConfig);
  147. LoadConfig(kConfig2, true /* already_loaded */);
  148. TestObserver observer;
  149. notifier_->AddObserver(&observer);
  150. observer.WaitForNotification();
  151. EXPECT_THAT(observer.configs_received(),
  152. testing::ElementsAre(testing::Optional(kConfig2)));
  153. observer.ExpectNoMoreNotifications();
  154. notifier_->RemoveObserver(&observer);
  155. }
  156. TEST_F(SystemDnsConfigChangeNotifierTest, NotificationsStopAfterRemoval) {
  157. TestObserver observer;
  158. notifier_->AddObserver(&observer);
  159. notifier_->RemoveObserver(&observer);
  160. LoadConfig(kConfig);
  161. LoadConfig(kConfig2, true /* already_loaded */);
  162. EXPECT_TRUE(observer.configs_received().empty());
  163. observer.ExpectNoMoreNotifications();
  164. }
  165. TEST_F(SystemDnsConfigChangeNotifierTest, UnchangedConfigs) {
  166. LoadConfig(kConfig);
  167. TestObserver observer;
  168. notifier_->AddObserver(&observer);
  169. observer.WaitForNotification();
  170. // Expect no notifications from duplicate configs.
  171. notifier_task_runner_->PostTask(
  172. FROM_HERE,
  173. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  174. base::Unretained(test_config_service_), kConfig));
  175. notifier_task_runner_->PostTask(
  176. FROM_HERE,
  177. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  178. base::Unretained(test_config_service_), kConfig));
  179. observer.ExpectNoMoreNotifications();
  180. // Notification on new config.
  181. notifier_task_runner_->PostTask(
  182. FROM_HERE,
  183. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  184. base::Unretained(test_config_service_), kConfig2));
  185. observer.WaitForNotification();
  186. EXPECT_THAT(observer.configs_received(),
  187. testing::ElementsAre(testing::Optional(kConfig2)));
  188. observer.ExpectNoMoreNotifications();
  189. notifier_->RemoveObserver(&observer);
  190. }
  191. TEST_F(SystemDnsConfigChangeNotifierTest, UnloadedConfig) {
  192. LoadConfig(kConfig);
  193. TestObserver observer;
  194. notifier_->AddObserver(&observer);
  195. // Initial config.
  196. observer.WaitForNotification();
  197. notifier_task_runner_->PostTask(
  198. FROM_HERE, base::BindOnce(&TestDnsConfigService::InvalidateConfig,
  199. base::Unretained(test_config_service_)));
  200. observer.WaitForNotification();
  201. EXPECT_THAT(observer.configs_received(),
  202. testing::ElementsAre(testing::Optional(kConfig), absl::nullopt));
  203. observer.ExpectNoMoreNotifications();
  204. notifier_->RemoveObserver(&observer);
  205. }
  206. // All invalid configs are considered the same for notifications, so only expect
  207. // a single notification on multiple config invalidations.
  208. TEST_F(SystemDnsConfigChangeNotifierTest, UnloadedConfig_Multiple) {
  209. LoadConfig(kConfig);
  210. TestObserver observer;
  211. notifier_->AddObserver(&observer);
  212. // Initial config.
  213. observer.WaitForNotification();
  214. notifier_task_runner_->PostTask(
  215. FROM_HERE, base::BindOnce(&TestDnsConfigService::InvalidateConfig,
  216. base::Unretained(test_config_service_)));
  217. notifier_task_runner_->PostTask(
  218. FROM_HERE, base::BindOnce(&TestDnsConfigService::InvalidateConfig,
  219. base::Unretained(test_config_service_)));
  220. observer.WaitForNotification(); // Only 1 notification expected.
  221. EXPECT_THAT(observer.configs_received(),
  222. testing::ElementsAre(testing::Optional(kConfig), absl::nullopt));
  223. observer.ExpectNoMoreNotifications();
  224. notifier_->RemoveObserver(&observer);
  225. }
  226. TEST_F(SystemDnsConfigChangeNotifierTest, InitialConfigInvalid) {
  227. // Add and invalidate a config (using an extra observer to wait for
  228. // invalidation to complete).
  229. LoadConfig(kConfig);
  230. TestObserver setup_observer;
  231. notifier_->AddObserver(&setup_observer);
  232. setup_observer.WaitForNotification();
  233. notifier_task_runner_->PostTask(
  234. FROM_HERE, base::BindOnce(&TestDnsConfigService::InvalidateConfig,
  235. base::Unretained(test_config_service_)));
  236. setup_observer.WaitForNotification();
  237. notifier_->RemoveObserver(&setup_observer);
  238. TestObserver observer;
  239. notifier_->AddObserver(&observer);
  240. // No notification expected until first valid config.
  241. observer.ExpectNoMoreNotifications();
  242. // Notification on new config.
  243. notifier_task_runner_->PostTask(
  244. FROM_HERE,
  245. base::BindOnce(&TestDnsConfigService::OnConfigRead,
  246. base::Unretained(test_config_service_), kConfig));
  247. observer.WaitForNotification();
  248. EXPECT_THAT(observer.configs_received(),
  249. testing::ElementsAre(testing::Optional(kConfig)));
  250. observer.ExpectNoMoreNotifications();
  251. notifier_->RemoveObserver(&observer);
  252. }
  253. TEST_F(SystemDnsConfigChangeNotifierTest, RefreshConfig) {
  254. test_config_service_->SetConfigForRefresh(kConfig);
  255. TestObserver observer;
  256. notifier_->AddObserver(&observer);
  257. notifier_->RefreshConfig();
  258. observer.WaitForNotification();
  259. EXPECT_THAT(observer.configs_received(),
  260. testing::ElementsAre(testing::Optional(kConfig)));
  261. observer.ExpectNoMoreNotifications();
  262. notifier_->RemoveObserver(&observer);
  263. }
  264. } // namespace net