blob: aba4c8fb009fa524001ea1e7f1e8df3e8a645daa [file] [log] [blame]
// 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