github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/artifact/repo/git_test.go (about) 1 //go:build unix 2 3 package repo 4 5 import ( 6 "context" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/sosedoff/gitkit" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 "github.com/devseccon/trivy/pkg/fanal/artifact" 15 "github.com/devseccon/trivy/pkg/fanal/cache" 16 "github.com/devseccon/trivy/pkg/fanal/types" 17 18 _ "github.com/devseccon/trivy/pkg/fanal/analyzer/config/all" 19 _ "github.com/devseccon/trivy/pkg/fanal/analyzer/secret" 20 ) 21 22 func setupGitServer() (*httptest.Server, error) { 23 service := gitkit.New(gitkit.Config{ 24 Dir: "./testdata", 25 AutoCreate: false, 26 }) 27 28 if err := service.Setup(); err != nil { 29 return nil, err 30 } 31 32 ts := httptest.NewServer(service) 33 34 return ts, nil 35 } 36 37 func TestNewArtifact(t *testing.T) { 38 ts, err := setupGitServer() 39 require.NoError(t, err) 40 defer ts.Close() 41 42 type args struct { 43 target string 44 c cache.ArtifactCache 45 noProgress bool 46 repoBranch string 47 repoTag string 48 repoCommit string 49 } 50 tests := []struct { 51 name string 52 args args 53 assertion assert.ErrorAssertionFunc 54 }{ 55 { 56 name: "remote repo", 57 args: args{ 58 target: ts.URL + "/test.git", 59 c: nil, 60 noProgress: false, 61 }, 62 assertion: assert.NoError, 63 }, 64 { 65 name: "local repo", 66 args: args{ 67 target: "testdata", 68 c: nil, 69 noProgress: false, 70 }, 71 assertion: assert.NoError, 72 }, 73 { 74 name: "happy noProgress", 75 args: args{ 76 target: ts.URL + "/test.git", 77 c: nil, 78 noProgress: true, 79 }, 80 assertion: assert.NoError, 81 }, 82 { 83 name: "branch", 84 args: args{ 85 target: ts.URL + "/test.git", 86 c: nil, 87 repoBranch: "valid-branch", 88 }, 89 assertion: assert.NoError, 90 }, 91 { 92 name: "tag", 93 args: args{ 94 target: ts.URL + "/test.git", 95 c: nil, 96 repoTag: "v1.0.0", 97 }, 98 assertion: assert.NoError, 99 }, 100 { 101 name: "commit", 102 args: args{ 103 target: ts.URL + "/test.git", 104 c: nil, 105 repoCommit: "6ac152fe2b87cb5e243414df71790a32912e778d", 106 }, 107 assertion: assert.NoError, 108 }, 109 { 110 name: "sad path", 111 args: args{ 112 target: ts.URL + "/unknown.git", 113 c: nil, 114 noProgress: false, 115 }, 116 assertion: func(t assert.TestingT, err error, args ...interface{}) bool { 117 return assert.ErrorContains(t, err, "repository not found") 118 }, 119 }, 120 { 121 name: "invalid url", 122 args: args{ 123 target: "ht tp://foo.com", 124 c: nil, 125 noProgress: false, 126 }, 127 assertion: func(t assert.TestingT, err error, args ...interface{}) bool { 128 return assert.ErrorContains(t, err, "url parse error") 129 }, 130 }, 131 { 132 name: "invalid branch", 133 args: args{ 134 target: ts.URL + "/test.git", 135 c: nil, 136 repoBranch: "invalid-branch", 137 }, 138 assertion: func(t assert.TestingT, err error, args ...interface{}) bool { 139 return assert.ErrorContains(t, err, `couldn't find remote ref "refs/heads/invalid-branch"`) 140 }, 141 }, 142 { 143 name: "invalid tag", 144 args: args{ 145 target: ts.URL + "/test.git", 146 c: nil, 147 repoTag: "v1.0.9", 148 }, 149 assertion: func(t assert.TestingT, err error, args ...interface{}) bool { 150 return assert.ErrorContains(t, err, `couldn't find remote ref "refs/tags/v1.0.9"`) 151 }, 152 }, 153 { 154 name: "invalid commit", 155 args: args{ 156 target: ts.URL + "/test.git", 157 c: nil, 158 repoCommit: "6ac152fe2b87cb5e243414df71790a32912e778e", 159 }, 160 assertion: func(t assert.TestingT, err error, args ...interface{}) bool { 161 return assert.ErrorContains(t, err, "git checkout error: object not found") 162 }, 163 }, 164 } 165 166 for _, tt := range tests { 167 t.Run(tt.name, func(t *testing.T) { 168 _, cleanup, err := NewArtifact(tt.args.target, tt.args.c, artifact.Option{ 169 NoProgress: tt.args.noProgress, 170 RepoBranch: tt.args.repoBranch, 171 RepoTag: tt.args.repoTag, 172 RepoCommit: tt.args.repoCommit, 173 }) 174 tt.assertion(t, err) 175 defer cleanup() 176 }) 177 } 178 } 179 180 func TestArtifact_Inspect(t *testing.T) { 181 ts, err := setupGitServer() 182 require.NoError(t, err) 183 defer ts.Close() 184 185 tests := []struct { 186 name string 187 rawurl string 188 want types.ArtifactReference 189 wantErr bool 190 }{ 191 { 192 name: "happy path", 193 rawurl: ts.URL + "/test.git", 194 want: types.ArtifactReference{ 195 Name: ts.URL + "/test.git", 196 Type: types.ArtifactRepository, 197 ID: "sha256:1fa928c33b16a335015ce96e1384127f8463c4f27ed0786806a6d4584b63d091", 198 BlobIDs: []string{ 199 "sha256:1fa928c33b16a335015ce96e1384127f8463c4f27ed0786806a6d4584b63d091", 200 }, 201 }, 202 }, 203 } 204 205 for _, tt := range tests { 206 t.Run(tt.name, func(t *testing.T) { 207 fsCache, err := cache.NewFSCache(t.TempDir()) 208 require.NoError(t, err) 209 210 art, cleanup, err := NewArtifact(tt.rawurl, fsCache, artifact.Option{}) 211 require.NoError(t, err) 212 defer cleanup() 213 214 ref, err := art.Inspect(context.Background()) 215 assert.NoError(t, err) 216 assert.Equal(t, tt.want, ref) 217 }) 218 } 219 } 220 221 func Test_newURL(t *testing.T) { 222 type args struct { 223 rawurl string 224 } 225 tests := []struct { 226 name string 227 args args 228 want string 229 wantErr string 230 }{ 231 { 232 name: "happy path", 233 args: args{ 234 rawurl: "https://github.com/aquasecurity/fanal", 235 }, 236 want: "https://github.com/aquasecurity/fanal", 237 }, 238 { 239 name: "happy path: no scheme", 240 args: args{ 241 rawurl: "github.com/aquasecurity/fanal", 242 }, 243 want: "https://github.com/aquasecurity/fanal", 244 }, 245 { 246 name: "sad path: invalid url", 247 args: args{ 248 rawurl: "ht tp://foo.com", 249 }, 250 wantErr: "first path segment in URL cannot contain colon", 251 }, 252 } 253 for _, tt := range tests { 254 t.Run(tt.name, func(t *testing.T) { 255 got, err := newURL(tt.args.rawurl) 256 if tt.wantErr != "" { 257 require.NotNil(t, err) 258 assert.Contains(t, err.Error(), tt.wantErr) 259 return 260 } else { 261 require.NoError(t, err) 262 } 263 264 assert.Equal(t, tt.want, got.String()) 265 }) 266 } 267 }