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