1 #include "data_interface_mock.hpp"
2 #include "flags.hpp"
3 #include "status.hpp"
4 #include "tool_errors.hpp"
5 #include "updater.hpp"
6 #include "updater_mock.hpp"
7 #include "util.hpp"
8
9 #include <blobs-ipmid/blobs.hpp>
10 #include <ipmiblob/blob_errors.hpp>
11 #include <ipmiblob/test/blob_interface_mock.hpp>
12
13 #include <string>
14 #include <vector>
15
16 #include <gmock/gmock.h>
17 #include <gtest/gtest.h>
18
19 namespace host_tool
20 {
21
22 using ::testing::_;
23 using ::testing::Return;
24 using ::testing::Throw;
25 using ::testing::TypedEq;
26
27 class UpdateHandlerTest : public ::testing::Test
28 {
29 protected:
30 const std::uint16_t session = 0xbeef;
31
32 DataInterfaceMock handlerMock;
33 ipmiblob::BlobInterfaceMock blobMock;
34 UpdateHandler updater{&blobMock, &handlerMock};
35 };
36
TEST_F(UpdateHandlerTest,CheckAvailableSuccess)37 TEST_F(UpdateHandlerTest, CheckAvailableSuccess)
38 {
39 EXPECT_CALL(blobMock, getBlobList())
40 .WillOnce(
41 Return(std::vector<std::string>({ipmi_flash::staticLayoutBlobId})));
42
43 EXPECT_TRUE(updater.checkAvailable(ipmi_flash::staticLayoutBlobId));
44 }
45
TEST_F(UpdateHandlerTest,CheckAvailableFailure)46 TEST_F(UpdateHandlerTest, CheckAvailableFailure)
47 {
48 EXPECT_CALL(blobMock, getBlobList())
49 .WillOnce(Return(std::vector<std::string>()));
50
51 EXPECT_FALSE(updater.checkAvailable(ipmi_flash::staticLayoutBlobId));
52 }
53
TEST_F(UpdateHandlerTest,SendFileSuccess)54 TEST_F(UpdateHandlerTest, SendFileSuccess)
55 {
56 /* Call sendFile to verify it does what we expect. */
57 std::string firmwareImage = "image.bin";
58
59 std::uint16_t supported =
60 static_cast<std::uint16_t>(
61 ipmi_flash::FirmwareFlags::UpdateFlags::lpc) |
62 static_cast<std::uint16_t>(
63 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
64
65 EXPECT_CALL(handlerMock, supportedType())
66 .WillOnce(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
67
68 EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
69 .WillOnce(Return(session));
70
71 EXPECT_CALL(handlerMock, sendContents(firmwareImage, session))
72 .WillOnce(Return(true));
73
74 EXPECT_CALL(blobMock, closeBlob(session)).Times(1);
75
76 updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage);
77 }
78
TEST_F(UpdateHandlerTest,SendFileExceptsOnBlobOpening)79 TEST_F(UpdateHandlerTest, SendFileExceptsOnBlobOpening)
80 {
81 std::string firmwareImage = "image.bin";
82
83 std::uint16_t supported =
84 static_cast<std::uint16_t>(
85 ipmi_flash::FirmwareFlags::UpdateFlags::lpc) |
86 static_cast<std::uint16_t>(
87 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
88
89 EXPECT_CALL(handlerMock, supportedType())
90 .WillOnce(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
91
92 EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
93 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
94
95 EXPECT_THROW(
96 updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage),
97 ToolException);
98 }
99
TEST_F(UpdateHandlerTest,SendFileHandlerFailureCausesException)100 TEST_F(UpdateHandlerTest, SendFileHandlerFailureCausesException)
101 {
102 std::string firmwareImage = "image.bin";
103
104 std::uint16_t supported =
105 static_cast<std::uint16_t>(
106 ipmi_flash::FirmwareFlags::UpdateFlags::lpc) |
107 static_cast<std::uint16_t>(
108 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
109
110 EXPECT_CALL(handlerMock, supportedType())
111 .WillRepeatedly(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
112
113 EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
114 .WillRepeatedly(Return(session));
115
116 EXPECT_CALL(handlerMock, sendContents(firmwareImage, session))
117 .WillRepeatedly(Return(false));
118
119 EXPECT_CALL(blobMock, closeBlob(session)).Times(3);
120
121 EXPECT_THROW(
122 updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage),
123 ToolException);
124 }
125
TEST_F(UpdateHandlerTest,SendFileHandlerPassWithRetries)126 TEST_F(UpdateHandlerTest, SendFileHandlerPassWithRetries)
127 {
128 std::string firmwareImage = "image.bin";
129
130 std::uint16_t supported =
131 static_cast<std::uint16_t>(
132 ipmi_flash::FirmwareFlags::UpdateFlags::lpc) |
133 static_cast<std::uint16_t>(
134 ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
135
136 EXPECT_CALL(handlerMock, supportedType())
137 .WillRepeatedly(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
138
139 EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
140 .WillRepeatedly(Return(session));
141
142 EXPECT_CALL(handlerMock, sendContents(firmwareImage, session))
143 .WillOnce(Return(false))
144 .WillOnce(Return(false))
145 .WillOnce(Return(true));
146
147 EXPECT_CALL(blobMock, closeBlob(session)).Times(3);
148
149 updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage);
150 }
151
TEST_F(UpdateHandlerTest,VerifyFileHandleReturnsTrueOnSuccess)152 TEST_F(UpdateHandlerTest, VerifyFileHandleReturnsTrueOnSuccess)
153 {
154 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
155 .WillOnce(Return(session));
156 EXPECT_CALL(blobMock, commit(session, _)).WillOnce(Return());
157 ipmiblob::StatResponse verificationResponse = {};
158 /* the other details of the response are ignored, and should be. */
159 verificationResponse.metadata.push_back(
160 static_cast<std::uint8_t>(ipmi_flash::ActionStatus::success));
161
162 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
163 .WillOnce(Return(verificationResponse));
164 EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
165
166 EXPECT_TRUE(updater.verifyFile(ipmi_flash::verifyBlobId, false));
167 }
168
TEST_F(UpdateHandlerTest,VerifyFileHandleSkipsPollingIfIgnoreStatus)169 TEST_F(UpdateHandlerTest, VerifyFileHandleSkipsPollingIfIgnoreStatus)
170 {
171 /* if ignoreStatus, it'll skip polling for a verification result. */
172 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
173 .WillOnce(Return(session));
174 EXPECT_CALL(blobMock, commit(session, _)).WillOnce(Return());
175
176 EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
177
178 EXPECT_TRUE(updater.verifyFile(ipmi_flash::verifyBlobId, true));
179 }
180
TEST_F(UpdateHandlerTest,VerifyFileConvertsOpenBlobExceptionToToolException)181 TEST_F(UpdateHandlerTest, VerifyFileConvertsOpenBlobExceptionToToolException)
182 {
183 /* On open, it can except and this is converted to a ToolException. */
184 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
185 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
186 EXPECT_THROW(updater.verifyFile(ipmi_flash::verifyBlobId, false),
187 ToolException);
188 }
189
TEST_F(UpdateHandlerTest,VerifyFileToolException)190 TEST_F(UpdateHandlerTest, VerifyFileToolException)
191 {
192 /* On open, it can except and this is converted to a ToolException. */
193 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
194 .Times(3)
195 .WillRepeatedly(Throw(ToolException("asdf")));
196 EXPECT_THROW(updater.verifyFile(ipmi_flash::verifyBlobId, false),
197 ToolException);
198 }
199
TEST_F(UpdateHandlerTest,VerifyFileHandleReturnsTrueOnSuccessWithRetries)200 TEST_F(UpdateHandlerTest, VerifyFileHandleReturnsTrueOnSuccessWithRetries)
201 {
202 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
203 .Times(3)
204 .WillRepeatedly(Return(session));
205 EXPECT_CALL(blobMock, commit(session, _))
206 .WillOnce(Throw(ToolException("asdf")))
207 .WillOnce(Throw(ToolException("asdf")))
208 .WillOnce(Return());
209 ipmiblob::StatResponse verificationResponse = {};
210 /* the other details of the response are ignored, and should be. */
211 verificationResponse.metadata.push_back(
212 static_cast<std::uint8_t>(ipmi_flash::ActionStatus::success));
213
214 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
215 .WillOnce(Return(verificationResponse));
216 EXPECT_CALL(blobMock, closeBlob(session)).Times(3).WillRepeatedly(Return());
217
218 EXPECT_TRUE(updater.verifyFile(ipmi_flash::verifyBlobId, false));
219 }
220
TEST_F(UpdateHandlerTest,VerifyFileCommitExceptionForwards)221 TEST_F(UpdateHandlerTest, VerifyFileCommitExceptionForwards)
222 {
223 /* On commit, it can except. */
224 EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))
225 .WillOnce(Return(session));
226 EXPECT_CALL(blobMock, commit(session, _))
227 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
228 EXPECT_THROW(updater.verifyFile(ipmi_flash::verifyBlobId, false),
229 ToolException);
230 }
231
TEST_F(UpdateHandlerTest,ReadVerisonReturnExpected)232 TEST_F(UpdateHandlerTest, ReadVerisonReturnExpected)
233 {
234 /* It can return as expected, when polling and readBytes succeeds. */
235 EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
236 .WillOnce(Return(session));
237 ipmiblob::StatResponse readVersionResponse = {};
238 readVersionResponse.blob_state =
239 blobs::StateFlags::open_read | blobs::StateFlags::committed;
240 readVersionResponse.size = 10;
241 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
242 .WillOnce(Return(readVersionResponse));
243 std::vector<uint8_t> resp = {0x2d, 0xfe};
244 EXPECT_CALL(blobMock, readBytes(session, 0, _)).WillOnce(Return(resp));
245
246 EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
247 EXPECT_EQ(resp, updater.readVersion(ipmi_flash::biosVersionBlobId));
248 }
249
TEST_F(UpdateHandlerTest,ReadVersionExceptionWhenPollingSucceedsReadBytesFails)250 TEST_F(UpdateHandlerTest, ReadVersionExceptionWhenPollingSucceedsReadBytesFails)
251 {
252 /* On readBytes, it can except. */
253 EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
254 .WillOnce(Return(session));
255 ipmiblob::StatResponse readVersionResponse = {};
256 readVersionResponse.blob_state =
257 blobs::StateFlags::open_read | blobs::StateFlags::committed;
258 readVersionResponse.size = 10;
259 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
260 .WillOnce(Return(readVersionResponse));
261 EXPECT_CALL(blobMock, readBytes(session, 0, _))
262 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
263 EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
264 EXPECT_THROW(updater.readVersion(ipmi_flash::biosVersionBlobId),
265 ToolException);
266 }
267
TEST_F(UpdateHandlerTest,ReadVersionReturnsErrorIfPollingFails)268 TEST_F(UpdateHandlerTest, ReadVersionReturnsErrorIfPollingFails)
269 {
270 /* It can throw an error, when polling fails. */
271 EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
272 .Times(3)
273 .WillRepeatedly(Return(session));
274 ipmiblob::StatResponse readVersionResponse = {};
275 readVersionResponse.blob_state = blobs::StateFlags::commit_error;
276 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
277 .Times(3)
278 .WillRepeatedly(Return(readVersionResponse));
279 EXPECT_CALL(blobMock, closeBlob(session)).Times(3).WillRepeatedly(Return());
280 EXPECT_THROW(updater.readVersion(ipmi_flash::biosVersionBlobId),
281 ToolException);
282 }
283
TEST_F(UpdateHandlerTest,ReadVersionReturnExpectedWithRetries)284 TEST_F(UpdateHandlerTest, ReadVersionReturnExpectedWithRetries)
285 {
286 /* It can return as expected, when polling and readBytes succeeds. */
287 EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
288 .Times(3)
289 .WillRepeatedly(Return(session));
290 ipmiblob::StatResponse readVersionResponse = {};
291 readVersionResponse.blob_state =
292 blobs::StateFlags::open_read | blobs::StateFlags::committed;
293 readVersionResponse.size = 10;
294 EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
295 .Times(3)
296 .WillRepeatedly(Return(readVersionResponse));
297 std::vector<uint8_t> resp = {0x2d, 0xfe};
298 EXPECT_CALL(blobMock, readBytes(session, 0, _))
299 .WillOnce(Throw(ToolException("asdf")))
300 .WillOnce(Throw(ToolException("asdf")))
301 .WillOnce(Return(resp));
302
303 EXPECT_CALL(blobMock, closeBlob(session)).Times(3).WillRepeatedly(Return());
304 EXPECT_EQ(resp, updater.readVersion(ipmi_flash::biosVersionBlobId));
305 }
306
TEST_F(UpdateHandlerTest,ReadVersionCovertsOpenBlobExceptionToToolException)307 TEST_F(UpdateHandlerTest, ReadVersionCovertsOpenBlobExceptionToToolException)
308 {
309 /* On open, it can except and this is converted to a ToolException. */
310 EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
311 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
312 EXPECT_THROW(updater.readVersion(ipmi_flash::biosVersionBlobId),
313 ToolException);
314 }
315
TEST_F(UpdateHandlerTest,CleanArtifactsSkipsCleanupIfUnableToOpen)316 TEST_F(UpdateHandlerTest, CleanArtifactsSkipsCleanupIfUnableToOpen)
317 {
318 /* It only tries to commit if it's able to open the blob. However, if
319 * committing fails, this error is ignored.
320 */
321 EXPECT_CALL(blobMock, openBlob(ipmi_flash::cleanupBlobId, _))
322 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
323 EXPECT_CALL(blobMock, commit(_, _)).Times(0);
324 EXPECT_CALL(blobMock, closeBlob(_)).Times(0);
325
326 updater.cleanArtifacts();
327 }
328
TEST_F(UpdateHandlerTest,CleanArtifactsIfOpenDoesClose)329 TEST_F(UpdateHandlerTest, CleanArtifactsIfOpenDoesClose)
330 {
331 /* The closeBlob call is called even if commit excepts. */
332 std::uint16_t session = 0xa5eb;
333 EXPECT_CALL(blobMock, openBlob(ipmi_flash::cleanupBlobId, _))
334 .WillOnce(Return(session));
335 EXPECT_CALL(blobMock, commit(session, _))
336 .WillOnce(Throw(ipmiblob::BlobException("asdf")));
337 EXPECT_CALL(blobMock, closeBlob(session));
338
339 updater.cleanArtifacts();
340 }
341
TEST_F(UpdateHandlerTest,CleanArtifactsSuccessPath)342 TEST_F(UpdateHandlerTest, CleanArtifactsSuccessPath)
343 {
344 std::uint16_t session = 0xa5eb;
345 EXPECT_CALL(blobMock, openBlob(ipmi_flash::cleanupBlobId, _))
346 .WillOnce(Return(session));
347 EXPECT_CALL(blobMock, commit(session, _));
348 EXPECT_CALL(blobMock, closeBlob(session));
349
350 updater.cleanArtifacts();
351 }
352
353 class UpdaterTest : public ::testing::Test
354 {
355 protected:
356 static constexpr char image[] = "image.bin";
357 static constexpr char signature[] = "signature.bin";
358 static constexpr char layout[] = "static";
359 static constexpr char path[] = "/flash/static";
360
361 ipmiblob::BlobInterfaceMock blobMock;
362 std::uint16_t session = 0xbeef;
363 bool defaultIgnore = false;
364 };
365
TEST_F(UpdaterTest,UpdateMainReturnsSuccessIfAllSuccess)366 TEST_F(UpdaterTest, UpdateMainReturnsSuccessIfAllSuccess)
367 {
368 UpdateHandlerMock handler;
369
370 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(true));
371 EXPECT_CALL(handler, sendFile(path, image)).WillOnce(Return());
372 EXPECT_CALL(handler, sendFile(ipmi_flash::hashBlobId, signature))
373 .WillOnce(Return());
374 EXPECT_CALL(handler, verifyFile(ipmi_flash::verifyBlobId, defaultIgnore))
375 .WillOnce(Return(true));
376 EXPECT_CALL(handler, verifyFile(ipmi_flash::updateBlobId, defaultIgnore))
377 .WillOnce(Return(true));
378 EXPECT_CALL(blobMock, getBlobList())
379 .WillOnce(Return(std::vector<std::string>({})));
380
381 updaterMain(&handler, &blobMock, image, signature, layout, defaultIgnore);
382 }
383
TEST_F(UpdaterTest,UpdateMainReturnsSuccessIfAllSuccessWithDeleteActiveBlob)384 TEST_F(UpdaterTest, UpdateMainReturnsSuccessIfAllSuccessWithDeleteActiveBlob)
385 {
386 UpdateHandlerMock handler;
387
388 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(true));
389 EXPECT_CALL(handler, sendFile(path, image)).WillOnce(Return());
390 EXPECT_CALL(handler, sendFile(ipmi_flash::hashBlobId, signature))
391 .WillOnce(Return());
392 EXPECT_CALL(handler, verifyFile(ipmi_flash::verifyBlobId, defaultIgnore))
393 .WillOnce(Return(true));
394 EXPECT_CALL(handler, verifyFile(ipmi_flash::updateBlobId, defaultIgnore))
395 .WillOnce(Return(true));
396 EXPECT_CALL(handler, cleanArtifacts()).WillOnce(Return());
397 EXPECT_CALL(blobMock, deleteBlob(ipmi_flash::activeImageBlobId))
398 .WillOnce(Return(true));
399 EXPECT_CALL(blobMock, getBlobList())
400 .WillOnce(Return(std::vector<std::string>(
401 {ipmi_flash::staticLayoutBlobId, ipmi_flash::activeImageBlobId})));
402
403 updaterMain(&handler, &blobMock, image, signature, layout, defaultIgnore);
404 }
405
TEST_F(UpdaterTest,UpdateMainReturnsSuccessWithIgnoreUpdate)406 TEST_F(UpdaterTest, UpdateMainReturnsSuccessWithIgnoreUpdate)
407 {
408 UpdateHandlerMock handler;
409 bool updateIgnore = true;
410
411 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(true));
412 EXPECT_CALL(handler, sendFile(path, image)).WillOnce(Return());
413 EXPECT_CALL(handler, sendFile(ipmi_flash::hashBlobId, signature))
414 .WillOnce(Return());
415 EXPECT_CALL(handler, verifyFile(ipmi_flash::verifyBlobId, defaultIgnore))
416 .WillOnce(Return(true));
417 EXPECT_CALL(handler, verifyFile(ipmi_flash::updateBlobId, updateIgnore))
418 .WillOnce(Return(true));
419 EXPECT_CALL(blobMock, getBlobList())
420 .WillOnce(Return(std::vector<std::string>({})));
421
422 updaterMain(&handler, &blobMock, image, signature, layout, updateIgnore);
423 }
424
TEST_F(UpdaterTest,UpdateMainCleansUpOnFailure)425 TEST_F(UpdaterTest, UpdateMainCleansUpOnFailure)
426 {
427 UpdateHandlerMock handler;
428
429 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(true));
430 EXPECT_CALL(handler, sendFile(path, image)).WillOnce(Return());
431 EXPECT_CALL(handler, sendFile(ipmi_flash::hashBlobId, signature))
432 .WillOnce(Return());
433 EXPECT_CALL(handler, verifyFile(ipmi_flash::verifyBlobId, defaultIgnore))
434 .WillOnce(Return(false));
435 EXPECT_CALL(handler, cleanArtifacts()).WillOnce(Return());
436 EXPECT_CALL(blobMock, getBlobList())
437 .WillOnce(Return(std::vector<std::string>({})));
438
439 EXPECT_THROW(updaterMain(&handler, &blobMock, image, signature, layout,
440 defaultIgnore),
441 ToolException);
442 }
443
TEST_F(UpdaterTest,UpdateMainExceptsOnUpdateBlobFailure)444 TEST_F(UpdaterTest, UpdateMainExceptsOnUpdateBlobFailure)
445 {
446 UpdateHandlerMock handler;
447
448 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(true));
449 EXPECT_CALL(handler, sendFile(path, image)).WillOnce(Return());
450 EXPECT_CALL(handler, sendFile(ipmi_flash::hashBlobId, signature))
451 .WillOnce(Return());
452 EXPECT_CALL(handler, verifyFile(ipmi_flash::verifyBlobId, defaultIgnore))
453 .WillOnce(Return(true));
454 EXPECT_CALL(handler, verifyFile(ipmi_flash::updateBlobId, defaultIgnore))
455 .WillOnce(Return(false));
456 EXPECT_CALL(handler, cleanArtifacts()).WillOnce(Return());
457 EXPECT_CALL(blobMock, getBlobList())
458 .WillOnce(Return(std::vector<std::string>({})));
459
460 EXPECT_THROW(updaterMain(&handler, &blobMock, image, signature, layout,
461 defaultIgnore),
462 ToolException);
463 }
464
TEST_F(UpdaterTest,UpdateMainExceptsIfAvailableNotFound)465 TEST_F(UpdaterTest, UpdateMainExceptsIfAvailableNotFound)
466 {
467 UpdateHandlerMock handler;
468
469 EXPECT_CALL(handler, checkAvailable(path)).WillOnce(Return(false));
470
471 EXPECT_THROW(updaterMain(&handler, &blobMock, image, signature, layout,
472 defaultIgnore),
473 ToolException);
474 }
475
476 } // namespace host_tool
477