github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/inspectimage/writer/structured_format_test.go (about)

     1  package writer_test
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/heroku/color"
    10  	"github.com/sclevine/spec"
    11  	"github.com/sclevine/spec/report"
    12  
    13  	"github.com/buildpacks/lifecycle/buildpack"
    14  
    15  	"github.com/buildpacks/pack/internal/config"
    16  	"github.com/buildpacks/pack/internal/inspectimage"
    17  	"github.com/buildpacks/pack/internal/inspectimage/writer"
    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 TestStructuredFormat(t *testing.T) {
    25  	color.Disable(true)
    26  	defer color.Disable(false)
    27  	spec.Run(t, "StructuredFormat Writer", testStructuredFormat, spec.Parallel(), spec.Report(report.Terminal{}))
    28  }
    29  
    30  func testStructuredFormat(t *testing.T, when spec.G, it spec.S) {
    31  	var (
    32  		assert = h.NewAssertionManager(t)
    33  		outBuf bytes.Buffer
    34  
    35  		remoteInfo                    *client.ImageInfo
    36  		localInfo                     *client.ImageInfo
    37  		remoteWithExtensionInfo       *client.ImageInfo
    38  		localWithExtensionInfo        *client.ImageInfo
    39  		localInfoWithExtensionDisplay *inspectimage.InfoDisplay
    40  	)
    41  
    42  	when("Print", func() {
    43  		it.Before(func() {
    44  			remoteInfo = &client.ImageInfo{}
    45  			localInfo = &client.ImageInfo{}
    46  			remoteWithExtensionInfo = &client.ImageInfo{}
    47  			localWithExtensionInfo = &client.ImageInfo{
    48  				StackID: "test.stack.id.local",
    49  				Buildpacks: []buildpack.GroupElement{
    50  					{ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"},
    51  				},
    52  				Extensions: []buildpack.GroupElement{
    53  					{ID: "test.bp.one.local", Version: "1.0.0", Homepage: "https://some-homepage-one"},
    54  				},
    55  			}
    56  			localInfoWithExtensionDisplay = &inspectimage.InfoDisplay{
    57  				StackID: "test.stack.id.local",
    58  				Buildpacks: []dist.ModuleInfo{
    59  					{
    60  						ID:       "test.bp.one.local",
    61  						Version:  "1.0.0",
    62  						Homepage: "https://some-homepage-one",
    63  					},
    64  				},
    65  				Extensions: []dist.ModuleInfo{
    66  					{
    67  						ID:       "test.bp.one.local",
    68  						Version:  "1.0.0",
    69  						Homepage: "https://some-homepage-one",
    70  					},
    71  				},
    72  			}
    73  			outBuf = bytes.Buffer{}
    74  		})
    75  
    76  		// Just test error cases, all error-free cases will be tested in JSON, TOML, and YAML subclasses.
    77  		when("failure cases", func() {
    78  			when("both info objects are nil", func() {
    79  				it("displays a 'missing image' error message'", func() {
    80  					sharedImageInfo := inspectimage.GeneralInfo{
    81  						Name:            "missing-image",
    82  						RunImageMirrors: []config.RunImage{},
    83  					}
    84  
    85  					structuredWriter := writer.StructuredFormat{
    86  						MarshalFunc: testMarshalFunc,
    87  					}
    88  
    89  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
    90  					err := structuredWriter.Print(logger, sharedImageInfo, nil, nil, nil, nil)
    91  					assert.ErrorWithMessage(err, fmt.Sprintf("unable to find image '%s' locally or remotely", "missing-image"))
    92  				})
    93  			})
    94  			when("a localErr is passed to Print", func() {
    95  				it("still prints remote information", func() {
    96  					sharedImageInfo := inspectimage.GeneralInfo{
    97  						Name:            "localErr-image",
    98  						RunImageMirrors: []config.RunImage{},
    99  					}
   100  					structuredWriter := writer.StructuredFormat{
   101  						MarshalFunc: testMarshalFunc,
   102  					}
   103  
   104  					localErr := errors.New("a local error occurred")
   105  
   106  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   107  					err := structuredWriter.Print(logger, sharedImageInfo, nil, remoteInfo, localErr, nil)
   108  					assert.ErrorWithMessage(err, "preparing output for 'localErr-image': a local error occurred")
   109  				})
   110  			})
   111  
   112  			when("a localWithExtension is passed to Print", func() {
   113  				it("prints localWithExtension information", func() {
   114  					var marshalInput interface{}
   115  					sharedImageInfo := inspectimage.GeneralInfo{
   116  						Name:            "localExtension-image",
   117  						RunImageMirrors: []config.RunImage{},
   118  					}
   119  					structuredWriter := writer.StructuredFormat{
   120  						MarshalFunc: func(i interface{}) ([]byte, error) {
   121  							marshalInput = i
   122  							return []byte("marshalled"), nil
   123  						},
   124  					}
   125  
   126  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   127  					err := structuredWriter.Print(logger, sharedImageInfo, localWithExtensionInfo, nil, nil, nil)
   128  					assert.Nil(err)
   129  					assert.Equal(marshalInput, inspectimage.InspectOutput{
   130  						ImageName: "localExtension-image",
   131  						Local:     localInfoWithExtensionDisplay,
   132  					})
   133  				})
   134  			})
   135  
   136  			when("a localErr is passed to Print", func() {
   137  				it("still prints remote information", func() {
   138  					sharedImageInfo := inspectimage.GeneralInfo{
   139  						Name:            "localErr-image",
   140  						RunImageMirrors: []config.RunImage{},
   141  					}
   142  					structuredWriter := writer.StructuredFormat{
   143  						MarshalFunc: testMarshalFunc,
   144  					}
   145  
   146  					localErr := errors.New("a local error occurred")
   147  
   148  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   149  					err := structuredWriter.Print(logger, sharedImageInfo, nil, remoteWithExtensionInfo, localErr, nil)
   150  					assert.ErrorWithMessage(err, "preparing output for 'localErr-image': a local error occurred")
   151  				})
   152  			})
   153  
   154  			when("a remoteErr is passed to print", func() {
   155  				it("still prints local information", func() {
   156  					sharedImageInfo := inspectimage.GeneralInfo{
   157  						Name:            "remoteErr-image",
   158  						RunImageMirrors: []config.RunImage{},
   159  					}
   160  					structuredWriter := writer.StructuredFormat{
   161  						MarshalFunc: testMarshalFunc,
   162  					}
   163  
   164  					remoteErr := errors.New("a remote error occurred")
   165  
   166  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   167  					err := structuredWriter.Print(logger, sharedImageInfo, localInfo, nil, nil, remoteErr)
   168  					assert.ErrorWithMessage(err, "preparing output for 'remoteErr-image': a remote error occurred")
   169  				})
   170  			})
   171  
   172  			when("a remoteErr is passed to print", func() {
   173  				it("still prints local information", func() {
   174  					sharedImageInfo := inspectimage.GeneralInfo{
   175  						Name:            "remoteErr-image",
   176  						RunImageMirrors: []config.RunImage{},
   177  					}
   178  					structuredWriter := writer.StructuredFormat{
   179  						MarshalFunc: testMarshalFunc,
   180  					}
   181  
   182  					remoteErr := errors.New("a remote error occurred")
   183  
   184  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   185  					err := structuredWriter.Print(logger, sharedImageInfo, localWithExtensionInfo, nil, nil, remoteErr)
   186  					assert.ErrorWithMessage(err, "preparing output for 'remoteErr-image': a remote error occurred")
   187  				})
   188  			})
   189  		})
   190  	})
   191  }
   192  
   193  //
   194  // testfunctions and helpers
   195  //
   196  
   197  func testMarshalFunc(i interface{}) ([]byte, error) {
   198  	return []byte("marshalled"), nil
   199  }