Skip to content

Commit

Permalink
Merge develop
Browse files Browse the repository at this point in the history
  • Loading branch information
uweseimet committed Dec 12, 2023
1 parent ec152ff commit 7f01221
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 55 deletions.
2 changes: 1 addition & 1 deletion cpp/buses/in_process_bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ bool InProcessBus::WaitSignal(int pin, bool state)

bool InProcessBus::WaitForSelection()
{
// TODO Is there a better way to avoid busy waiting?
// Busy waiting cannot be avoided
const timespec ts = { .tv_sec = 0, .tv_nsec = 10'000'000 };
nanosleep(&ts, nullptr);

Expand Down
2 changes: 1 addition & 1 deletion cpp/buses/rpi_bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ bool RpiBus::GetREQ() const
return GetSignal(PIN_REQ);
}

inline void RpiBus::SetREQ(bool ast)
void RpiBus::SetREQ(bool ast)
{
SetSignal(PIN_REQ, ast);
}
Expand Down
10 changes: 6 additions & 4 deletions cpp/controllers/controller_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ bool ControllerFactory::DeleteController(const AbstractController &controller)
void ControllerFactory::DeleteAllControllers()
{
unordered_set<shared_ptr<AbstractController>> values;
ranges::transform(controllers, inserter(values, values.begin()),
[](const auto &controller) {return controller.second;});
ranges::transform(controllers, inserter(values, values.begin()), [](const auto &controller) {
return controller.second;
});

for (const auto &controller : values) {
DeleteController(*controller);
Expand All @@ -73,8 +74,9 @@ void ControllerFactory::DeleteAllControllers()

AbstractController::shutdown_mode ControllerFactory::ProcessOnController(int id_data) const
{
if (const auto &it = ranges::find_if(controllers, [&](const auto &c) {return (id_data & (1 << c.first));});
it != controllers.end()) {
if (const auto &it = ranges::find_if(controllers, [&](const auto &c) {
return (id_data & (1 << c.first));
}); it != controllers.end()) {
(*it).second->ProcessOnController(id_data);

return (*it).second->GetShutdownMode();
Expand Down
1 change: 1 addition & 0 deletions cpp/shared_protobuf/protobuf_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ string protobuf_util::SetCommandParams(PbCommand &command, const string &params)
break;

default:
assert(false);
break;
}

Expand Down
13 changes: 13 additions & 0 deletions cpp/test/abstract_controller_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@

using namespace scsi_defs;

TEST(AbstractControllerTest, ShutdownMode)
{
MockAbstractController controller;

EXPECT_EQ(AbstractController::shutdown_mode::NONE, controller.GetShutdownMode());
controller.ScheduleShutdown(AbstractController::shutdown_mode::STOP_S2P);
EXPECT_EQ(AbstractController::shutdown_mode::STOP_S2P, controller.GetShutdownMode());
controller.ScheduleShutdown(AbstractController::shutdown_mode::STOP_PI);
EXPECT_EQ(AbstractController::shutdown_mode::STOP_PI, controller.GetShutdownMode());
controller.ScheduleShutdown(AbstractController::shutdown_mode::RESTART_PI);
EXPECT_EQ(AbstractController::shutdown_mode::RESTART_PI, controller.GetShutdownMode());
}

TEST(AbstractControllerTest, AllocateCmd)
{
MockAbstractController controller;
Expand Down
64 changes: 64 additions & 0 deletions cpp/test/in_process_bus_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//---------------------------------------------------------------------------
//
// SCSI target emulator and SCSI tools for the Raspberry Pi
//
// Copyright (C) 2023 Uwe Seimet
//
//---------------------------------------------------------------------------

#include "mocks.h"
#include "buses/in_process_bus.h"

TEST(InProcessBusTest, IsTarget)
{
MockInProcessBus bus;

EXPECT_TRUE(bus.IsTarget());
}

TEST(InProcessBusTest, Acquire)
{
InProcessBus bus;

bus.SetDAT(0x12);
EXPECT_EQ(0x12, bus.Acquire());
}

TEST(InProcessBusTest, Reset)
{
InProcessBus bus;

bus.SetSignal(PIN_BSY, true);
EXPECT_TRUE(bus.GetSignal(PIN_BSY));
bus.Reset();
EXPECT_FALSE(bus.GetSignal(PIN_BSY));
}

TEST(InProcessBusTest, SetGetSignal)
{
InProcessBus bus;

bus.SetSignal(PIN_REQ, true);
EXPECT_TRUE(bus.GetSignal(PIN_REQ));
bus.SetSignal(PIN_REQ, false);
EXPECT_FALSE(bus.GetSignal(PIN_REQ));
}

TEST(InProcessBusTest, WaitSignal)
{
InProcessBus bus;

bus.SetSignal(PIN_ACK, true);
EXPECT_TRUE(bus.WaitSignal(PIN_ACK, true));

bus.SetSignal(PIN_ACK, false);
bus.SetSignal(PIN_RST, true);
EXPECT_FALSE(bus.WaitSignal(PIN_ACK, true));
}

TEST(InProcessBusTest, WaitForSelection)
{
InProcessBus bus;

EXPECT_TRUE(bus.WaitForSelection());
}
11 changes: 10 additions & 1 deletion cpp/test/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include <gmock/gmock.h>
#include "shared_command/command_executor.h"
#include "buses/bus.h"
#include "buses/in_process_bus.h"
#include "controllers/scsi_controller.h"
#include "devices/scsi_hd.h"
#include "devices/scsi_cd.h"
Expand Down Expand Up @@ -64,6 +64,15 @@ class MockBus : public Bus // NOSONAR Having many fields/methods cannot be avoid
~MockBus() override = default;
};

class MockInProcessBus : public InProcessBus
{
FRIEND_TEST(InProcessBusTest, IsTarget);

public:

using InProcessBus::InProcessBus;
};

class MockPhaseHandler : public PhaseHandler
{
FRIEND_TEST(PhaseHandlerTest, Phases);
Expand Down
97 changes: 52 additions & 45 deletions cpp/test/primary_device_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,37 +55,37 @@ TEST(PrimaryDeviceTest, Reset)

device->Dispatch(scsi_command::cmd_reserve6);
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for initiator ID 1";
<< "Device must be reserved for initiator ID 1";
device->Reset();
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved anymore for initiator ID 1";
<< "Device must not be reserved anymore for initiator ID 1";
}

TEST(PrimaryDeviceTest, CheckReservation)
{
auto [controller, device] = CreatePrimaryDevice();

EXPECT_TRUE(device->CheckReservation(0, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved for initiator ID 0";
<< "Device must not be reserved for initiator ID 0";

device->Dispatch(scsi_command::cmd_reserve6);
EXPECT_TRUE(device->CheckReservation(0, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved for initiator ID 0";
<< "Device must not be reserved for initiator ID 0";
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for initiator ID 1";
<< "Device must be reserved for initiator ID 1";
EXPECT_FALSE(device->CheckReservation(-1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for unknown initiator";
<< "Device must be reserved for unknown initiator";
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_inquiry, false))
<< "Device must not be reserved for INQUIRY";
<< "Device must not be reserved for INQUIRY";
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_request_sense, false))
<< "Device must not be reserved for REQUEST SENSE";
<< "Device must not be reserved for REQUEST SENSE";
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_release6, false))
<< "Device must not be reserved for RELEASE (6)";
<< "Device must not be reserved for RELEASE (6)";

EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_prevent_allow_medium_removal, false))
<< "Device must not be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit not set";
<< "Device must not be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit not set";
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_prevent_allow_medium_removal, true))
<< "Device must be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit set";
<< "Device must be reserved for PREVENT ALLOW MEDIUM REMOVAL with prevent bit set";
}

