//--------------------------------------------------------------------------- // // SCSI Target Emulator RaSCSI Reloaded // for Raspberry Pi // // Copyright (C) 2022 Uwe Seimet // //--------------------------------------------------------------------------- #include "mocks.h" #include "controllers/controller_manager.h" #include "rascsi_version.h" #include "test_shared.h" #include #include #include #include using namespace std; using namespace filesystem; shared_ptr CreateDevice(PbDeviceType type, MockAbstractController& controller, const string& extension) { DeviceFactory device_factory; auto controller_manager = make_shared(controller.GetBus()); auto device = device_factory.CreateDevice(*controller_manager, type, 0, extension); controller.AddDevice(device); return device; } void TestInquiry(PbDeviceType type, device_type t, scsi_level l, const string& ident, int additional_length, bool removable, const string& extension) { NiceMock controller(make_shared(), 0); auto device = CreateDevice(type, controller, extension); vector& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 255; EXPECT_CALL(controller, DataIn()); EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); const vector& buffer = controller.GetBuffer(); EXPECT_EQ(t, static_cast(buffer[0])); EXPECT_EQ(removable ? 0x80: 0x00, buffer[1]); EXPECT_EQ(l, static_cast(buffer[2])); EXPECT_EQ(l > scsi_level::SCSI_2 ? scsi_level::SCSI_2 : l, static_cast(buffer[3])); EXPECT_EQ(additional_length, buffer[4]); string product_data; if (ident.size() == 24) { ostringstream s; s << ident << setw(2) << setfill('0') << rascsi_major_version << rascsi_minor_version; product_data = s.str(); } else { product_data = ident; } EXPECT_TRUE(!memcmp(product_data.c_str(), &buffer[8], 28)); } void TestDispatch(PbDeviceType type) { NiceMock controller(make_shared(), 0); auto device = CreateDevice(type, controller); EXPECT_FALSE(device->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; } pair OpenTempFile() { const string filename = string(temp_directory_path()) + "/rascsi_test-XXXXXX"; //NOSONAR Publicly writable directory is fine here vector f(filename.begin(), filename.end()); f.push_back(0); const int fd = mkstemp(f.data()); EXPECT_NE(-1, fd) << "Couldn't create temporary file '" << f.data() << "'"; return make_pair(fd, path(f.data())); } path CreateTempFile(int size) { const auto [fd, filename] = OpenTempFile(); vector data(size); const size_t count = write(fd, data.data(), data.size()); close(fd); EXPECT_EQ(count, data.size()) << "Couldn't create temporary file '" << string(filename) << "'"; return path(filename); } int GetInt16(const vector& buf, int offset) { assert(buf.size() > static_cast(offset) + 1); return (to_integer(buf[offset]) << 8) | to_integer(buf[offset + 1]); } uint32_t GetInt32(const vector& buf, int offset) { assert(buf.size() > static_cast(offset) + 3); return (to_integer(buf[offset]) << 24) | (to_integer(buf[offset + 1]) << 16) | (to_integer(buf[offset + 2]) << 8) | to_integer(buf[offset + 3]); }