Activation: Support to update multiple PSUs
Queue the update on multiple PSUs, and do the update one-by-one.
Tested: Write unit test cases and verify the cases pass.
On witherspoon, verify the dummy update services are run on all
PSUs.
Signed-off-by: Lei YU <mine260309@gmail.com>
Change-Id: Icfe0f6e74623e54840df8d731d852d53d6071768
diff --git a/test/test_activation.cpp b/test/test_activation.cpp
index 0ea3640..338dc60 100644
--- a/test/test_activation.cpp
+++ b/test/test_activation.cpp
@@ -1,4 +1,5 @@
#include "activation.hpp"
+#include "mocked_utils.hpp"
#include <sdbusplus/test/sdbus_mock.hpp>
@@ -7,24 +8,43 @@
using namespace phosphor::software::updater;
+using ::testing::_;
+using ::testing::Return;
+
class TestActivation : public ::testing::Test
{
public:
- using ActivationStatus = sdbusplus::xyz::openbmc_project::Software::server::
- Activation::Activations;
- TestActivation()
+ using Status = Activation::Status;
+ using RequestedStatus = Activation::RequestedActivations;
+ TestActivation() :
+ mockedUtils(
+ reinterpret_cast<const utils::MockedUtils&>(utils::getUtils()))
{
}
~TestActivation()
{
}
+
+ void onUpdateDone()
+ {
+ activation->onUpdateDone();
+ }
+ void onUpdateFailed()
+ {
+ activation->onUpdateFailed();
+ }
+ int getProgress()
+ {
+ return activation->activationProgress->progress();
+ }
static constexpr auto dBusPath = SOFTWARE_OBJPATH;
sdbusplus::SdBusMock sdbusMock;
sdbusplus::bus::bus mockedBus = sdbusplus::get_mocked_new(&sdbusMock);
+ const utils::MockedUtils& mockedUtils;
std::unique_ptr<Activation> activation;
std::string versionId = "abcdefgh";
std::string extVersion = "Some Ext Version";
- ActivationStatus status = ActivationStatus::Active;
+ Status status = Status::Ready;
AssociationList associations;
};
@@ -51,3 +71,102 @@
psuInventoryPath, versionId);
EXPECT_EQ(toCompare, service);
}
+
+TEST_F(TestActivation, doUpdateWhenNoPSU)
+{
+ activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
+ extVersion, status, associations);
+ ON_CALL(mockedUtils, getPSUInventoryPath(_))
+ .WillByDefault(
+ Return(std::vector<std::string>({}))); // No PSU inventory
+ activation->requestedActivation(RequestedStatus::Active);
+
+ EXPECT_EQ(Status::Failed, activation->activation());
+}
+
+TEST_F(TestActivation, doUpdateOnePSUOK)
+{
+ constexpr auto psu0 = "/com/example/inventory/psu0";
+ activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
+ extVersion, status, associations);
+ ON_CALL(mockedUtils, getPSUInventoryPath(_))
+ .WillByDefault(
+ Return(std::vector<std::string>({psu0}))); // One PSU inventory
+ activation->requestedActivation(RequestedStatus::Active);
+
+ EXPECT_EQ(Status::Activating, activation->activation());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Active, activation->activation());
+}
+
+TEST_F(TestActivation, doUpdateFourPSUsOK)
+{
+ constexpr auto psu0 = "/com/example/inventory/psu0";
+ constexpr auto psu1 = "/com/example/inventory/psu1";
+ constexpr auto psu2 = "/com/example/inventory/psu2";
+ constexpr auto psu3 = "/com/example/inventory/psu3";
+ activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
+ extVersion, status, associations);
+ ON_CALL(mockedUtils, getPSUInventoryPath(_))
+ .WillByDefault(Return(
+ std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
+ activation->requestedActivation(RequestedStatus::Active);
+
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(10, getProgress());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(30, getProgress());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(50, getProgress());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(70, getProgress());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Active, activation->activation());
+}
+
+TEST_F(TestActivation, doUpdateFourPSUsFailonSecond)
+{
+ constexpr auto psu0 = "/com/example/inventory/psu0";
+ constexpr auto psu1 = "/com/example/inventory/psu1";
+ constexpr auto psu2 = "/com/example/inventory/psu2";
+ constexpr auto psu3 = "/com/example/inventory/psu3";
+ activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
+ extVersion, status, associations);
+ ON_CALL(mockedUtils, getPSUInventoryPath(_))
+ .WillByDefault(Return(
+ std::vector<std::string>({psu0, psu1, psu2, psu3}))); // 4 PSUs
+ activation->requestedActivation(RequestedStatus::Active);
+
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(10, getProgress());
+
+ onUpdateDone();
+ EXPECT_EQ(Status::Activating, activation->activation());
+ EXPECT_EQ(30, getProgress());
+
+ onUpdateFailed();
+ EXPECT_EQ(Status::Failed, activation->activation());
+}
+
+TEST_F(TestActivation, doUpdateOnExceptionFromDbus)
+{
+ constexpr auto psu0 = "/com/example/inventory/psu0";
+ activation = std::make_unique<Activation>(mockedBus, dBusPath, versionId,
+ extVersion, status, associations);
+ ON_CALL(mockedUtils, getPSUInventoryPath(_))
+ .WillByDefault(
+ Return(std::vector<std::string>({psu0}))); // One PSU inventory
+ ON_CALL(sdbusMock, sd_bus_call(_, _, _, _, nullptr))
+ .WillByDefault(Return(-1)); // Make sdbus call failure
+ activation->requestedActivation(RequestedStatus::Active);
+
+ EXPECT_EQ(Status::Failed, activation->activation());
+}