TEST(PrimaryDeviceTest, ReserveReleaseUnit)
Expand All @@ -94,20 +94,20 @@ TEST(PrimaryDeviceTest, ReserveReleaseUnit)

device->Dispatch(scsi_command::cmd_reserve6);
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for initiator ID 1";
<< "Device must be reserved for initiator ID 1";

device->Dispatch(scsi_command::cmd_release6);
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved anymore for initiator ID 1";
<< "Device must not be reserved anymore for initiator ID 1";

ON_CALL(*controller, GetInitiatorId).WillByDefault(Return(-1));
device->Dispatch(scsi_command::cmd_reserve6);
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for unknown initiator";
<< "Device must be reserved for unknown initiator";

device->Dispatch(scsi_command::cmd_release6);
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved anymore for unknown initiator";
<< "Device must not be reserved anymore for unknown initiator";
}

TEST(PrimaryDeviceTest, DiscardReservation)
Expand All @@ -116,10 +116,10 @@ TEST(PrimaryDeviceTest, DiscardReservation)

device->Dispatch(scsi_command::cmd_reserve6);
EXPECT_FALSE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must be reserved for initiator ID 1";
<< "Device must be reserved for initiator ID 1";
device->DiscardReservation();
EXPECT_TRUE(device->CheckReservation(1, scsi_command::cmd_test_unit_ready, false))
<< "Device must not be reserved anymore for initiator ID 1";
<< "Device must not be reserved anymore for initiator ID 1";
}

