github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/internal/fileresolver/excluding_file_test.go (about) 1 package fileresolver 2 3 import ( 4 "io" 5 "strings" 6 "testing" 7 8 "github.com/nextlinux/gosbom/gosbom/file" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestExcludingResolver(t *testing.T) { 13 14 tests := []struct { 15 name string 16 locations []string 17 excludeFn excludeFn 18 expected []string 19 }{ 20 { 21 name: "keeps locations", 22 locations: []string{"a", "b", "c"}, 23 excludeFn: func(s string) bool { 24 return false 25 }, 26 expected: []string{"a", "b", "c"}, 27 }, 28 { 29 name: "removes locations", 30 locations: []string{"d", "e", "f"}, 31 excludeFn: func(s string) bool { 32 return true 33 }, 34 expected: []string{}, 35 }, 36 { 37 name: "removes first match", 38 locations: []string{"g", "h", "i"}, 39 excludeFn: func(s string) bool { 40 return s == "g" 41 }, 42 expected: []string{"h", "i"}, 43 }, 44 { 45 name: "removes last match", 46 locations: []string{"j", "k", "l"}, 47 excludeFn: func(s string) bool { 48 return s == "l" 49 }, 50 expected: []string{"j", "k"}, 51 }, 52 } 53 for _, test := range tests { 54 t.Run(test.name, func(t *testing.T) { 55 resolver := &mockResolver{ 56 locations: test.locations, 57 } 58 er := NewExcluding(resolver, test.excludeFn) 59 60 locations, _ := er.FilesByPath() 61 assert.ElementsMatch(t, locationPaths(locations), test.expected) 62 63 locations, _ = er.FilesByGlob() 64 assert.ElementsMatch(t, locationPaths(locations), test.expected) 65 66 locations, _ = er.FilesByMIMEType() 67 assert.ElementsMatch(t, locationPaths(locations), test.expected) 68 69 locations = []file.Location{} 70 71 channel := er.AllLocations() 72 for location := range channel { 73 locations = append(locations, location) 74 } 75 assert.ElementsMatch(t, locationPaths(locations), test.expected) 76 77 diff := difference(test.locations, test.expected) 78 79 for _, path := range diff { 80 assert.False(t, er.HasPath(path)) 81 c, err := er.FileContentsByLocation(file.NewLocation(path)) 82 assert.Nil(t, c) 83 assert.Error(t, err) 84 m, err := er.FileMetadataByLocation(file.NewLocation(path)) 85 assert.Empty(t, m.LinkDestination) 86 assert.Error(t, err) 87 l := er.RelativeFileByPath(file.NewLocation(""), path) 88 assert.Nil(t, l) 89 } 90 91 for _, path := range test.expected { 92 assert.True(t, er.HasPath(path)) 93 c, err := er.FileContentsByLocation(file.NewLocation(path)) 94 assert.NotNil(t, c) 95 assert.Nil(t, err) 96 m, err := er.FileMetadataByLocation(file.NewLocation(path)) 97 assert.NotEmpty(t, m.LinkDestination) 98 assert.Nil(t, err) 99 l := er.RelativeFileByPath(file.NewLocation(""), path) 100 assert.NotNil(t, l) 101 } 102 }) 103 } 104 } 105 106 // difference returns the elements in `a` that aren't in `b`. 107 func difference(a, b []string) []string { 108 mb := make(map[string]struct{}, len(b)) 109 for _, x := range b { 110 mb[x] = struct{}{} 111 } 112 var diff []string 113 for _, x := range a { 114 if _, found := mb[x]; !found { 115 diff = append(diff, x) 116 } 117 } 118 return diff 119 } 120 121 func locationPaths(locations []file.Location) []string { 122 paths := []string{} 123 for _, l := range locations { 124 paths = append(paths, l.RealPath) 125 } 126 return paths 127 } 128 129 type mockResolver struct { 130 locations []string 131 } 132 133 func (r *mockResolver) getLocations() ([]file.Location, error) { 134 out := []file.Location{} 135 for _, path := range r.locations { 136 out = append(out, file.NewLocation(path)) 137 } 138 return out, nil 139 } 140 141 func (r *mockResolver) FileContentsByLocation(_ file.Location) (io.ReadCloser, error) { 142 return io.NopCloser(strings.NewReader("Hello, world!")), nil 143 } 144 145 func (r *mockResolver) FileMetadataByLocation(_ file.Location) (file.Metadata, error) { 146 return file.Metadata{ 147 LinkDestination: "MOCK", 148 }, nil 149 } 150 151 func (r *mockResolver) HasPath(_ string) bool { 152 return true 153 } 154 155 func (r *mockResolver) FilesByPath(_ ...string) ([]file.Location, error) { 156 return r.getLocations() 157 } 158 159 func (r *mockResolver) FilesByGlob(_ ...string) ([]file.Location, error) { 160 return r.getLocations() 161 } 162 163 func (r *mockResolver) FilesByMIMEType(_ ...string) ([]file.Location, error) { 164 return r.getLocations() 165 } 166 167 func (r *mockResolver) FilesByExtension(_ ...string) ([]file.Location, error) { 168 return r.getLocations() 169 } 170 171 func (r *mockResolver) FilesByBasename(_ ...string) ([]file.Location, error) { 172 return r.getLocations() 173 } 174 175 func (r *mockResolver) FilesByBasenameGlob(_ ...string) ([]file.Location, error) { 176 return r.getLocations() 177 } 178 179 func (r *mockResolver) RelativeFileByPath(_ file.Location, path string) *file.Location { 180 l := file.NewLocation(path) 181 return &l 182 } 183 184 func (r *mockResolver) AllLocations() <-chan file.Location { 185 c := make(chan file.Location) 186 go func() { 187 defer close(c) 188 locations, _ := r.getLocations() 189 for _, location := range locations { 190 c <- location 191 } 192 }() 193 return c 194 }