network_change_notifier_fuchsia_unittest.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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 "net/base/network_change_notifier_fuchsia.h"
  5. #include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include "base/auto_reset.h"
  11. #include "base/bind.h"
  12. #include "base/logging.h"
  13. #include "base/run_loop.h"
  14. #include "base/test/task_environment.h"
  15. #include "base/threading/sequence_bound.h"
  16. #include "base/threading/thread.h"
  17. #include "net/base/ip_address.h"
  18. #include "net/dns/dns_config_service.h"
  19. #include "net/dns/system_dns_config_change_notifier.h"
  20. #include "testing/gmock/include/gmock/gmock.h"
  21. #include "testing/gtest/include/gtest/gtest.h"
  22. namespace net {
  23. namespace {
  24. enum : uint32_t { kDefaultInterfaceId = 1, kSecondaryInterfaceId = 2 };
  25. using IPv4Octets = std::array<uint8_t, 4>;
  26. using IPv6Octets = std::array<uint8_t, 16>;
  27. constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
  28. constexpr uint8_t kDefaultIPv4Prefix = 16;
  29. constexpr IPv4Octets kSecondaryIPv4Address = {10, 0, 0, 1};
  30. constexpr uint8_t kSecondaryIPv4Prefix = 8;
  31. constexpr IPv6Octets kDefaultIPv6Address = {0x20, 0x01, 0x01};
  32. constexpr uint8_t kDefaultIPv6Prefix = 16;
  33. constexpr IPv6Octets kSecondaryIPv6Address = {0x20, 0x01, 0x02};
  34. constexpr uint8_t kSecondaryIPv6Prefix = 16;
  35. fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
  36. fuchsia::net::IpAddress output;
  37. output.ipv4().addr = octets;
  38. return output;
  39. }
  40. fuchsia::net::IpAddress IpAddressFrom(IPv6Octets octets) {
  41. fuchsia::net::IpAddress output;
  42. output.ipv6().addr = octets;
  43. return output;
  44. }
  45. template <typename T>
  46. fuchsia::net::Subnet SubnetFrom(T octets, uint8_t prefix) {
  47. fuchsia::net::Subnet output;
  48. output.addr = IpAddressFrom(octets);
  49. output.prefix_len = prefix;
  50. return output;
  51. }
  52. template <typename T>
  53. fuchsia::net::interfaces::Address InterfaceAddressFrom(T octets,
  54. uint8_t prefix) {
  55. fuchsia::net::interfaces::Address addr;
  56. addr.set_addr(SubnetFrom(octets, prefix));
  57. return addr;
  58. }
  59. template <typename T>
  60. std::vector<T> MakeSingleItemVec(T item) {
  61. std::vector<T> vec;
  62. vec.push_back(std::move(item));
  63. return vec;
  64. }
  65. fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
  66. fuchsia::hardware::network::DeviceClass device_class =
  67. fuchsia::hardware::network::DeviceClass::ETHERNET) {
  68. // For most tests a live interface with an IPv4 address and ethernet class is
  69. // sufficient.
  70. fuchsia::net::interfaces::Properties interface;
  71. interface.set_id(kDefaultInterfaceId);
  72. interface.set_online(true);
  73. interface.set_has_default_ipv4_route(true);
  74. interface.set_has_default_ipv6_route(true);
  75. interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
  76. std::move(device_class)));
  77. interface.set_addresses(MakeSingleItemVec(
  78. InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix)));
  79. return interface;
  80. }
  81. fuchsia::net::interfaces::Properties SecondaryInterfaceProperties() {
  82. // For most tests a live interface with an IPv4 address and ethernet class is
  83. // sufficient.
  84. fuchsia::net::interfaces::Properties interface;
  85. interface.set_id(kSecondaryInterfaceId);
  86. interface.set_online(true);
  87. interface.set_has_default_ipv4_route(false);
  88. interface.set_has_default_ipv6_route(false);
  89. interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
  90. fuchsia::hardware::network::DeviceClass::ETHERNET));
  91. interface.set_addresses(MakeSingleItemVec(
  92. InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
  93. return interface;
  94. }
  95. template <typename F>
  96. fuchsia::net::interfaces::Event MakeChangeEvent(uint64_t interface_id, F fn) {
  97. fuchsia::net::interfaces::Properties props;
  98. props.set_id(interface_id);
  99. fn(&props);
  100. return fuchsia::net::interfaces::Event::WithChanged(std::move(props));
  101. }
  102. // Partial fake implementation of a fuchsia.net.interfaces/Watcher.
  103. class FakeWatcher : public fuchsia::net::interfaces::testing::Watcher_TestBase {
  104. public:
  105. explicit FakeWatcher() : binding_(this) {
  106. // Always create the watcher with an empty set of interfaces.
  107. // Callers can override the initial set of events with SetInitial.
  108. pending_.push(fuchsia::net::interfaces::Event::WithIdle(
  109. fuchsia::net::interfaces::Empty{}));
  110. }
  111. FakeWatcher(const FakeWatcher&) = delete;
  112. FakeWatcher& operator=(const FakeWatcher&) = delete;
  113. ~FakeWatcher() override = default;
  114. void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
  115. CHECK_EQ(ZX_OK, binding_.Bind(std::move(request)));
  116. }
  117. void PushEvent(fuchsia::net::interfaces::Event event) {
  118. if (pending_callback_) {
  119. pending_callback_(std::move(event));
  120. pending_callback_ = nullptr;
  121. } else {
  122. pending_.push(std::move(event));
  123. }
  124. }
  125. void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
  126. // Discard any pending events.
  127. pending_ = std::queue<fuchsia::net::interfaces::Event>();
  128. for (auto& prop : props) {
  129. pending_.push(
  130. fuchsia::net::interfaces::Event::WithExisting(std::move(prop)));
  131. }
  132. pending_.push(fuchsia::net::interfaces::Event::WithIdle(
  133. fuchsia::net::interfaces::Empty{}));
  134. // We should not have a pending callback already when setting initial state.
  135. CHECK(!pending_callback_);
  136. }
  137. private:
  138. void Watch(WatchCallback callback) override {
  139. ASSERT_FALSE(pending_callback_);
  140. if (pending_.empty()) {
  141. pending_callback_ = std::move(callback);
  142. } else {
  143. callback(std::move(pending_.front()));
  144. pending_.pop();
  145. }
  146. }
  147. void NotImplemented_(const std::string& name) override {
  148. LOG(FATAL) << "Unimplemented function called: " << name;
  149. }
  150. std::queue<fuchsia::net::interfaces::Event> pending_;
  151. fidl::Binding<fuchsia::net::interfaces::Watcher> binding_;
  152. WatchCallback pending_callback_ = nullptr;
  153. };
  154. class FakeWatcherAsync {
  155. public:
  156. explicit FakeWatcherAsync() {
  157. base::Thread::Options options(base::MessagePumpType::IO, 0);
  158. CHECK(thread_.StartWithOptions(std::move(options)));
  159. watcher_ = base::SequenceBound<FakeWatcher>(thread_.task_runner());
  160. }
  161. FakeWatcherAsync(const FakeWatcherAsync&) = delete;
  162. FakeWatcherAsync& operator=(const FakeWatcherAsync&) = delete;
  163. ~FakeWatcherAsync() = default;
  164. void Bind(fidl::InterfaceRequest<fuchsia::net::interfaces::Watcher> request) {
  165. watcher_.AsyncCall(&FakeWatcher::Bind).WithArgs(std::move(request));
  166. }
  167. // Asynchronously push an event to the watcher.
  168. void PushEvent(fuchsia::net::interfaces::Event event) {
  169. watcher_.AsyncCall(&FakeWatcher::PushEvent).WithArgs(std::move(event));
  170. }
  171. // Asynchronously push an initial set of interfaces to the watcher.
  172. void SetInitial(std::vector<fuchsia::net::interfaces::Properties> props) {
  173. watcher_.AsyncCall(&FakeWatcher::SetInitial).WithArgs(std::move(props));
  174. }
  175. // Asynchronously push an initial single intface to the watcher.
  176. void SetInitial(fuchsia::net::interfaces::Properties prop) {
  177. SetInitial(MakeSingleItemVec(std::move(prop)));
  178. }
  179. // Ensures that any PushEvent() or SetInitial() calls have
  180. // been processed.
  181. void FlushThread() { thread_.FlushForTesting(); }
  182. private:
  183. base::Thread thread_{"Watcher Thread"};
  184. base::SequenceBound<FakeWatcher> watcher_;
  185. };
  186. template <class T>
  187. class ResultReceiver {
  188. public:
  189. ~ResultReceiver() { EXPECT_EQ(entries_.size(), 0u); }
  190. bool RunAndExpectEntries(std::vector<T> expected_entries) {
  191. if (entries_.size() < expected_entries.size()) {
  192. base::RunLoop loop;
  193. base::AutoReset<size_t> size(&expected_count_, expected_entries.size());
  194. base::AutoReset<base::OnceClosure> quit(&quit_loop_, loop.QuitClosure());
  195. loop.Run();
  196. }
  197. return expected_entries == std::exchange(entries_, {});
  198. }
  199. void AddEntry(T entry) {
  200. entries_.push_back(entry);
  201. if (quit_loop_ && entries_.size() >= expected_count_)
  202. std::move(quit_loop_).Run();
  203. }
  204. protected:
  205. size_t expected_count_ = 0u;
  206. std::vector<T> entries_;
  207. base::OnceClosure quit_loop_;
  208. };
  209. // Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
  210. class FakeConnectionTypeObserver final
  211. : public NetworkChangeNotifier::ConnectionTypeObserver {
  212. public:
  213. FakeConnectionTypeObserver() {
  214. NetworkChangeNotifier::AddConnectionTypeObserver(this);
  215. }
  216. ~FakeConnectionTypeObserver() override {
  217. NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
  218. }
  219. bool RunAndExpectConnectionTypes(
  220. std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
  221. return receiver_.RunAndExpectEntries(sequence);
  222. }
  223. // ConnectionTypeObserver implementation.
  224. void OnConnectionTypeChanged(
  225. NetworkChangeNotifier::ConnectionType type) override {
  226. receiver_.AddEntry(type);
  227. }
  228. protected:
  229. ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
  230. };
  231. // Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
  232. class FakeNetworkChangeObserver final
  233. : public NetworkChangeNotifier::NetworkChangeObserver {
  234. public:
  235. FakeNetworkChangeObserver() {
  236. NetworkChangeNotifier::AddNetworkChangeObserver(this);
  237. }
  238. ~FakeNetworkChangeObserver() override {
  239. NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  240. }
  241. bool RunAndExpectNetworkChanges(
  242. std::vector<NetworkChangeNotifier::ConnectionType> sequence) {
  243. return receiver_.RunAndExpectEntries(sequence);
  244. }
  245. // NetworkChangeObserver implementation.
  246. void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
  247. receiver_.AddEntry(type);
  248. }
  249. protected:
  250. ResultReceiver<NetworkChangeNotifier::ConnectionType> receiver_;
  251. };
  252. // Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
  253. class FakeIPAddressObserver final
  254. : public NetworkChangeNotifier::IPAddressObserver {
  255. public:
  256. FakeIPAddressObserver() { NetworkChangeNotifier::AddIPAddressObserver(this); }
  257. ~FakeIPAddressObserver() override {
  258. NetworkChangeNotifier::RemoveIPAddressObserver(this);
  259. EXPECT_EQ(ip_change_count_, 0u);
  260. }
  261. size_t ip_change_count() const { return ip_change_count_; }
  262. bool RunAndExpectCallCount(size_t expected_count) {
  263. if (ip_change_count_ < expected_count) {
  264. base::RunLoop loop;
  265. base::AutoReset<size_t> expectation(&expected_count_, expected_count);
  266. base::AutoReset<base::OnceClosure> quit(&quit_loop_, loop.QuitClosure());
  267. loop.Run();
  268. }
  269. return std::exchange(ip_change_count_, 0u) == expected_count;
  270. }
  271. // IPAddressObserver implementation.
  272. void OnIPAddressChanged() override {
  273. ip_change_count_++;
  274. if (quit_loop_ && ip_change_count_ >= expected_count_)
  275. std::move(quit_loop_).Run();
  276. }
  277. protected:
  278. size_t expected_count_ = 0u;
  279. size_t ip_change_count_ = 0u;
  280. base::OnceClosure quit_loop_;
  281. };
  282. } // namespace
  283. class NetworkChangeNotifierFuchsiaTest : public testing::Test {
  284. public:
  285. NetworkChangeNotifierFuchsiaTest() = default;
  286. NetworkChangeNotifierFuchsiaTest(const NetworkChangeNotifierFuchsiaTest&) =
  287. delete;
  288. NetworkChangeNotifierFuchsiaTest& operator=(
  289. const NetworkChangeNotifierFuchsiaTest&) = delete;
  290. ~NetworkChangeNotifierFuchsiaTest() override = default;
  291. // Creates a NetworkChangeNotifier that binds to |watcher_|.
  292. // |observer_| is registered last, so that tests need only express
  293. // expectations on changes they make themselves.
  294. void CreateNotifier(bool requires_wlan = false) {
  295. // Ensure that internal state is up-to-date before the
  296. // notifier queries it.
  297. watcher_.FlushThread();
  298. CHECK(!watcher_handle_);
  299. watcher_.Bind(watcher_handle_.NewRequest());
  300. // Use a noop DNS notifier.
  301. dns_config_notifier_ = std::make_unique<SystemDnsConfigChangeNotifier>(
  302. nullptr /* task_runner */, nullptr /* dns_config_service */);
  303. notifier_ = base::WrapUnique(new NetworkChangeNotifierFuchsia(
  304. std::move(watcher_handle_), requires_wlan, dns_config_notifier_.get()));
  305. type_observer_ = std::make_unique<FakeConnectionTypeObserver>();
  306. ip_observer_ = std::make_unique<FakeIPAddressObserver>();
  307. }
  308. void TearDown() override {
  309. // Spin the loops to catch any unintended notifications.
  310. watcher_.FlushThread();
  311. base::RunLoop().RunUntilIdle();
  312. }
  313. protected:
  314. base::test::SingleThreadTaskEnvironment task_environment_{
  315. base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
  316. fidl::InterfaceHandle<fuchsia::net::interfaces::Watcher> watcher_handle_;
  317. FakeWatcherAsync watcher_;
  318. // Allows us to allocate our own NetworkChangeNotifier for unit testing.
  319. NetworkChangeNotifier::DisableForTest disable_for_test_;
  320. std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
  321. std::unique_ptr<NetworkChangeNotifierFuchsia> notifier_;
  322. std::unique_ptr<FakeConnectionTypeObserver> type_observer_;
  323. std::unique_ptr<FakeIPAddressObserver> ip_observer_;
  324. };
  325. TEST_F(NetworkChangeNotifierFuchsiaTest, InitialState) {
  326. CreateNotifier();
  327. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
  328. notifier_->GetCurrentConnectionType());
  329. }
  330. TEST_F(NetworkChangeNotifierFuchsiaTest, InterfacesChangeDuringConstruction) {
  331. // Set a live interface with an IP address.
  332. watcher_.SetInitial(DefaultInterfaceProperties(
  333. fuchsia::hardware::network::DeviceClass::WLAN));
  334. // Inject an interfaces change event so that the notifier will receive it
  335. // immediately after the initial state.
  336. watcher_.PushEvent(MakeChangeEvent(
  337. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  338. props->set_addresses(MakeSingleItemVec(
  339. InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
  340. }));
  341. // Create the Notifier, which should process the initial network state before
  342. // returning, but not the change event, yet.
  343. CreateNotifier();
  344. EXPECT_EQ(ip_observer_->ip_change_count(), 0u);
  345. // Now spin the loop to allow the change event to be processed, triggering a
  346. // call to the |ip_observer_|.
  347. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  348. }
  349. TEST_F(NetworkChangeNotifierFuchsiaTest, NotifyNetworkChangeOnInitialIPChange) {
  350. // Set a live interface with an IP address and create the notifier.
  351. watcher_.SetInitial(DefaultInterfaceProperties(
  352. fuchsia::hardware::network::DeviceClass::WLAN));
  353. CreateNotifier();
  354. // Add the NetworkChangeNotifier, and change the IP address. This should
  355. // trigger a network change notification.
  356. FakeNetworkChangeObserver network_change_observer;
  357. watcher_.PushEvent(MakeChangeEvent(
  358. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  359. props->set_addresses(MakeSingleItemVec(
  360. InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
  361. }));
  362. EXPECT_TRUE(network_change_observer.RunAndExpectNetworkChanges(
  363. {NetworkChangeNotifier::CONNECTION_NONE,
  364. NetworkChangeNotifier::CONNECTION_WIFI}));
  365. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  366. }
  367. TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) {
  368. // Set a live interface with an IP address and create the notifier.
  369. watcher_.SetInitial(DefaultInterfaceProperties());
  370. CreateNotifier();
  371. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  372. notifier_->GetCurrentConnectionType());
  373. // Push an event with no side-effects.
  374. watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
  375. }
  376. TEST_F(NetworkChangeNotifierFuchsiaTest, NoChangeV6) {
  377. auto initial = DefaultInterfaceProperties();
  378. initial.set_addresses(MakeSingleItemVec(
  379. InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
  380. watcher_.SetInitial(std::move(initial));
  381. CreateNotifier();
  382. // Push an event with no side-effects.
  383. watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
  384. }
  385. TEST_F(NetworkChangeNotifierFuchsiaTest, MultiInterfaceNoChange) {
  386. std::vector<fuchsia::net::interfaces::Properties> props;
  387. props.push_back(DefaultInterfaceProperties());
  388. props.push_back(SecondaryInterfaceProperties());
  389. watcher_.SetInitial(std::move(props));
  390. CreateNotifier();
  391. // Push an event with no side-effects.
  392. watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
  393. }
  394. TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
  395. auto props = DefaultInterfaceProperties();
  396. props.mutable_addresses()->push_back(
  397. InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
  398. props.mutable_addresses()->push_back(
  399. InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));
  400. watcher_.SetInitial(std::move(props));
  401. CreateNotifier();
  402. // Push an event with no side-effects.
  403. watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
  404. }
  405. TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
  406. watcher_.SetInitial(DefaultInterfaceProperties());
  407. CreateNotifier();
  408. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  409. notifier_->GetCurrentConnectionType());
  410. watcher_.PushEvent(MakeChangeEvent(
  411. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  412. props->set_addresses(MakeSingleItemVec(
  413. InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
  414. }));
  415. // Expect a single OnIPAddressChanged() notification.
  416. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  417. }
  418. TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
  419. auto props = DefaultInterfaceProperties();
  420. props.set_addresses(MakeSingleItemVec(
  421. InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
  422. watcher_.SetInitial(std::move(props));
  423. CreateNotifier();
  424. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  425. notifier_->GetCurrentConnectionType());
  426. watcher_.PushEvent(MakeChangeEvent(
  427. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  428. props->set_addresses(MakeSingleItemVec(
  429. InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix)));
  430. }));
  431. // Expect a single OnIPAddressChanged() notification.
  432. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  433. }
  434. TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
  435. auto props = DefaultInterfaceProperties();
  436. props.mutable_addresses()->push_back(
  437. InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
  438. watcher_.SetInitial(std::move(props));
  439. CreateNotifier();
  440. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  441. notifier_->GetCurrentConnectionType());
  442. watcher_.PushEvent(MakeChangeEvent(
  443. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  444. std::vector<fuchsia::net::interfaces::Address> addrs;
  445. addrs.push_back(
  446. InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix));
  447. addrs.push_back(
  448. InterfaceAddressFrom(kSecondaryIPv6Address, kSecondaryIPv6Prefix));
  449. props->set_addresses(std::move(addrs));
  450. }));
  451. // Expect a single OnIPAddressChanged() notification.
  452. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  453. }
  454. TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
  455. watcher_.SetInitial(DefaultInterfaceProperties());
  456. CreateNotifier();
  457. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  458. notifier_->GetCurrentConnectionType());
  459. watcher_.PushEvent(MakeChangeEvent(
  460. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  461. // Add the initial default address + a new IPv6 one. Address changes are
  462. // always sent as the entire new list of addresses.
  463. props->mutable_addresses()->push_back(
  464. InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix));
  465. props->mutable_addresses()->push_back(
  466. InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix));
  467. }));
  468. // Expect a single OnIPAddressChanged() notification.
  469. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  470. }
  471. TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
  472. watcher_.SetInitial(DefaultInterfaceProperties());
  473. CreateNotifier();
  474. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  475. notifier_->GetCurrentConnectionType());
  476. watcher_.PushEvent(MakeChangeEvent(
  477. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  478. props->set_online(false);
  479. }));
  480. EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
  481. {NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
  482. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  483. }
  484. TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
  485. auto props = DefaultInterfaceProperties();
  486. props.set_online(false);
  487. watcher_.SetInitial(std::move(props));
  488. CreateNotifier();
  489. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
  490. notifier_->GetCurrentConnectionType());
  491. watcher_.PushEvent(MakeChangeEvent(
  492. kDefaultInterfaceId, [](fuchsia::net::interfaces::Properties* props) {
  493. props->set_online(true);
  494. }));
  495. EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
  496. {NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET}));
  497. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  498. }
  499. TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
  500. watcher_.SetInitial(DefaultInterfaceProperties());
  501. CreateNotifier();
  502. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
  503. notifier_->GetCurrentConnectionType());
  504. watcher_.PushEvent(
  505. fuchsia::net::interfaces::Event::WithRemoved(kDefaultInterfaceId));
  506. EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
  507. {NetworkChangeNotifier::ConnectionType::CONNECTION_NONE}));
  508. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  509. }
  510. TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceAdded) {
  511. // Initial interface list is intentionally left empty.
  512. CreateNotifier();
  513. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
  514. notifier_->GetCurrentConnectionType());
  515. watcher_.PushEvent(
  516. fuchsia::net::interfaces::Event::WithAdded(DefaultInterfaceProperties(
  517. fuchsia::hardware::network::DeviceClass::WLAN)));
  518. EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
  519. {NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI}));
  520. EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
  521. }
  522. TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceAddedNoop) {
  523. watcher_.SetInitial(DefaultInterfaceProperties());
  524. CreateNotifier();
  525. watcher_.PushEvent(fuchsia::net::interfaces::Event::WithAdded(
  526. SecondaryInterfaceProperties()));
  527. }
  528. TEST_F(NetworkChangeNotifierFuchsiaTest, SecondaryInterfaceDeletedNoop) {
  529. std::vector<fuchsia::net::interfaces::Properties> interfaces;
  530. interfaces.push_back(DefaultInterfaceProperties());
  531. interfaces.push_back(SecondaryInterfaceProperties());
  532. watcher_.SetInitial(std::move(interfaces));
  533. CreateNotifier();
  534. watcher_.PushEvent(
  535. fuchsia::net::interfaces::Event::WithRemoved(kSecondaryInterfaceId));
  536. }
  537. TEST_F(NetworkChangeNotifierFuchsiaTest, FoundWiFi) {
  538. watcher_.SetInitial(DefaultInterfaceProperties(
  539. fuchsia::hardware::network::DeviceClass::WLAN));
  540. CreateNotifier();
  541. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
  542. notifier_->GetCurrentConnectionType());
  543. }
  544. TEST_F(NetworkChangeNotifierFuchsiaTest, FindsInterfaceWithRequiredWlan) {
  545. watcher_.SetInitial(DefaultInterfaceProperties(
  546. fuchsia::hardware::network::DeviceClass::WLAN));
  547. CreateNotifier(/*require_wlan=*/true);
  548. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI,
  549. notifier_->GetCurrentConnectionType());
  550. }
  551. TEST_F(NetworkChangeNotifierFuchsiaTest, IgnoresNonWlanInterface) {
  552. watcher_.SetInitial(DefaultInterfaceProperties());
  553. CreateNotifier(/*require_wlan=*/true);
  554. EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_NONE,
  555. notifier_->GetCurrentConnectionType());
  556. }
  557. } // namespace net