blob: 16761de5de80e5f42158e2fed0249a89371cd22d [file] [log] [blame]
// Copyright 2022 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 "flex_id/flex_id.h"
#include <optional>
#include <base/files/scoped_temp_dir.h>
#include <gtest/gtest.h>
namespace flex_id {
namespace {
constexpr char kClientId[] = "reven-client_id";
constexpr char kLegacyClientId[] = "CloudReady-aa:aa:aa:11:22:33";
constexpr char kUuid[] = "fc71ace7-5fbb-4108-a2f5-b48a98635aeb";
constexpr char kGoodSerial[] = "good_example_serial";
constexpr char kBadSerial[] = "to be filled by o.e.m.";
constexpr char kShortSerial[] = "a";
constexpr char kRepeatedSerial[] = "aaaaaa";
constexpr char kPriorityInterfaceName[] = "eth0";
constexpr char kGoodInterfaceName[] = "wlan1";
constexpr char kBadInterfaceName[] = "arc_1";
constexpr char kGoodMacAddress[] = "aa:bb:cc:11:22:33";
constexpr char kGoodMacAddress2[] = "dd:ee:ff:44:55:66";
constexpr char kBadMacAddress[] = "00:00:00:00:00:00";
constexpr char kPciModAlias[] = "pci:0000";
constexpr char kUsbModAlias[] = "usb:0000";
} // namespace
class FlexIdTest : public ::testing::Test {
protected:
void SetUp() override {
CHECK(test_dir_.CreateUniqueTempDir());
test_path_ = test_dir_.GetPath();
flex_id_generator_ = flex_id::FlexIdGenerator(test_path_);
}
void CreateSerial(const std::string& serial) {
base::FilePath serial_path =
test_path_.Append("sys/devices/virtual/dmi/id");
CHECK(base::CreateDirectory(serial_path));
CHECK(base::WriteFile(serial_path.Append("product_serial"), serial));
}
void CreateInterface(const std::string& name,
const std::string& address,
const std::string& modalias) {
base::FilePath interface_path =
test_path_.Append("sys/class/net").Append(name);
CHECK(base::CreateDirectory(interface_path.Append("device")));
CHECK(base::WriteFile(interface_path.Append("address"), address));
CHECK(base::WriteFile(interface_path.Append("device").Append("modalias"),
modalias));
}
void CreateClientId() {
base::FilePath client_id_path = test_path_.Append("var/lib/client_id");
CHECK(base::CreateDirectory(client_id_path));
CHECK(base::WriteFile(client_id_path.Append("client_id"), kClientId));
}
void CreateLegacy() {
base::FilePath legacy_path =
test_path_.Append("mnt/stateful_partition/cloudready");
CHECK(base::CreateDirectory(legacy_path));
CHECK(base::WriteFile(legacy_path.Append("client_id"), kLegacyClientId));
}
void CreateUuid() {
base::FilePath uuid_path = test_path_.Append("proc/sys/kernel/random");
CHECK(base::CreateDirectory(uuid_path));
CHECK(base::WriteFile(uuid_path.Append("uuid"), kUuid));
}
void DeleteFlexId() {
base::FilePath flex_id_path = test_path_.Append("var/lib/flex_id/flex_id");
CHECK(base::DeleteFile(flex_id_path));
}
std::optional<flex_id::FlexIdGenerator> flex_id_generator_;
base::ScopedTempDir test_dir_;
base::FilePath test_path_;
};
TEST_F(FlexIdTest, ClientId) {
EXPECT_FALSE(flex_id_generator_->TryClientId());
CreateClientId();
EXPECT_EQ(flex_id_generator_->TryClientId(), kClientId);
}
TEST_F(FlexIdTest, LegacyClientId) {
EXPECT_FALSE(flex_id_generator_->TryLegacy());
CreateLegacy();
EXPECT_EQ(flex_id_generator_->TryLegacy(), kLegacyClientId);
}
TEST_F(FlexIdTest, SerialNumber) {
EXPECT_FALSE(flex_id_generator_->TrySerial());
// a too short serial should not be used
CreateSerial(kShortSerial);
EXPECT_FALSE(flex_id_generator_->TrySerial());
// a known bad serial should not be used
CreateSerial(kBadSerial);
EXPECT_FALSE(flex_id_generator_->TrySerial());
// a serial of only one repeated character should not be used
CreateSerial(kRepeatedSerial);
EXPECT_FALSE(flex_id_generator_->TrySerial());
// a good serial should be used
CreateSerial(kGoodSerial);
EXPECT_EQ(flex_id_generator_->TrySerial(), kGoodSerial);
}
TEST_F(FlexIdTest, MacAddress) {
EXPECT_FALSE(flex_id_generator_->TryMac());
// 00:00:00:00:00:00 mac should not be used
CreateInterface(kPriorityInterfaceName, kBadMacAddress, kPciModAlias);
EXPECT_FALSE(flex_id_generator_->TryMac());
// a non priority usb device should not be used
CreateInterface(kGoodInterfaceName, kGoodMacAddress, kUsbModAlias);
EXPECT_FALSE(flex_id_generator_->TryMac());
// a blocked interface should not be used
CreateInterface(kBadInterfaceName, kGoodMacAddress, kPciModAlias);
EXPECT_FALSE(flex_id_generator_->TryMac());
// eth0 should be used
CreateInterface(kPriorityInterfaceName, kGoodMacAddress, kPciModAlias);
EXPECT_EQ(flex_id_generator_->TryMac(), kGoodMacAddress);
}
TEST_F(FlexIdTest, Uuid) {
EXPECT_FALSE(flex_id_generator_->TryUuid());
CreateUuid();
EXPECT_EQ(flex_id_generator_->TryUuid(), kUuid);
}
TEST_F(FlexIdTest, GenerateAndSaveFlexId) {
// no flex_id should be generated if there are no sources
EXPECT_FALSE(flex_id_generator_->GenerateAndSaveFlexId());
// uuid should be used for the flex_id
CreateUuid();
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(),
flex_id_generator_->AddFlexIdPrefix(kUuid).value());
// a bad interface should not be used
DeleteFlexId();
CreateInterface(kGoodInterfaceName, kGoodMacAddress, kUsbModAlias);
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(),
flex_id_generator_->AddFlexIdPrefix(kUuid).value());
// a good interface should take priority over uuid
DeleteFlexId();
CreateInterface(kGoodInterfaceName, kGoodMacAddress, kPciModAlias);
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(),
flex_id_generator_->AddFlexIdPrefix(kGoodMacAddress).value());
// a priority interface should take priority over a good interface
DeleteFlexId();
CreateInterface(kPriorityInterfaceName, kGoodMacAddress2, kPciModAlias);
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(),
flex_id_generator_->AddFlexIdPrefix(kGoodMacAddress2).value());
// a bad serial should not be used
DeleteFlexId();
CreateSerial(kBadSerial);
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(),
flex_id_generator_->AddFlexIdPrefix(kGoodMacAddress2).value());
// a good serial should take priority over mac address
DeleteFlexId();
CreateSerial(kGoodSerial);
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(), kGoodSerial);
// legacy client_id should take priority over a good serial
DeleteFlexId();
CreateLegacy();
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(), kLegacyClientId);
// client_id should take priority over a legacy client_id
DeleteFlexId();
CreateClientId();
EXPECT_TRUE(flex_id_generator_->GenerateAndSaveFlexId());
EXPECT_EQ(flex_id_generator_->ReadFlexId().value(), kClientId);
}
} // namespace flex_id