RASCSI/cpp/test/protobuf_util_test.cpp

220 lines
5.8 KiB
C++
Raw Normal View History

//---------------------------------------------------------------------------
//
// SCSI Target Emulator PiSCSI
// for Raspberry Pi
//
// Copyright (C) 2022-2023 Uwe Seimet
//
//---------------------------------------------------------------------------
#include "mocks.h"
#include "shared/protobuf_util.h"
#include "shared/piscsi_exceptions.h"
#include "generated/piscsi_interface.pb.h"
#include <filesystem>
using namespace piscsi_interface;
using namespace protobuf_util;
void TestSpecialDevice(const string& name)
{
PbDeviceDefinition device;
ParseParameters(device, name);
EXPECT_EQ(name, GetParam(device, "file"));
EXPECT_EQ("", GetParam(device, "interfaces"));
}
TEST(ProtobufUtil, GetSetParam)
{
// The implementation is a function template, testing one possible T is sufficient
PbCommand command;
SetParam(command, "key", "value");
EXPECT_EQ("value", GetParam(command, "key"));
EXPECT_EQ("", GetParam(command, "xyz"));
EXPECT_EQ("", GetParam(command, ""));
}
TEST(ProtobufUtil, ParseParameters)
{
PbDeviceDefinition device1;
ParseParameters(device1, "a=b:c=d:e");
EXPECT_EQ("b", GetParam(device1, "a"));
EXPECT_EQ("d", GetParam(device1, "c"));
EXPECT_EQ("", GetParam(device1, "e"));
// Old style parameter
PbDeviceDefinition device2;
ParseParameters(device2, "a");
EXPECT_EQ("a", GetParam(device2, "file"));
TestSpecialDevice("bridge");
TestSpecialDevice("daynaport");
TestSpecialDevice("printer");
TestSpecialDevice("services");
}
TEST(ProtobufUtil, SetPatternParams)
{
PbCommand command1;
SetPatternParams(command1, "file");
EXPECT_EQ("", GetParam(command1, "folder_pattern"));
EXPECT_EQ("file", GetParam(command1, "file_pattern"));
PbCommand command2;
SetPatternParams(command2, ":file");
EXPECT_EQ("", GetParam(command2, "folder_pattern"));
EXPECT_EQ("file", GetParam(command2, "file_pattern"));
PbCommand command3;
SetPatternParams(command3, "folder:");
EXPECT_EQ("folder", GetParam(command3, "folder_pattern"));
EXPECT_EQ("", GetParam(command3, "file_pattern"));
PbCommand command4;
SetPatternParams(command4, "folder:file");
EXPECT_EQ("folder", GetParam(command4, "folder_pattern"));
EXPECT_EQ("file", GetParam(command4, "file_pattern"));
}
TEST(ProtobufUtil, ListDevices)
{
vector<PbDevice> devices;
EXPECT_FALSE(ListDevices(devices).empty());
PbDevice device;
device.set_type(SCHD);
devices.push_back(device);
device.set_type(SCBR);
devices.push_back(device);
device.set_type(SCDP);
devices.push_back(device);
device.set_type(SCHS);
devices.push_back(device);
device.set_type(SCLP);
devices.push_back(device);
const string device_list = ListDevices(devices);
EXPECT_FALSE(device_list.empty());
EXPECT_NE(string::npos, device_list.find("X68000 HOST BRIDGE"));
EXPECT_NE(string::npos, device_list.find("DaynaPort SCSI/Link"));
EXPECT_NE(string::npos, device_list.find("Host Services"));
EXPECT_NE(string::npos, device_list.find("SCSI Printer"));
}
TEST(ProtobufUtil, SetProductData)
{
PbDeviceDefinition device;
SetProductData(device, "");
EXPECT_EQ("", device.vendor());
EXPECT_EQ("", device.product());
EXPECT_EQ("", device.revision());
SetProductData(device, "vendor");
EXPECT_EQ("vendor", device.vendor());
EXPECT_EQ("", device.product());
EXPECT_EQ("", device.revision());
SetProductData(device, "vendor:product");
EXPECT_EQ("vendor", device.vendor());
EXPECT_EQ("product", device.product());
EXPECT_EQ("", device.revision());
SetProductData(device, "vendor:product:revision");
EXPECT_EQ("vendor", device.vendor());
EXPECT_EQ("product", device.product());
EXPECT_EQ("revision", device.revision());
}
TEST(ProtobufUtil, SetIdAndLun)
{
PbDeviceDefinition device;
EXPECT_NE("", SetIdAndLun(device, ""));
EXPECT_EQ("", SetIdAndLun(device, "1"));
EXPECT_EQ(1, device.id());
EXPECT_EQ("", SetIdAndLun(device, "2:0"));
EXPECT_EQ(2, device.id());
EXPECT_EQ(0, device.unit());
}
TEST(ProtobufUtil, SerializeMessage)
{
PbResult result;
const int fd = open("/dev/null", O_WRONLY);
ASSERT_NE(-1, fd);
SerializeMessage(fd, result);
close(fd);
EXPECT_THROW(SerializeMessage(-1, result), io_exception) << "Writing a message must fail";
}
TEST(ProtobufUtil, DeserializeMessage)
{
PbResult result;
vector<byte> buf(1);
int fd = open("/dev/null", O_RDONLY);
ASSERT_NE(-1, fd);
EXPECT_THROW(DeserializeMessage(fd, result), io_exception) << "Reading the message header must fail";
close(fd);
auto [fd1, filename1] = OpenTempFile();
// Data size -1
buf = { byte{0xff}, byte{0xff}, byte{0xff}, byte{0xff} };
EXPECT_EQ(buf.size(), write(fd1, buf.data(), buf.size()));
close(fd1);
fd1 = open(filename1.c_str(), O_RDONLY);
ASSERT_NE(-1, fd1);
EXPECT_THROW(DeserializeMessage(fd1, result), io_exception) << "Invalid header was not rejected";
remove(filename1);
auto [fd2, filename2] = OpenTempFile();
// Data size 2
buf = { byte{0x02}, byte{0x00}, byte{0x00}, byte{0x00} };
EXPECT_EQ(buf.size(), write(fd2, buf.data(), buf.size()));
close(fd2);
fd2 = open(filename2.c_str(), O_RDONLY);
EXPECT_NE(-1, fd2);
EXPECT_THROW(DeserializeMessage(fd2, result), io_exception) << "Invalid data were not rejected";
remove(filename2);
}
TEST(ProtobufUtil, SerializeDeserializeMessage)
{
PbResult result;
result.set_status(true);
auto [fd, filename] = OpenTempFile();
ASSERT_NE(-1, fd);
SerializeMessage(fd, result);
close(fd);
result.set_status(false);
fd = open(filename.c_str(), O_RDONLY);
ASSERT_NE(-1, fd);
DeserializeMessage(fd, result);
close(fd);
remove(filename);
EXPECT_TRUE(result.status());
}
TEST(ProtobufUtil, ReadBytes)
{
vector<byte> buf1(1);
vector<byte> buf2;
int fd = open("/dev/null", O_RDONLY);
ASSERT_NE(-1, fd);
EXPECT_EQ(0, ReadBytes(fd, buf1));
EXPECT_EQ(0, ReadBytes(fd, buf2));
close(fd);
fd = open("/dev/zero", O_RDONLY);
ASSERT_NE(-1, fd);
EXPECT_EQ(1, ReadBytes(fd, buf1));
EXPECT_EQ(0, ReadBytes(fd, buf2));
close(fd);
}