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 }