//--------------------------------------------------------------------------- // // SCSI Target Emulator PiSCSI // for Raspberry Pi // // Copyright (C) 2022 Uwe Seimet // //--------------------------------------------------------------------------- #include "mocks.h" #include "shared/piscsi_exceptions.h" #include "controllers/abstract_controller.h" using namespace scsi_defs; TEST(AbstractControllerTest, AllocateCmd) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); EXPECT_EQ(16, controller.GetCmd().size()); controller.AllocateCmd(1234); EXPECT_EQ(1234, controller.GetCmd().size()); } TEST(AbstractControllerTest, AllocateBuffer) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.AllocateBuffer(1); EXPECT_LE(1, controller.GetBuffer().size()); controller.AllocateBuffer(10000); EXPECT_LE(10000, controller.GetBuffer().size()); } TEST(AbstractControllerTest, Reset) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); auto controller = make_shared(controller_manager, 0); auto device = make_shared(0); controller->AddDevice(device); controller->SetPhase(phase_t::status); EXPECT_EQ(phase_t::status, controller->GetPhase()); controller->Reset(); EXPECT_TRUE(controller->IsBusFree()); EXPECT_EQ(status::GOOD, controller->GetStatus()); EXPECT_EQ(0, controller->GetLength()); } TEST(AbstractControllerTest, Next) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetNext(0x1234); EXPECT_EQ(0x1234, controller.GetNext()); controller.IncrementNext(); EXPECT_EQ(0x1235, controller.GetNext()); } TEST(AbstractControllerTest, Message) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetMessage(0x12); EXPECT_EQ(0x12, controller.GetMessage()); } TEST(AbstractControllerTest, ByteTransfer) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetByteTransfer(false); EXPECT_FALSE(controller.IsByteTransfer()); controller.SetByteTransfer(true); EXPECT_TRUE(controller.IsByteTransfer()); } TEST(AbstractControllerTest, BytesToTransfer) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetBytesToTransfer(0x1234); EXPECT_EQ(0x1234, controller.GetBytesToTransfer()); controller.SetByteTransfer(false); EXPECT_EQ(0, controller.GetBytesToTransfer()); } TEST(AbstractControllerTest, GetMaxLuns) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); EXPECT_EQ(32, controller.GetMaxLuns()); } TEST(AbstractControllerTest, Status) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetStatus(status::RESERVATION_CONFLICT); EXPECT_EQ(status::RESERVATION_CONFLICT, controller.GetStatus()); } TEST(AbstractControllerTest, ProcessPhase) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetPhase(phase_t::selection); EXPECT_CALL(controller, Selection); controller.ProcessPhase(); controller.SetPhase(phase_t::busfree); EXPECT_CALL(controller, BusFree); controller.ProcessPhase(); controller.SetPhase(phase_t::datain); EXPECT_CALL(controller, DataIn); controller.ProcessPhase(); controller.SetPhase(phase_t::dataout); EXPECT_CALL(controller, DataOut); controller.ProcessPhase(); controller.SetPhase(phase_t::command); EXPECT_CALL(controller, Command); controller.ProcessPhase(); controller.SetPhase(phase_t::status); EXPECT_CALL(controller, Status); controller.ProcessPhase(); controller.SetPhase(phase_t::msgin); EXPECT_CALL(controller, MsgIn); controller.ProcessPhase(); controller.SetPhase(phase_t::msgout); EXPECT_CALL(controller, MsgOut); controller.ProcessPhase(); controller.SetPhase(phase_t::reselection); EXPECT_THAT([&] { controller.ProcessPhase(); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND), Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION)))); controller.SetPhase(phase_t::reserved); EXPECT_THAT([&] { controller.ProcessPhase(); }, Throws(AllOf( Property(&scsi_exception::get_sense_key, sense_key::ABORTED_COMMAND), Property(&scsi_exception::get_asc, asc::NO_ADDITIONAL_SENSE_INFORMATION)))); } TEST(AbstractControllerTest, DeviceLunLifeCycle) { const int ID = 1; const int LUN = 4; auto bus = make_shared(); auto controller_manager = make_shared(*bus); auto controller = make_shared>(controller_manager, ID); auto device1 = make_shared(LUN); auto device2 = make_shared(32); auto device3 = make_shared(-1); EXPECT_EQ(0, controller->GetLunCount()); EXPECT_EQ(ID, controller->GetTargetId()); EXPECT_TRUE(controller->AddDevice(device1)); EXPECT_FALSE(controller->AddDevice(device2)); EXPECT_FALSE(controller->AddDevice(device3)); EXPECT_TRUE(controller->GetLunCount() > 0); EXPECT_TRUE(controller->HasDeviceForLun(LUN)); EXPECT_FALSE(controller->HasDeviceForLun(0)); EXPECT_NE(nullptr, controller->GetDeviceForLun(LUN)); EXPECT_EQ(nullptr, controller->GetDeviceForLun(0)); EXPECT_TRUE(controller->RemoveDevice(device1)); EXPECT_EQ(0, controller->GetLunCount()); EXPECT_FALSE(controller->RemoveDevice(device1)); } TEST(AbstractControllerTest, ExtractInitiatorId) { const int ID = 1; const int INITIATOR_ID = 7; auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, ID); EXPECT_EQ(INITIATOR_ID, controller.ExtractInitiatorId((1 << INITIATOR_ID) | ( 1 << ID))); EXPECT_EQ(AbstractController::UNKNOWN_INITIATOR_ID, controller.ExtractInitiatorId(1 << ID)); } TEST(AbstractControllerTest, GetOpcode) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); auto& cmd = controller.GetCmd(); cmd[0] = static_cast(scsi_command::eCmdInquiry); EXPECT_EQ(scsi_command::eCmdInquiry, controller.GetOpcode()); } TEST(AbstractControllerTest, GetLun) { const int LUN = 3; auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); auto& cmd = controller.GetCmd(); cmd[1] = LUN << 5; EXPECT_EQ(LUN, controller.GetLun()); } TEST(AbstractControllerTest, Blocks) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.SetBlocks(1); EXPECT_EQ(1, controller.GetBlocks()); controller.DecrementBlocks(); EXPECT_EQ(0, controller.GetBlocks()); } TEST(AbstractControllerTest, Length) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); EXPECT_FALSE(controller.HasValidLength()); controller.SetLength(1); EXPECT_EQ(1, controller.GetLength()); EXPECT_TRUE(controller.HasValidLength()); } TEST(AbstractControllerTest, UpdateOffsetAndLength) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); EXPECT_FALSE(controller.HasValidLength()); controller.UpdateOffsetAndLength(); EXPECT_EQ(0, controller.GetLength()); } TEST(AbstractControllerTest, Offset) { auto bus = make_shared(); auto controller_manager = make_shared(*bus); MockAbstractController controller(controller_manager, 0); controller.ResetOffset(); EXPECT_EQ(0, controller.GetOffset()); controller.UpdateOffsetAndLength(); EXPECT_EQ(0, controller.GetOffset()); }