github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/builder/writer/human_readable_test.go (about) 1 package writer_test 2 3 import ( 4 "bytes" 5 "errors" 6 "testing" 7 8 "github.com/Masterminds/semver" 9 "github.com/buildpacks/lifecycle/api" 10 "github.com/heroku/color" 11 "github.com/sclevine/spec" 12 "github.com/sclevine/spec/report" 13 14 pubbldr "github.com/buildpacks/pack/builder" 15 "github.com/buildpacks/pack/internal/builder" 16 "github.com/buildpacks/pack/internal/builder/writer" 17 "github.com/buildpacks/pack/internal/config" 18 "github.com/buildpacks/pack/pkg/client" 19 "github.com/buildpacks/pack/pkg/dist" 20 "github.com/buildpacks/pack/pkg/logging" 21 h "github.com/buildpacks/pack/testhelpers" 22 ) 23 24 func TestHumanReadable(t *testing.T) { 25 color.Disable(true) 26 defer color.Disable(false) 27 spec.Run(t, "Builder Writer", testHumanReadable, spec.Parallel(), spec.Report(report.Terminal{})) 28 } 29 30 func testHumanReadable(t *testing.T, when spec.G, it spec.S) { 31 var ( 32 assert = h.NewAssertionManager(t) 33 outBuf bytes.Buffer 34 35 remoteInfo *client.BuilderInfo 36 localInfo *client.BuilderInfo 37 38 expectedRemoteOutput = ` 39 REMOTE: 40 41 Description: Some remote description 42 43 Created By: 44 Name: Pack CLI 45 Version: 1.2.3 46 47 Trusted: No 48 49 Stack: 50 ID: test.stack.id 51 52 Lifecycle: 53 Version: 6.7.8 54 Buildpack APIs: 55 Deprecated: (none) 56 Supported: 1.2, 2.3 57 Platform APIs: 58 Deprecated: 0.1, 1.2 59 Supported: 4.5 60 61 Run Images: 62 first/local (user-configured) 63 second/local (user-configured) 64 some/run-image 65 first/default 66 second/default 67 68 Buildpacks: 69 ID NAME VERSION HOMEPAGE 70 test.top.nested - test.top.nested.version - 71 test.nested - http://geocities.com/top-bp 72 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 73 test.bp.two - test.bp.two.version - 74 test.bp.three - test.bp.three.version - 75 76 Detection Order: 77 ├ Group #1: 78 │ ├ test.top.nested@test.top.nested.version 79 │ │ └ Group #1: 80 │ │ ├ test.nested 81 │ │ │ └ Group #1: 82 │ │ │ └ test.bp.one@test.bp.one.version (optional) 83 │ │ ├ test.bp.three@test.bp.three.version (optional) 84 │ │ └ test.nested.two@test.nested.two.version 85 │ │ └ Group #2: 86 │ │ └ test.bp.one@test.bp.one.version (optional)[cyclic] 87 │ └ test.bp.two@test.bp.two.version (optional) 88 └ test.bp.three@test.bp.three.version 89 90 Extensions: 91 ID NAME VERSION HOMEPAGE 92 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 93 test.bp.two - test.bp.two.version - 94 test.bp.three - test.bp.three.version - 95 96 Detection Order (Extensions): 97 ├ test.top.nested@test.top.nested.version 98 ├ test.bp.one@test.bp.one.version (optional) 99 ├ test.bp.two@test.bp.two.version (optional) 100 └ test.bp.three@test.bp.three.version 101 ` 102 expectedRemoteOutputWithoutExtensions = ` 103 REMOTE: 104 105 Description: Some remote description 106 107 Created By: 108 Name: Pack CLI 109 Version: 1.2.3 110 111 Trusted: No 112 113 Stack: 114 ID: test.stack.id 115 116 Lifecycle: 117 Version: 6.7.8 118 Buildpack APIs: 119 Deprecated: (none) 120 Supported: 1.2, 2.3 121 Platform APIs: 122 Deprecated: 0.1, 1.2 123 Supported: 4.5 124 125 Run Images: 126 first/local (user-configured) 127 second/local (user-configured) 128 some/run-image 129 first/default 130 second/default 131 132 Buildpacks: 133 ID NAME VERSION HOMEPAGE 134 test.top.nested - test.top.nested.version - 135 test.nested - http://geocities.com/top-bp 136 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 137 test.bp.two - test.bp.two.version - 138 test.bp.three - test.bp.three.version - 139 140 Detection Order: 141 ├ Group #1: 142 │ ├ test.top.nested@test.top.nested.version 143 │ │ └ Group #1: 144 │ │ ├ test.nested 145 │ │ │ └ Group #1: 146 │ │ │ └ test.bp.one@test.bp.one.version (optional) 147 │ │ ├ test.bp.three@test.bp.three.version (optional) 148 │ │ └ test.nested.two@test.nested.two.version 149 │ │ └ Group #2: 150 │ │ └ test.bp.one@test.bp.one.version (optional)[cyclic] 151 │ └ test.bp.two@test.bp.two.version (optional) 152 └ test.bp.three@test.bp.three.version 153 ` 154 155 expectedLocalOutput = ` 156 LOCAL: 157 158 Description: Some local description 159 160 Created By: 161 Name: Pack CLI 162 Version: 4.5.6 163 164 Trusted: No 165 166 Stack: 167 ID: test.stack.id 168 169 Lifecycle: 170 Version: 4.5.6 171 Buildpack APIs: 172 Deprecated: 4.5, 6.7 173 Supported: 8.9, 10.11 174 Platform APIs: 175 Deprecated: (none) 176 Supported: 7.8 177 178 Run Images: 179 first/local (user-configured) 180 second/local (user-configured) 181 some/run-image 182 first/local-default 183 second/local-default 184 185 Buildpacks: 186 ID NAME VERSION HOMEPAGE 187 test.top.nested - test.top.nested.version - 188 test.nested - http://geocities.com/top-bp 189 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 190 test.bp.two - test.bp.two.version - 191 test.bp.three - test.bp.three.version - 192 193 Detection Order: 194 ├ Group #1: 195 │ ├ test.top.nested@test.top.nested.version 196 │ │ └ Group #1: 197 │ │ ├ test.nested 198 │ │ │ └ Group #1: 199 │ │ │ └ test.bp.one@test.bp.one.version (optional) 200 │ │ ├ test.bp.three@test.bp.three.version (optional) 201 │ │ └ test.nested.two@test.nested.two.version 202 │ │ └ Group #2: 203 │ │ └ test.bp.one@test.bp.one.version (optional)[cyclic] 204 │ └ test.bp.two@test.bp.two.version (optional) 205 └ test.bp.three@test.bp.three.version 206 207 Extensions: 208 ID NAME VERSION HOMEPAGE 209 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 210 test.bp.two - test.bp.two.version - 211 test.bp.three - test.bp.three.version - 212 213 Detection Order (Extensions): 214 ├ test.top.nested@test.top.nested.version 215 ├ test.bp.one@test.bp.one.version (optional) 216 ├ test.bp.two@test.bp.two.version (optional) 217 └ test.bp.three@test.bp.three.version 218 ` 219 220 expectedLocalOutputWithoutExtensions = ` 221 LOCAL: 222 223 Description: Some local description 224 225 Created By: 226 Name: Pack CLI 227 Version: 4.5.6 228 229 Trusted: No 230 231 Stack: 232 ID: test.stack.id 233 234 Lifecycle: 235 Version: 4.5.6 236 Buildpack APIs: 237 Deprecated: 4.5, 6.7 238 Supported: 8.9, 10.11 239 Platform APIs: 240 Deprecated: (none) 241 Supported: 7.8 242 243 Run Images: 244 first/local (user-configured) 245 second/local (user-configured) 246 some/run-image 247 first/local-default 248 second/local-default 249 250 Buildpacks: 251 ID NAME VERSION HOMEPAGE 252 test.top.nested - test.top.nested.version - 253 test.nested - http://geocities.com/top-bp 254 test.bp.one - test.bp.one.version http://geocities.com/cool-bp 255 test.bp.two - test.bp.two.version - 256 test.bp.three - test.bp.three.version - 257 258 Detection Order: 259 ├ Group #1: 260 │ ├ test.top.nested@test.top.nested.version 261 │ │ └ Group #1: 262 │ │ ├ test.nested 263 │ │ │ └ Group #1: 264 │ │ │ └ test.bp.one@test.bp.one.version (optional) 265 │ │ ├ test.bp.three@test.bp.three.version (optional) 266 │ │ └ test.nested.two@test.nested.two.version 267 │ │ └ Group #2: 268 │ │ └ test.bp.one@test.bp.one.version (optional)[cyclic] 269 │ └ test.bp.two@test.bp.two.version (optional) 270 └ test.bp.three@test.bp.three.version 271 ` 272 273 expectedVerboseStack = ` 274 Stack: 275 ID: test.stack.id 276 Mixins: 277 mixin1 278 mixin2 279 build:mixin3 280 build:mixin4 281 ` 282 expectedNilLifecycleVersion = ` 283 Lifecycle: 284 Version: (none) 285 ` 286 expectedEmptyRunImages = ` 287 Run Images: 288 (none) 289 ` 290 expectedEmptyBuildpacks = ` 291 Buildpacks: 292 (none) 293 ` 294 expectedEmptyOrder = ` 295 Detection Order: 296 (none) 297 ` 298 expectedEmptyOrderExt = ` 299 Detection Order (Extensions): 300 (none) 301 ` 302 expectedMissingLocalInfo = ` 303 LOCAL: 304 (not present) 305 ` 306 expectedMissingRemoteInfo = ` 307 REMOTE: 308 (not present) 309 ` 310 ) 311 312 when("Print", func() { 313 it.Before(func() { 314 remoteInfo = &client.BuilderInfo{ 315 Description: "Some remote description", 316 Stack: "test.stack.id", 317 Mixins: []string{"mixin1", "mixin2", "build:mixin3", "build:mixin4"}, 318 RunImages: []pubbldr.RunImageConfig{{Image: "some/run-image", Mirrors: []string{"first/default", "second/default"}}}, 319 Buildpacks: buildpacks, 320 Order: order, 321 Extensions: extensions, 322 OrderExtensions: orderExtensions, 323 BuildpackLayers: dist.ModuleLayers{}, 324 Lifecycle: builder.LifecycleDescriptor{ 325 Info: builder.LifecycleInfo{ 326 Version: &builder.Version{ 327 Version: *semver.MustParse("6.7.8"), 328 }, 329 }, 330 APIs: builder.LifecycleAPIs{ 331 Buildpack: builder.APIVersions{ 332 Deprecated: nil, 333 Supported: builder.APISet{api.MustParse("1.2"), api.MustParse("2.3")}, 334 }, 335 Platform: builder.APIVersions{ 336 Deprecated: builder.APISet{api.MustParse("0.1"), api.MustParse("1.2")}, 337 Supported: builder.APISet{api.MustParse("4.5")}, 338 }, 339 }, 340 }, 341 CreatedBy: builder.CreatorMetadata{ 342 Name: "Pack CLI", 343 Version: "1.2.3", 344 }, 345 } 346 347 localInfo = &client.BuilderInfo{ 348 Description: "Some local description", 349 Stack: "test.stack.id", 350 Mixins: []string{"mixin1", "mixin2", "build:mixin3", "build:mixin4"}, 351 RunImages: []pubbldr.RunImageConfig{{Image: "some/run-image", Mirrors: []string{"first/local-default", "second/local-default"}}}, 352 Buildpacks: buildpacks, 353 Order: order, 354 Extensions: extensions, 355 OrderExtensions: orderExtensions, 356 BuildpackLayers: dist.ModuleLayers{}, 357 Lifecycle: builder.LifecycleDescriptor{ 358 Info: builder.LifecycleInfo{ 359 Version: &builder.Version{ 360 Version: *semver.MustParse("4.5.6"), 361 }, 362 }, 363 APIs: builder.LifecycleAPIs{ 364 Buildpack: builder.APIVersions{ 365 Deprecated: builder.APISet{api.MustParse("4.5"), api.MustParse("6.7")}, 366 Supported: builder.APISet{api.MustParse("8.9"), api.MustParse("10.11")}, 367 }, 368 Platform: builder.APIVersions{ 369 Deprecated: nil, 370 Supported: builder.APISet{api.MustParse("7.8")}, 371 }, 372 }, 373 }, 374 CreatedBy: builder.CreatorMetadata{ 375 Name: "Pack CLI", 376 Version: "4.5.6", 377 }, 378 } 379 380 outBuf = bytes.Buffer{} 381 }) 382 383 it("prints both local and remote builders in a human readable format", func() { 384 humanReadableWriter := writer.NewHumanReadable() 385 386 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 387 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 388 assert.Nil(err) 389 390 assert.Contains(outBuf.String(), "Inspecting builder: 'test-builder'") 391 assert.Contains(outBuf.String(), expectedRemoteOutput) 392 assert.Contains(outBuf.String(), expectedLocalOutput) 393 }) 394 395 when("builder is default", func() { 396 it("prints inspecting default builder", func() { 397 defaultSharedBuildInfo := sharedBuilderInfo 398 defaultSharedBuildInfo.IsDefault = true 399 400 humanReadableWriter := writer.NewHumanReadable() 401 402 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 403 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, defaultSharedBuildInfo) 404 assert.Nil(err) 405 406 assert.Contains(outBuf.String(), "Inspecting default builder: 'test-builder'") 407 }) 408 }) 409 410 when("builder doesn't exist locally or remotely", func() { 411 it("returns an error", func() { 412 localInfo = nil 413 remoteInfo = nil 414 415 humanReadableWriter := writer.NewHumanReadable() 416 417 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 418 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 419 assert.ErrorWithMessage(err, "unable to find builder 'test-builder' locally or remotely") 420 }) 421 }) 422 423 when("builder doesn't exist locally", func() { 424 it("shows not present for local builder, and normal output for remote", func() { 425 localInfo = nil 426 427 humanReadableWriter := writer.NewHumanReadable() 428 429 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 430 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 431 assert.Nil(err) 432 433 assert.Contains(outBuf.String(), expectedMissingLocalInfo) 434 assert.Contains(outBuf.String(), expectedRemoteOutput) 435 }) 436 }) 437 438 when("builder doesn't exist remotely", func() { 439 it("shows not present for remote builder, and normal output for local", func() { 440 remoteInfo = nil 441 442 humanReadableWriter := writer.NewHumanReadable() 443 444 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 445 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 446 assert.Nil(err) 447 448 assert.Contains(outBuf.String(), expectedMissingRemoteInfo) 449 assert.Contains(outBuf.String(), expectedLocalOutput) 450 }) 451 }) 452 453 when("localErr is an error", func() { 454 it("error is logged, local info is not displayed, but remote info is", func() { 455 errorMessage := "failed to retrieve local info" 456 457 humanReadableWriter := writer.NewHumanReadable() 458 459 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 460 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, errors.New(errorMessage), nil, sharedBuilderInfo) 461 assert.Nil(err) 462 463 assert.Contains(outBuf.String(), errorMessage) 464 assert.NotContains(outBuf.String(), expectedLocalOutput) 465 assert.Contains(outBuf.String(), expectedRemoteOutput) 466 }) 467 }) 468 469 when("remoteErr is an error", func() { 470 it("error is logged, remote info is not displayed, but local info is", func() { 471 errorMessage := "failed to retrieve remote info" 472 473 humanReadableWriter := writer.NewHumanReadable() 474 475 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 476 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, errors.New(errorMessage), sharedBuilderInfo) 477 assert.Nil(err) 478 479 assert.Contains(outBuf.String(), errorMessage) 480 assert.NotContains(outBuf.String(), expectedRemoteOutput) 481 assert.Contains(outBuf.String(), expectedLocalOutput) 482 }) 483 }) 484 485 when("description is blank", func() { 486 it("doesn't print the description block", func() { 487 localInfo.Description = "" 488 remoteInfo.Description = "" 489 490 humanReadableWriter := writer.NewHumanReadable() 491 492 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 493 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 494 assert.Nil(err) 495 496 assert.NotContains(outBuf.String(), "Description:") 497 }) 498 }) 499 500 when("created by name is blank", func() { 501 it("doesn't print created by block", func() { 502 localInfo.CreatedBy.Name = "" 503 remoteInfo.CreatedBy.Name = "" 504 505 humanReadableWriter := writer.NewHumanReadable() 506 507 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 508 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 509 assert.Nil(err) 510 511 assert.NotContains(outBuf.String(), "Created By:") 512 }) 513 }) 514 515 when("logger is verbose", func() { 516 it("displays mixins associated with the stack", func() { 517 humanReadableWriter := writer.NewHumanReadable() 518 519 logger := logging.NewLogWithWriters(&outBuf, &outBuf, logging.WithVerbose()) 520 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 521 assert.Nil(err) 522 523 assert.Contains(outBuf.String(), expectedVerboseStack) 524 }) 525 }) 526 527 when("lifecycle version is not set", func() { 528 it("displays lifecycle version as (none) and warns that version if not set", func() { 529 localInfo.Lifecycle.Info.Version = nil 530 remoteInfo.Lifecycle.Info.Version = nil 531 532 humanReadableWriter := writer.NewHumanReadable() 533 534 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 535 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 536 assert.Nil(err) 537 538 assert.Contains(outBuf.String(), expectedNilLifecycleVersion) 539 assert.Contains(outBuf.String(), "test-builder does not specify a Lifecycle version") 540 }) 541 }) 542 543 when("there are no supported buildpack APIs specified", func() { 544 it("prints a warning", func() { 545 localInfo.Lifecycle.APIs.Buildpack.Supported = builder.APISet{} 546 remoteInfo.Lifecycle.APIs.Buildpack.Supported = builder.APISet{} 547 548 humanReadableWriter := writer.NewHumanReadable() 549 550 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 551 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 552 assert.Nil(err) 553 554 assert.Contains(outBuf.String(), "test-builder does not specify supported Lifecycle Buildpack APIs") 555 }) 556 }) 557 558 when("there are no supported platform APIs specified", func() { 559 it("prints a warning", func() { 560 localInfo.Lifecycle.APIs.Platform.Supported = builder.APISet{} 561 remoteInfo.Lifecycle.APIs.Platform.Supported = builder.APISet{} 562 563 humanReadableWriter := writer.NewHumanReadable() 564 565 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 566 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 567 assert.Nil(err) 568 569 assert.Contains(outBuf.String(), "test-builder does not specify supported Lifecycle Platform APIs") 570 }) 571 }) 572 573 when("no run images are specified", func() { 574 it("displays run images as (none) and warns about unset run image", func() { 575 localInfo.RunImages = []pubbldr.RunImageConfig{} 576 remoteInfo.RunImages = []pubbldr.RunImageConfig{} 577 emptyLocalRunImages := []config.RunImage{} 578 579 humanReadableWriter := writer.NewHumanReadable() 580 581 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 582 err := humanReadableWriter.Print(logger, emptyLocalRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 583 assert.Nil(err) 584 585 assert.Contains(outBuf.String(), expectedEmptyRunImages) 586 assert.Contains(outBuf.String(), "test-builder does not specify a run image") 587 assert.Contains(outBuf.String(), "Users must build with an explicitly specified run image") 588 }) 589 }) 590 591 when("no buildpacks are specified", func() { 592 it("displays buildpacks as (none) and prints warnings", func() { 593 localInfo.Buildpacks = []dist.ModuleInfo{} 594 remoteInfo.Buildpacks = []dist.ModuleInfo{} 595 596 humanReadableWriter := writer.NewHumanReadable() 597 598 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 599 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 600 assert.Nil(err) 601 602 assert.Contains(outBuf.String(), expectedEmptyBuildpacks) 603 assert.Contains(outBuf.String(), "test-builder has no buildpacks") 604 assert.Contains(outBuf.String(), "Users must supply buildpacks from the host machine") 605 }) 606 }) 607 608 when("no extensions are specified", func() { 609 it("displays no extensions as (none)", func() { 610 localInfo.Extensions = []dist.ModuleInfo{} 611 remoteInfo.Extensions = []dist.ModuleInfo{} 612 613 humanReadableWriter := writer.NewHumanReadable() 614 615 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 616 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 617 assert.Nil(err) 618 619 assert.Contains(outBuf.String(), "Inspecting builder: 'test-builder'") 620 assert.Contains(outBuf.String(), expectedRemoteOutputWithoutExtensions) 621 assert.Contains(outBuf.String(), expectedLocalOutputWithoutExtensions) 622 }) 623 }) 624 625 when("multiple top level groups", func() { 626 it("displays order correctly", func() { 627 628 }) 629 }) 630 631 when("no detection order is specified", func() { 632 it("displays detection order as (none) and prints warnings", func() { 633 localInfo.Order = pubbldr.DetectionOrder{} 634 remoteInfo.Order = pubbldr.DetectionOrder{} 635 636 humanReadableWriter := writer.NewHumanReadable() 637 638 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 639 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 640 assert.Nil(err) 641 642 assert.Contains(outBuf.String(), expectedEmptyOrder) 643 assert.Contains(outBuf.String(), "test-builder has no buildpacks") 644 assert.Contains(outBuf.String(), "Users must build with explicitly specified buildpacks") 645 }) 646 }) 647 648 when("no detection order for extension is specified", func() { 649 it("displays detection order for extensions as (none)", func() { 650 localInfo.OrderExtensions = pubbldr.DetectionOrder{} 651 remoteInfo.OrderExtensions = pubbldr.DetectionOrder{} 652 653 humanReadableWriter := writer.NewHumanReadable() 654 655 logger := logging.NewLogWithWriters(&outBuf, &outBuf) 656 err := humanReadableWriter.Print(logger, localRunImages, localInfo, remoteInfo, nil, nil, sharedBuilderInfo) 657 assert.Nil(err) 658 659 assert.Contains(outBuf.String(), expectedEmptyOrderExt) 660 }) 661 }) 662 }) 663 }