blob: de940d3dcea4a0520b91690dfe6b2cd2f353d4e9 [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.h"
#include <string>
#include <base/time/time.h>
#include <brillo/dbus/mock_dbus_object.h>
#include <brillo/errors/error.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "peerd/service.h"
#include "peerd/test_util.h"
using brillo::ErrorPtr;
using brillo::dbus_utils::DBusObject;
using brillo::dbus_utils::ExportedObjectManager;
using dbus::Bus;
using dbus::MockBus;
using dbus::MockExportedObject;
using dbus::ObjectPath;
using peerd::Peer;
using peerd::errors::peer::kDuplicateServiceID;
using peerd::errors::peer::kInvalidTime;
using peerd::errors::peer::kInvalidUUID;
using peerd::test_util::MakeMockCompletionAction;
using std::string;
using std::unique_ptr;
using testing::AnyNumber;
using testing::Invoke;
using testing::Property;
using testing::Return;
using testing::StartsWith;
using testing::_;
namespace {
const char kPeerPath[] = "/some/path/ending/with";
const char kServicePathPrefix[] = "/some/path/ending/with/services/";
const char kServicePath[] = "/some/path/ending/with/services/1";
const char kUUID[] = "123e4567-e89b-12d3-a456-426655440000";
} // namespace
namespace peerd {
class PeerTest : public ::testing::Test {
public:
virtual void SetUp() {
// Ignore threading concerns.
EXPECT_CALL(*mock_bus_, AssertOnOriginThread()).Times(AnyNumber());
EXPECT_CALL(*mock_bus_, AssertOnDBusThread()).Times(AnyNumber());
// Return appropriate objects when asked.
EXPECT_CALL(*mock_bus_,
GetExportedObject(Property(&ObjectPath::value,
kPeerPath)))
.WillRepeatedly(Return(peer_object_.get()));
EXPECT_CALL(*mock_bus_,
GetExportedObject(Property(&ObjectPath::value,
StartsWith(kServicePathPrefix))))
.WillRepeatedly(Return(service_object_.get()));
// Just immediately call callbacks on ExportMethod calls.
EXPECT_CALL(*peer_object_, ExportMethod(_, _, _, _))
.WillRepeatedly(Invoke(&test_util::HandleMethodExport));
EXPECT_CALL(*service_object_, ExportMethod(_, _, _, _))
.WillRepeatedly(Invoke(&test_util::HandleMethodExport));
// Ignore Unregister calls.
EXPECT_CALL(*peer_object_, Unregister()).Times(AnyNumber());
EXPECT_CALL(*service_object_, Unregister()).Times(AnyNumber());
}
unique_ptr<Peer> MakePeer() {
unique_ptr<Peer> peer{new Peer{mock_bus_, nullptr, ObjectPath{kPeerPath}}};
brillo::ErrorPtr error;
EXPECT_TRUE(peer->RegisterAsync(
&error,
kUUID,
base::Time::UnixEpoch() + base::TimeDelta::FromDays(1),
MakeMockCompletionAction()));
EXPECT_EQ(nullptr, error.get());
return peer;
}
void AssertBadFactoryArgs(const string& uuid, const string& error_code) {
brillo::ErrorPtr error;
unique_ptr<Peer> peer{
new Peer{mock_bus_, nullptr, ObjectPath{kPeerPath}}};
EXPECT_FALSE(peer->RegisterAsync(
&error,
uuid,
base::Time::UnixEpoch(),
MakeMockCompletionAction()));
ASSERT_NE(nullptr, error.get());
EXPECT_TRUE(error->HasError(peerd::kPeerdErrorDomain, error_code));
}
void TestBadUUID(const string& uuid) {
AssertBadFactoryArgs(uuid, kInvalidUUID);
}
scoped_refptr<MockBus> mock_bus_{new MockBus{Bus::Options{}}};
scoped_refptr<dbus::MockExportedObject> peer_object_{
new MockExportedObject{mock_bus_.get(), ObjectPath{kPeerPath}}};
scoped_refptr<dbus::MockExportedObject> service_object_{
new MockExportedObject{mock_bus_.get(), ObjectPath{kServicePath}}};
};
TEST_F(PeerTest, ShouldRejectObviouslyNotUUID) {
TestBadUUID("definitely a bad UUID");
}
TEST_F(PeerTest, ShouldRejectWrongUUIDLen) {
TestBadUUID(string(kUUID, strlen(kUUID)- 1));
}
TEST_F(PeerTest, ShouldRejectBadDashInUUID) {
string bad_uuid(kUUID);
bad_uuid[23] = 'a'; // Index 23 is the final -.
TestBadUUID(bad_uuid);
}
TEST_F(PeerTest, ShouldRejectBadCharacterInUUID) {
string bad_uuid(kUUID);
bad_uuid[bad_uuid.length() - 1] = '-';
TestBadUUID(bad_uuid);
}
TEST_F(PeerTest, ShouldRegisterWithDBus) {
auto peer = MakePeer();
EXPECT_EQ(peer->GetUUID(), kUUID);
}
TEST_F(PeerTest, ShouldRejectStaleUpdate) {
auto peer = MakePeer();
brillo::ErrorPtr error;
EXPECT_FALSE(peer->SetLastSeen(&error, base::Time::UnixEpoch()));
ASSERT_NE(nullptr, error.get());
EXPECT_TRUE(error->HasError(kPeerdErrorDomain, kInvalidTime));
}
TEST_F(PeerTest, ShouldRejectDuplicateServiceID) {
auto peer = MakePeer();
brillo::ErrorPtr error;
const string service_id{"a-service"};
EXPECT_TRUE(peer->AddService(&error, service_id, {}, {}, {}));
EXPECT_FALSE(peer->AddService(&error, service_id, {}, {}, {}));
EXPECT_TRUE(error->HasError(kPeerdErrorDomain, kDuplicateServiceID));
}
} // namespace peerd