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 = blobs::StateFlags::open_read |
239                                      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 = blobs::StateFlags::open_read |
257                                      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 = blobs::StateFlags::open_read |
292                                      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