From c41373d9bd9ac6120f879542edfd1537364a61c7 Mon Sep 17 00:00:00 2001 From: Uwe Seimet <48174652+uweseimet@users.noreply.github.com> Date: Wed, 2 Nov 2022 15:36:19 +0100 Subject: [PATCH] Use lambdas for dispatcher, code cleanup, test updates (#958) * Using lambdas instead of member function pointers simplifies the command dispatching and reduces the code volume * Removed duplicate error handling * Fix for issue #956 * Unit test updates * Resolved SonarQube issues --- cpp/bus.cpp | 19 ++ cpp/bus.h | 3 +- cpp/controllers/abstract_controller.cpp | 1 + cpp/controllers/scsi_controller.cpp | 71 ++--- cpp/devices/ctapdriver.cpp | 13 - cpp/devices/device.h | 3 +- cpp/devices/device_factory.cpp | 1 + cpp/devices/disk.cpp | 176 +++++-------- cpp/devices/disk.h | 18 +- cpp/devices/dispatcher.h | 55 ---- cpp/devices/host_services.cpp | 18 +- cpp/devices/host_services.h | 10 +- .../interfaces/scsi_primary_commands.h | 5 +- cpp/devices/mode_page_device.cpp | 44 ++-- cpp/devices/mode_page_device.h | 14 +- cpp/devices/primary_device.cpp | 58 ++-- cpp/devices/primary_device.h | 32 ++- cpp/devices/scsi_command_util.cpp | 17 +- cpp/devices/scsi_daynaport.cpp | 39 ++- cpp/devices/scsi_daynaport.h | 10 +- cpp/devices/scsi_host_bridge.cpp | 35 +-- cpp/devices/scsi_host_bridge.h | 9 +- cpp/devices/scsi_printer.cpp | 50 ++-- cpp/devices/scsi_printer.h | 24 +- cpp/devices/scsicd.cpp | 22 +- cpp/devices/scsicd.h | 9 +- cpp/devices/scsihd.cpp | 4 +- cpp/devices/scsihd.h | 4 +- cpp/devices/scsihd_nec.cpp | 2 +- cpp/devices/scsihd_nec.h | 2 +- cpp/devices/scsimo.cpp | 4 +- cpp/devices/scsimo.h | 4 +- cpp/devices/storage_device.cpp | 10 +- cpp/devices/storage_device.h | 7 +- cpp/hal/gpiobus.cpp | 22 +- cpp/hal/gpiobus.h | 2 - cpp/rascsi/rascsi_executor.cpp | 6 +- cpp/rascsi/rascsi_response.cpp | 1 + cpp/scsi.h | 64 ++++- cpp/test/abstract_controller_test.cpp | 48 +++- cpp/test/bus_test.cpp | 31 +++ cpp/test/controller_manager_test.cpp | 12 +- cpp/test/device_factory_test.cpp | 53 ++-- cpp/test/disk_test.cpp | 248 +++++++++++------- cpp/test/gpiobus_test.cpp | 44 ---- cpp/test/host_services_test.cpp | 31 ++- cpp/test/mocks.h | 9 +- cpp/test/mode_page_device_test.cpp | 30 +-- cpp/test/primary_device_test.cpp | 166 ++++++------ cpp/test/rascsi_executor_test.cpp | 6 +- cpp/test/rascsi_response_test.cpp | 17 +- cpp/test/scsi_command_util_test.cpp | 14 +- cpp/test/scsi_controller_test.cpp | 8 +- cpp/test/scsi_daynaport_test.cpp | 36 ++- cpp/test/scsi_host_bridge_test.cpp | 5 - cpp/test/scsi_printer_test.cpp | 20 +- cpp/test/scsicd_test.cpp | 7 +- cpp/test/scsihd_test.cpp | 5 - cpp/test/scsimo_test.cpp | 6 - cpp/test/storage_device_test.cpp | 11 - cpp/test/test_shared.cpp | 15 +- cpp/test/test_shared.h | 2 - 62 files changed, 821 insertions(+), 891 deletions(-) delete mode 100644 cpp/devices/dispatcher.h delete mode 100644 cpp/test/gpiobus_test.cpp diff --git a/cpp/bus.cpp b/cpp/bus.cpp index 206e1701..e791940f 100644 --- a/cpp/bus.cpp +++ b/cpp/bus.cpp @@ -12,6 +12,25 @@ using namespace std; +//--------------------------------------------------------------------------- +// +// Get the number of bytes for a command +// TODO Add the byte count to the enum value/command name mapping and remove the comparisons +// +//--------------------------------------------------------------------------- +int BUS::GetCommandByteCount(uint8_t opcode) +{ + if (opcode == 0x88 || opcode == 0x8A || opcode == 0x8F || opcode == 0x91 || opcode == 0x9E || opcode == 0x9F) { + return 16; + } else if (opcode == 0xA0) { + return 12; + } else if (opcode >= 0x20 && opcode <= 0x7D) { + return 10; + } else { + return 6; + } +} + //--------------------------------------------------------------------------- // // Phase Acquisition diff --git a/cpp/bus.h b/cpp/bus.h index fd927226..c24c9182 100644 --- a/cpp/bus.h +++ b/cpp/bus.h @@ -44,7 +44,8 @@ public: BUS() = default; virtual ~BUS() = default; - // Basic Functions + static int GetCommandByteCount(uint8_t); + virtual bool Init(mode_e mode) = 0; virtual void Reset() = 0; virtual void Cleanup() = 0; diff --git a/cpp/controllers/abstract_controller.cpp b/cpp/controllers/abstract_controller.cpp index be54f6bb..0dd6a1a2 100644 --- a/cpp/controllers/abstract_controller.cpp +++ b/cpp/controllers/abstract_controller.cpp @@ -7,6 +7,7 @@ // //--------------------------------------------------------------------------- +#include "log.h" #include "rascsi_exceptions.h" #include "devices/primary_device.h" #include "abstract_controller.h" diff --git a/cpp/controllers/scsi_controller.cpp b/cpp/controllers/scsi_controller.cpp index 2b466ed5..16166a98 100644 --- a/cpp/controllers/scsi_controller.cpp +++ b/cpp/controllers/scsi_controller.cpp @@ -196,8 +196,7 @@ void ScsiController::Command() GetBus()->SetIO(false); const int actual_count = GetBus()->CommandHandShake(GetBuffer().data()); - // TODO Try to move GetCommandByteCount() to BUS, so that the controller does not need to know GPIOBUS - const int command_byte_count = GPIOBUS::GetCommandByteCount(GetBuffer()[0]); + const int command_byte_count = BUS::GetCommandByteCount(GetBuffer()[0]); // If not able to receive all, move to the status phase if (actual_count != command_byte_count) { @@ -225,7 +224,7 @@ void ScsiController::Command() void ScsiController::Execute() { - LOGDEBUG("++++ CMD ++++ %s Executing command $%02X", __PRETTY_FUNCTION__, static_cast(GetOpcode())) + LOGDEBUG("++++ CMD ++++ Executing command $%02X", static_cast(GetOpcode())) // Initialization for data transfer ResetOffset(); @@ -240,24 +239,25 @@ void ScsiController::Execute() int lun = GetEffectiveLun(); if (!HasDeviceForLun(lun)) { if (GetOpcode() != scsi_command::eCmdInquiry && GetOpcode() != scsi_command::eCmdRequestSense) { - LOGDEBUG("Invalid LUN %d for ID %d", lun, GetTargetId()) + LOGTRACE("Invalid LUN %d for device ID %d", lun, GetTargetId()) Error(sense_key::ILLEGAL_REQUEST, asc::INVALID_LUN); + return; } - // Use LUN 0 for INQUIRY and REQUEST SENSE because LUN0 is assumed to be always available. - // INQUIRY and REQUEST SENSE have a special LUN handling of their own, required by the SCSI standard. - else { - if (!HasDeviceForLun(0)) { - LOGERROR("No LUN 0 for device %d", GetTargetId()) - GetBuffer().data()[0] = 0x7f; + assert(HasDeviceForLun(0)); - return; - } + lun = 0; + } - lun = 0; - } + // SCSI-2 4.4.3 Incorrect logical unit handling + if (GetOpcode() == scsi_command::eCmdInquiry && !HasDeviceForLun(lun)) { + LOGTRACE("Reporting LUN %d for device ID %d as not supported", GetEffectiveLun(), GetTargetId()) + + GetBuffer().data()[0] = 0x7f; + + return; } auto device = GetDeviceForLun(lun); @@ -267,31 +267,16 @@ void ScsiController::Execute() device->SetStatusCode(0); } - if (!device->CheckReservation(initiator_id, GetOpcode(), GetCmd(4) & 0x01)) { - Error(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, status::RESERVATION_CONFLICT); + if (device->CheckReservation(initiator_id, GetOpcode(), GetCmd(4) & 0x01)) { + try { + device->Dispatch(GetOpcode()); + } + catch(const scsi_exception& e) { + Error(e.get_sense_key(), e.get_asc()); + } } else { - try { - if (!device->Dispatch(GetOpcode())) { - LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetTargetId(), lun, static_cast(GetOpcode())) - - throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); - } - } - catch(const scsi_exception& e) { //NOSONAR This exception is handled properly - Error(e.get_sense_key(), e.get_asc()); - - // Fall through - } - } - - // SCSI-2 p.104 4.4.3 Incorrect logical unit handling - if (GetOpcode() == scsi_command::eCmdInquiry && !HasDeviceForLun(lun)) { - lun = GetEffectiveLun(); - - LOGTRACE("Reporting LUN %d for device ID %d as not supported", lun, device->GetId()) - - GetBuffer().data()[0] = 0x7f; + Error(sense_key::ABORTED_COMMAND, asc::NO_ADDITIONAL_SENSE_INFORMATION, status::RESERVATION_CONFLICT); } } @@ -494,7 +479,7 @@ void ScsiController::Send() LOGTRACE("%s%s", __PRETTY_FUNCTION__, (" Sending handhake with offset " + to_string(GetOffset()) + ", length " + to_string(GetLength())).c_str()) - // TODO The delay has to be taken from ctrl.unit[lun], but as there are currently no Daynaport drivers for + // The delay should be taken from the respective LUN, but as there are no Daynaport drivers for // LUNs other than 0 this work-around works. if (const int len = GetBus()->SendHandShake(GetBuffer().data() + GetOffset(), GetLength(), HasDeviceForLun(0) ? GetDeviceForLun(0)->GetSendDelay() : 0); @@ -850,7 +835,6 @@ bool ScsiController::XferIn(vector& buf) ResetOffset(); break; - // Other (impossible) default: assert(false); return false; @@ -929,14 +913,7 @@ bool ScsiController::XferOutBlockOriented(bool cont) break; } - // Check the next block - try { - SetLength(disk->WriteCheck(GetNext() - 1)); - } - catch(const scsi_exception&) { - return false; - } - + SetLength(disk->GetSectorSizeInBytes()); ResetOffset(); break; } diff --git a/cpp/devices/ctapdriver.cpp b/cpp/devices/ctapdriver.cpp index 236c4a48..02f24a27 100644 --- a/cpp/devices/ctapdriver.cpp +++ b/cpp/devices/ctapdriver.cpp @@ -129,19 +129,6 @@ bool CTapDriver::Init(const unordered_map& const_params) return false; #else unordered_map params = const_params; - if (params.count("interfaces")) { - LOGWARN("You are using the deprecated 'interfaces' parameter. " - "Provide the interface list and the IP address/netmask with the 'interface' and 'inet' parameters") - - // TODO Remove the deprecated syntax in a future version - const string& ifaces = params["interfaces"]; - size_t separatorPos = ifaces.find(':'); - if (separatorPos != string::npos) { - params["interface"] = ifaces.substr(0, separatorPos); - params["inet"] = ifaces.substr(separatorPos + 1); - } - } - stringstream s(params["interface"]); string interface; while (getline(s, interface, ',')) { diff --git a/cpp/devices/device.h b/cpp/devices/device.h index 5a8fd383..cb403ef4 100644 --- a/cpp/devices/device.h +++ b/cpp/devices/device.h @@ -64,11 +64,10 @@ class Device //NOSONAR The number of fields and methods is justified, the comple // The default parameters unordered_map default_params; - // Sense Key, ASC and ASCQ + // Sense Key and ASC // MSB Reserved (0x00) // Sense Key // Additional Sense Code (ASC) - // LSB Additional Sense Code Qualifier(ASCQ) int status_code = 0; protected: diff --git a/cpp/devices/device_factory.cpp b/cpp/devices/device_factory.cpp index 52d66697..dff49457 100644 --- a/cpp/devices/device_factory.cpp +++ b/cpp/devices/device_factory.cpp @@ -22,6 +22,7 @@ #include #include #include +#include using namespace std; using namespace rascsi_interface; diff --git a/cpp/devices/disk.cpp b/cpp/devices/disk.cpp index 0741ddfc..e619b326 100644 --- a/cpp/devices/disk.cpp +++ b/cpp/devices/disk.cpp @@ -14,45 +14,14 @@ // //--------------------------------------------------------------------------- +#include "log.h" #include "rascsi_exceptions.h" -#include "dispatcher.h" #include "scsi_command_util.h" #include "disk.h" using namespace scsi_defs; using namespace scsi_command_util; -const unordered_map Disk::shift_counts = { { 512, 9 }, { 1024, 10 }, { 2048, 11 }, { 4096, 12 } }; - -Disk::Disk(PbDeviceType type, int lun) : StorageDevice(type, lun) -{ - // REZERO implementation is identical with Seek - dispatcher.Add(scsi_command::eCmdRezero, "Rezero", &Disk::Seek); - dispatcher.Add(scsi_command::eCmdFormat, "FormatUnit", &Disk::FormatUnit); - // REASSIGN BLOCKS implementation is identical with Seek - dispatcher.Add(scsi_command::eCmdReassign, "ReassignBlocks", &Disk::Seek); - dispatcher.Add(scsi_command::eCmdRead6, "Read6", &Disk::Read6); - dispatcher.Add(scsi_command::eCmdWrite6, "Write6", &Disk::Write6); - dispatcher.Add(scsi_command::eCmdSeek6, "Seek6", &Disk::Seek6); - dispatcher.Add(scsi_command::eCmdStartStop, "StartStopUnit", &Disk::StartStopUnit); - dispatcher.Add(scsi_command::eCmdRemoval, "PreventAllowMediumRemoval", &Disk::PreventAllowMediumRemoval); - dispatcher.Add(scsi_command::eCmdReadCapacity10, "ReadCapacity10", &Disk::ReadCapacity10); - dispatcher.Add(scsi_command::eCmdRead10, "Read10", &Disk::Read10); - dispatcher.Add(scsi_command::eCmdWrite10, "Write10", &Disk::Write10); - dispatcher.Add(scsi_command::eCmdReadLong10, "ReadLong10", &Disk::ReadWriteLong10); - dispatcher.Add(scsi_command::eCmdWriteLong10, "WriteLong10", &Disk::ReadWriteLong10); - dispatcher.Add(scsi_command::eCmdWriteLong16, "WriteLong16", &Disk::ReadWriteLong16); - dispatcher.Add(scsi_command::eCmdSeek10, "Seek10", &Disk::Seek10); - dispatcher.Add(scsi_command::eCmdVerify10, "Verify10", &Disk::Verify10); - dispatcher.Add(scsi_command::eCmdSynchronizeCache10, "SynchronizeCache10", &Disk::SynchronizeCache); - dispatcher.Add(scsi_command::eCmdSynchronizeCache16, "SynchronizeCache16", &Disk::SynchronizeCache); - dispatcher.Add(scsi_command::eCmdReadDefectData10, "ReadDefectData10", &Disk::ReadDefectData10); - dispatcher.Add(scsi_command::eCmdRead16, "Read16", &Disk::Read16); - dispatcher.Add(scsi_command::eCmdWrite16, "Write16", &Disk::Write16); - dispatcher.Add(scsi_command::eCmdVerify16, "Verify16", &Disk::Verify16); - dispatcher.Add(scsi_command::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16", &Disk::ReadCapacity16_ReadLong16); -} - Disk::~Disk() { // Save disk cache, only if ready @@ -61,7 +30,40 @@ Disk::~Disk() } } -bool Disk::Dispatch(scsi_command cmd) +bool Disk::Init(const unordered_map& params) +{ + StorageDevice::Init(params); + + // REZERO implementation is identical with Seek + AddCommand(scsi_command::eCmdRezero, [this] { Seek(); }); + AddCommand(scsi_command::eCmdFormatUnit, [this] { FormatUnit(); }); + // REASSIGN BLOCKS implementation is identical with Seek + AddCommand(scsi_command::eCmdReassignBlocks, [this] { Seek(); }); + AddCommand(scsi_command::eCmdRead6, [this] { Read6(); }); + AddCommand(scsi_command::eCmdWrite6, [this] { Write6(); }); + AddCommand(scsi_command::eCmdSeek6, [this] { Seek6(); }); + AddCommand(scsi_command::eCmdStartStop, [this] { StartStopUnit(); }); + AddCommand(scsi_command::eCmdPreventAllowMediumRemoval, [this]{ PreventAllowMediumRemoval(); }); + AddCommand(scsi_command::eCmdReadCapacity10, [this] { ReadCapacity10(); }); + AddCommand(scsi_command::eCmdRead10, [this] { Read10(); }); + AddCommand(scsi_command::eCmdWrite10, [this] { Write10(); }); + AddCommand(scsi_command::eCmdReadLong10, [this] { ReadWriteLong10(); }); + AddCommand(scsi_command::eCmdWriteLong10, [this] { ReadWriteLong10(); }); + AddCommand(scsi_command::eCmdWriteLong16, [this] { ReadWriteLong16(); }); + AddCommand(scsi_command::eCmdSeek10, [this] { Seek10(); }); + AddCommand(scsi_command::eCmdVerify10, [this] { Verify10(); }); + AddCommand(scsi_command::eCmdSynchronizeCache10, [this] { SynchronizeCache(); }); + AddCommand(scsi_command::eCmdSynchronizeCache16, [this] { SynchronizeCache(); }); + AddCommand(scsi_command::eCmdReadDefectData10, [this] { ReadDefectData10(); }); + AddCommand(scsi_command::eCmdRead16,[this] { Read16(); }); + AddCommand(scsi_command::eCmdWrite16, [this] { Write16(); }); + AddCommand(scsi_command::eCmdVerify16, [this] { Verify16(); }); + AddCommand(scsi_command::eCmdReadCapacity16_ReadLong16, [this] { ReadCapacity16_ReadLong16(); }); + + return true; +} + +void Disk::Dispatch(scsi_command cmd) { // Media changes must be reported on the next access, i.e. not only for TEST UNIT READY if (IsMediumChanged()) { @@ -69,11 +71,11 @@ bool Disk::Dispatch(scsi_command cmd) SetMediumChanged(false); - throw scsi_exception(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); + controller->Error(sense_key::UNIT_ATTENTION, asc::NOT_READY_TO_READY_CHANGE); + } + else { + PrimaryDevice::Dispatch(cmd); } - - // The superclass handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); } void Disk::SetUpCache(off_t image_offset, bool raw) @@ -109,11 +111,11 @@ void Disk::FormatUnit() void Disk::Read(access_mode mode) { - uint64_t start; - uint32_t blocks; - if (CheckAndGetStartAndCount(start, blocks, mode)) { + const auto& [valid, start, blocks] = CheckAndGetStartAndCount(mode); + if (valid) { controller->SetBlocks(blocks); controller->SetLength(Read(controller->GetCmd(), controller->GetBuffer(), start)); + LOGTRACE("%s ctrl.length is %d", __PRETTY_FUNCTION__, controller->GetLength()) // Set next block @@ -128,35 +130,38 @@ void Disk::Read(access_mode mode) void Disk::ReadWriteLong10() { + ValidateBlockAddress(RW10); + // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (GetInt16(controller->GetCmd(), 7) != 0) { throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - ValidateBlockAddress(RW10); - EnterStatusPhase(); } void Disk::ReadWriteLong16() { + ValidateBlockAddress(RW16); + // Transfer lengths other than 0 are not supported, which is compliant with the SCSI standard if (GetInt16(controller->GetCmd(), 12) != 0) { throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - ValidateBlockAddress(RW16); - EnterStatusPhase(); } void Disk::Write(access_mode mode) { - uint64_t start; - uint32_t blocks; - if (CheckAndGetStartAndCount(start, blocks, mode)) { + if (IsProtected()) { + throw scsi_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); + } + + const auto& [valid, start, blocks] = CheckAndGetStartAndCount(mode); + if (valid) { controller->SetBlocks(blocks); - controller->SetLength(WriteCheck(start)); + controller->SetLength(GetSectorSizeInBytes()); // Set next block controller->SetNext(start + 1); @@ -170,9 +175,8 @@ void Disk::Write(access_mode mode) void Disk::Verify(access_mode mode) { - uint64_t start; - uint32_t blocks; - if (CheckAndGetStartAndCount(start, blocks, mode)) { + const auto& [valid, start, blocks] = CheckAndGetStartAndCount(mode); + if (valid) { // if BytChk=0 if ((controller->GetCmd(1) & 0x02) == 0) { Seek(); @@ -261,7 +265,7 @@ void Disk::ReadDefectData10() bool Disk::Eject(bool force) { - const bool status = super::Eject(force); + const bool status = PrimaryDevice::Eject(force); if (status) { FlushCache(); cache.reset(); @@ -389,11 +393,8 @@ void Disk::SetUpModePages(map>& pages, int page, bool changeab void Disk::AddErrorPage(map>& pages, bool) const { - vector buf(12); - // Retry count is 0, limit time uses internal default value - - pages[1] = buf; + pages[1] = vector(12); } void Disk::AddFormatPage(map>& pages, bool changeable) const @@ -491,16 +492,10 @@ void Disk::AddCachePage(map>& pages, bool changeable) const int Disk::Read(const vector&, vector& buf, uint64_t block) { - LOGTRACE("%s", __PRETTY_FUNCTION__) + assert(block < GetBlockCount()); CheckReady(); - // Error if the total number of blocks is exceeded - if (block >= GetBlockCount()) { - throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); - } - - // leave it to the cache if (!cache->ReadSector(buf, static_cast(block))) { throw scsi_exception(sense_key::MEDIUM_ERROR, asc::READ_FAULT); } @@ -508,40 +503,12 @@ int Disk::Read(const vector&, vector& buf, uint64_t block) return GetSectorSizeInBytes(); } -int Disk::WriteCheck(uint64_t block) -{ - CheckReady(); - - // Error if the total number of blocks is exceeded - if (block >= GetBlockCount()) { - throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); - } - - // Error if write protected - if (IsProtected()) { - throw scsi_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); - } - - return GetSectorSizeInBytes(); -} - void Disk::Write(const vector&, const vector& buf, uint64_t block) { - LOGTRACE("%s", __PRETTY_FUNCTION__) + assert(block < GetBlockCount()); CheckReady(); - // Error if the total number of blocks is exceeded - if (block >= GetBlockCount()) { - throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::LBA_OUT_OF_RANGE); - } - - // Error if write protected - if (IsProtected()) { - throw scsi_exception(sense_key::DATA_PROTECT, asc::WRITE_PROTECTED); - } - - // Leave it to the cache if (!cache->WriteSector(buf, static_cast(block))) { throw scsi_exception(sense_key::MEDIUM_ERROR, asc::WRITE_FAULT); } @@ -556,8 +523,8 @@ void Disk::Seek() void Disk::Seek6() { - uint64_t start; - if (uint32_t blocks; CheckAndGetStartAndCount(start, blocks, SEEK6)) { + const auto& [valid, start, blocks] = CheckAndGetStartAndCount(SEEK6); + if (valid) { CheckReady(); } @@ -566,8 +533,8 @@ void Disk::Seek6() void Disk::Seek10() { - uint64_t start; - if (uint32_t blocks; CheckAndGetStartAndCount(start, blocks, SEEK10)) { + const auto& [valid, start, blocks] = CheckAndGetStartAndCount(SEEK10); + if (valid) { CheckReady(); } @@ -596,7 +563,6 @@ void Disk::ReadCapacity10() // Create block length (1 << size) SetInt32(buf, 4, 1 << size_shift_count); - // the size controller->SetLength(8); EnterDataInPhase(); @@ -623,7 +589,6 @@ void Disk::ReadCapacity16() // Logical blocks per physical block: not reported (1 or more) buf[13] = 0; - // the size controller->SetLength(14); EnterDataInPhase(); @@ -647,12 +612,6 @@ void Disk::ReadCapacity16_ReadLong16() } } -//--------------------------------------------------------------------------- -// -// Check/Get start sector and sector count for a READ/WRITE or READ/WRITE LONG operation -// -//--------------------------------------------------------------------------- - void Disk::ValidateBlockAddress(access_mode mode) const { const uint64_t block = mode == RW16 ? GetInt64(controller->GetCmd(), 2) : GetInt32(controller->GetCmd(), 2); @@ -664,8 +623,11 @@ void Disk::ValidateBlockAddress(access_mode mode) const } } -bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mode mode) const +tuple Disk::CheckAndGetStartAndCount(access_mode mode) const { + uint64_t start; + uint32_t count; + if (mode == RW6 || mode == SEEK6) { start = GetInt24(controller->GetCmd(), 1); @@ -700,10 +662,10 @@ bool Disk::CheckAndGetStartAndCount(uint64_t& start, uint32_t& count, access_mod // Do not process 0 blocks if (!count && (mode != SEEK6 && mode != SEEK10)) { - return false; + return tuple(false, start, count); } - return true; + return tuple(true, start, count); } uint32_t Disk::CalculateShiftCount(uint32_t size_in_bytes) diff --git a/cpp/devices/disk.h b/cpp/devices/disk.h index 2513cb70..31c46146 100644 --- a/cpp/devices/disk.h +++ b/cpp/devices/disk.h @@ -24,6 +24,7 @@ #include #include #include +#include using namespace std; @@ -31,8 +32,6 @@ class Disk : public StorageDevice, private ScsiBlockCommands { enum access_mode { RW6, RW10, RW16, SEEK6, SEEK10 }; - Dispatcher dispatcher; - unique_ptr cache; // The supported configurable sector sizes, empty if not configurable @@ -44,15 +43,15 @@ class Disk : public StorageDevice, private ScsiBlockCommands public: - Disk(PbDeviceType, int); + Disk(PbDeviceType type, int lun) : StorageDevice(type, lun) {} ~Disk() override; - bool Dispatch(scsi_command) override; + bool Init(const unordered_map&) override; + + void Dispatch(scsi_command) override; bool Eject(bool) override; - // Command helpers - virtual int WriteCheck(uint64_t); virtual void Write(const vector&, const vector&, uint64_t); virtual int Read(const vector&, vector& , uint64_t); @@ -64,8 +63,6 @@ public: private: - using super = StorageDevice; - // Commands covered by the SCSI specifications (see https://www.t10.org/drafts.htm) void StartStopUnit(); void PreventAllowMediumRemoval(); @@ -93,12 +90,13 @@ private: void ReadCapacity16_ReadLong16(); void ValidateBlockAddress(access_mode) const; - bool CheckAndGetStartAndCount(uint64_t&, uint32_t&, access_mode) const; + tuple CheckAndGetStartAndCount(access_mode) const; int ModeSense6(const vector&, vector&) const override; int ModeSense10(const vector&, vector&) const override; - static const unordered_map shift_counts; + static inline const unordered_map shift_counts = + { { 512, 9 }, { 1024, 10 }, { 2048, 11 }, { 4096, 12 } }; protected: diff --git a/cpp/devices/dispatcher.h b/cpp/devices/dispatcher.h deleted file mode 100644 index 8290937b..00000000 --- a/cpp/devices/dispatcher.h +++ /dev/null @@ -1,55 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2022 Uwe Seimet -// -// A template for dispatching SCSI commands -// -//--------------------------------------------------------------------------- - -#pragma once - -#include "log.h" -#include - -using namespace std; -using namespace scsi_defs; - -template -class Dispatcher -{ -public: - - Dispatcher() = default; - ~Dispatcher() = default; - - using operation = void (T::*)(); - using command_t = struct _command_t { - const char *name; - operation execute; - - _command_t(const char *_name, operation _execute) : name(_name), execute(_execute) { }; - }; - unordered_map> commands; - - void Add(scsi_command opcode, const char *name, operation execute) - { - commands[opcode] = make_unique(name, execute); - } - - bool Dispatch(T *instance, scsi_command cmd) const - { - if (const auto& it = commands.find(cmd); it != commands.end()) { - LOGDEBUG("%s Executing %s ($%02X)", __PRETTY_FUNCTION__, it->second->name, (int)cmd) - - (instance->*it->second->execute)(); - - return true; - } - - // Unknown command - return false; - } -}; diff --git a/cpp/devices/host_services.cpp b/cpp/devices/host_services.cpp index ee780746..043d2f7c 100644 --- a/cpp/devices/host_services.cpp +++ b/cpp/devices/host_services.cpp @@ -24,26 +24,22 @@ #include "controllers/scsi_controller.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "host_services.h" #include using namespace scsi_defs; using namespace scsi_command_util; -HostServices::HostServices(int lun, const ControllerManager& manager) - : ModePageDevice(SCHS, lun), controller_manager(manager) +bool HostServices::Init(const unordered_map& params) { - dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &HostServices::TestUnitReady); - dispatcher.Add(scsi_command::eCmdStartStop, "StartStopUnit", &HostServices::StartStopUnit); + ModePageDevice::Init(params); + + AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); }); + AddCommand(scsi_command::eCmdStartStop, [this] { StartStopUnit(); }); SetReady(true); -} -bool HostServices::Dispatch(scsi_command cmd) -{ - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); + return true; } void HostServices::TestUnitReady() @@ -52,7 +48,7 @@ void HostServices::TestUnitReady() EnterStatusPhase(); } -vector HostServices::InquiryInternal() const +vector HostServices::InquiryInternal() const { return HandleInquiry(device_type::PROCESSOR, scsi_level::SPC_3, false); } diff --git a/cpp/devices/host_services.h b/cpp/devices/host_services.h index deaad8f8..365c5b5a 100644 --- a/cpp/devices/host_services.h +++ b/cpp/devices/host_services.h @@ -22,12 +22,12 @@ class HostServices: public ModePageDevice public: - HostServices(int, const ControllerManager&); + HostServices(int lun, const ControllerManager& manager) : ModePageDevice(SCHS, lun), controller_manager(manager) {} ~HostServices() override = default; - bool Dispatch(scsi_command) override; + bool Init(const unordered_map&) override; - vector InquiryInternal() const override; + vector InquiryInternal() const override; void TestUnitReady() override; protected: @@ -49,10 +49,6 @@ private: uint8_t second; // 0-59 }; - using super = ModePageDevice; - - Dispatcher dispatcher; - const ControllerManager& controller_manager; void StartStopUnit(); diff --git a/cpp/devices/interfaces/scsi_primary_commands.h b/cpp/devices/interfaces/scsi_primary_commands.h index 110de77a..1a9ca6dd 100644 --- a/cpp/devices/interfaces/scsi_primary_commands.h +++ b/cpp/devices/interfaces/scsi_primary_commands.h @@ -24,6 +24,9 @@ public: virtual void Inquiry() = 0; virtual void ReportLuns() = 0; - // Implemented for all RaSCSI device types + // Optional commands implemented by all RaSCSI device types virtual void RequestSense() = 0; + virtual void ReleaseUnit() = 0; + virtual void ReserveUnit() = 0; + virtual void SendDiagnostic() = 0; }; diff --git a/cpp/devices/mode_page_device.cpp b/cpp/devices/mode_page_device.cpp index c3b8e82c..2c021086 100644 --- a/cpp/devices/mode_page_device.cpp +++ b/cpp/devices/mode_page_device.cpp @@ -12,7 +12,6 @@ #include "log.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "mode_page_device.h" #include @@ -20,23 +19,21 @@ using namespace std; using namespace scsi_defs; using namespace scsi_command_util; -ModePageDevice::ModePageDevice(PbDeviceType type, int lun) : PrimaryDevice(type, lun) +bool ModePageDevice::Init(const unordered_map& params) { - dispatcher.Add(scsi_command::eCmdModeSense6, "ModeSense6", &ModePageDevice::ModeSense6); - dispatcher.Add(scsi_command::eCmdModeSense10, "ModeSense10", &ModePageDevice::ModeSense10); - dispatcher.Add(scsi_command::eCmdModeSelect6, "ModeSelect6", &ModePageDevice::ModeSelect6); - dispatcher.Add(scsi_command::eCmdModeSelect10, "ModeSelect10", &ModePageDevice::ModeSelect10); -} + PrimaryDevice::Init(params); -bool ModePageDevice::Dispatch(scsi_command cmd) -{ - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); + AddCommand(scsi_command::eCmdModeSense6, [this] { ModeSense6(); }); + AddCommand(scsi_command::eCmdModeSense10, [this] { ModeSense10(); }); + AddCommand(scsi_command::eCmdModeSelect6, [this] { ModeSelect6(); }); + AddCommand(scsi_command::eCmdModeSelect10, [this] { ModeSelect10(); }); + + return true; } int ModePageDevice::AddModePages(const vector& cdb, vector& buf, int offset, int length, int max_size) const { - int max_length = length - offset; + const int max_length = length - offset; if (max_length < 0) { return length; } @@ -61,7 +58,7 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, i vector result; vector page0; - for (auto const& [index, data] : pages) { + for (const auto& [index, data] : pages) { // The specification mandates that page 0 must be returned after all others if (index) { const size_t off = result.size(); @@ -80,7 +77,7 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, i // Page 0 must be last if (!page0.empty()) { - size_t off = result.size(); + const size_t off = result.size(); // Page data result.insert(result.end(), page0.begin(), page0.end()); @@ -92,7 +89,7 @@ int ModePageDevice::AddModePages(const vector& cdb, vector& buf, i throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - auto size = static_cast(min(static_cast(max_length), result.size())); + const auto size = static_cast(min(static_cast(max_length), result.size())); memcpy(&buf.data()[offset], result.data(), size); // Do not return more than the requested number of bytes @@ -115,30 +112,29 @@ void ModePageDevice::ModeSense10() void ModePageDevice::ModeSelect(scsi_command, const vector&, const vector&, int) const { + // There is no default implementation of MDOE SELECT throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); } void ModePageDevice::ModeSelect6() { - controller->SetLength(SaveParametersCheck(controller->GetCmd(4))); - - EnterDataOutPhase(); + SaveParametersCheck(controller->GetCmd(4)); } void ModePageDevice::ModeSelect10() { - const size_t length = min(controller->GetBuffer().size(), static_cast(GetInt16(controller->GetCmd(), 7))); + const auto length = min(controller->GetBuffer().size(), static_cast(GetInt16(controller->GetCmd(), 7))); - controller->SetLength(SaveParametersCheck(static_cast(length))); - - EnterDataOutPhase(); + SaveParametersCheck(static_cast(length)); } -int ModePageDevice::SaveParametersCheck(int length) const +void ModePageDevice::SaveParametersCheck(int length) { if (!SupportsSaveParameters() && (controller->GetCmd(1) & 0x01)) { throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - return length; + controller->SetLength(length); + + EnterDataOutPhase(); } diff --git a/cpp/devices/mode_page_device.h b/cpp/devices/mode_page_device.h index 5e258899..fa6dd838 100644 --- a/cpp/devices/mode_page_device.h +++ b/cpp/devices/mode_page_device.h @@ -14,14 +14,14 @@ #include #include -class ModePageDevice: public PrimaryDevice +// TODO Maybe this should better be a mixin class because not all storage devicess have mode pages +class ModePageDevice : public PrimaryDevice { public: - ModePageDevice(PbDeviceType, int); - ~ModePageDevice() override = default; + using PrimaryDevice::PrimaryDevice; - bool Dispatch(scsi_command) override; + bool Init(const unordered_map&) override; virtual void ModeSelect(scsi_defs::scsi_command, const vector&, const vector&, int) const; @@ -37,10 +37,6 @@ protected: private: - using super = PrimaryDevice; - - Dispatcher dispatcher; - bool supports_save_parameters = false; virtual int ModeSense6(const vector&, vector&) const = 0; @@ -51,5 +47,5 @@ private: void ModeSelect6(); void ModeSelect10(); - int SaveParametersCheck(int) const; + void SaveParametersCheck(int); }; diff --git a/cpp/devices/primary_device.cpp b/cpp/devices/primary_device.cpp index 50f52043..f9478d87 100644 --- a/cpp/devices/primary_device.cpp +++ b/cpp/devices/primary_device.cpp @@ -10,30 +10,47 @@ #include "log.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "primary_device.h" using namespace std; using namespace scsi_defs; using namespace scsi_command_util; -PrimaryDevice::PrimaryDevice(PbDeviceType type, int lun) : Device(type, lun) +bool PrimaryDevice::Init(const unordered_map& params) { // Mandatory SCSI primary commands - dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &PrimaryDevice::TestUnitReady); - dispatcher.Add(scsi_command::eCmdInquiry, "Inquiry", &PrimaryDevice::Inquiry); - dispatcher.Add(scsi_command::eCmdReportLuns, "ReportLuns", &PrimaryDevice::ReportLuns); + AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); }); + AddCommand(scsi_command::eCmdInquiry, [this] { Inquiry(); }); + AddCommand(scsi_command::eCmdReportLuns, [this] { ReportLuns(); }); // Optional commands supported by all RaSCSI devices - dispatcher.Add(scsi_command::eCmdRequestSense, "RequestSense", &PrimaryDevice::RequestSense); - dispatcher.Add(scsi_command::eCmdReserve6, "ReserveUnit", &PrimaryDevice::ReserveUnit); - dispatcher.Add(scsi_command::eCmdRelease6, "ReleaseUnit", &PrimaryDevice::ReleaseUnit); - dispatcher.Add(scsi_command::eCmdSendDiag, "SendDiagnostic", &PrimaryDevice::SendDiagnostic); + AddCommand(scsi_command::eCmdRequestSense, [this] { RequestSense(); }); + AddCommand(scsi_command::eCmdReserve6, [this] { ReserveUnit(); }); + AddCommand(scsi_command::eCmdRelease6, [this] { ReleaseUnit(); }); + AddCommand(scsi_command::eCmdSendDiagnostic, [this] { SendDiagnostic(); }); + + SetParams(params); + + return true; } -bool PrimaryDevice::Dispatch(scsi_command cmd) +void PrimaryDevice::AddCommand(scsi_command opcode, const operation& execute) { - return dispatcher.Dispatch(this, cmd); + commands[opcode] = execute; +} + +void PrimaryDevice::Dispatch(scsi_command cmd) +{ + if (const auto& it = commands.find(cmd); it != commands.end()) { + LOGDEBUG("Executing %s ($%02X)", command_names.find(cmd)->second, static_cast(cmd)) + + it->second(); + } + else { + LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetId(), GetLun(), static_cast(cmd)) + + throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_COMMAND_OPERATION_CODE); + } } void PrimaryDevice::Reset() @@ -71,7 +88,7 @@ void PrimaryDevice::Inquiry() throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_CDB); } - vector buf = InquiryInternal(); + vector buf = InquiryInternal(); const size_t allocation_length = min(buf.size(), static_cast(GetInt16(controller->GetCmd(), 3))); @@ -187,9 +204,9 @@ void PrimaryDevice::CheckReady() LOGTRACE("%s Device is ready", __PRETTY_FUNCTION__) } -vector PrimaryDevice::HandleInquiry(device_type type, scsi_level level, bool is_removable) const +vector PrimaryDevice::HandleInquiry(device_type type, scsi_level level, bool is_removable) const { - vector buf(0x1F + 5); + vector buf(0x1F + 5); // Basic data // buf[0] ... SCSI device type @@ -197,11 +214,12 @@ vector PrimaryDevice::HandleInquiry(device_type type, scsi_level level, bo // buf[2] ... SCSI compliance level of command system // buf[3] ... SCSI compliance level of Inquiry response // buf[4] ... Inquiry additional data - buf[0] = (byte)type; - buf[1] = (byte)(is_removable ? 0x80 : 0x00); - buf[2] = (byte)level; - buf[3] = (byte)(level >= scsi_level::SCSI_2 ? scsi_level::SCSI_2 : scsi_level::SCSI_1_CCS); - buf[4] = (byte)0x1F; + buf[0] = static_cast(type); + buf[1] = is_removable ? 0x80 : 0x00; + buf[2] = static_cast(level); + buf[3] = level >= scsi_level::SCSI_2 ? + static_cast(scsi_level::SCSI_2) : static_cast(scsi_level::SCSI_1_CCS); + buf[4] = 0x1F; // Padded vendor, product, revision memcpy(&buf.data()[8], GetPaddedName().c_str(), 28); @@ -280,7 +298,7 @@ bool PrimaryDevice::CheckReservation(int initiator_id, scsi_command cmd, bool pr return true; } // PREVENT ALLOW MEDIUM REMOVAL is permitted if the prevent bit is 0 - if (cmd == scsi_command::eCmdRemoval && !prevent_removal) { + if (cmd == scsi_command::eCmdPreventAllowMediumRemoval && !prevent_removal) { return true; } diff --git a/cpp/devices/primary_device.h b/cpp/devices/primary_device.h index 053efa1c..1933dd5e 100644 --- a/cpp/devices/primary_device.h +++ b/cpp/devices/primary_device.h @@ -11,24 +11,34 @@ #pragma once +#include "scsi.h" #include "interfaces/scsi_primary_commands.h" #include "controllers/abstract_controller.h" #include "device.h" -#include "dispatcher.h" #include +#include +#include + +using namespace std; +using namespace scsi_defs; class PrimaryDevice: private ScsiPrimaryCommands, public Device { + using operation = function; + public: - PrimaryDevice(PbDeviceType, int); + PrimaryDevice(PbDeviceType type, int lun) : Device(type, lun) {} ~PrimaryDevice() override = default; - virtual bool Dispatch(scsi_command); + virtual bool Init(const unordered_map&); + + virtual void Dispatch(scsi_command); int GetId() const override; void SetController(AbstractController *); + virtual bool WriteByteSequence(vector&, uint32_t); int GetSendDelay() const { return send_delay; } @@ -36,8 +46,6 @@ public: bool CheckReservation(int, scsi_command, bool) const; void DiscardReservation(); - // Override for device specific initializations - virtual bool Init(const unordered_map&) { return false; }; void Reset() override; virtual void FlushCache() { @@ -46,15 +54,17 @@ public: protected: - vector HandleInquiry(scsi_defs::device_type, scsi_level, bool) const; - virtual vector InquiryInternal() const = 0; + void AddCommand(scsi_command, const operation&); + + vector HandleInquiry(scsi_defs::device_type, scsi_level, bool) const; + virtual vector InquiryInternal() const = 0; void CheckReady(); void SetSendDelay(int s) { send_delay = s; } - virtual void SendDiagnostic(); - virtual void ReserveUnit(); - virtual void ReleaseUnit(); + void SendDiagnostic() override; + void ReserveUnit() override; + void ReleaseUnit() override; void EnterStatusPhase() { controller->Status(); } void EnterDataInPhase() { controller->DataIn(); } @@ -74,7 +84,7 @@ private: vector HandleRequestSense() const; - Dispatcher dispatcher; + unordered_map commands; int send_delay = BUS::SEND_NO_DELAY; diff --git a/cpp/devices/scsi_command_util.cpp b/cpp/devices/scsi_command_util.cpp index edfbebee..9737f7ea 100644 --- a/cpp/devices/scsi_command_util.cpp +++ b/cpp/devices/scsi_command_util.cpp @@ -21,8 +21,9 @@ void scsi_command_util::ModeSelect(scsi_command cmd, const vector& cdb, con // PF if (!(cdb[1] & 0x10)) { - // Vendor-specific parameters (SCSI-1) are not supported - throw scsi_exception(sense_key::ILLEGAL_REQUEST, asc::INVALID_FIELD_IN_PARAMETER_LIST); + // Vendor-specific parameters (SCSI-1) are not supported. + // Do not report an error in order to support Apple's HD SC Setup. + return; } // Skip block descriptors @@ -62,7 +63,7 @@ void scsi_command_util::ModeSelect(scsi_command cmd, const vector& cdb, con } // Advance to the next page - int size = buf[offset + 1] + 2; + const int size = buf[offset + 1] + 2; length -= size; offset += size; @@ -77,9 +78,7 @@ void scsi_command_util::EnrichFormatPage(map>& pages, bool cha { if (changeable) { // The sector size is simulated to be changeable, see the MODE SELECT implementation for details - vector& format_page = pages[3]; - format_page[12] = (byte)(sector_size >> 8); - format_page[13] = (byte)sector_size; + SetInt16(pages[3], 12, sector_size); } } @@ -88,15 +87,13 @@ void scsi_command_util::AddAppleVendorModePage(map>& pages, bo // Page code 48 (30h) - Apple Vendor Mode Page // Needed for SCCD for stock Apple driver support // Needed for SCHD for stock Apple HD SC Setup - vector buf(30); + pages[48] = vector(30); // No changeable area if (!changeable) { const char APPLE_DATA[] = "APPLE COMPUTER, INC "; - memcpy(&buf.data()[2], APPLE_DATA, sizeof(APPLE_DATA)); + memcpy(&pages[48].data()[2], APPLE_DATA, sizeof(APPLE_DATA)); } - - pages[48] = buf; } int scsi_command_util::GetInt16(const vector& buf, int offset) diff --git a/cpp/devices/scsi_daynaport.cpp b/cpp/devices/scsi_daynaport.cpp index 590603d0..55ef94d4 100644 --- a/cpp/devices/scsi_daynaport.cpp +++ b/cpp/devices/scsi_daynaport.cpp @@ -24,40 +24,31 @@ // Note: This requires a DaynaPort SCSI Link driver. //--------------------------------------------------------------------------- +#include "log.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "scsi_daynaport.h" using namespace scsi_defs; using namespace scsi_command_util; -SCSIDaynaPort::SCSIDaynaPort(int lun) : PrimaryDevice(SCDP, lun) +bool SCSIDaynaPort::Init(const unordered_map& params) { - dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &SCSIDaynaPort::TestUnitReady); - dispatcher.Add(scsi_command::eCmdRead6, "Read6", &SCSIDaynaPort::Read6); - dispatcher.Add(scsi_command::eCmdWrite6, "Write6", &SCSIDaynaPort::Write6); - dispatcher.Add(scsi_command::eCmdRetrieveStats, "RetrieveStats", &SCSIDaynaPort::RetrieveStatistics); - dispatcher.Add(scsi_command::eCmdSetIfaceMode, "SetIfaceMode", &SCSIDaynaPort::SetInterfaceMode); - dispatcher.Add(scsi_command::eCmdSetMcastAddr, "SetMcastAddr", &SCSIDaynaPort::SetMcastAddr); - dispatcher.Add(scsi_command::eCmdEnableInterface, "EnableInterface", &SCSIDaynaPort::EnableInterface); + PrimaryDevice::Init(params); + + AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); }); + AddCommand(scsi_command::eCmdRead6, [this] { Read6(); }); + AddCommand(scsi_command::eCmdWrite6, [this] { Write6(); }); + AddCommand(scsi_command::eCmdRetrieveStats, [this] { RetrieveStatistics(); }); + AddCommand(scsi_command::eCmdSetIfaceMode, [this] { SetInterfaceMode(); }); + AddCommand(scsi_command::eCmdSetMcastAddr, [this] { SetMcastAddr(); }); + AddCommand(scsi_command::eCmdEnableInterface, [this] { EnableInterface(); }); // The Daynaport needs to have a delay after the size/flags field of the read response. // In the MacOS driver, it looks like the driver is doing two "READ" system calls. SetSendDelay(DAYNAPORT_READ_HEADER_SZ); SupportsParams(true); -} - -bool SCSIDaynaPort::Dispatch(scsi_command cmd) -{ - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); -} - -bool SCSIDaynaPort::Init(const unordered_map& params) -{ - SetParams(params); m_bTapEnable = m_tap.Init(GetParams()); if(!m_bTapEnable){ @@ -78,14 +69,14 @@ bool SCSIDaynaPort::Init(const unordered_map& params) return true; } -vector SCSIDaynaPort::InquiryInternal() const +vector SCSIDaynaPort::InquiryInternal() const { - vector buf = HandleInquiry(device_type::PROCESSOR, scsi_level::SCSI_2, false); + vector buf = HandleInquiry(device_type::PROCESSOR, scsi_level::SCSI_2, false); // The Daynaport driver for the Mac expects 37 bytes: Increase additional length and // add a vendor-specific byte in order to satisfy this driver. - buf[4] = (byte)(to_integer(buf[4]) + 1); - buf.push_back((byte)0); + buf[4]++; + buf.push_back(0); return buf; } diff --git a/cpp/devices/scsi_daynaport.h b/cpp/devices/scsi_daynaport.h index cc3ecbe6..0a2dfa9f 100644 --- a/cpp/devices/scsi_daynaport.h +++ b/cpp/devices/scsi_daynaport.h @@ -45,13 +45,13 @@ class SCSIDaynaPort : public PrimaryDevice, public ByteWriter { public: - explicit SCSIDaynaPort(int); + explicit SCSIDaynaPort(int lun) : PrimaryDevice(SCDP, lun) {} ~SCSIDaynaPort() override = default; bool Init(const unordered_map&) override; // Commands - vector InquiryInternal() const override; + vector InquiryInternal() const override; int Read(const vector&, vector&, uint64_t); bool WriteBytes(const vector&, vector&, uint32_t) override; @@ -65,8 +65,6 @@ public: void SetMcastAddr(); void EnableInterface(); - bool Dispatch(scsi_command) override; - static const int DAYNAPORT_BUFFER_SIZE = 0x1000000; static const int CMD_SCSILINK_STATS = 0x09; @@ -88,10 +86,6 @@ public: private: - using super = PrimaryDevice; - - Dispatcher dispatcher; - enum class read_data_flags_t : uint32_t { e_no_more_data = 0x00000000, e_more_data_available = 0x00000001, diff --git a/cpp/devices/scsi_host_bridge.cpp b/cpp/devices/scsi_host_bridge.cpp index 0b61ecd6..4429fd01 100644 --- a/cpp/devices/scsi_host_bridge.cpp +++ b/cpp/devices/scsi_host_bridge.cpp @@ -16,9 +16,9 @@ // work with the Sharp X68000 operating system. //--------------------------------------------------------------------------- +#include "log.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "scsi_host_bridge.h" #include #include @@ -27,21 +27,18 @@ using namespace std; using namespace scsi_defs; using namespace scsi_command_util; -SCSIBR::SCSIBR(int lun) : PrimaryDevice(SCBR, lun) +bool SCSIBR::Init(const unordered_map& params) { + PrimaryDevice::Init(params); + // Create host file system fs.Reset(); - dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &SCSIBR::TestUnitReady); - dispatcher.Add(scsi_command::eCmdRead6, "GetMessage10", &SCSIBR::GetMessage10); - dispatcher.Add(scsi_command::eCmdWrite6, "SendMessage10", &SCSIBR::SendMessage10); + AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); }); + AddCommand(scsi_command::eCmdGetMessage10, [this] { GetMessage10(); }); + AddCommand(scsi_command::eCmdSendMessage10, [this] { SendMessage10(); }); SupportsParams(true); -} - -bool SCSIBR::Init(const unordered_map& params) -{ - SetParams(params); #ifdef __linux__ // TAP Driver Generation @@ -71,31 +68,25 @@ bool SCSIBR::Init(const unordered_map& params) #endif } -bool SCSIBR::Dispatch(scsi_command cmd) +vector SCSIBR::InquiryInternal() const { - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); -} - -vector SCSIBR::InquiryInternal() const -{ - vector buf = HandleInquiry(device_type::COMMUNICATIONS, scsi_level::SCSI_2, false); + vector buf = HandleInquiry(device_type::COMMUNICATIONS, scsi_level::SCSI_2, false); // The bridge returns more additional bytes than the other devices buf.resize(0x1F + 8 + 5); - buf[4] = byte{0x1F + 8}; + buf[4] = 0x1F + 8; // Optional function valid flag - buf[36] = byte{'0'}; + buf[36] = '0'; // TAP Enable if (m_bTapEnable) { - buf[37] = byte{'1'}; + buf[37] = '1'; } // CFileSys Enable - buf[38] = byte{'1'}; + buf[38] = '1'; return buf; } diff --git a/cpp/devices/scsi_host_bridge.h b/cpp/devices/scsi_host_bridge.h index 0eabd531..d2a69612 100644 --- a/cpp/devices/scsi_host_bridge.h +++ b/cpp/devices/scsi_host_bridge.h @@ -32,14 +32,13 @@ class SCSIBR : public PrimaryDevice, public ByteWriter public: - explicit SCSIBR(int); + explicit SCSIBR(int lun) : PrimaryDevice(SCBR, lun) {} ~SCSIBR() override = default; bool Init(const unordered_map&) override; - bool Dispatch(scsi_command) override; // Commands - vector InquiryInternal() const override; + vector InquiryInternal() const override; int GetMessage10(const vector&, vector&); bool WriteBytes(const vector&, vector&, uint32_t) override; void TestUnitReady() override; @@ -48,10 +47,6 @@ public: private: - using super = PrimaryDevice; - - Dispatcher dispatcher; - int GetMacAddr(vector&) const; // Get MAC address void SetMacAddr(const vector&); // Set MAC address void ReceivePacket(); // Receive a packet diff --git a/cpp/devices/scsi_printer.cpp b/cpp/devices/scsi_printer.cpp index 1e46e62a..fa242063 100644 --- a/cpp/devices/scsi_printer.cpp +++ b/cpp/devices/scsi_printer.cpp @@ -29,11 +29,11 @@ // With STOP PRINT printing can be cancelled before SYNCHRONIZE BUFFER was sent. // -#include +#include "log.h" #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "scsi_printer.h" +#include #include using namespace std; @@ -41,18 +41,25 @@ using namespace filesystem; using namespace scsi_defs; using namespace scsi_command_util; -SCSIPrinter::SCSIPrinter(int lun) : PrimaryDevice(SCLP, lun) +bool SCSIPrinter::Init(const unordered_map& params) { - dispatcher.Add(scsi_command::eCmdTestUnitReady, "TestUnitReady", &SCSIPrinter::TestUnitReady); - dispatcher.Add(scsi_command::eCmdPrint, "Print", &SCSIPrinter::Print); - dispatcher.Add(scsi_command::eCmdSynchronizeBuffer, "SynchronizeBuffer", &SCSIPrinter::SynchronizeBuffer); + PrimaryDevice::Init(params); + + AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); }); + AddCommand(scsi_command::eCmdPrint, [this] { Print(); }); + AddCommand(scsi_command::eCmdSynchronizeBuffer, [this] { SynchronizeBuffer(); }); // STOP PRINT is identical with TEST UNIT READY, it just returns the status - dispatcher.Add(scsi_command::eCmdStopPrint, "StopPrint", &SCSIPrinter::TestUnitReady); + AddCommand(scsi_command::eCmdStopPrint, [this] { TestUnitReady(); }); // Required also in this class in order to fulfill the ScsiPrinterCommands interface contract - dispatcher.Add(scsi_command::eCmdReserve6, "ReserveUnit", &SCSIPrinter::ReserveUnit); - dispatcher.Add(scsi_command::eCmdRelease6, "ReleaseUnit", &SCSIPrinter::ReleaseUnit); - dispatcher.Add(scsi_command::eCmdSendDiag, "SendDiagnostic", &SCSIPrinter::SendDiagnostic); + AddCommand(scsi_command::eCmdReserve6, [this] { ReserveUnit(); }); + AddCommand(scsi_command::eCmdRelease6, [this] { ReleaseUnit(); }); + AddCommand(scsi_command::eCmdSendDiagnostic, [this] { SendDiagnostic(); }); + + if (GetParam("cmd").find("%f") == string::npos) { + LOGERROR("Missing filename specifier %%f") + return false; + } error_code error; file_template = temp_directory_path(error); //NOSONAR Publicly writable directory is fine here @@ -60,38 +67,17 @@ SCSIPrinter::SCSIPrinter(int lun) : PrimaryDevice(SCLP, lun) SupportsParams(true); SetReady(true); -} - -SCSIPrinter::~SCSIPrinter() -{ - Cleanup(); -} - -bool SCSIPrinter::Init(const unordered_map& params) -{ - SetParams(params); - - if (GetParam("cmd").find("%f") == string::npos) { - LOGERROR("Missing filename specifier %s", "%f") - return false; - } return true; } -bool SCSIPrinter::Dispatch(scsi_command cmd) -{ - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); -} - void SCSIPrinter::TestUnitReady() { // The printer is always ready EnterStatusPhase(); } -vector SCSIPrinter::InquiryInternal() const +vector SCSIPrinter::InquiryInternal() const { return HandleInquiry(device_type::PRINTER, scsi_level::SCSI_2, false); } diff --git a/cpp/devices/scsi_printer.h b/cpp/devices/scsi_printer.h index 6c6afd82..ca9995e7 100644 --- a/cpp/devices/scsi_printer.h +++ b/cpp/devices/scsi_printer.h @@ -18,7 +18,7 @@ using namespace std; -class SCSIPrinter : public PrimaryDevice, ScsiPrinterCommands //NOSONAR Custom destructor cannot be removed +class SCSIPrinter : public PrimaryDevice, private ScsiPrinterCommands { static const int NOT_RESERVED = -2; @@ -26,15 +26,17 @@ class SCSIPrinter : public PrimaryDevice, ScsiPrinterCommands //NOSONAR Custom d public: - explicit SCSIPrinter(int); - ~SCSIPrinter() override; - - bool Dispatch(scsi_command) override; + explicit SCSIPrinter(int lun) : PrimaryDevice(SCLP, lun) {} + ~SCSIPrinter() override = default; bool Init(const unordered_map&) override; - void Cleanup(); - vector InquiryInternal() const override; + vector InquiryInternal() const override; + + bool WriteByteSequence(vector&, uint32_t) override; + +private: + void TestUnitReady() override; void ReserveUnit() override { PrimaryDevice::ReserveUnit(); } void ReleaseUnit() override { PrimaryDevice::ReleaseUnit(); } @@ -42,13 +44,7 @@ public: void Print() override; void SynchronizeBuffer(); - bool WriteByteSequence(vector&, uint32_t) override; - -private: - - using super = PrimaryDevice; - - Dispatcher dispatcher; + void Cleanup(); string file_template; diff --git a/cpp/devices/scsicd.cpp b/cpp/devices/scsicd.cpp index 8403a94c..735f5f2b 100644 --- a/cpp/devices/scsicd.cpp +++ b/cpp/devices/scsicd.cpp @@ -16,7 +16,6 @@ #include "rascsi_exceptions.h" #include "scsi_command_util.h" -#include "dispatcher.h" #include "scsicd.h" #include #include @@ -27,18 +26,19 @@ using namespace scsi_command_util; SCSICD::SCSICD(int lun, const unordered_set& sector_sizes) : Disk(SCCD, lun) { SetSectorSizes(sector_sizes); +} - dispatcher.Add(scsi_command::eCmdReadToc, "ReadToc", &SCSICD::ReadToc); +bool SCSICD::Init(const unordered_map& params) +{ + Disk::Init(params); + + AddCommand(scsi_command::eCmdReadToc, [this] { ReadToc(); }); SetReadOnly(true); SetRemovable(true); SetLockable(true); -} -bool SCSICD::Dispatch(scsi_command cmd) -{ - // The superclass class handles the less specific commands - return dispatcher.Dispatch(this, cmd) ? true : super::Dispatch(cmd); + return true; } void SCSICD::Open() @@ -72,7 +72,7 @@ void SCSICD::Open() } } - super::ValidateFile(); + Disk::ValidateFile(); SetUpCache(0, rawfile); @@ -167,14 +167,14 @@ void SCSICD::ReadToc() EnterDataInPhase(); } -vector SCSICD::InquiryInternal() const +vector SCSICD::InquiryInternal() const { return HandleInquiry(device_type::CD_ROM, scsi_level::SCSI_2, true); } void SCSICD::SetUpModePages(map>& pages, int page, bool changeable) const { - super::SetUpModePages(pages, page, changeable); + Disk::SetUpModePages(pages, page, changeable); // Page code 13 if (page == 0x0d || page == 0x3f) { @@ -251,7 +251,7 @@ int SCSICD::Read(const vector& cdb, vector& buf, uint64_t block) // Base class assert(dataindex >= 0); - return super::Read(cdb, buf, block); + return Disk::Read(cdb, buf, block); } int SCSICD::ReadTocInternal(const vector& cdb, vector& buf) diff --git a/cpp/devices/scsicd.h b/cpp/devices/scsicd.h index 6f3fa7bc..ab29e690 100644 --- a/cpp/devices/scsicd.h +++ b/cpp/devices/scsicd.h @@ -25,12 +25,11 @@ public: SCSICD(int, const unordered_set&); ~SCSICD() override = default; - bool Dispatch(scsi_command) override; + bool Init(const unordered_map&) override; void Open() override; - // Commands - vector InquiryInternal() const override; + vector InquiryInternal() const override; int Read(const vector&, vector&, uint64_t) override; protected: @@ -40,10 +39,6 @@ protected: private: - using super = Disk; - - Dispatcher dispatcher; - int ReadTocInternal(const vector&, vector&); void AddCDROMPage(map>&, bool) const; diff --git a/cpp/devices/scsihd.cpp b/cpp/devices/scsihd.cpp index 3cc42b24..c76dfee6 100644 --- a/cpp/devices/scsihd.cpp +++ b/cpp/devices/scsihd.cpp @@ -56,7 +56,7 @@ string SCSIHD::GetProductData() const void SCSIHD::FinalizeSetup(off_t image_offset) { - super::ValidateFile(); + Disk::ValidateFile(); // For non-removable media drives set the default product name based on the drive capacity if (!IsRemovable()) { @@ -79,7 +79,7 @@ void SCSIHD::Open() FinalizeSetup(0); } -vector SCSIHD::InquiryInternal() const +vector SCSIHD::InquiryInternal() const { return HandleInquiry(device_type::DIRECT_ACCESS, scsi_level, IsRemovable()); } diff --git a/cpp/devices/scsihd.h b/cpp/devices/scsihd.h index 2253346c..c2ccd6e7 100644 --- a/cpp/devices/scsihd.h +++ b/cpp/devices/scsihd.h @@ -35,7 +35,7 @@ public: void Open() override; // Commands - vector InquiryInternal() const override; + vector InquiryInternal() const override; void ModeSelect(scsi_defs::scsi_command, const vector&, const vector&, int) const override; void AddFormatPage(map>&, bool) const override; @@ -45,7 +45,5 @@ private: string GetProductData() const; - using super = Disk; - scsi_defs::scsi_level scsi_level; }; diff --git a/cpp/devices/scsihd_nec.cpp b/cpp/devices/scsihd_nec.cpp index 6c8bdd17..66fadb17 100644 --- a/cpp/devices/scsihd_nec.cpp +++ b/cpp/devices/scsihd_nec.cpp @@ -112,7 +112,7 @@ pair SCSIHD_NEC::SetParameters(const array& data, int size) return make_pair(image_size, sector_size); } -vector SCSIHD_NEC::InquiryInternal() const +vector SCSIHD_NEC::InquiryInternal() const { return HandleInquiry(device_type::DIRECT_ACCESS, scsi_level::SCSI_1_CCS, false); } diff --git a/cpp/devices/scsihd_nec.h b/cpp/devices/scsihd_nec.h index 1c29b7a6..423ecdcb 100644 --- a/cpp/devices/scsihd_nec.h +++ b/cpp/devices/scsihd_nec.h @@ -40,7 +40,7 @@ public: protected: - vector InquiryInternal() const override; + vector InquiryInternal() const override; void AddFormatPage(map>&, bool) const override; void AddDrivePage(map>&, bool) const override; diff --git a/cpp/devices/scsimo.cpp b/cpp/devices/scsimo.cpp index 448cf6e2..c660d631 100644 --- a/cpp/devices/scsimo.cpp +++ b/cpp/devices/scsimo.cpp @@ -49,7 +49,7 @@ void SCSIMO::Open() SetBlockCount(size >> GetSectorSizeShiftCount()); } - super::ValidateFile(); + Disk::ValidateFile(); SetUpCache(0); @@ -59,7 +59,7 @@ void SCSIMO::Open() } } -vector SCSIMO::InquiryInternal() const +vector SCSIMO::InquiryInternal() const { return HandleInquiry(device_type::OPTICAL_MEMORY, scsi_level::SCSI_2, true); } diff --git a/cpp/devices/scsimo.h b/cpp/devices/scsimo.h index c763823d..d6b24546 100644 --- a/cpp/devices/scsimo.h +++ b/cpp/devices/scsimo.h @@ -29,7 +29,7 @@ public: void Open() override; - vector InquiryInternal() const override; + vector InquiryInternal() const override; void ModeSelect(scsi_defs::scsi_command, const vector&, const vector&, int) const override; protected: @@ -40,8 +40,6 @@ protected: private: - using super = Disk; - void AddOptionPage(map>&, bool) const; bool SetGeometryForCapacity(uint64_t); diff --git a/cpp/devices/storage_device.cpp b/cpp/devices/storage_device.cpp index db733187..0714bd9c 100644 --- a/cpp/devices/storage_device.cpp +++ b/cpp/devices/storage_device.cpp @@ -9,6 +9,7 @@ #include "rascsi_exceptions.h" #include "storage_device.h" +#include #include #include @@ -49,13 +50,6 @@ void StorageDevice::ValidateFile() SetReady(true); } -void StorageDevice::MediumChanged() -{ - assert(IsRemovable()); - - medium_changed = true; -} - void StorageDevice::ReserveFile(const string& file, int id, int lun) const { assert(!file.empty()); @@ -71,7 +65,7 @@ void StorageDevice::UnreserveFile() filename = ""; } -pair StorageDevice::GetIdsForReservedFile(const string& file) +id_set StorageDevice::GetIdsForReservedFile(const string& file) { if (const auto& it = reserved_files.find(file); it != reserved_files.end()) { return make_pair(it->second.first, it->second.second); diff --git a/cpp/devices/storage_device.h b/cpp/devices/storage_device.h index 81b0d571..83f40fbd 100644 --- a/cpp/devices/storage_device.h +++ b/cpp/devices/storage_device.h @@ -31,8 +31,6 @@ public: string GetFilename() const { return filename; } void SetFilename(string_view f) { filename = f; } - void MediumChanged(); - uint64_t GetBlockCount() const { return blocks; } void ReserveFile(const string&, int, int) const; @@ -42,16 +40,17 @@ public: static bool FileExists(const string&); bool IsReadOnlyFile() const; + void SetMediumChanged(bool b) { medium_changed = b; } + static unordered_map GetReservedFiles() { return reserved_files; } static void SetReservedFiles(const unordered_map& r) { reserved_files = r; } - static pair GetIdsForReservedFile(const string&); + static id_set GetIdsForReservedFile(const string&); protected: void ValidateFile(); bool IsMediumChanged() const { return medium_changed; } - void SetMediumChanged(bool b) { medium_changed = b; } void SetBlockCount(uint64_t b) { blocks = b; } diff --git a/cpp/hal/gpiobus.cpp b/cpp/hal/gpiobus.cpp index 850a50e9..e5250851 100644 --- a/cpp/hal/gpiobus.cpp +++ b/cpp/hal/gpiobus.cpp @@ -505,7 +505,7 @@ int GPIOBUS::CommandHandShake(uint8_t *buf) } } - int command_byte_count = GetCommandByteCount(*buf); + const int command_byte_count = GetCommandByteCount(*buf); // Increment buffer pointer buf++; @@ -966,23 +966,3 @@ BUS::phase_t GPIOBUS::GetPhaseRaw(uint32_t raw_data) mci |= GetPinRaw(raw_data, PIN_IO) ? 0x01 : 0x00; return GetPhase(mci); } - -//--------------------------------------------------------------------------- -// -// Get the number of bytes for a command -// -//--------------------------------------------------------------------------- -int GPIOBUS::GetCommandByteCount(uint8_t opcode) -{ - GPIO_FUNCTION_TRACE - - if (opcode == 0x88 || opcode == 0x8A || opcode == 0x8F || opcode == 0x91 || opcode == 0x9E || opcode == 0x9F) { - return 16; - } else if (opcode == 0xA0) { - return 12; - } else if (opcode >= 0x20 && opcode <= 0x7D) { - return 10; - } else { - return 6; - } -} diff --git a/cpp/hal/gpiobus.h b/cpp/hal/gpiobus.h index 103536ef..a5198a43 100644 --- a/cpp/hal/gpiobus.h +++ b/cpp/hal/gpiobus.h @@ -342,8 +342,6 @@ class GPIOBUS : public BUS static BUS::phase_t GetPhaseRaw(uint32_t raw_data); // Get the phase based on raw data - static int GetCommandByteCount(uint8_t opcode); - #ifdef USE_SEL_EVENT_ENABLE // SEL signal interrupt bool PollSelectEvent(); diff --git a/cpp/rascsi/rascsi_executor.cpp b/cpp/rascsi/rascsi_executor.cpp index 04f83874..4c7095db 100644 --- a/cpp/rascsi/rascsi_executor.cpp +++ b/cpp/rascsi/rascsi_executor.cpp @@ -318,7 +318,7 @@ bool RascsiExecutor::Attach(const CommandContext& context, const PbDeviceDefinit params.erase("file"); } - if (device->SupportsParams() && !device->Init(params)) { + if (!device->Init(params)) { return context.ReturnLocalizedError(LocalizationKey::ERROR_INITIALIZATION, PbDeviceType_Name(device->GetType()), to_string(id), to_string(lun)); } @@ -389,7 +389,7 @@ bool RascsiExecutor::Insert(const CommandContext& context, const PbDeviceDefinit storage_device->SetProtected(pb_device.protected_()); storage_device->ReserveFile(full_path, storage_device->GetId(), storage_device->GetLun()); - storage_device->MediumChanged(); + storage_device->SetMediumChanged(true); return true; } @@ -522,7 +522,7 @@ string RascsiExecutor::SetReservedIds(string_view ids) if (!reserved_ids.empty()) { string s; bool isFirst = true; - for (auto const& reserved_id : reserved) { + for (const auto& reserved_id : reserved) { if (!isFirst) { s += ", "; } diff --git a/cpp/rascsi/rascsi_response.cpp b/cpp/rascsi/rascsi_response.cpp index 58042cbe..8c1ce5bb 100644 --- a/cpp/rascsi/rascsi_response.cpp +++ b/cpp/rascsi/rascsi_response.cpp @@ -7,6 +7,7 @@ // //--------------------------------------------------------------------------- +#include "log.h" #include "controllers/controller_manager.h" #include "devices/disk.h" #include "devices/device_factory.h" diff --git a/cpp/scsi.h b/cpp/scsi.h index 749b9956..37d29f8c 100644 --- a/cpp/scsi.h +++ b/cpp/scsi.h @@ -9,6 +9,10 @@ #pragma once +#include + +using namespace std; + namespace scsi_defs { enum class scsi_level : int { SCSI_1_CCS = 1, @@ -30,17 +34,20 @@ namespace scsi_defs { COMMUNICATIONS = 9 }; - // TODO Use a mapping of enum to structure with command byte count and enum name enum class scsi_command : int { eCmdTestUnitReady = 0x00, eCmdRezero = 0x01, eCmdRequestSense = 0x03, - eCmdFormat = 0x04, - eCmdReassign = 0x07, + eCmdFormatUnit = 0x04, + eCmdReassignBlocks = 0x07, eCmdRead6 = 0x08, + // Bridge specific command + eCmdGetMessage10 = 0x08, // DaynaPort specific command eCmdRetrieveStats = 0x09, eCmdWrite6 = 0x0A, + // Bridge specific ommand + eCmdSendMessage10 = 0x0A, eCmdPrint = 0x0A, eCmdSeek6 = 0x0B, // DaynaPort specific command @@ -57,10 +64,8 @@ namespace scsi_defs { eCmdModeSense6 = 0x1A, eCmdStartStop = 0x1B, eCmdStopPrint = 0x1B, - eCmdSendDiag = 0x1D, - eCmdRemoval = 0x1E, - // ICD specific command, evaluated by the controller - eCmdIcd = 0x1F, + eCmdSendDiagnostic = 0x1D, + eCmdPreventAllowMediumRemoval = 0x1E, eCmdReadCapacity10 = 0x25, eCmdRead10 = 0x28, eCmdWrite10 = 0x2A, @@ -114,4 +119,49 @@ namespace scsi_defs { MEDIUM_NOT_PRESENT = 0x3a, LOAD_OR_EJECT_FAILED = 0x53 }; + + static const unordered_map command_names = { + { scsi_command::eCmdTestUnitReady, "TestUnitReady" }, + { scsi_command::eCmdRezero, "Rezero" }, + { scsi_command::eCmdRequestSense, "RequestSense" }, + { scsi_command::eCmdFormatUnit, "FormatUnit" }, + { scsi_command::eCmdReassignBlocks, "ReassignBlocks" }, + { scsi_command::eCmdRead6, "Read6/GetMessage10" }, + { scsi_command::eCmdRetrieveStats, "RetrieveStats" }, + { scsi_command::eCmdWrite6, "Write6/Print/SendMessage10" }, + { scsi_command::eCmdSeek6, "Seek6" }, + { scsi_command::eCmdSetIfaceMode, "SetIfaceMode" }, + { scsi_command::eCmdSetMcastAddr, "SetMcastAddr" }, + { scsi_command::eCmdEnableInterface, "EnableInterface" }, + { scsi_command::eCmdSynchronizeBuffer, "SynchronizeBuffer" }, + { scsi_command::eCmdInquiry, "Inquiry" }, + { scsi_command::eCmdModeSelect6, "ModeSelect6" }, + { scsi_command::eCmdReserve6, "Reserve6" }, + { scsi_command::eCmdRelease6, "Release6" }, + { scsi_command::eCmdModeSense6, "ModeSense6" }, + { scsi_command::eCmdStartStop, "StartStop" }, + { scsi_command::eCmdStopPrint, "StopPrint" }, + { scsi_command::eCmdSendDiagnostic, "SendDiagnostic" }, + { scsi_command::eCmdPreventAllowMediumRemoval, "PreventAllowMediumRemoval" }, + { scsi_command::eCmdReadCapacity10, "ReadCapacity10" }, + { scsi_command::eCmdRead10, "Read10" }, + { scsi_command::eCmdWrite10, "Write10" }, + { scsi_command::eCmdSeek10, "Seek10" }, + { scsi_command::eCmdVerify10, "Verify10" }, + { scsi_command::eCmdSynchronizeCache10, "SynchronizeCache10" }, + { scsi_command::eCmdReadDefectData10, "ReadDefectData10" }, + { scsi_command::eCmdReadLong10, "ReadLong10" }, + { scsi_command::eCmdWriteLong10, "WriteLong10" }, + { scsi_command::eCmdReadToc, "ReadToc" }, + { scsi_command::eCmdGetEventStatusNotification, "GetEventStatusNotification" }, + { scsi_command::eCmdModeSelect10, "ModeSelect10" }, + { scsi_command::eCmdModeSense10, "ModeSense10" }, + { scsi_command::eCmdRead16, "Read16" }, + { scsi_command::eCmdWrite16, "Write16" }, + { scsi_command::eCmdVerify16, "Verify16" }, + { scsi_command::eCmdSynchronizeCache16, "SynchronizeCache16" }, + { scsi_command::eCmdReadCapacity16_ReadLong16, "ReadCapacity16/ReadLong16" }, + { scsi_command::eCmdWriteLong16, "WriteLong16" }, + { scsi_command::eCmdReportLuns, "ReportLuns" } + }; }; diff --git a/cpp/test/abstract_controller_test.cpp b/cpp/test/abstract_controller_test.cpp index c6c98482..6ef6b0aa 100644 --- a/cpp/test/abstract_controller_test.cpp +++ b/cpp/test/abstract_controller_test.cpp @@ -48,6 +48,24 @@ TEST(AbstractControllerTest, Reset) EXPECT_EQ(0, controller.GetLength()); } +TEST(AbstractControllerTest, Next) +{ + MockAbstractController controller(make_shared(), 0); + + controller.SetNext(0x1234); + EXPECT_EQ(0x1234, controller.GetNext()); + controller.IncrementNext(); + EXPECT_EQ(0x1235, controller.GetNext()); +} + +TEST(AbstractControllerTest, Message) +{ + MockAbstractController controller(make_shared(), 0); + + controller.SetMessage(0x12); + EXPECT_EQ(0x12, controller.GetMessage()); +} + TEST(AbstractControllerTest, ByteTransfer) { MockAbstractController controller(make_shared(), 0); @@ -58,6 +76,16 @@ TEST(AbstractControllerTest, ByteTransfer) EXPECT_TRUE(controller.IsByteTransfer()); } +TEST(AbstractControllerTest, BytesToTransfer) +{ + MockAbstractController controller(make_shared(), 0); + + controller.SetBytesToTransfer(0x1234); + EXPECT_EQ(0x1234, controller.GetBytesToTransfer()); + controller.SetByteTransfer(false); + EXPECT_EQ(0, controller.GetBytesToTransfer()); +} + TEST(AbstractControllerTest, GetMaxLuns) { MockAbstractController controller(make_shared(), 0); @@ -78,35 +106,35 @@ TEST(AbstractControllerTest, ProcessPhase) MockAbstractController controller(make_shared(), 0); controller.SetPhase(BUS::phase_t::selection); - EXPECT_CALL(controller, Selection()); + EXPECT_CALL(controller, Selection); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::busfree); - EXPECT_CALL(controller, BusFree()); + EXPECT_CALL(controller, BusFree); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::datain); - EXPECT_CALL(controller, DataIn()); + EXPECT_CALL(controller, DataIn); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::dataout); - EXPECT_CALL(controller, DataOut()); + EXPECT_CALL(controller, DataOut); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::command); - EXPECT_CALL(controller, Command()); + EXPECT_CALL(controller, Command); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::status); - EXPECT_CALL(controller, Status()); + EXPECT_CALL(controller, Status); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::msgin); - EXPECT_CALL(controller, MsgIn()); + EXPECT_CALL(controller, MsgIn); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::msgout); - EXPECT_CALL(controller, MsgOut()); + EXPECT_CALL(controller, MsgOut); controller.ProcessPhase(); controller.SetPhase(BUS::phase_t::reselection); @@ -162,7 +190,7 @@ TEST(AbstractControllerTest, GetOpcode) { MockAbstractController controller(make_shared(), 0); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[0] = static_cast(scsi_command::eCmdInquiry); EXPECT_EQ(scsi_command::eCmdInquiry, controller.GetOpcode()); @@ -174,7 +202,7 @@ TEST(AbstractControllerTest, GetLun) MockAbstractController controller(make_shared(), 0); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[1] = LUN << 5; EXPECT_EQ(LUN, controller.GetLun()); diff --git a/cpp/test/bus_test.cpp b/cpp/test/bus_test.cpp index 02df56e7..8d5665b9 100644 --- a/cpp/test/bus_test.cpp +++ b/cpp/test/bus_test.cpp @@ -10,6 +10,37 @@ #include "mocks.h" #include "bus.h" +TEST(BusTest, GetCommandByteCount) +{ + unordered_set opcodes; + + EXPECT_EQ(16, BUS::GetCommandByteCount(0x88)); + opcodes.insert(0x88); + EXPECT_EQ(16, BUS::GetCommandByteCount(0x8a)); + opcodes.insert(0x8a); + EXPECT_EQ(16, BUS::GetCommandByteCount(0x8f)); + opcodes.insert(0x8f); + EXPECT_EQ(16, BUS::GetCommandByteCount(0x91)); + opcodes.insert(0x91); + EXPECT_EQ(16, BUS::GetCommandByteCount(0x9e)); + opcodes.insert(0x9e); + EXPECT_EQ(16, BUS::GetCommandByteCount(0x9f)); + opcodes.insert(0x9f); + EXPECT_EQ(12, BUS::GetCommandByteCount(0xa0)); + opcodes.insert(0xa0); + + for (int i = 0x20; i <= 0x7d; i++) { + EXPECT_EQ(10, BUS::GetCommandByteCount(i)); + opcodes.insert(i); + } + + for (int i = 0; i < 256; i++) { + if (opcodes.find(i) == opcodes.end()) { + EXPECT_EQ(6, BUS::GetCommandByteCount(i)); + } + } +} + TEST(BusTest, GetPhase) { EXPECT_EQ(BUS::phase_t::dataout, BUS::GetPhase(0b000)); diff --git a/cpp/test/controller_manager_test.cpp b/cpp/test/controller_manager_test.cpp index fd0fa564..caecde4b 100644 --- a/cpp/test/controller_manager_test.cpp +++ b/cpp/test/controller_manager_test.cpp @@ -17,8 +17,8 @@ TEST(ControllerManagerTest, LifeCycle) const int LUN1 = 0; const int LUN2 = 3; - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; auto device = device_factory.CreateDevice(controller_manager, SCHS, -1, ""); @@ -52,8 +52,8 @@ TEST(ControllerManagerTest, AttachToScsiController) const int LUN1 = 3; const int LUN2 = 0; - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; auto device1 = device_factory.CreateDevice(controller_manager, SCHS, LUN1, ""); @@ -69,8 +69,8 @@ TEST(ControllerManagerTest, ResetAllControllers) { const int ID = 2; - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; auto device = device_factory.CreateDevice(controller_manager, SCHS, 0, ""); diff --git a/cpp/test/device_factory_test.cpp b/cpp/test/device_factory_test.cpp index c976d2fc..63786caf 100644 --- a/cpp/test/device_factory_test.cpp +++ b/cpp/test/device_factory_test.cpp @@ -122,9 +122,9 @@ TEST(DeviceFactoryTest, GetDefaultParams) TEST(DeviceFactoryTest, UnknownDeviceType) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device1 = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "test"); EXPECT_EQ(nullptr, device1); @@ -138,11 +138,14 @@ TEST(DeviceFactoryTest, UnknownDeviceType) TEST(DeviceFactoryTest, SCHD_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "test.hda"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCHD, device->GetType()); EXPECT_TRUE(device->SupportsFile()); @@ -177,11 +180,14 @@ TEST(DeviceFactoryTest, SCHD_Device_Defaults) void TestRemovableDrive(PbDeviceType type, const string& filename, const string& product) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, filename); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(type, device->GetType()); EXPECT_TRUE(device->SupportsFile()); @@ -215,11 +221,14 @@ TEST(DeviceFactoryTest, SCMO_Device_Defaults) TEST(DeviceFactoryTest, SCCD_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "test.iso"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCCD, device->GetType()); EXPECT_TRUE(device->SupportsFile()); @@ -242,11 +251,14 @@ TEST(DeviceFactoryTest, SCCD_Device_Defaults) TEST(DeviceFactoryTest, SCBR_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "bridge"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCBR, device->GetType()); EXPECT_FALSE(device->SupportsFile()); @@ -269,11 +281,14 @@ TEST(DeviceFactoryTest, SCBR_Device_Defaults) TEST(DeviceFactoryTest, SCDP_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "daynaport"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCDP, device->GetType()); EXPECT_FALSE(device->SupportsFile()); @@ -295,11 +310,14 @@ TEST(DeviceFactoryTest, SCDP_Device_Defaults) TEST(DeviceFactoryTest, SCHS_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "services"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCHS, device->GetType()); EXPECT_FALSE(device->SupportsFile()); @@ -322,11 +340,14 @@ TEST(DeviceFactoryTest, SCHS_Device_Defaults) TEST(DeviceFactoryTest, SCLP_Device_Defaults) { - auto bus_ptr = make_shared(); + auto bus = make_shared(); DeviceFactory device_factory; - ControllerManager controller_manager(bus_ptr); + ControllerManager controller_manager(bus); auto device = device_factory.CreateDevice(controller_manager, UNDEFINED, 0, "printer"); + const unordered_map params; + device->Init(params); + EXPECT_NE(nullptr, device); EXPECT_EQ(SCLP, device->GetType()); EXPECT_FALSE(device->SupportsFile()); diff --git a/cpp/test/disk_test.cpp b/cpp/test/disk_test.cpp index 5338e436..c1df0b0f 100644 --- a/cpp/test/disk_test.cpp +++ b/cpp/test/disk_test.cpp @@ -19,18 +19,31 @@ using namespace scsi_command_util; TEST(DiskTest, Dispatch) { MockAbstractController controller(make_shared(), 0); - const unordered_set sector_sizes; auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - EXPECT_FALSE(disk->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; + disk->SetRemovable(true); + disk->SetMediumChanged(false); + disk->SetReady(true); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdTestUnitReady); + EXPECT_EQ(status::GOOD, controller.GetStatus()); + + disk->SetMediumChanged(true); + EXPECT_CALL(controller, Error); + disk->Dispatch(scsi_command::eCmdTestUnitReady); + EXPECT_FALSE(disk->IsMediumChanged()); } TEST(DiskTest, Rezero) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -41,8 +54,8 @@ TEST(DiskTest, Rezero) disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRezero)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdRezero); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -50,25 +63,27 @@ TEST(DiskTest, FormatUnit) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); - EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormat); }, Throws(AllOf( + EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormatUnit); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::NOT_READY), Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT)))) << "FORMAT UNIT must fail because drive is not ready"; disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdFormat)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdFormatUnit); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[1] = 0x10; cmd[4] = 1; - EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormat); }, Throws(AllOf( + EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdFormatUnit); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))); } @@ -77,18 +92,20 @@ TEST(DiskTest, ReassignBlocks) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReassign); }, Throws(AllOf( + EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReassignBlocks); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::NOT_READY), Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT)))) << "REASSIGN must fail because drive is not ready"; disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReassign)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdReassignBlocks); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -96,10 +113,12 @@ TEST(DiskTest, Seek6) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek6); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), @@ -116,8 +135,8 @@ TEST(DiskTest, Seek6) disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSeek6)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdSeek6); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -125,10 +144,12 @@ TEST(DiskTest, Seek10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdSeek10); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), @@ -145,8 +166,8 @@ TEST(DiskTest, Seek10) disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSeek10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdSeek10); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -154,6 +175,8 @@ TEST(DiskTest, ReadCapacity10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -169,15 +192,15 @@ TEST(DiskTest, ReadCapacity10) << "READ CAPACITY(10) must fail because the medium has no capacity"; disk->SetBlockCount(0x12345678); - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10)); + EXPECT_CALL(controller, DataIn); + disk->Dispatch(scsi_command::eCmdReadCapacity10); auto& buf = controller.GetBuffer(); EXPECT_EQ(0x1234, GetInt16(buf, 0)); EXPECT_EQ(0x5677, GetInt16(buf, 2)); disk->SetBlockCount(0x1234567887654321); - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity10)); + EXPECT_CALL(controller, DataIn); + disk->Dispatch(scsi_command::eCmdReadCapacity10); buf = controller.GetBuffer(); EXPECT_EQ(0xffff, GetInt16(buf, 0)); EXPECT_EQ(0xffff, GetInt16(buf, 2)); @@ -187,10 +210,12 @@ TEST(DiskTest, ReadCapacity16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[1] = 0x00; EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); }, Throws(AllOf( @@ -213,8 +238,8 @@ TEST(DiskTest, ReadCapacity16) disk->SetBlockCount(0x1234567887654321); disk->SetSectorSizeInBytes(1024); - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16)); + EXPECT_CALL(controller, DataIn); + disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); const auto& buf = controller.GetBuffer(); EXPECT_EQ(0x1234, GetInt16(buf, 0)); EXPECT_EQ(0x5678, GetInt16(buf, 2)); @@ -228,6 +253,8 @@ TEST(DiskTest, Read6) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -243,6 +270,8 @@ TEST(DiskTest, Read10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -252,8 +281,8 @@ TEST(DiskTest, Read10) << "READ(10) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRead10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdRead10); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -263,6 +292,8 @@ TEST(DiskTest, Read16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -272,8 +303,8 @@ TEST(DiskTest, Read16) << "READ(16) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRead16)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdRead16); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -283,13 +314,23 @@ TEST(DiskTest, Write6) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWrite6); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::LBA_OUT_OF_RANGE)))) - << "WRIte(6) must fail for a medium with 0 blocks"; + << "WRITE(6) must fail for a medium with 0 blocks"; + + disk->SetBlockCount(1); + disk->SetReady(true); + disk->SetProtectable(true); + disk->SetProtected(true); + EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWrite6); }, Throws(AllOf( + Property(&scsi_exception::get_sense_key, sense_key::DATA_PROTECT), + Property(&scsi_exception::get_asc, asc::WRITE_PROTECTED)))); // Further testing requires filesystem access } @@ -298,6 +339,8 @@ TEST(DiskTest, Write10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -307,8 +350,8 @@ TEST(DiskTest, Write10) << "WRITE(10) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWrite10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdWrite10); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -318,6 +361,8 @@ TEST(DiskTest, Write16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -327,8 +372,8 @@ TEST(DiskTest, Write16) << "WRITE(16) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWrite16)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdWrite16); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -338,6 +383,8 @@ TEST(DiskTest, Verify10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -347,8 +394,8 @@ TEST(DiskTest, Verify10) << "VERIFY(10) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdVerify10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdVerify10); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -358,6 +405,8 @@ TEST(DiskTest, Verify16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); @@ -367,8 +416,8 @@ TEST(DiskTest, Verify16) << "VERIFY(16) must fail for a medium with 0 blocks"; disk->SetBlockCount(1); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdVerify16)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdVerify16); EXPECT_EQ(status::GOOD, controller.GetStatus()); // Further testing requires filesystem access @@ -378,13 +427,15 @@ TEST(DiskTest, ReadLong10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadLong10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdReadLong10); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[2] = 1; @@ -405,10 +456,12 @@ TEST(DiskTest, ReadLong16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // READ LONG(16), not READ CAPACITY(16) cmd[1] = 0x11; @@ -419,8 +472,8 @@ TEST(DiskTest, ReadLong16) << "READ LONG(16) must fail because the capacity is exceeded"; cmd[2] = 0; - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdReadCapacity16_ReadLong16); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[13] = 1; @@ -434,13 +487,15 @@ TEST(DiskTest, WriteLong10) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWriteLong10)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdWriteLong10); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[2] = 1; @@ -461,10 +516,12 @@ TEST(DiskTest, WriteLong16) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[2] = 1; EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdWriteLong16); }, Throws(AllOf( @@ -473,8 +530,8 @@ TEST(DiskTest, WriteLong16) << "WRITE LONG(16) must fail because the capacity is exceeded"; cmd[2] = 0; - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdWriteLong16)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdWriteLong16); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[13] = 1; @@ -488,17 +545,20 @@ TEST(DiskTest, StartStopUnit) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); + disk->SetRemovable(true); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Stop/Unload disk->SetReady(true); - EXPECT_CALL(controller, Status()); + EXPECT_CALL(controller, Status); EXPECT_CALL(*disk, FlushCache); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdStartStop)); + disk->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); EXPECT_TRUE(disk->IsStopped()); @@ -506,9 +566,9 @@ TEST(DiskTest, StartStopUnit) cmd[4] = 0x02; disk->SetReady(true); disk->SetLocked(false); - EXPECT_CALL(controller, Status()); + EXPECT_CALL(controller, Status); EXPECT_CALL(*disk, FlushCache); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdStartStop)); + disk->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); disk->SetReady(false); @@ -526,15 +586,15 @@ TEST(DiskTest, StartStopUnit) // Start/Unload cmd[4] = 0x01; - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); EXPECT_FALSE(disk->IsStopped()); // Start/Load cmd[4] = 0x03; - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdStartStop)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -542,26 +602,28 @@ TEST(DiskTest, PreventAllowMediumRemoval) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); - EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdRemoval); }, Throws(AllOf( + EXPECT_THAT([&] { disk->Dispatch(scsi_command::eCmdPreventAllowMediumRemoval); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::NOT_READY), Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT)))) << "REMOVAL must fail because drive is not ready"; disk->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRemoval)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdPreventAllowMediumRemoval); EXPECT_EQ(status::GOOD, controller.GetStatus()); EXPECT_FALSE(disk->IsLocked()); cmd[4] = 1; - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdRemoval)); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdPreventAllowMediumRemoval); EXPECT_EQ(status::GOOD, controller.GetStatus()); EXPECT_TRUE(disk->IsLocked()); } @@ -629,10 +691,12 @@ TEST(DiskTest, ModeSense6) { NiceMock controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Drive must be ready on order to return all data disk->SetReady(true); @@ -640,18 +704,18 @@ TEST(DiskTest, ModeSense6) cmd[2] = 0x3f; // ALLOCATION LENGTH cmd[4] = 255; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); EXPECT_EQ(0x08, controller.GetBuffer()[3]) << "Wrong block descriptor length"; // No block descriptor cmd[1] = 0x08; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); EXPECT_EQ(0x00, controller.GetBuffer()[2]) << "Wrong device-specific parameter"; disk->SetReadOnly(false); disk->SetProtectable(true); disk->SetProtected(true); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); const auto& buf = controller.GetBuffer(); EXPECT_EQ(0x80, buf[2]) << "Wrong device-specific parameter"; @@ -661,18 +725,18 @@ TEST(DiskTest, ModeSense6) // Format page cmd[2] = 3; disk->SetSectorSizeInBytes(1024); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); DiskTest_ValidateFormatPage(controller, 12); // Rigid disk drive page cmd[2] = 4; disk->SetBlockCount(0x12345678); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); DiskTest_ValidateDrivePage(controller, 12); // Cache page cmd[2] = 8; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense6)); + disk->Dispatch(scsi_command::eCmdModeSense6); DiskTest_ValidateCachePage(controller, 12); } @@ -680,10 +744,12 @@ TEST(DiskTest, ModeSense10) { NiceMock controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Drive must be ready on order to return all data disk->SetReady(true); @@ -691,19 +757,19 @@ TEST(DiskTest, ModeSense10) cmd[2] = 0x3f; // ALLOCATION LENGTH cmd[8] = 255; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); EXPECT_EQ(0x08, controller.GetBuffer()[7]) << "Wrong block descriptor length"; // No block descriptor cmd[1] = 0x08; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); auto& buf = controller.GetBuffer(); EXPECT_EQ(0x00, controller.GetBuffer()[3]) << "Wrong device-specific parameter"; disk->SetReadOnly(false); disk->SetProtectable(true); disk->SetProtected(true); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); buf = controller.GetBuffer(); EXPECT_EQ(0x80, buf[3]) << "Wrong device-specific parameter"; @@ -711,7 +777,7 @@ TEST(DiskTest, ModeSense10) cmd[1] = 0x00; disk->SetBlockCount(0x1234); disk->SetSectorSizeInBytes(1024); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); buf = controller.GetBuffer(); EXPECT_EQ(0x00, buf[4]) << "Wrong LONGLBA field"; EXPECT_EQ(0x08, buf[7]) << "Wrong block descriptor length"; @@ -723,7 +789,7 @@ TEST(DiskTest, ModeSense10) // Return long block descriptor cmd[1] = 0x10; disk->SetBlockCount((uint64_t)0xffffffff + 1); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); buf = controller.GetBuffer(); EXPECT_EQ(0x01, buf[4]) << "Wrong LONGLBA field"; EXPECT_EQ(0x10, buf[7]) << "Wrong block descriptor length"; @@ -738,18 +804,18 @@ TEST(DiskTest, ModeSense10) // Format page cmd[2] = 3; disk->SetSectorSizeInBytes(1024); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); DiskTest_ValidateFormatPage(controller, 16); // Rigid disk drive page cmd[2] = 4; disk->SetBlockCount(0x12345678); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); DiskTest_ValidateDrivePage(controller, 16); // Cache page cmd[2] = 8; - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdModeSense10)); + disk->Dispatch(scsi_command::eCmdModeSense10); DiskTest_ValidateCachePage(controller, 16); } @@ -757,17 +823,19 @@ TEST(DiskTest, SynchronizeCache) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - EXPECT_CALL(*disk, FlushCache()); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSynchronizeCache10)); + EXPECT_CALL(*disk, FlushCache); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdSynchronizeCache10); EXPECT_EQ(status::GOOD, controller.GetStatus()); - EXPECT_CALL(*disk, FlushCache()); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdSynchronizeCache16)); + EXPECT_CALL(*disk, FlushCache); + EXPECT_CALL(controller, Status); + disk->Dispatch(scsi_command::eCmdSynchronizeCache16); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -775,11 +843,13 @@ TEST(DiskTest, ReadDefectData) { MockAbstractController controller(make_shared(), 0); auto disk = make_shared(); + const unordered_map params; + disk->Init(params); controller.AddDevice(disk); - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(disk->Dispatch(scsi_command::eCmdReadDefectData10)); + EXPECT_CALL(controller, DataIn); + disk->Dispatch(scsi_command::eCmdReadDefectData10); EXPECT_EQ(status::GOOD, controller.GetStatus()); } diff --git a/cpp/test/gpiobus_test.cpp b/cpp/test/gpiobus_test.cpp deleted file mode 100644 index faaf920e..00000000 --- a/cpp/test/gpiobus_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI Reloaded -// for Raspberry Pi -// -// Copyright (C) 2022 Uwe Seimet -// -//--------------------------------------------------------------------------- - -#include - -#include "hal/gpiobus.h" -#include - -TEST(GpioBusTest, GetCommandByteCount) -{ - unordered_set opcodes; - - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x88)); - opcodes.insert(0x88); - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x8a)); - opcodes.insert(0x8a); - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x8f)); - opcodes.insert(0x8f); - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x91)); - opcodes.insert(0x91); - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x9e)); - opcodes.insert(0x9e); - EXPECT_EQ(16, GPIOBUS::GetCommandByteCount(0x9f)); - opcodes.insert(0x9f); - EXPECT_EQ(12, GPIOBUS::GetCommandByteCount(0xa0)); - opcodes.insert(0xa0); - - for (int i = 0x20; i <= 0x7d; i++) { - EXPECT_EQ(10, GPIOBUS::GetCommandByteCount(i)); - opcodes.insert(i); - } - - for (int i = 0; i < 256; i++) { - if (opcodes.find(i) == opcodes.end()) { - EXPECT_EQ(6, GPIOBUS::GetCommandByteCount(i)); - } - } -} diff --git a/cpp/test/host_services_test.cpp b/cpp/test/host_services_test.cpp index 0699b717..3ea261b1 100644 --- a/cpp/test/host_services_test.cpp +++ b/cpp/test/host_services_test.cpp @@ -20,18 +20,13 @@ void HostServices_SetUpModePages(map>& pages) EXPECT_EQ(10, pages[32].size()); } -TEST(HostServicesTest, Dispatch) -{ - TestDispatch(SCHS); -} - TEST(HostServicesTest, TestUnitReady) { NiceMock controller(make_shared(), 0); auto services = CreateDevice(SCHS, controller); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdTestUnitReady)) << "TEST UNIT READY must never fail"; + services->Dispatch(scsi_command::eCmdTestUnitReady); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -45,26 +40,26 @@ TEST(HostServicesTest, StartStopUnit) NiceMock controller(make_shared(), 0); auto services = CreateDevice(SCHS, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // STOP EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::STOP_RASCSI)); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + services->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); // LOAD cmd[4] = 0x02; EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::STOP_PI)); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + services->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); // UNLOAD cmd[4] = 0x03; EXPECT_CALL(controller, ScheduleShutdown(AbstractController::rascsi_shutdown_mode::RESTART_PI)); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdStartStop)); + services->Dispatch(scsi_command::eCmdStartStop); EXPECT_EQ(status::GOOD, controller.GetStatus()); // START @@ -78,8 +73,10 @@ TEST(HostServicesTest, ModeSense6) { NiceMock controller(make_shared(), 0); auto services = CreateDevice(SCHS, controller); + const unordered_map params; + services->Init(params); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense6); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), @@ -96,7 +93,7 @@ TEST(HostServicesTest, ModeSense6) // ALLOCATION LENGTH cmd[4] = 255; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense6)); + services->Dispatch(scsi_command::eCmdModeSense6); vector& buffer = controller.GetBuffer(); // Major version 1 EXPECT_EQ(0x01, buffer[6]); @@ -110,7 +107,7 @@ TEST(HostServicesTest, ModeSense6) // ALLOCATION LENGTH cmd[4] = 2; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense6)); + services->Dispatch(scsi_command::eCmdModeSense6); buffer = controller.GetBuffer(); EXPECT_EQ(0x02, buffer[0]); } @@ -119,8 +116,10 @@ TEST(HostServicesTest, ModeSense10) { NiceMock controller(make_shared(), 0); auto services = CreateDevice(SCHS, controller); + const unordered_map params; + services->Init(params); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_THAT([&] { services->Dispatch(scsi_command::eCmdModeSense10); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), @@ -137,7 +136,7 @@ TEST(HostServicesTest, ModeSense10) // ALLOCATION LENGTH cmd[8] = 255; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense10)); + services->Dispatch(scsi_command::eCmdModeSense10); vector& buffer = controller.GetBuffer(); // Major version 1 EXPECT_EQ(0x01, buffer[10]); @@ -151,7 +150,7 @@ TEST(HostServicesTest, ModeSense10) // ALLOCATION LENGTH cmd[8] = 2; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(services->Dispatch(scsi_command::eCmdModeSense10)); + services->Dispatch(scsi_command::eCmdModeSense10); buffer = controller.GetBuffer(); EXPECT_EQ(0x02, buffer[1]); } diff --git a/cpp/test/mocks.h b/cpp/test/mocks.h index 42432bab..6b066484 100644 --- a/cpp/test/mocks.h +++ b/cpp/test/mocks.h @@ -24,6 +24,7 @@ #include "devices/host_services.h" #include "rascsi/command_context.h" #include "rascsi/rascsi_executor.h" +#include using namespace testing; @@ -221,7 +222,7 @@ class MockPrimaryDevice : public PrimaryDevice public: - MOCK_METHOD(vector, InquiryInternal, (), (const)); + MOCK_METHOD(vector, InquiryInternal, (), (const)); explicit MockPrimaryDevice(int lun) : PrimaryDevice(UNDEFINED, lun) {} ~MockPrimaryDevice() override = default; @@ -235,7 +236,7 @@ class MockModePageDevice : public ModePageDevice public: - MOCK_METHOD(vector, InquiryInternal, (), (const)); + MOCK_METHOD(vector, InquiryInternal, (), (const)); MOCK_METHOD(int, ModeSense6, (const vector&, vector&), (const override)); MOCK_METHOD(int, ModeSense10, (const vector&, vector&), (const override)); @@ -277,7 +278,7 @@ class MockStorageDevice : public StorageDevice public: - MOCK_METHOD(vector, InquiryInternal, (), (const)); + MOCK_METHOD(vector, InquiryInternal, (), (const)); MOCK_METHOD(void, Open, (), (override)); MOCK_METHOD(int, ModeSense6, (const vector&, vector&), (const override)); MOCK_METHOD(int, ModeSense10, (const vector&, vector&), (const override)); @@ -323,7 +324,7 @@ class MockDisk : public Disk public: - MOCK_METHOD(vector, InquiryInternal, (), (const)); + MOCK_METHOD(vector, InquiryInternal, (), (const)); MOCK_METHOD(void, FlushCache, (), (override)); MOCK_METHOD(void, Open, (), (override)); diff --git a/cpp/test/mode_page_device_test.cpp b/cpp/test/mode_page_device_test.cpp index 53f217d2..df0b2c4c 100644 --- a/cpp/test/mode_page_device_test.cpp +++ b/cpp/test/mode_page_device_test.cpp @@ -78,36 +78,30 @@ TEST(ModePageDeviceTest, AddVendorPage) EXPECT_TRUE(pages.empty()) << "There must not be any default vendor page"; } -TEST(ModePageDeviceTest, Dispatch) -{ - MockAbstractController controller(make_shared(), 0); - auto device = make_shared>(); - - controller.AddDevice(device); - - EXPECT_FALSE(device->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; -} - TEST(ModePageDeviceTest, ModeSense6) { MockAbstractController controller(make_shared(), 0); auto device = make_shared>(); + const unordered_map params; + device->Init(params); controller.AddDevice(device); EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSense6)); + device->Dispatch(scsi_command::eCmdModeSense6); } TEST(ModePageDeviceTest, ModeSense10) { MockAbstractController controller(make_shared(), 0); auto device = make_shared>(); + const unordered_map params; + device->Init(params); controller.AddDevice(device); EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSense10)); + device->Dispatch(scsi_command::eCmdModeSense10); } TEST(ModePageDeviceTest, ModeSelect) @@ -130,13 +124,15 @@ TEST(ModePageDeviceTest, ModeSelect6) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_CALL(controller, DataOut()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect6)); + device->Dispatch(scsi_command::eCmdModeSelect6); cmd[1] = 0x01; EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdModeSelect6); }, Throws(AllOf( @@ -149,13 +145,15 @@ TEST(ModePageDeviceTest, ModeSelect10) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_CALL(controller, DataOut()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdModeSelect10)); + device->Dispatch(scsi_command::eCmdModeSelect10); cmd[1] = 0x01; EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdModeSelect10); }, Throws(AllOf( diff --git a/cpp/test/primary_device_test.cpp b/cpp/test/primary_device_test.cpp index 1da71a6a..575f3222 100644 --- a/cpp/test/primary_device_test.cpp +++ b/cpp/test/primary_device_test.cpp @@ -12,8 +12,10 @@ #include "rascsi_exceptions.h" #include "devices/primary_device.h" #include "devices/device_factory.h" +#include "devices/scsi_command_util.h" using namespace scsi_defs; +using namespace scsi_command_util; TEST(PrimaryDeviceTest, GetId) { @@ -21,6 +23,8 @@ TEST(PrimaryDeviceTest, GetId) MockAbstractController controller(make_shared(), ID); auto device = make_shared(0); + const unordered_map params; + device->Init(params); EXPECT_EQ(-1, device->GetId()) << "Device ID cannot be known without assignment to a controller"; @@ -32,16 +36,18 @@ TEST(PrimaryDeviceTest, PhaseChange) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - EXPECT_CALL(controller, Status()); + EXPECT_CALL(controller, Status); device->EnterStatusPhase(); - EXPECT_CALL(controller, DataIn()); + EXPECT_CALL(controller, DataIn); device->EnterDataInPhase(); - EXPECT_CALL(controller, DataOut()); + EXPECT_CALL(controller, DataOut); device->EnterDataOutPhase(); } @@ -49,10 +55,12 @@ TEST(PrimaryDeviceTest, Reset) { NiceMock controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdReserve6)); + device->Dispatch(scsi_command::eCmdReserve6); EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must be reserved for initiator ID 1"; device->Reset(); @@ -64,13 +72,15 @@ TEST(PrimaryDeviceTest, CheckReservation) { NiceMock controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); EXPECT_TRUE(device->CheckReservation(0, scsi_command::eCmdTestUnitReady, false)) << "Device must not be reserved for initiator ID 0"; - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdReserve6)); + device->Dispatch(scsi_command::eCmdReserve6); EXPECT_TRUE(device->CheckReservation(0, scsi_command::eCmdTestUnitReady, false)) << "Device must not be reserved for initiator ID 0"; EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) @@ -84,9 +94,9 @@ TEST(PrimaryDeviceTest, CheckReservation) EXPECT_TRUE(device->CheckReservation(1, scsi_command::eCmdRelease6, false)) << "Device must not be reserved for RELEASE (6)"; - EXPECT_TRUE(device->CheckReservation(1, scsi_command::eCmdRemoval, false)) + EXPECT_TRUE(device->CheckReservation(1, scsi_command::eCmdPreventAllowMediumRemoval, false)) << "Device must not be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit not set"; - EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdRemoval, true)) + EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdPreventAllowMediumRemoval, true)) << "Device must be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit set"; } @@ -94,23 +104,25 @@ TEST(PrimaryDeviceTest, ReserveReleaseUnit) { NiceMock controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdReserve6)); + device->Dispatch(scsi_command::eCmdReserve6); EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must be reserved for initiator ID 1"; - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdRelease6)); + device->Dispatch(scsi_command::eCmdRelease6); EXPECT_TRUE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must not be reserved anymore for initiator ID 1"; ON_CALL(controller, GetInitiatorId).WillByDefault(Return(-1)); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdReserve6)); + device->Dispatch(scsi_command::eCmdReserve6); EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must be reserved for unknown initiator"; - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdRelease6)); + device->Dispatch(scsi_command::eCmdRelease6); EXPECT_TRUE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must not be reserved anymore for unknown initiator"; } @@ -119,10 +131,12 @@ TEST(PrimaryDeviceTest, DiscardReservation) { NiceMock controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdReserve6)); + device->Dispatch(scsi_command::eCmdReserve6); EXPECT_FALSE(device->CheckReservation(1, scsi_command::eCmdTestUnitReady, false)) << "Device must be reserved for initiator ID 1"; device->DiscardReservation(); @@ -134,46 +148,48 @@ TEST(PrimaryDeviceTest, TestUnitReady) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); device->SetReset(true); device->SetAttn(true); device->SetReady(false); - EXPECT_CALL(controller, DataIn()).Times(0); + EXPECT_CALL(controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION), Property(&scsi_exception::get_asc, asc::POWER_ON_OR_RESET)))); device->SetReset(false); - EXPECT_CALL(controller, DataIn()).Times(0); + EXPECT_CALL(controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION), Property(&scsi_exception::get_asc, asc::NOT_READY_TO_READY_CHANGE)))); device->SetReset(true); device->SetAttn(false); - EXPECT_CALL(controller, DataIn()).Times(0); + EXPECT_CALL(controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION), Property(&scsi_exception::get_asc, asc::POWER_ON_OR_RESET)))); device->SetReset(false); device->SetAttn(true); - EXPECT_CALL(controller, DataIn()).Times(0); + EXPECT_CALL(controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::UNIT_ATTENTION), Property(&scsi_exception::get_asc, asc::NOT_READY_TO_READY_CHANGE)))); device->SetAttn(false); - EXPECT_CALL(controller, DataIn()).Times(0); + EXPECT_CALL(controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdTestUnitReady); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::NOT_READY), Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT)))); device->SetReady(true); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdTestUnitReady)); + EXPECT_CALL(controller, Status); + device->Dispatch(scsi_command::eCmdTestUnitReady); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -181,27 +197,30 @@ TEST(PrimaryDeviceTest, Inquiry) { auto controller = make_shared>(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller->AddDevice(device); - vector& cmd = controller->GetCmd(); + auto& cmd = controller->GetCmd(); + // ALLOCATION LENGTH cmd[4] = 255; ON_CALL(*device, InquiryInternal()).WillByDefault([&device]() { return device->HandleInquiry(device_type::PROCESSOR, scsi_level::SPC_3, false); }); - EXPECT_CALL(*device, InquiryInternal()); - EXPECT_CALL(*controller, DataIn()); + EXPECT_CALL(*device, InquiryInternal); + EXPECT_CALL(*controller, DataIn); ON_CALL(*controller, GetEffectiveLun()).WillByDefault(Return(1)); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + device->Dispatch(scsi_command::eCmdInquiry); EXPECT_EQ(0x7f, controller->GetBuffer()[0]) << "Invalid LUN was not reported"; ON_CALL(*controller, GetEffectiveLun()).WillByDefault(Return(0)); EXPECT_FALSE(controller->AddDevice(make_shared(0))) << "Duplicate LUN was not rejected"; - EXPECT_CALL(*device, InquiryInternal()); - EXPECT_CALL(*controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + EXPECT_CALL(*device, InquiryInternal); + EXPECT_CALL(*controller, DataIn); + device->Dispatch(scsi_command::eCmdInquiry); EXPECT_EQ(device_type::PROCESSOR, (device_type)controller->GetBuffer()[0]); EXPECT_EQ(0x00, controller->GetBuffer()[1]) << "Device was not reported as non-removable"; EXPECT_EQ(scsi_level::SPC_3, (scsi_level)controller->GetBuffer()[2]) << "Wrong SCSI level"; @@ -211,9 +230,9 @@ TEST(PrimaryDeviceTest, Inquiry) ON_CALL(*device, InquiryInternal()).WillByDefault([&device]() { return device->HandleInquiry(device_type::DIRECT_ACCESS, scsi_level::SCSI_1_CCS, true); }); - EXPECT_CALL(*device, InquiryInternal()); - EXPECT_CALL(*controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + EXPECT_CALL(*device, InquiryInternal); + EXPECT_CALL(*controller, DataIn); + device->Dispatch(scsi_command::eCmdInquiry); EXPECT_EQ(device_type::DIRECT_ACCESS, (device_type)controller->GetBuffer()[0]); EXPECT_EQ(0x80, controller->GetBuffer()[1]) << "Device was not reported as removable"; EXPECT_EQ(scsi_level::SCSI_1_CCS, (scsi_level)controller->GetBuffer()[2]) << "Wrong SCSI level"; @@ -221,14 +240,14 @@ TEST(PrimaryDeviceTest, Inquiry) EXPECT_EQ(0x1f, controller->GetBuffer()[4]) << "Wrong additional data size"; cmd[1] = 0x01; - EXPECT_CALL(*controller, DataIn()).Times(0); + EXPECT_CALL(*controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdInquiry); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))) << "EVPD bit is not supported"; cmd[2] = 0x01; - EXPECT_CALL(*controller, DataIn()).Times(0); + EXPECT_CALL(*controller, DataIn).Times(0); EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdInquiry); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))) @@ -238,9 +257,9 @@ TEST(PrimaryDeviceTest, Inquiry) cmd[2] = 0x00; // ALLOCATION LENGTH cmd[4] = 1; - EXPECT_CALL(*device, InquiryInternal()); - EXPECT_CALL(*controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + EXPECT_CALL(*device, InquiryInternal); + EXPECT_CALL(*controller, DataIn); + device->Dispatch(scsi_command::eCmdInquiry); EXPECT_EQ(0x1f, controller->GetBuffer()[4]) << "Wrong additional data size"; EXPECT_EQ(1, controller->GetLength()) << "Wrong ALLOCATION LENGTH handling"; } @@ -249,10 +268,12 @@ TEST(PrimaryDeviceTest, RequestSense) { NiceMock controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 255; @@ -262,8 +283,8 @@ TEST(PrimaryDeviceTest, RequestSense) Property(&scsi_exception::get_asc, asc::MEDIUM_NOT_PRESENT)))); device->SetReady(true); - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdRequestSense)); + EXPECT_CALL(controller, DataIn); + device->Dispatch(scsi_command::eCmdRequestSense); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -271,30 +292,32 @@ TEST(PrimaryDeviceTest, SendDiagnostic) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); - EXPECT_CALL(controller, Status()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdSendDiag)); + EXPECT_CALL(controller, Status); + device->Dispatch(scsi_command::eCmdSendDiagnostic); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[1] = 0x10; - EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws(AllOf( + EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiagnostic); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))) << "SEND DIAGNOSTIC must fail because PF bit is not supported"; cmd[1] = 0; cmd[3] = 1; - EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws(AllOf( + EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiagnostic); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; cmd[3] = 0; cmd[4] = 1; - EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiag); }, Throws(AllOf( + EXPECT_THAT([&] { device->Dispatch(scsi_command::eCmdSendDiagnostic); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_CDB)))) << "SEND DIAGNOSTIC must fail because parameter list is not supported"; @@ -308,39 +331,32 @@ TEST(PrimaryDeviceTest, ReportLuns) MockAbstractController controller(make_shared(), 0); auto device1 = make_shared(LUN1); auto device2 = make_shared(LUN2); + const unordered_map params; + device1->Init(params); + device2->Init(params); controller.AddDevice(device1); EXPECT_TRUE(controller.HasDeviceForLun(LUN1)); controller.AddDevice(device2); EXPECT_TRUE(controller.HasDeviceForLun(LUN2)); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[9] = 255; - EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(device1->Dispatch(scsi_command::eCmdReportLuns)); + EXPECT_CALL(controller, DataIn); + device1->Dispatch(scsi_command::eCmdReportLuns); const vector& buffer = controller.GetBuffer(); - EXPECT_EQ(0x00, buffer[0]) << "Wrong data length"; - EXPECT_EQ(0x00, buffer[1]) << "Wrong data length"; - EXPECT_EQ(0x00, buffer[2]) << "Wrong data length"; - EXPECT_EQ(0x10, buffer[3]) << "Wrong data length"; - EXPECT_EQ(0x00, buffer[8]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[9]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[10]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[11]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[12]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[13]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[14]) << "Wrong LUN1 number"; - EXPECT_EQ(LUN1, buffer[15]) << "Wrong LUN1 number"; - EXPECT_EQ(0x00, buffer[16]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[17]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[18]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[19]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[20]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[21]) << "Wrong LUN2 number"; - EXPECT_EQ(0x00, buffer[22]) << "Wrong LUN2 number"; - EXPECT_EQ(LUN2, buffer[23]) << "Wrong LUN2 number"; + EXPECT_EQ(0, GetInt16(buffer, 0)) << "Wrong data length"; + EXPECT_EQ(16, GetInt16(buffer, 2)) << "Wrong data length"; + EXPECT_EQ(0, GetInt16(buffer, 8)) << "Wrong LUN1 number"; + EXPECT_EQ(0, GetInt16(buffer, 10)) << "Wrong LUN1 number"; + EXPECT_EQ(0, GetInt16(buffer, 12)) << "Wrong LUN1 number"; + EXPECT_EQ(LUN1, GetInt16(buffer, 14)) << "Wrong LUN1 number"; + EXPECT_EQ(0, GetInt16(buffer, 16)) << "Wrong LUN2 number"; + EXPECT_EQ(0, GetInt16(buffer, 18)) << "Wrong LUN2 number"; + EXPECT_EQ(0, GetInt16(buffer, 20)) << "Wrong LUN2 number"; + EXPECT_EQ(LUN2, GetInt16(buffer, 22)) << "Wrong LUN2 number"; cmd[2] = 0x01; EXPECT_THAT([&] { device1->Dispatch(scsi_command::eCmdReportLuns); }, Throws(AllOf( @@ -349,24 +365,16 @@ TEST(PrimaryDeviceTest, ReportLuns) << "Only SELECT REPORT mode 0 is supported"; } -TEST(PrimaryDeviceTest, UnknownCommand) +TEST(PrimaryDeviceTest, Dispatch) { MockAbstractController controller(make_shared(), 0); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - EXPECT_FALSE(device->Dispatch((scsi_command)0xFF)); -} - -TEST(PrimaryDeviceTest, Dispatch) -{ - MockAbstractController controller(make_shared(), 0); - auto device = make_shared>(0); - - controller.AddDevice(device); - - EXPECT_FALSE(device->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; + EXPECT_THROW(device->Dispatch(static_cast(0x1f)), scsi_exception) << "Unknown command"; } TEST(PrimaryDeviceTest, WriteByteSequence) @@ -391,7 +399,7 @@ TEST(PrimaryDeviceTest, Init) unordered_map params; MockPrimaryDevice device(0); - EXPECT_FALSE(device.Init(params)) << "Initialization of primary device must fail"; + EXPECT_TRUE(device.Init(params)) << "Initialization of primary device must not fail"; } TEST(PrimaryDeviceTest, FlushCache) diff --git a/cpp/test/rascsi_executor_test.cpp b/cpp/test/rascsi_executor_test.cpp index 17d3f75d..86bcddbc 100644 --- a/cpp/test/rascsi_executor_test.cpp +++ b/cpp/test/rascsi_executor_test.cpp @@ -152,10 +152,10 @@ TEST_F(RascsiExecutorTest, ProcessDeviceCmd) TEST_F(RascsiExecutorTest, ProcessCmd) { - shared_ptr bus_ptr; + shared_ptr bus; DeviceFactory device_factory; - MockAbstractController controller(bus_ptr, 0); - ControllerManager controller_manager(bus_ptr); + MockAbstractController controller(bus, 0); + ControllerManager controller_manager(bus); RascsiImage rascsi_image; RascsiResponse rascsi_response(device_factory, controller_manager, 32); auto executor = make_shared(rascsi_response, rascsi_image, device_factory, controller_manager); diff --git a/cpp/test/rascsi_response_test.cpp b/cpp/test/rascsi_response_test.cpp index 263bbee8..43f627d9 100644 --- a/cpp/test/rascsi_response_test.cpp +++ b/cpp/test/rascsi_response_test.cpp @@ -18,8 +18,8 @@ using namespace rascsi_interface; TEST(RascsiResponseTest, Operation_Count) { - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; RascsiResponse response(device_factory, controller_manager, 32); PbResult result; @@ -30,29 +30,32 @@ TEST(RascsiResponseTest, Operation_Count) void TestNonDiskDevice(PbDeviceType type, int default_param_count) { - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; RascsiResponse response(device_factory, controller_manager, 32); auto d = device_factory.CreateDevice(controller_manager, type, 0, ""); + const unordered_map params; + d->Init(params); EXPECT_TRUE(controller_manager.AttachToScsiController(0, d)); PbServerInfo info; response.GetDevices(info, "image_folder"); EXPECT_EQ(1, info.devices_info().devices().size()); + const auto& device = info.devices_info().devices()[0]; EXPECT_FALSE(device.properties().read_only()); EXPECT_FALSE(device.properties().protectable()); EXPECT_FALSE(device.properties().stoppable()); EXPECT_FALSE(device.properties().removable()); EXPECT_FALSE(device.properties().lockable()); - EXPECT_EQ(0, device.params().size()); EXPECT_EQ(32, device.properties().luns()); EXPECT_EQ(0, device.block_size()); EXPECT_EQ(0, device.block_count()); EXPECT_EQ(default_param_count, device.properties().default_params().size()); + EXPECT_EQ(default_param_count, device.params().size()); EXPECT_FALSE(device.properties().supports_file()); if (default_param_count) { EXPECT_TRUE(device.properties().supports_params()); @@ -85,8 +88,8 @@ TEST(RascsiResponseTest, GetImageFile) TEST(RascsiResponseTest, GetReservedIds) { - auto bus_ptr = make_shared(); - ControllerManager controller_manager(bus_ptr); + auto bus = make_shared(); + ControllerManager controller_manager(bus); DeviceFactory device_factory; RascsiResponse response(device_factory, controller_manager, 32); unordered_set ids; diff --git a/cpp/test/scsi_command_util_test.cpp b/cpp/test/scsi_command_util_test.cpp index a336fbb1..d198413b 100644 --- a/cpp/test/scsi_command_util_test.cpp +++ b/cpp/test/scsi_command_util_test.cpp @@ -21,12 +21,9 @@ TEST(ScsiCommandUtilTest, ModeSelect6) vector cdb(6); vector buf(LENGTH); - // PF (vendor-specific parameter format) + // PF (vendor-specific parameter format) must not fail but be ignored cdb[1] = 0x00; - EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 0); }, Throws(AllOf( - Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), - Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST)))) - << "Vendor-specific parameters are not supported"; + ModeSelect(scsi_command::eCmdModeSelect6, cdb, buf, LENGTH, 0); cdb[0] = 0x15; // PF (standard parameter format) @@ -71,12 +68,9 @@ TEST(ScsiCommandUtilTest, ModeSelect10) vector cdb(10); vector buf(LENGTH); - // PF (vendor-specific parameter format) + // PF (vendor-specific parameter format) must not fail but be ignored cdb[1] = 0x00; - EXPECT_THAT([&] { ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 0); }, Throws(AllOf( - Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), - Property(&scsi_exception::get_asc, asc::INVALID_FIELD_IN_PARAMETER_LIST)))) - << "Vendor-specific parameters are not supported"; + ModeSelect(scsi_command::eCmdModeSelect10, cdb, buf, LENGTH, 0); // PF (standard parameter format) cdb[1] = 0x10; diff --git a/cpp/test/scsi_controller_test.cpp b/cpp/test/scsi_controller_test.cpp index 4cb3f52e..76ab8cf3 100644 --- a/cpp/test/scsi_controller_test.cpp +++ b/cpp/test/scsi_controller_test.cpp @@ -284,10 +284,12 @@ TEST(ScsiControllerTest, RequestSense) { MockScsiController controller(make_shared>()); auto device = make_shared(0); + const unordered_map params; + device->Init(params); controller.AddDevice(device); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 255; // Non-existing LUN @@ -295,6 +297,6 @@ TEST(ScsiControllerTest, RequestSense) device->SetReady(true); EXPECT_CALL(controller, Status); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdRequestSense)); - EXPECT_EQ(status::GOOD, controller.GetStatus()) << "Illegal CHECK CONDITION for non-exsting LUN"; + device->Dispatch(scsi_command::eCmdRequestSense); + EXPECT_EQ(status::GOOD, controller.GetStatus()) << "Illegal CHECK CONDITION for non-existing LUN"; } diff --git a/cpp/test/scsi_daynaport_test.cpp b/cpp/test/scsi_daynaport_test.cpp index d924dabf..297800b9 100644 --- a/cpp/test/scsi_daynaport_test.cpp +++ b/cpp/test/scsi_daynaport_test.cpp @@ -16,21 +16,13 @@ TEST(ScsiDaynaportTest, Inquiry) TestInquiry(SCDP, device_type::PROCESSOR, scsi_level::SCSI_2, "Dayna SCSI/Link 1.4a", 0x20, false); } -TEST(ScsiDaynaportTest, Dispatch) -{ - NiceMock controller(make_shared(), 0); - auto daynaport = CreateDevice(SCDP, controller); - - EXPECT_FALSE(daynaport->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; -} - TEST(ScsiDaynaportTest, TestUnitReady) { NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdTestUnitReady)) << "TEST UNIT READY must never fail"; + daynaport->Dispatch(scsi_command::eCmdTestUnitReady); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -40,7 +32,7 @@ TEST(ScsiDaynaportTest, Read) NiceMock controller(make_shared(), 0); auto daynaport = dynamic_pointer_cast(CreateDevice(SCDP, controller)); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 1; @@ -53,7 +45,7 @@ TEST(ScsiDaynaportTest, WriteBytes) NiceMock controller(make_shared(), 0); auto daynaport = dynamic_pointer_cast(CreateDevice(SCDP, controller)); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Unknown data format cmd[5] = 0xff; @@ -65,7 +57,7 @@ TEST(ScsiDaynaportTest, Read6) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[5] = 0xff; EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdRead6); }, Throws(AllOf( @@ -79,7 +71,7 @@ TEST(ScsiDaynaportTest, Write6) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); cmd[5] = 0x00; EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdWrite6); }, Throws(AllOf( @@ -109,12 +101,12 @@ TEST(ScsiDaynaportTest, TestRetrieveStats) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 255; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdRetrieveStats)); + daynaport->Dispatch(scsi_command::eCmdRetrieveStats); } TEST(ScsiDaynaportTest, SetInterfaceMode) @@ -122,7 +114,7 @@ TEST(ScsiDaynaportTest, SetInterfaceMode) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Unknown interface command EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); }, Throws(AllOf( @@ -132,12 +124,12 @@ TEST(ScsiDaynaportTest, SetInterfaceMode) // Not implemented, do nothing cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SETMODE; EXPECT_CALL(controller, Status()); - EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode)); + daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); EXPECT_EQ(status::GOOD, controller.GetStatus()); cmd[5] = SCSIDaynaPort::CMD_SCSILINK_SETMAC; EXPECT_CALL(controller, DataOut()); - EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetIfaceMode)); + daynaport->Dispatch(scsi_command::eCmdSetIfaceMode); // Not implemented cmd[5] = SCSIDaynaPort::CMD_SCSILINK_STATS; @@ -163,7 +155,7 @@ TEST(ScsiDaynaportTest, SetMcastAddr) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdSetMcastAddr); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ILLEGAL_REQUEST), @@ -172,7 +164,7 @@ TEST(ScsiDaynaportTest, SetMcastAddr) cmd[4] = 1; EXPECT_CALL(controller, DataOut()); - EXPECT_TRUE(daynaport->Dispatch(scsi_command::eCmdSetMcastAddr)); + daynaport->Dispatch(scsi_command::eCmdSetMcastAddr); } TEST(ScsiDaynaportTest, EnableInterface) @@ -180,7 +172,7 @@ TEST(ScsiDaynaportTest, EnableInterface) NiceMock controller(make_shared(), 0); auto daynaport = CreateDevice(SCDP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // Enable EXPECT_THAT([&] { daynaport->Dispatch(scsi_command::eCmdEnableInterface); }, Throws(AllOf( @@ -197,6 +189,8 @@ TEST(ScsiDaynaportTest, EnableInterface) TEST(ScsiDaynaportTest, GetSendDelay) { SCSIDaynaPort daynaport(0); + const unordered_map params; + daynaport.Init(params); EXPECT_EQ(6, daynaport.GetSendDelay()); } diff --git a/cpp/test/scsi_host_bridge_test.cpp b/cpp/test/scsi_host_bridge_test.cpp index 7a820fea..23ca3f82 100644 --- a/cpp/test/scsi_host_bridge_test.cpp +++ b/cpp/test/scsi_host_bridge_test.cpp @@ -13,8 +13,3 @@ TEST(ScsiHostBridgeTest, Inquiry) { TestInquiry(SCBR, device_type::COMMUNICATIONS, scsi_level::SCSI_2, "RaSCSI RASCSI BRIDGE ", 0x27, false); } - -TEST(ScsiHostBridgeTest, Dispatch) -{ - TestDispatch(SCBR); -} diff --git a/cpp/test/scsi_printer_test.cpp b/cpp/test/scsi_printer_test.cpp index abfc75c2..b397fbb1 100644 --- a/cpp/test/scsi_printer_test.cpp +++ b/cpp/test/scsi_printer_test.cpp @@ -29,18 +29,13 @@ TEST(ScsiPrinterTest, Init) EXPECT_TRUE(printer->Init(params)); } -TEST(ScsiPrinterTest, Dispatch) -{ - TestDispatch(SCLP); -} - TEST(ScsiPrinterTest, TestUnitReady) { NiceMock controller(make_shared(), 0); auto printer = CreateDevice(SCLP, controller); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdTestUnitReady)); + printer->Dispatch(scsi_command::eCmdTestUnitReady); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -55,7 +50,7 @@ TEST(ScsiPrinterTest, ReserveUnit) auto printer = CreateDevice(SCLP, controller); EXPECT_CALL(controller, Status()).Times(1); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdReserve6)); + printer->Dispatch(scsi_command::eCmdReserve6); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -65,7 +60,7 @@ TEST(ScsiPrinterTest, ReleaseUnit) auto printer = CreateDevice(SCLP, controller); EXPECT_CALL(controller, Status()).Times(1); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdRelease6)); + printer->Dispatch(scsi_command::eCmdRelease6); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -75,7 +70,7 @@ TEST(ScsiPrinterTest, SendDiagnostic) auto printer = CreateDevice(SCLP, controller); EXPECT_CALL(controller, Status()).Times(1); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdSendDiag)); + printer->Dispatch(scsi_command::eCmdSendDiagnostic); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -84,10 +79,10 @@ TEST(ScsiPrinterTest, Print) NiceMock controller(make_shared(), 0); auto printer = CreateDevice(SCLP, controller); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); EXPECT_CALL(controller, DataOut()); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdPrint)); + printer->Dispatch(scsi_command::eCmdPrint); cmd[3] = 0xff; cmd[4] = 0xff; @@ -103,7 +98,7 @@ TEST(ScsiPrinterTest, StopPrint) auto printer = CreateDevice(SCLP, controller); EXPECT_CALL(controller, Status()); - EXPECT_TRUE(printer->Dispatch(scsi_command::eCmdStopPrint)); + printer->Dispatch(scsi_command::eCmdStopPrint); EXPECT_EQ(status::GOOD, controller.GetStatus()); } @@ -127,5 +122,4 @@ TEST(ScsiPrinterTest, WriteByteSequence) vector buf(1); EXPECT_TRUE(printer->WriteByteSequence(buf, buf.size())); - printer->Cleanup(); } diff --git a/cpp/test/scsicd_test.cpp b/cpp/test/scsicd_test.cpp index 76228310..b027b078 100644 --- a/cpp/test/scsicd_test.cpp +++ b/cpp/test/scsicd_test.cpp @@ -32,11 +32,6 @@ TEST(ScsiCdTest, Inquiry) TestInquiry(SCCD, device_type::CD_ROM, scsi_level::SCSI_2, "RaSCSI SCSI CD-ROM ", 0x1f, true); } -TEST(ScsiCdTest, Dispatch) -{ - TestDispatch(SCCD); -} - TEST(ScsiCdTest, SetUpModePages) { map> pages; @@ -120,6 +115,8 @@ TEST(ScsiCdTest, ReadToc) MockAbstractController controller(make_shared(), 0); const unordered_set sector_sizes; auto cd = make_shared(0, sector_sizes); + const unordered_map params; + cd->Init(params); controller.AddDevice(cd); diff --git a/cpp/test/scsihd_test.cpp b/cpp/test/scsihd_test.cpp index 7459fd50..4d9d6cd9 100644 --- a/cpp/test/scsihd_test.cpp +++ b/cpp/test/scsihd_test.cpp @@ -117,8 +117,3 @@ TEST(ScsiHdTest, ModeSelect) buf[20] = 0x02; EXPECT_NO_THROW(hd.ModeSelect(scsi_command::eCmdModeSelect10, cmd, buf, 255)) << "MODE SELECT(10) is supported"; } - -TEST(ScsiHdTest, Dispatch) -{ - TestDispatch(SCHD); -} diff --git a/cpp/test/scsimo_test.cpp b/cpp/test/scsimo_test.cpp index 86ba4004..2ac0cb93 100644 --- a/cpp/test/scsimo_test.cpp +++ b/cpp/test/scsimo_test.cpp @@ -148,9 +148,3 @@ TEST(ScsiMoTest, ModeSelect) buf[20] = 0x08; EXPECT_NO_THROW(mo.ModeSelect(scsi_command::eCmdModeSelect10, cmd, buf, 255)) << "MODE SELECT(10) is supported"; } - -TEST(ScsiMoTest, Dispatch) -{ - TestDispatch(SCMO); -} - diff --git a/cpp/test/storage_device_test.cpp b/cpp/test/storage_device_test.cpp index 651859ae..d9e4f9b3 100644 --- a/cpp/test/storage_device_test.cpp +++ b/cpp/test/storage_device_test.cpp @@ -151,14 +151,3 @@ TEST(StorageDeviceTest, GetFileSize) device.SetFilename("/non_existing_file"); EXPECT_THROW(device.GetFileSize(), io_exception); } - -TEST(StorageDeviceTest, Dispatch) -{ - MockAbstractController controller(make_shared(), 0); - auto device = make_shared>(); - - controller.AddDevice(device); - - EXPECT_FALSE(device->Dispatch(scsi_command::eCmdIcd)) << "Command is not supported by this class"; -} - diff --git a/cpp/test/test_shared.cpp b/cpp/test/test_shared.cpp index e32aa67f..f4532a30 100644 --- a/cpp/test/test_shared.cpp +++ b/cpp/test/test_shared.cpp @@ -9,6 +9,7 @@ #include "mocks.h" #include "controllers/controller_manager.h" +#include "rascsi_exceptions.h" #include "rascsi_version.h" #include "test_shared.h" #include @@ -25,6 +26,8 @@ shared_ptr CreateDevice(PbDeviceType type, MockAbstractController auto controller_manager = make_shared(controller.GetBus()); auto device = device_factory.CreateDevice(*controller_manager, type, 0, extension); + unordered_map params; + device->Init(params); controller.AddDevice(device); @@ -37,12 +40,12 @@ void TestInquiry(PbDeviceType type, device_type t, scsi_level l, const string& i NiceMock controller(make_shared(), 0); auto device = CreateDevice(type, controller, extension); - vector& cmd = controller.GetCmd(); + auto& cmd = controller.GetCmd(); // ALLOCATION LENGTH cmd[4] = 255; EXPECT_CALL(controller, DataIn()); - EXPECT_TRUE(device->Dispatch(scsi_command::eCmdInquiry)); + device->Dispatch(scsi_command::eCmdInquiry); const vector& buffer = controller.GetBuffer(); EXPECT_EQ(t, static_cast(buffer[0])); EXPECT_EQ(removable ? 0x80: 0x00, buffer[1]); @@ -61,14 +64,6 @@ void TestInquiry(PbDeviceType type, device_type t, scsi_level l, const string& i 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 diff --git a/cpp/test/test_shared.h b/cpp/test/test_shared.h index 0bc07118..e38212f7 100644 --- a/cpp/test/test_shared.h +++ b/cpp/test/test_shared.h @@ -27,8 +27,6 @@ shared_ptr CreateDevice(PbDeviceType, MockAbstractController&, co void TestInquiry(PbDeviceType, scsi_defs::device_type, scsi_defs::scsi_level, const string&, int, bool, const string& = ""); -void TestDispatch(PbDeviceType); - pair OpenTempFile(); path CreateTempFile(int);