TEST(PrimaryDeviceTest, TestUnitReady)
Expand All @@ -133,21 +133,21 @@ TEST(PrimaryDeviceTest, TestUnitReady)
device->SetReady(false);
EXPECT_CALL(*controller, DataIn).Times(0);
EXPECT_THAT([&]
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
Throws<scsi_exception>(
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_THAT([&]
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
Throws<scsi_exception>(
AllOf(Property(&scsi_exception::get_sense_key, sense_key::unit_attention),
Property(&scsi_exception::get_asc, asc::not_ready_to_ready_change))));
Expand All @@ -156,10 +156,10 @@ TEST(PrimaryDeviceTest, TestUnitReady)
device->SetAttn(false);
EXPECT_CALL(*controller, DataIn).Times(0);
EXPECT_THAT([&]
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
Throws<scsi_exception>(
AllOf(Property(&scsi_exception::get_sense_key, sense_key::unit_attention),
Property(&scsi_exception::get_asc, asc::power_on_or_reset))));
Expand All @@ -168,21 +168,21 @@ TEST(PrimaryDeviceTest, TestUnitReady)
device->SetAttn(true);
EXPECT_CALL(*controller, DataIn).Times(0);
EXPECT_THAT([&]
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
Throws<scsi_exception>(
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_THAT([&]
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
{
d->Dispatch(scsi_command::cmd_test_unit_ready)
;
},
Throws<scsi_exception>(
AllOf(Property(&scsi_exception::get_sense_key, sense_key::not_ready),
Property(&scsi_exception::get_asc, asc::medium_not_present))));
Expand Down Expand Up @@ -268,10 +268,10 @@ TEST(PrimaryDeviceTest, RequestSense)

device->SetReady(false);
EXPECT_THAT([&]
{
d->Dispatch(scsi_command::cmd_request_sense)
;
},
{
d->Dispatch(scsi_command::cmd_request_sense)
;
},
Throws<scsi_exception>(
AllOf(Property(&scsi_exception::get_sense_key, sense_key::not_ready),
Property(&scsi_exception::get_asc, asc::medium_not_present))));
Expand All @@ -296,20 +296,20 @@ TEST(PrimaryDeviceTest, SendDiagnostic)
EXPECT_THAT([&] {d->Dispatch(scsi_command::cmd_send_diagnostic);}, Throws<scsi_exception>(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";
<< "SEND DIAGNOSTIC must fail because PF bit is not supported";
controller->SetCmdByte(1, 0);

controller->SetCmdByte(3, 1);
EXPECT_THAT([&] {d->Dispatch(scsi_command::cmd_send_diagnostic);}, Throws<scsi_exception>(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";
<< "SEND DIAGNOSTIC must fail because parameter list is not supported";
controller->SetCmdByte(3, 0);
controller->SetCmdByte(4, 1);
EXPECT_THAT([&] {d->Dispatch(scsi_command::cmd_send_diagnostic);}, Throws<scsi_exception>(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";
<< "SEND DIAGNOSTIC must fail because parameter list is not supported";
}

TEST(PrimaryDeviceTest, ReportLuns)
Expand Down Expand Up @@ -349,7 +349,7 @@ TEST(PrimaryDeviceTest, ReportLuns)
EXPECT_THAT([&] {device1->Dispatch(scsi_command::cmd_reportLuns);}, Throws<scsi_exception>(AllOf(
Property(&scsi_exception::get_sense_key, sense_key::illegal_request),
Property(&scsi_exception::get_asc, asc::invalid_field_in_cdb))))
<< "Only SELECT REPORT mode 0 is supported";
<< "Only SELECT REPORT mode 0 is supported";
}

TEST(PrimaryDeviceTest, Dispatch)
Expand All @@ -373,3 +373,10 @@ TEST(PrimaryDeviceTest, Init)

EXPECT_TRUE(device.Init(params)) << "Initialization of primary device must not fail";
}

TEST(PrimaryDeviceTest, GetStatistics)
{
MockPrimaryDevice device(0);

EXPECT_TRUE(device.GetStatistics().empty());
}
Loading

0 comments on commit 7f01221

Please sign in to comment.