github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/cmd/syft/cli/options/writer_test.go (about)

     1  package options
     2  
     3  import (
     4  	"io"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/docker/docker/pkg/homedir"
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	"github.com/anchore/syft/syft/sbom"
    13  )
    14  
    15  func Test_MakeSBOMWriter(t *testing.T) {
    16  	tests := []struct {
    17  		outputs []string
    18  		wantErr assert.ErrorAssertionFunc
    19  	}{
    20  		{
    21  			outputs: []string{"json"},
    22  			wantErr: assert.NoError,
    23  		},
    24  		{
    25  			outputs: []string{"table", "json"},
    26  			wantErr: assert.NoError,
    27  		},
    28  		{
    29  			outputs: []string{"unknown"},
    30  			wantErr: func(t assert.TestingT, err error, bla ...interface{}) bool {
    31  				return assert.ErrorContains(t, err, `unsupported output format "unknown", supported formats are: [`)
    32  			},
    33  		},
    34  	}
    35  
    36  	for _, tt := range tests {
    37  		_, err := makeSBOMWriter(tt.outputs, "", "")
    38  		tt.wantErr(t, err)
    39  	}
    40  }
    41  
    42  func dummyEncoder(io.Writer, sbom.SBOM) error {
    43  	return nil
    44  }
    45  
    46  func dummyFormat(name string) sbom.Format {
    47  	return sbom.NewFormat(sbom.AnyVersion, dummyEncoder, nil, nil, sbom.FormatID(name))
    48  }
    49  
    50  func Test_newSBOMMultiWriter(t *testing.T) {
    51  	type writerConfig struct {
    52  		format string
    53  		file   string
    54  	}
    55  
    56  	tmp := t.TempDir()
    57  
    58  	testName := func(options []sbomWriterDescription, err bool) string {
    59  		var out []string
    60  		for _, opt := range options {
    61  			out = append(out, string(opt.Format.ID())+"="+opt.Path)
    62  		}
    63  		errs := ""
    64  		if err {
    65  			errs = "(err)"
    66  		}
    67  		return strings.Join(out, ", ") + errs
    68  	}
    69  
    70  	tests := []struct {
    71  		outputs  []sbomWriterDescription
    72  		err      bool
    73  		expected []writerConfig
    74  	}{
    75  		{
    76  			outputs: []sbomWriterDescription{},
    77  			err:     true,
    78  		},
    79  		{
    80  			outputs: []sbomWriterDescription{
    81  				{
    82  					Format: dummyFormat("table"),
    83  					Path:   "",
    84  				},
    85  			},
    86  			expected: []writerConfig{
    87  				{
    88  					format: "table",
    89  				},
    90  			},
    91  		},
    92  		{
    93  			outputs: []sbomWriterDescription{
    94  				{
    95  					Format: dummyFormat("json"),
    96  				},
    97  			},
    98  			expected: []writerConfig{
    99  				{
   100  					format: "json",
   101  				},
   102  			},
   103  		},
   104  		{
   105  			outputs: []sbomWriterDescription{
   106  				{
   107  					Format: dummyFormat("json"),
   108  					Path:   "test-2.json",
   109  				},
   110  			},
   111  			expected: []writerConfig{
   112  				{
   113  					format: "json",
   114  					file:   "test-2.json",
   115  				},
   116  			},
   117  		},
   118  		{
   119  			outputs: []sbomWriterDescription{
   120  				{
   121  					Format: dummyFormat("json"),
   122  					Path:   "test-3/1.json",
   123  				},
   124  				{
   125  					Format: dummyFormat("spdx-json"),
   126  					Path:   "test-3/2.json",
   127  				},
   128  			},
   129  			expected: []writerConfig{
   130  				{
   131  					format: "json",
   132  					file:   "test-3/1.json",
   133  				},
   134  				{
   135  					format: "spdx-json",
   136  					file:   "test-3/2.json",
   137  				},
   138  			},
   139  		},
   140  		{
   141  			outputs: []sbomWriterDescription{
   142  				{
   143  					Format: dummyFormat("text"),
   144  				},
   145  				{
   146  					Format: dummyFormat("spdx-json"),
   147  					Path:   "test-4.json",
   148  				},
   149  			},
   150  			expected: []writerConfig{
   151  				{
   152  					format: "text",
   153  				},
   154  				{
   155  					format: "spdx-json",
   156  					file:   "test-4.json",
   157  				},
   158  			},
   159  		},
   160  	}
   161  
   162  	for _, test := range tests {
   163  		t.Run(testName(test.outputs, test.err), func(t *testing.T) {
   164  			outputs := test.outputs
   165  			for i := range outputs {
   166  				if outputs[i].Path != "" {
   167  					outputs[i].Path = tmp + outputs[i].Path
   168  				}
   169  			}
   170  
   171  			mw, err := newSBOMMultiWriter(outputs...)
   172  
   173  			if test.err {
   174  				assert.Error(t, err)
   175  				return
   176  			} else {
   177  				assert.NoError(t, err)
   178  			}
   179  
   180  			assert.Len(t, mw.writers, len(test.expected))
   181  
   182  			for i, e := range test.expected {
   183  				switch w := mw.writers[i].(type) {
   184  				case *sbomStreamWriter:
   185  					assert.Equal(t, string(w.format.ID()), e.format)
   186  					if e.file != "" {
   187  						assert.NotNil(t, w.out)
   188  					} else {
   189  						assert.NotNil(t, w.out)
   190  					}
   191  					if e.file != "" {
   192  						assert.FileExists(t, tmp+e.file)
   193  					}
   194  				case *sbomPublisher:
   195  					assert.Equal(t, string(w.format.ID()), e.format)
   196  				default:
   197  					t.Fatalf("unknown writer type: %T", w)
   198  				}
   199  
   200  			}
   201  		})
   202  	}
   203  }
   204  
   205  func Test_newSBOMWriterDescription(t *testing.T) {
   206  	tests := []struct {
   207  		name     string
   208  		path     string
   209  		expected string
   210  	}{
   211  		{
   212  			name:     "expand home dir",
   213  			path:     "~/place.txt",
   214  			expected: filepath.Join(homedir.Get(), "place.txt"),
   215  		},
   216  		{
   217  			name:     "passthrough other paths",
   218  			path:     "/other/place.txt",
   219  			expected: "/other/place.txt",
   220  		},
   221  		{
   222  			name:     "no path",
   223  			path:     "",
   224  			expected: "",
   225  		},
   226  	}
   227  	for _, tt := range tests {
   228  		t.Run(tt.name, func(t *testing.T) {
   229  			o := newSBOMWriterDescription(dummyFormat("table"), tt.path)
   230  			assert.Equal(t, tt.expected, o.Path)
   231  		})
   232  	}
   233  }