xref: /openbmc/phosphor-ipmi-flash/bmc/firmware-handler/test/firmware_json_unittest.cpp (revision c893f43d5f8a3c0b05c0f6f67d1b232a8117cf71)
1 #include "firmware_handlers_builder.hpp"
2 #include "general_systemd.hpp"
3 #include "skip_action.hpp"
4 
5 #include <nlohmann/json.hpp>
6 
7 #include <gmock/gmock.h>
8 #include <gtest/gtest.h>
9 
10 namespace ipmi_flash
11 {
12 namespace
13 {
14 using ::testing::IsEmpty;
15 
16 using json = nlohmann::json;
17 
18 TEST(FirmwareJsonTest, InvalidHandlerType)
19 {
20     auto j2 = R"(
21         [{
22             "blob" : "/flash/image",
23             "handler" : {
24                 "type" : "unsupported",
25                 "path" : "/run/initramfs/bmc-image"
26             },
27             "actions" : {
28                 "preparation" : {
29                     "type" : "systemd",
30                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
31                 },
32                 "verification" : {
33                     "type" : "fileSystemdVerify",
34                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
35                     "path" : "/tmp/bmc.verify"
36                 },
37                 "update" : {
38                     "type" : "reboot"
39                 }
40             }
41          }]
42     )"_json;
43     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
44 }
45 
46 TEST(FirmwareJsonTest, InvalidPreparationType)
47 {
48     auto j2 = R"(
49         [{
50             "blob" : "/flash/image",
51             "handler" : {
52                 "type" : "file",
53                 "path" : "/run/initramfs/bmc-image"
54             },
55             "actions" : {
56                 "preparation" : {
57                     "type" : "superfun",
58                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
59                 },
60                 "verification" : {
61                     "type" : "fileSystemdVerify",
62                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
63                     "path" : "/tmp/bmc.verify"
64                 },
65                 "update" : {
66                     "type" : "reboot"
67                 }
68             }
69          }]
70     )"_json;
71 
72     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
73 }
74 
75 TEST(FirmwareJsonTest, InvalidVerificationType)
76 {
77     auto j2 = R"(
78         [{
79             "blob" : "/flash/image",
80             "handler" : {
81                 "type" : "file",
82                 "path" : "/run/initramfs/bmc-image"
83             },
84             "actions" : {
85                 "preparation" : {
86                     "type" : "systemd",
87                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
88                 },
89                 "verification" : {
90                     "type" : "funtimes",
91                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
92                     "path" : "/tmp/bmc.verify"
93                 },
94                 "update" : {
95                     "type" : "reboot"
96                 }
97             }
98          }]
99     )"_json;
100 
101     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
102 }
103 
104 TEST(FirmwareJsonTest, InvalidUpdateType)
105 {
106     auto j2 = R"(
107         [{
108             "blob" : "/flash/image",
109             "handler" : {
110                 "type" : "file",
111                 "path" : "/run/initramfs/bmc-image"
112             },
113             "actions" : {
114                 "preparation" : {
115                     "type" : "systemd",
116                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
117                 },
118                 "verification" : {
119                     "type" : "fileSystemdVerify",
120                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
121                     "path" : "/tmp/bmc.verify"
122                 },
123                 "update" : {
124                     "type" : "systemd"
125                 }
126             }
127          }]
128     )"_json;
129 
130     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
131 }
132 
133 TEST(FirmwareJsonTest, MissingHandler)
134 {
135     auto j2 = R"(
136         [{
137             "blob" : "/flash/image",
138             "actions" : {
139                 "preparation" : {
140                     "type" : "systemd",
141                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
142                 },
143                 "verification" : {
144                     "type" : "fileSystemdVerify",
145                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
146                     "path" : "/tmp/bmc.verify"
147                 },
148                 "update" : {
149                     "type" : "reboot"
150                 }
151             }
152         }]
153     )"_json;
154 
155     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
156 }
157 
158 TEST(FirmwareJsonTest, MissingActions)
159 {
160     auto j2 = R"(
161         [{
162             "blob" : "/flash/image",
163             "handler" : {
164                 "type" : "file",
165                 "path" : "/run/initramfs/bmc-image"
166             }
167         }]
168     )"_json;
169 
170     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
171 }
172 
173 TEST(FirmwareJsonTest, MissingActionPreparation)
174 {
175     auto j2 = R"(
176         [{
177             "blob" : "/flash/image",
178             "handler" : {
179                 "type" : "file",
180                 "path" : "/run/initramfs/bmc-image"
181             },
182             "actions" : {
183                 "verification" : {
184                     "type" : "fileSystemdVerify",
185                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
186                     "path" : "/tmp/bmc.verify"
187                 },
188                 "update" : {
189                     "type" : "reboot"
190                 }
191             }
192         }]
193     )"_json;
194 
195     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
196 }
197 
198 TEST(FirmwareJsonTest, MissingActionVerification)
199 {
200     auto j2 = R"(
201         [{
202             "blob" : "/flash/image",
203             "handler" : {
204                 "type" : "file",
205                 "path" : "/run/initramfs/bmc-image"
206             },
207             "actions" : {
208                 "preparation" : {
209                     "type" : "systemd",
210                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
211                 },
212                 "update" : {
213                     "type" : "reboot"
214                 }
215             }
216         }]
217     )"_json;
218 
219     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
220 }
221 
222 TEST(FirmwareJsonTest, MissingActionUpdate)
223 {
224     auto j2 = R"(
225         [{
226             "blob" : "/flash/image",
227             "handler" : {
228                 "type" : "file",
229                 "path" : "/run/initramfs/bmc-image"
230             },
231             "actions" : {
232                 "preparation" : {
233                     "type" : "systemd",
234                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
235                 },
236                 "verification" : {
237                     "type" : "fileSystemdVerify",
238                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
239                     "path" : "/tmp/bmc.verify"
240                 }
241             }
242         }]
243     )"_json;
244 
245     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
246 }
247 
248 TEST(FirmwareJsonTest, TwoConfigsOneInvalidReturnsValid)
249 {
250     auto j2 = R"(
251         [{
252             "blob" : "/flash/image",
253             "actions" : {
254                 "preparation" : {
255                     "type" : "systemd",
256                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
257                 },
258                 "verification" : {
259                     "type" : "fileSystemdVerify",
260                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
261                     "path" : "/tmp/bmc.verify"
262                 },
263                 "update" : {
264                     "type" : "reboot"
265                 }
266             }
267          },
268          {
269             "blob" : "/flash/image2",
270             "handler" : {
271                 "type" : "file",
272                 "path" : "/run/initramfs/bmc-image"
273             },
274             "actions" : {
275                 "preparation" : {
276                     "type" : "systemd",
277                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
278                 },
279                 "verification" : {
280                     "type" : "fileSystemdVerify",
281                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
282                     "path" : "/tmp/bmc.verify"
283                 },
284                 "update" : {
285                     "type" : "reboot"
286                 }
287             }
288         }]
289     )"_json;
290 
291     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
292     EXPECT_EQ(h[0].blobId, "/flash/image2");
293     EXPECT_EQ(h.size(), 1);
294 }
295 
296 /*
297  * TODO: It may be worth individually using builders per type, and testing
298  * those.
299  *
300  * TODO: Only allow unique handler blob paths (tested at a higher level).
301  */
302 
303 TEST(FirmwareJsonTest, VerifyBlobNameMatches)
304 {
305     /* A perfect configuration except the blob name doesn't start with "/flash/"
306      */
307     auto j2 = R"(
308         [{
309             "blob" : "bmc-image-flash",
310             "handler" : {
311                 "type" : "file",
312                 "path" : "/run/initramfs/bmc-image"
313             },
314             "actions" : {
315                 "preparation" : {
316                     "type" : "systemd",
317                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
318                 },
319                 "verification" : {
320                     "type" : "fileSystemdVerify",
321                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
322                     "path" : "/tmp/bmc.verify"
323                 },
324                 "update" : {
325                     "type" : "reboot"
326                 }
327             }
328          }]
329     )"_json;
330 
331     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
332 }
333 
334 TEST(FirmwareJsonTest, VerifyMinimumBlobNameLength)
335 {
336     /* A perfect configuration except the blob name is effectively zero length.
337      */
338     auto j2 = R"(
339         [{
340             "blob" : "/flash/",
341             "handler" : {
342                 "type" : "file",
343                 "path" : "/run/initramfs/bmc-image"
344             },
345             "actions" : {
346                 "preparation" : {
347                     "type" : "systemd",
348                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
349                 },
350                 "verification" : {
351                     "type" : "fileSystemdVerify",
352                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
353                     "path" : "/tmp/bmc.verify"
354                 },
355                 "update" : {
356                     "type" : "reboot"
357                 }
358             }
359          }]
360     )"_json;
361 
362     EXPECT_THAT(FirmwareHandlersBuilder().buildHandlerFromJson(j2), IsEmpty());
363 }
364 
365 TEST(FirmwareJsonTest, VerifySystemdWithReboot)
366 {
367     auto j2 = R"(
368         [{
369             "blob" : "/flash/image",
370             "handler" : {
371                 "type" : "file",
372                 "path" : "/run/initramfs/bmc-image"
373             },
374             "actions" : {
375                 "preparation" : {
376                     "type" : "systemd",
377                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
378                 },
379                 "verification" : {
380                     "type" : "fileSystemdVerify",
381                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
382                     "path" : "/tmp/bmc.verify"
383                 },
384                 "update" : {
385                     "type" : "reboot"
386                 }
387             }
388          }]
389     )"_json;
390 
391     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
392     EXPECT_EQ(h[0].blobId, "/flash/image");
393     EXPECT_FALSE(h[0].handler == nullptr);
394     EXPECT_FALSE(h[0].actions == nullptr);
395     EXPECT_FALSE(h[0].actions->preparation == nullptr);
396     EXPECT_FALSE(h[0].actions->verification == nullptr);
397     EXPECT_FALSE(h[0].actions->update == nullptr);
398 }
399 
400 TEST(FirmwareJsonTest, VerifyMultipleHandlersReturned)
401 {
402     auto j2 = R"(
403         [{
404             "blob" : "/flash/image",
405             "handler" : {
406                 "type" : "file",
407                 "path" : "/run/initramfs/bmc-image"
408             },
409             "actions" : {
410                 "preparation" : {
411                     "type" : "systemd",
412                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
413                 },
414                 "verification" : {
415                     "type" : "fileSystemdVerify",
416                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
417                     "path" : "/tmp/bmc.verify"
418                 },
419                 "update" : {
420                     "type" : "systemd",
421                     "unit" : "phosphor-ipmi-flash-bmc-update.target"
422                 }
423             }
424         },
425         {
426             "blob" : "/flash/bios",
427             "handler" : {
428                 "type" : "file",
429                 "path" : "/run/initramfs/bmc-image"
430             },
431             "actions" : {
432                 "preparation" : {
433                     "type" : "systemd",
434                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
435                 },
436                 "verification" : {
437                     "type" : "fileSystemdVerify",
438                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
439                     "path" : "/tmp/bmc.verify"
440                 },
441                 "update" : {
442                     "type" : "systemd",
443                     "unit" : "phosphor-ipmi-flash-bmc-update.target"
444                 }
445             }
446         }]
447     )"_json;
448 
449     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
450     EXPECT_EQ(h.size(), 2);
451     EXPECT_EQ(h[0].blobId, "/flash/image");
452     EXPECT_EQ(h[1].blobId, "/flash/bios");
453 }
454 
455 TEST(FirmwareJsonTest, VerifyValidSingleNonReboot)
456 {
457     auto j2 = R"(
458         [{
459             "blob" : "/flash/image",
460             "handler" : {
461                 "type" : "file",
462                 "path" : "/run/initramfs/bmc-image"
463             },
464             "actions" : {
465                 "preparation" : {
466                     "type" : "systemd",
467                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
468                 },
469                 "verification" : {
470                     "type" : "fileSystemdVerify",
471                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
472                     "path" : "/tmp/bmc.verify"
473                 },
474                 "update" : {
475                     "type" : "systemd",
476                     "unit" : "phosphor-ipmi-flash-bmc-update.target"
477                 }
478             }
479          }]
480     )"_json;
481 
482     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
483     EXPECT_EQ(h[0].blobId, "/flash/image");
484     EXPECT_FALSE(h[0].handler == nullptr);
485     EXPECT_FALSE(h[0].actions == nullptr);
486     EXPECT_FALSE(h[0].actions->preparation == nullptr);
487     EXPECT_FALSE(h[0].actions->verification == nullptr);
488     auto verifier = reinterpret_cast<SystemdWithStatusFile*>(
489         h[0].actions->verification.get());
490     EXPECT_THAT(verifier->getMode(), "replace");
491     EXPECT_FALSE(h[0].actions->update == nullptr);
492     auto updater = reinterpret_cast<SystemdNoFile*>(h[0].actions->update.get());
493     EXPECT_THAT(updater->getMode(), "replace");
494 }
495 
496 TEST(FirmwareJsonTest, VerifyValidWithModes)
497 {
498     auto j2 = R"(
499         [{
500             "blob" : "/flash/image",
501             "handler" : {
502                 "type" : "file",
503                 "path" : "/run/initramfs/bmc-image"
504             },
505             "actions" : {
506                 "preparation" : {
507                     "type" : "systemd",
508                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
509                 },
510                 "verification" : {
511                     "type" : "fileSystemdVerify",
512                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
513                     "path" : "/tmp/bmc.verify",
514                     "mode" : "replace-nope"
515                 },
516                 "update" : {
517                     "type" : "systemd",
518                     "mode" : "replace-fake",
519                     "unit" : "phosphor-ipmi-flash-bmc-update.target"
520                 }
521             }
522          }]
523     )"_json;
524 
525     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
526     EXPECT_EQ(h[0].blobId, "/flash/image");
527     EXPECT_FALSE(h[0].handler == nullptr);
528     EXPECT_FALSE(h[0].actions == nullptr);
529     EXPECT_FALSE(h[0].actions->preparation == nullptr);
530     EXPECT_FALSE(h[0].actions->verification == nullptr);
531     auto verifier = reinterpret_cast<SystemdWithStatusFile*>(
532         h[0].actions->verification.get());
533     EXPECT_THAT(verifier->getMode(), "replace-nope");
534     EXPECT_FALSE(h[0].actions->update == nullptr);
535     auto updater = reinterpret_cast<SystemdNoFile*>(h[0].actions->update.get());
536     EXPECT_THAT(updater->getMode(), "replace-fake");
537 }
538 
539 TEST(FirmwareJsonTest, VerifyValidUpdateWithFilePath)
540 {
541     auto j2 = R"(
542         [{
543             "blob" : "/flash/image",
544             "handler" : {
545                 "type" : "file",
546                 "path" : "/run/initramfs/bmc-image"
547             },
548             "actions" : {
549                 "preparation" : {
550                     "type" : "systemd",
551                     "unit" : "phosphor-ipmi-flash-bmc-prepare.target"
552                 },
553                 "verification" : {
554                     "type" : "fileSystemdVerify",
555                     "unit" : "phosphor-ipmi-flash-bmc-verify.target",
556                     "path" : "/tmp/bmc.verify",
557                     "mode" : "replace-nope"
558                 },
559                 "update" : {
560                     "type" : "fileSystemdUpdate",
561                     "mode" : "replace-fake",
562                     "unit" : "phosphor-ipmi-flash-bmc-update.target",
563                     "path" : "/tmp/update.verify"
564                 }
565             }
566          }]
567     )"_json;
568 
569     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
570     EXPECT_EQ(h[0].blobId, "/flash/image");
571     EXPECT_FALSE(h[0].handler == nullptr);
572     EXPECT_FALSE(h[0].actions == nullptr);
573     EXPECT_FALSE(h[0].actions->preparation == nullptr);
574     EXPECT_FALSE(h[0].actions->verification == nullptr);
575     auto verifier = reinterpret_cast<SystemdWithStatusFile*>(
576         h[0].actions->verification.get());
577     EXPECT_THAT(verifier->getMode(), "replace-nope");
578     EXPECT_FALSE(h[0].actions->update == nullptr);
579     auto updater =
580         reinterpret_cast<SystemdWithStatusFile*>(h[0].actions->update.get());
581     EXPECT_THAT(updater->getMode(), "replace-fake");
582 }
583 
584 TEST(FirmwareJsonTest, VerifySkipFields)
585 {
586     // In this configuration, nothing happens because all actions are set to
587     // skip.
588     auto j2 = R"(
589         [{
590             "blob" : "/flash/image",
591             "handler" : {
592                 "type" : "file",
593                 "path" : "/run/initramfs/bmc-image"
594             },
595             "actions" : {
596                 "preparation" : {
597                     "type" : "skip"
598                 },
599                 "verification" : {
600                     "type" : "skip"
601                 },
602                 "update" : {
603                     "type" : "skip"
604                 }
605             }
606          }]
607     )"_json;
608 
609     auto h = FirmwareHandlersBuilder().buildHandlerFromJson(j2);
610     EXPECT_EQ(h[0].blobId, "/flash/image");
611     EXPECT_FALSE(h[0].handler == nullptr);
612     EXPECT_FALSE(h[0].actions == nullptr);
613     EXPECT_FALSE(h[0].actions->preparation == nullptr);
614     EXPECT_FALSE(h[0].actions->verification == nullptr);
615     EXPECT_FALSE(h[0].actions->update == nullptr);
616 }
617 
618 } // namespace
619 } // namespace ipmi_flash
620