blob: 1a2571a96ca9f7a9e87618f770163a8795c43054 [file] [log] [blame]
Alexander Hansen8d9e6da2025-01-14 14:17:19 +01001
2#include "nopdevice/nopdevice.hpp"
3#include "test/create_package/create_pldm_fw_package.hpp"
4
5#include <fcntl.h>
6#include <inttypes.h>
7#include <unistd.h>
8
9#include <phosphor-logging/lg2.hpp>
10#include <sdbusplus/async/context.hpp>
11#include <xyz/openbmc_project/Association/Definitions/client.hpp>
12#include <xyz/openbmc_project/Software/Update/client.hpp>
13#include <xyz/openbmc_project/Software/Version/client.hpp>
14
15#include <cassert>
16#include <cstdlib>
17#include <cstring>
18
19#include <gtest/gtest.h>
20
21// NOLINTBEGIN
22sdbusplus::async::task<>
23 testSoftwareUpdateSuccess(sdbusplus::async::context& ctx, int fd)
24// NOLINTEND
25{
26 NopCodeUpdater nopcu(ctx);
27 NopCodeUpdater* cu = &nopcu;
28
29 const std::string service = nopcu.setupBusName();
30
31 auto device = std::make_unique<NopDevice>(ctx, cu);
32
33 device->softwareCurrent =
34 std::make_unique<Software>(ctx, "myswid", *device);
35
36 device->softwareCurrent->setVersion("v12.345");
37
38 std::unique_ptr<SoftwareActivationProgress> sap =
39 std::make_unique<SoftwareActivationProgress>(ctx, "/");
40
41 const auto applyTimeImmediate = sdbusplus::common::xyz::openbmc_project::
42 software::ApplyTime::RequestedApplyTimes::Immediate;
43
44 device->softwareCurrent->enableUpdate({applyTimeImmediate});
45
46 std::string objPathCurrentSoftware =
47 device->softwareCurrent->getObjectPath();
48
49 // go via dbus to call the dbus method to start the update
50 auto client =
51 sdbusplus::client::xyz::openbmc_project::software::Update<>(ctx)
52 .service(service)
53 .path(objPathCurrentSoftware);
54
55 sdbusplus::message::object_path objPathNewSoftware =
56 co_await client.start_update(fd, applyTimeImmediate);
57
58 // TODO: somehow remove this sleep
59 co_await sdbusplus::async::sleep_for(ctx, std::chrono::seconds(2));
60
61 assert(objPathNewSoftware != objPathCurrentSoftware);
62
63 // assert that update function was called
64 assert(device->deviceSpecificUpdateFunctionCalled);
65
66 auto clientNewVersion =
67 sdbusplus::client::xyz::openbmc_project::software::Version<>(ctx)
68 .service(service)
69 .path(objPathNewSoftware.str);
70
71 const std::string newVersion = co_await clientNewVersion.version();
72
73 // assert the new version is not the old version
74 assert(newVersion != "v12.345");
75 assert(newVersion == "VersionString1");
76
77 auto clientAssoc =
78 sdbusplus::client::xyz::openbmc_project::association::Definitions<>(ctx)
79 .service(service)
80 .path(objPathNewSoftware.str);
81
82 // assert that the new version is associated as the running version
83 {
84 auto res = co_await clientAssoc.associations();
85 assert(res.size() == 1);
86
87 auto assoc = res[0];
88
89 std::string forward = std::get<0>(assoc);
90 std::string reverse = std::get<1>(assoc);
91 std::string endpoint = std::get<2>(assoc);
92
93 assert(forward == "running");
94 assert(reverse == "ran_on");
95 assert(endpoint == (co_await device->getInventoryItemObjectPath()));
96 }
97
98 ctx.request_stop();
99
100 co_return;
101}
102
103TEST(SoftwareUpdate, TestSoftwareUpdate)
104{
105 sdbusplus::async::context ctx;
106
107 int fd = memfd_create("test_memfd", 0);
108
109 assert(fd >= 0);
110
111 lg2::debug("create fd {FD}", "FD", fd);
112
113 uint8_t component_image[] = {0x12, 0x34, 0x83, 0x21};
114
115 size_t size_out = 0;
116 std::unique_ptr<uint8_t[]> buf = create_pldm_package_buffer(
117 component_image, sizeof(component_image),
118 std::optional<uint32_t>(exampleVendorIANA),
119 std::optional<std::string>(exampleCompatible), size_out);
120
121 ssize_t bytes_written = write(fd, (void*)buf.get(), size_out);
122 if (bytes_written == -1)
123 {
124 std::cerr << "Failed to write to memfd: " << strerror(errno)
125 << std::endl;
126 close(fd);
127 assert(false);
128 }
129 if (lseek(fd, 0, SEEK_SET) != 0)
130 {
131 lg2::error("could not seek to the beginning of the file");
132 assert(false);
133 }
134
135 ctx.spawn(testSoftwareUpdateSuccess(ctx, fd));
136
137 ctx.run();
138
139 close(fd);
140}