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