| // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "peerd/peer_manager_impl.h" |
| |
| #include <base/time/time.h> |
| #include <dbus/mock_bus.h> |
| #include <dbus/mock_exported_object.h> |
| #include <dbus/object_path.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "peerd/technologies.h" |
| #include "peerd/test_util.h" |
| |
| using base::Time; |
| using dbus::ObjectPath; |
| using dbus::MockExportedObject; |
| using peerd::technologies::tech_t; |
| using testing::AnyNumber; |
| using testing::Invoke; |
| using testing::Mock; |
| using testing::Property; |
| using testing::Return; |
| using testing::_; |
| |
| namespace { |
| |
| const char kPeerPath[] = "/org/chromium/peerd/peers/1"; |
| const char kServicePath[] = "/org/chromium/peerd/peers/1/services/1"; |
| |
| const char kPeerId[] = "123e4567-e89b-12d3-a456-426655440000"; |
| const char kName[] = "friendly name"; |
| const char kBadName[] = "#evil name"; |
| const char kNote[] = "descriptive note"; |
| const time_t kPeerLastSeen = 1; |
| const char kServiceId[] = "a-service-id"; |
| const char kBadServiceId[] = "#bad_service_id"; |
| const time_t kServiceLastSeen = 2; |
| tech_t kFakeTech1 = 1 << 29; |
| |
| } // namespace |
| |
| namespace peerd { |
| |
| class PeerManagerImplTest : public testing::Test { |
| public: |
| void SetUp() override { |
| // Ignore threading concerns. |
| EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber()); |
| EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber()); |
| // By default, don't let anyone have anyone export anything. |
| EXPECT_CALL(*bus_, GetExportedObject(_)) .Times(0); |
| EXPECT_CALL(*peer_object_, Unregister()).Times(0); |
| EXPECT_CALL(*service_object_, Unregister()).Times(0); |
| // Don't worry about signals. |
| EXPECT_CALL(*peer_object_, SendSignal(_)).Times(AnyNumber()); |
| EXPECT_CALL(*service_object_, SendSignal(_)).Times(AnyNumber()); |
| } |
| |
| void TearDown() override { |
| Mock::VerifyAndClearExpectations(bus_.get()); |
| Mock::VerifyAndClearExpectations(peer_object_.get()); |
| Mock::VerifyAndClearExpectations(service_object_.get()); |
| if (peer_exposed_) { |
| ExpectPeerRemoved(); |
| } |
| if (service_exposed_) { |
| ExpectServiceRemoved(); |
| } |
| } |
| |
| void ExpectPeerExposed() { |
| peer_exposed_ = true; |
| EXPECT_CALL(*bus_, GetExportedObject(Property(&ObjectPath::value, |
| kPeerPath))) |
| .WillOnce(Return(peer_object_.get())); |
| EXPECT_CALL(*peer_object_, ExportMethod(_, _, _, _)) |
| .WillRepeatedly(Invoke(&test_util::HandleMethodExport)); |
| } |
| |
| void ExpectPeerRemoved() { |
| Mock::VerifyAndClearExpectations(bus_.get()); |
| Mock::VerifyAndClearExpectations(peer_object_.get()); |
| peer_exposed_ = false; |
| EXPECT_CALL(*peer_object_, Unregister()).Times(1); |
| } |
| |
| void ExpectServiceExposed() { |
| service_exposed_ = true; |
| EXPECT_CALL(*bus_, GetExportedObject(Property(&ObjectPath::value, |
| kServicePath))) |
| .WillOnce(Return(service_object_.get())); |
| EXPECT_CALL(*service_object_, ExportMethod(_, _, _, _)) |
| .WillRepeatedly(Invoke(&test_util::HandleMethodExport)); |
| } |
| |
| void ExpectServiceRemoved() { |
| Mock::VerifyAndClearExpectations(bus_.get()); |
| Mock::VerifyAndClearExpectations(service_object_.get()); |
| service_exposed_ = false; |
| EXPECT_CALL(*service_object_, Unregister()).Times(1); |
| } |
| |
| scoped_refptr<dbus::MockBus> bus_{new dbus::MockBus{dbus::Bus::Options{}}}; |
| scoped_refptr<MockExportedObject> peer_object_{ |
| new MockExportedObject{bus_.get(), ObjectPath{kPeerPath}}}; |
| scoped_refptr<MockExportedObject> service_object_{ |
| new MockExportedObject{bus_.get(), ObjectPath{kServicePath}}}; |
| bool peer_exposed_{false}; |
| bool service_exposed_{false}; |
| PeerManagerImpl manager_{bus_, nullptr}; |
| }; |
| |
| TEST_F(PeerManagerImplTest, CanDiscoverPeer) { |
| ExpectPeerExposed(); |
| manager_.OnPeerDiscovered(kPeerId, kName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, CanDiscoverServiceOnPeer) { |
| ExpectPeerExposed(); |
| manager_.OnPeerDiscovered(kPeerId, kName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| ExpectServiceExposed(); |
| manager_.OnServiceDiscovered(kPeerId, kServiceId, {}, {}, |
| Time::FromTimeT(kServiceLastSeen), kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, CannotDiscoverServiceWithoutPeer) { |
| manager_.OnServiceDiscovered(kPeerId, kServiceId, {}, {}, |
| Time::FromTimeT(kServiceLastSeen), kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, CanForgetPeer) { |
| ExpectPeerExposed(); |
| manager_.OnPeerDiscovered(kPeerId, kName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| ExpectPeerRemoved(); |
| manager_.OnPeerRemoved(kPeerId, kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, CanShutdownLoneTechnology) { |
| ExpectPeerExposed(); |
| manager_.OnPeerDiscovered(kPeerId, kName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| ExpectServiceExposed(); |
| manager_.OnServiceDiscovered(kPeerId, kServiceId, {}, {}, |
| Time::FromTimeT(kServiceLastSeen), kFakeTech1); |
| ExpectServiceRemoved(); |
| ExpectPeerRemoved(); |
| manager_.OnTechnologyShutdown(kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, WillNotExposeCorruptPeer) { |
| manager_.OnPeerDiscovered(kPeerId, kBadName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| } |
| |
| TEST_F(PeerManagerImplTest, WillNotExposeCorruptService) { |
| ExpectPeerExposed(); |
| manager_.OnPeerDiscovered(kPeerId, kName, kNote, |
| Time::FromTimeT(kPeerLastSeen), kFakeTech1); |
| manager_.OnServiceDiscovered(kPeerId, kBadServiceId, {}, {}, |
| Time::FromTimeT(kServiceLastSeen), kFakeTech1); |
| } |
| |
| } // namespace peerd |