fido_device_discovery_unittest.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright 2017 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 "device/fido/fido_device_discovery.h"
  5. #include <utility>
  6. #include "base/run_loop.h"
  7. #include "base/test/task_environment.h"
  8. #include "device/fido/fido_authenticator.h"
  9. #include "device/fido/fido_device_authenticator.h"
  10. #include "device/fido/fido_test_data.h"
  11. #include "device/fido/mock_fido_device.h"
  12. #include "device/fido/mock_fido_discovery_observer.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. namespace device {
  16. namespace {
  17. using ::testing::_;
  18. using ::testing::DoAll;
  19. using ::testing::Return;
  20. using ::testing::SaveArg;
  21. using ::testing::UnorderedElementsAre;
  22. // A minimal implementation of FidoDeviceDiscovery that is no longer abstract.
  23. class ConcreteFidoDiscovery : public FidoDeviceDiscovery {
  24. public:
  25. explicit ConcreteFidoDiscovery(FidoTransportProtocol transport)
  26. : FidoDeviceDiscovery(transport) {}
  27. ConcreteFidoDiscovery(const ConcreteFidoDiscovery&) = delete;
  28. ConcreteFidoDiscovery& operator=(const ConcreteFidoDiscovery&) = delete;
  29. ~ConcreteFidoDiscovery() override = default;
  30. MOCK_METHOD0(StartInternal, void());
  31. using FidoDeviceDiscovery::AddDevice;
  32. using FidoDeviceDiscovery::NotifyDiscoveryStarted;
  33. using FidoDeviceDiscovery::RemoveDevice;
  34. };
  35. } // namespace
  36. TEST(FidoDiscoveryTest, TestAddAndRemoveObserver) {
  37. ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
  38. MockFidoDiscoveryObserver observer;
  39. EXPECT_EQ(nullptr, discovery.observer());
  40. discovery.set_observer(&observer);
  41. EXPECT_EQ(&observer, discovery.observer());
  42. discovery.set_observer(nullptr);
  43. EXPECT_EQ(nullptr, discovery.observer());
  44. }
  45. TEST(FidoDiscoveryTest, TestNotificationsOnSuccessfulStart) {
  46. base::test::TaskEnvironment task_environment_;
  47. ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
  48. MockFidoDiscoveryObserver observer;
  49. discovery.set_observer(&observer);
  50. EXPECT_FALSE(discovery.is_start_requested());
  51. EXPECT_FALSE(discovery.is_running());
  52. EXPECT_CALL(discovery, StartInternal());
  53. discovery.Start();
  54. task_environment_.RunUntilIdle();
  55. EXPECT_TRUE(discovery.is_start_requested());
  56. EXPECT_FALSE(discovery.is_running());
  57. ::testing::Mock::VerifyAndClearExpectations(&discovery);
  58. EXPECT_CALL(observer, DiscoveryStarted(&discovery, true,
  59. std::vector<FidoAuthenticator*>()));
  60. discovery.NotifyDiscoveryStarted(true);
  61. EXPECT_TRUE(discovery.is_start_requested());
  62. EXPECT_TRUE(discovery.is_running());
  63. ::testing::Mock::VerifyAndClearExpectations(&observer);
  64. }
  65. TEST(FidoDiscoveryTest, TestNotificationsOnFailedStart) {
  66. base::test::TaskEnvironment task_environment_;
  67. ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
  68. MockFidoDiscoveryObserver observer;
  69. discovery.set_observer(&observer);
  70. discovery.Start();
  71. task_environment_.RunUntilIdle();
  72. EXPECT_CALL(observer, DiscoveryStarted(&discovery, false,
  73. std::vector<FidoAuthenticator*>()));
  74. discovery.NotifyDiscoveryStarted(false);
  75. EXPECT_TRUE(discovery.is_start_requested());
  76. EXPECT_FALSE(discovery.is_running());
  77. ::testing::Mock::VerifyAndClearExpectations(&observer);
  78. }
  79. TEST(FidoDiscoveryTest, TestAddRemoveDevices) {
  80. base::test::TaskEnvironment task_environment_;
  81. ConcreteFidoDiscovery discovery(FidoTransportProtocol::kBluetoothLowEnergy);
  82. MockFidoDiscoveryObserver observer;
  83. discovery.set_observer(&observer);
  84. discovery.Start();
  85. // Expect successful insertion.
  86. auto device0 = std::make_unique<MockFidoDevice>();
  87. auto* device0_raw = device0.get();
  88. FidoAuthenticator* authenticator0 = nullptr;
  89. base::RunLoop device0_done;
  90. EXPECT_CALL(observer, DiscoveryStarted(&discovery, true, _))
  91. .WillOnce(testing::Invoke(
  92. [&](auto* discovery, bool success, auto authenticators) {
  93. EXPECT_EQ(1u, authenticators.size());
  94. authenticator0 = authenticators[0];
  95. device0_done.Quit();
  96. }));
  97. EXPECT_CALL(*device0, GetId()).WillRepeatedly(Return("device0"));
  98. EXPECT_TRUE(discovery.AddDevice(std::move(device0)));
  99. discovery.NotifyDiscoveryStarted(true);
  100. EXPECT_EQ("device0", authenticator0->GetId());
  101. EXPECT_EQ(device0_raw,
  102. static_cast<FidoDeviceAuthenticator*>(authenticator0)->device());
  103. device0_done.Run();
  104. ::testing::Mock::VerifyAndClearExpectations(&observer);
  105. // Expect successful insertion after starting.
  106. base::RunLoop device1_done;
  107. auto device1 = std::make_unique<MockFidoDevice>();
  108. auto* device1_raw = device1.get();
  109. FidoAuthenticator* authenticator1 = nullptr;
  110. EXPECT_CALL(observer, AuthenticatorAdded(&discovery, _))
  111. .WillOnce(DoAll(SaveArg<1>(&authenticator1),
  112. testing::InvokeWithoutArgs(
  113. [&device1_done]() { device1_done.Quit(); })));
  114. EXPECT_CALL(*device1, GetId()).WillRepeatedly(Return("device1"));
  115. EXPECT_TRUE(discovery.AddDevice(std::move(device1)));
  116. EXPECT_EQ("device1", authenticator1->GetId());
  117. EXPECT_EQ(device1_raw,
  118. static_cast<FidoDeviceAuthenticator*>(authenticator1)->device());
  119. device1_done.Run();
  120. ::testing::Mock::VerifyAndClearExpectations(&observer);
  121. // Inserting a device with an already present id should be prevented.
  122. auto device1_dup = std::make_unique<MockFidoDevice>();
  123. EXPECT_CALL(observer, AuthenticatorAdded(_, _)).Times(0);
  124. EXPECT_CALL(*device1_dup, GetId()).WillOnce(Return("device1"));
  125. EXPECT_FALSE(discovery.AddDevice(std::move(device1_dup)));
  126. ::testing::Mock::VerifyAndClearExpectations(&observer);
  127. EXPECT_EQ(authenticator0, discovery.GetAuthenticatorForTesting("device0"));
  128. EXPECT_EQ(authenticator1, discovery.GetAuthenticatorForTesting("device1"));
  129. EXPECT_THAT(discovery.GetAuthenticatorsForTesting(),
  130. UnorderedElementsAre(authenticator0, authenticator1));
  131. const FidoDeviceDiscovery& const_discovery = discovery;
  132. EXPECT_THAT(const_discovery.GetAuthenticatorsForTesting(),
  133. UnorderedElementsAre(authenticator0, authenticator1));
  134. // Trying to remove a non-present device should fail.
  135. EXPECT_CALL(observer, AuthenticatorRemoved(_, _)).Times(0);
  136. EXPECT_FALSE(discovery.RemoveDevice("device2"));
  137. ::testing::Mock::VerifyAndClearExpectations(&observer);
  138. EXPECT_CALL(observer, AuthenticatorRemoved(&discovery, authenticator1));
  139. EXPECT_TRUE(discovery.RemoveDevice("device1"));
  140. ::testing::Mock::VerifyAndClearExpectations(&observer);
  141. EXPECT_CALL(observer, AuthenticatorRemoved(&discovery, authenticator0));
  142. EXPECT_TRUE(discovery.RemoveDevice("device0"));
  143. ::testing::Mock::VerifyAndClearExpectations(&observer);
  144. }
  145. } // namespace device