mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-22 15:30:09 +00:00
52c2aa474f
* Rebrand project to PiSCSI - rascsi ->piscsi - rasctl -> scsictl - rasdump -> scsidump - ras* -> piscsi* (rasutil -> piscsi_util, etc.) * Refined the formatting and wording of the app startup banner * Kept some references to rascsi and rasctl where backwards compatibility is concerned * Point to the new github repo URL Co-authored-by: nucleogenic <nr@nucleogenic.com> Co-authored-by: Uwe Seimet <Uwe.Seimet@seimet.de>
286 lines
8.5 KiB
C++
286 lines
8.5 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// 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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
auto controller = make_shared<MockAbstractController>(controller_manager, 0);
|
|
auto device = make_shared<MockPrimaryDevice>(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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
MockAbstractController controller(controller_manager, 0);
|
|
|
|
controller.SetMessage(0x12);
|
|
EXPECT_EQ(0x12, controller.GetMessage());
|
|
}
|
|
|
|
TEST(AbstractControllerTest, ByteTransfer)
|
|
{
|
|
auto bus = make_shared<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
MockAbstractController controller(controller_manager, 0);
|
|
|
|
EXPECT_EQ(32, controller.GetMaxLuns());
|
|
}
|
|
|
|
TEST(AbstractControllerTest, Status)
|
|
{
|
|
auto bus = make_shared<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<scsi_exception>(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<scsi_exception>(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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
auto controller = make_shared<NiceMock<MockAbstractController>>(controller_manager, ID);
|
|
|
|
auto device1 = make_shared<MockPrimaryDevice>(LUN);
|
|
auto device2 = make_shared<MockPrimaryDevice>(32);
|
|
auto device3 = make_shared<MockPrimaryDevice>(-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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
MockAbstractController controller(controller_manager, 0);
|
|
|
|
auto& cmd = controller.GetCmd();
|
|
|
|
cmd[0] = static_cast<int>(scsi_command::eCmdInquiry);
|
|
EXPECT_EQ(scsi_command::eCmdInquiry, controller.GetOpcode());
|
|
}
|
|
|
|
TEST(AbstractControllerTest, GetLun)
|
|
{
|
|
const int LUN = 3;
|
|
|
|
auto bus = make_shared<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*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<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
MockAbstractController controller(controller_manager, 0);
|
|
|
|
EXPECT_FALSE(controller.HasValidLength());
|
|
|
|
controller.UpdateOffsetAndLength();
|
|
EXPECT_EQ(0, controller.GetLength());
|
|
}
|
|
|
|
TEST(AbstractControllerTest, Offset)
|
|
{
|
|
auto bus = make_shared<MockBus>();
|
|
auto controller_manager = make_shared<ControllerManager>(*bus);
|
|
MockAbstractController controller(controller_manager, 0);
|
|
|
|
controller.ResetOffset();
|
|
EXPECT_EQ(0, controller.GetOffset());
|
|
|
|
controller.UpdateOffsetAndLength();
|
|
EXPECT_EQ(0, controller.GetOffset());
|
|
}
|