blob: a971b8250c61ecebcd1453a1df36e9135ca4ef29 [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/service.h"
#include <string>
#include <chromeos/errors/error.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_exported_object.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "peerd/test_util.h"
using IpAddresses = peerd::Service::IpAddresses;
using ServiceInfo = peerd::Service::ServiceInfo;
using dbus::Bus;
using dbus::MockBus;
using dbus::MockExportedObject;
using dbus::ObjectPath;
using peerd::errors::service::kInvalidServiceId;
using peerd::errors::service::kInvalidServiceInfo;
using peerd::test_util::MakeMockCompletionAction;
using std::string;
using std::unique_ptr;
using testing::AnyNumber;
using testing::Invoke;
using testing::Return;
using testing::_;
namespace {
IpAddresses MakeValidIpAddresses() {
// TODO(wiley) return a non-trivial list here.
return {};
}
const char kServicePath[] = "/a/path";
const char kValidServiceId[] = "valid-id";
} // namespace
namespace peerd {
class ServiceTest : public ::testing::Test {
public:
void SetUp() override {
// Ignore threading concerns.
EXPECT_CALL(*bus_, AssertOnOriginThread()).Times(AnyNumber());
EXPECT_CALL(*bus_, AssertOnDBusThread()).Times(AnyNumber());
// Unless we expect to create a Service object, we won't.
EXPECT_CALL(*bus_, GetExportedObject(_)).Times(0);
// Just immediately call callbacks on ExportMethod calls.
EXPECT_CALL(*service_object_, ExportMethod(_, _, _, _))
.WillRepeatedly(Invoke(&test_util::HandleMethodExport));
// Ignore Unregister calls.
EXPECT_CALL(*service_object_, Unregister()).Times(AnyNumber());
}
void AssertMakeServiceFails(const string& service_id,
const IpAddresses& addresses,
const ServiceInfo& service_info,
const string& error_code) {
chromeos::ErrorPtr error;
EXPECT_FALSE(service_.RegisterAsync(
&error, service_id, addresses, service_info,
MakeMockCompletionAction()));
ASSERT_NE(nullptr, error.get());
EXPECT_TRUE(error->HasError(kPeerdErrorDomain, error_code));
}
void AssertMakeServiceSuccess(
const string& service_id,
const IpAddresses& addresses,
const ServiceInfo& service_info) {
chromeos::ErrorPtr error;
EXPECT_CALL(*bus_, GetExportedObject(_))
.WillOnce(Return(service_object_.get()));
EXPECT_TRUE(service_.RegisterAsync(
&error, service_id, addresses, service_info,
MakeMockCompletionAction()));
EXPECT_EQ(nullptr, error.get());
}
scoped_refptr<MockBus> bus_{new MockBus{Bus::Options{}}};
scoped_refptr<dbus::MockExportedObject> service_object_{
new MockExportedObject{bus_.get(), ObjectPath{kServicePath}}};
Service service_{bus_, nullptr, ObjectPath{kServicePath}};
};
TEST_F(ServiceTest, ShouldRejectZeroLengthServiceId) {
AssertMakeServiceFails("",
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectLongServiceId) {
AssertMakeServiceFails(string(Service::kMaxServiceIdLength + 1, 'a'),
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectInvalidCharInServiceId) {
AssertMakeServiceFails("not*allowed",
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectHyphenPrefix) {
AssertMakeServiceFails("-not-allowed",
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectHyphenSuffix) {
AssertMakeServiceFails("not-allowed-",
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectAdjacentHyphens) {
AssertMakeServiceFails("not--allowed",
MakeValidIpAddresses(),
ServiceInfo(),
kInvalidServiceId);
}
TEST_F(ServiceTest, ShouldRejectInvalidCharInServiceInfoKey) {
const ServiceInfo info = {{"spaces are illegal", "valid value"}};
AssertMakeServiceFails(kValidServiceId,
MakeValidIpAddresses(),
info,
kInvalidServiceInfo);
}
TEST_F(ServiceTest, ShouldRejectServiceInfoPairTooLong) {
const ServiceInfo info = {
{"k", string(Service::kMaxServiceInfoPairLength, 'v')},
};
AssertMakeServiceFails(kValidServiceId,
MakeValidIpAddresses(),
info,
kInvalidServiceInfo);
}
TEST_F(ServiceTest, RegisterWhenInputIsValid) {
AssertMakeServiceSuccess(kValidServiceId,
MakeValidIpAddresses(),
ServiceInfo());
}
TEST_F(ServiceTest, RegisterWhenInputIsValidBoundaryCases) {
const ServiceInfo service_info = {
{"a", string(Service::kMaxServiceInfoPairLength - 1, 'b')},
{"", ""},
{"b", ""},
};
AssertMakeServiceSuccess(
string(Service::kMaxServiceIdLength, 'a'),
MakeValidIpAddresses(),
service_info);
}
} // namespace peerd