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