9
9
"io"
10
10
"io/ioutil"
11
11
"os"
12
+ "sort"
12
13
"strings"
13
14
"testing"
14
15
"time"
@@ -44,6 +45,7 @@ import (
44
45
type testCase struct {
45
46
name string
46
47
imageName string
48
+ remoteImageName string
47
49
imageFile string
48
50
expectedOS types.OS
49
51
expectedPkgsFromCmds string
@@ -52,83 +54,109 @@ type testCase struct {
52
54
53
55
var testCases = []testCase {
54
56
{
55
- name : "happy path, alpine:3.10" ,
56
- imageName : "alpine:3.10" ,
57
- imageFile : "testdata/fixtures/alpine-310.tar.gz" ,
58
- expectedOS : types.OS {Name : "3.10.2" , Family : "alpine" },
57
+ name : "happy path, alpine:3.10" ,
58
+ imageName : "alpine:3.10" ,
59
+ remoteImageName : "knqyf263/alpine:3.10" ,
60
+ imageFile : "testdata/fixtures/alpine-310.tar.gz" ,
61
+ expectedOS : types.OS {Name : "3.10.2" , Family : "alpine" },
59
62
},
60
63
{
61
- name : "happy path, debian:buster" ,
62
- imageName : "debian:buster" ,
63
- imageFile : "testdata/fixtures/debian-buster.tar.gz" ,
64
- expectedOS : types.OS {Name : "10.1" , Family : "debian" },
64
+ name : "happy path, amazonlinux:2" ,
65
+ imageName : "amazonlinux:2" ,
66
+ remoteImageName : "knqyf263/amazonlinux:2" ,
67
+ imageFile : "testdata/fixtures/amazon-2.tar.gz" ,
68
+ expectedOS : types.OS {Name : "2 (Karoo)" , Family : "amazon" },
65
69
},
66
70
{
67
- name : "happy path, ubuntu:18.04" ,
68
- imageName : "ubuntu:18.04" ,
69
- imageFile : "testdata/fixtures/ubuntu-1804.tar.gz" ,
70
- expectedOS : types.OS {Name : "18.04" , Family : "ubuntu" },
71
+ name : "happy path, debian:buster" ,
72
+ imageName : "debian:buster" ,
73
+ remoteImageName : "knqyf263/debian:buster" ,
74
+ imageFile : "testdata/fixtures/debian-buster.tar.gz" ,
75
+ expectedOS : types.OS {Name : "10.1" , Family : "debian" },
71
76
},
72
77
{
73
- name : "happy path, centos6" ,
74
- imageName : "centos:6" ,
75
- imageFile : "testdata/fixtures/centos-6.tar.gz" ,
76
- expectedOS : types.OS {Name : "6.10" , Family : "centos" },
78
+ name : "happy path, photon:1.0" ,
79
+ imageName : "photon:1.0-20190823" ,
80
+ remoteImageName : "knqyf263/photon:1.0-20190823" ,
81
+ imageFile : "testdata/fixtures/photon-10.tar.gz" ,
82
+ expectedOS : types.OS {Name : "1.0" , Family : "photon" },
77
83
},
78
84
{
79
- name : "happy path, registry.redhat.io/ubi7" ,
80
- imageName : "registry.redhat.io/ubi7" ,
81
- imageFile : "testdata/fixtures/ubi-7.tar.gz" ,
82
- expectedOS : types.OS {Name : "7.7" , Family : "redhat" },
85
+ name : "happy path, registry.redhat.io/ubi7" ,
86
+ imageName : "registry.redhat.io/ubi7" ,
87
+ remoteImageName : "knqyf263/registry.redhat.io-ubi7:latest" ,
88
+ imageFile : "testdata/fixtures/ubi-7.tar.gz" ,
89
+ expectedOS : types.OS {Name : "7.7" , Family : "redhat" },
83
90
},
84
91
{
85
- name : "happy path, amazonlinux:2" ,
86
- imageName : "amazonlinux:2" ,
87
- imageFile : "testdata/fixtures/amazon-2.tar.gz" ,
88
- expectedOS : types.OS {Name : "2 (Karoo)" , Family : "amazon" },
89
- },
90
- {
91
- name : "happy path, oracle:8" ,
92
- imageName : "oraclelinux:8-slim" ,
93
- imageFile : "testdata/fixtures/oraclelinux-8-slim.tar.gz" ,
94
- expectedOS : types.OS {Name : "8.0" , Family : "oracle" },
95
- },
96
- {
97
- name : "happy path, distroless" ,
98
- imageName : "gcr.io/distroless/base:latest" ,
99
- imageFile : "testdata/fixtures/distroless-base.tar.gz" ,
100
- expectedOS : types.OS {Name : "9.9" , Family : "debian" },
101
- },
102
- {
103
- name : "happy path, photon:1.0" ,
104
- imageName : "photon:1.0-20190823" ,
105
- imageFile : "testdata/fixtures/photon-10.tar.gz" ,
106
- expectedOS : types.OS {Name : "1.0" , Family : "photon" },
107
- },
108
- {
109
- name : "happy path, opensuse leap 15.1" ,
110
- imageName : "opensuse/leap:latest" ,
111
- imageFile : "testdata/fixtures/opensuse-leap-151.tar.gz" ,
112
- expectedOS : types.OS {Name : "15.1" , Family : "opensuse.leap" },
92
+ name : "happy path, opensuse leap 15.1" ,
93
+ imageName : "opensuse/leap:latest" ,
94
+ remoteImageName : "knqyf263/opensuse-leap:latest" ,
95
+ imageFile : "testdata/fixtures/opensuse-leap-151.tar.gz" ,
96
+ expectedOS : types.OS {Name : "15.1" , Family : "opensuse.leap" },
113
97
},
114
98
{
115
99
name : "happy path, vulnimage with lock files" ,
116
100
imageName : "knqyf263/vuln-image:1.2.3" ,
101
+ remoteImageName : "knqyf263/vuln-image:1.2.3" ,
117
102
imageFile : "testdata/fixtures/vulnimage.tar.gz" ,
118
103
expectedOS : types.OS {Name : "3.7.1" , Family : "alpine" },
119
- expectedLibraries : "testdata/goldens/knqyf263vuln -image1.2.3.expectedlibs.golden" ,
120
- expectedPkgsFromCmds : "testdata/goldens/knqyf263vuln -image1.2.3.expectedpkgsfromcmds.golden" ,
104
+ expectedLibraries : "testdata/goldens/vuln -image1.2.3.expectedlibs.golden" ,
105
+ expectedPkgsFromCmds : "testdata/goldens/vuln -image1.2.3.expectedpkgsfromcmds.golden" ,
121
106
},
122
107
}
123
108
109
+ func TestFanal_Library_DockerLessMode (t * testing.T ) {
110
+ for _ , tc := range testCases {
111
+ tc := tc
112
+ t .Run (tc .name , func (t * testing.T ) {
113
+ t .Parallel ()
114
+ ctx := context .Background ()
115
+ d , _ := ioutil .TempDir ("" , "TestFanal_Library_DockerLessMode_*" )
116
+ defer os .RemoveAll (d )
117
+
118
+ c , err := cache .NewFSCache (d )
119
+ require .NoError (t , err , tc .name )
120
+
121
+ opt := types.DockerOption {
122
+ Timeout : 600 * time .Second ,
123
+ SkipPing : true ,
124
+ }
125
+
126
+ cli , err := client .NewClientWithOpts (client .FromEnv )
127
+ require .NoError (t , err , tc .name )
128
+
129
+ // remove existing Image if any
130
+ _ , _ = cli .ImageRemove (ctx , tc .remoteImageName , dtypes.ImageRemoveOptions {
131
+ Force : true ,
132
+ PruneChildren : true ,
133
+ })
134
+
135
+ ext , cleanup , err := docker .NewDockerExtractor (ctx , tc .remoteImageName , opt )
136
+ require .NoError (t , err , tc .name )
137
+ defer cleanup ()
138
+
139
+ ac := analyzer .New (ext , c )
140
+ applier := analyzer .NewApplier (c )
141
+
142
+ // run tests twice, one without cache and with cache
143
+ for i := 1 ; i <= 2 ; i ++ {
144
+ runChecks (t , ctx , ac , applier , tc )
145
+ }
146
+
147
+ // clear Cache
148
+ require .NoError (t , c .Clear (), tc .name )
149
+ })
150
+ }
151
+ }
152
+
124
153
func TestFanal_Library_DockerMode (t * testing.T ) {
125
- t .Parallel ()
126
154
for _ , tc := range testCases {
127
- tc := tc // save a copy of tc for use in t.Run https://gist.github.com/posener/92a55c4cd441fc5e5e85f27bca008721
155
+ tc := tc
128
156
t .Run (tc .name , func (t * testing.T ) {
129
157
t .Parallel ()
130
158
ctx := context .Background ()
131
- d , _ := ioutil .TempDir ("" , "TestFanal_Library_ " )
159
+ d , _ := ioutil .TempDir ("" , "TestFanal_Library_DockerMode_* " )
132
160
defer os .RemoveAll (d )
133
161
c , err := cache .NewFSCache (d )
134
162
require .NoError (t , err )
@@ -186,13 +214,12 @@ func TestFanal_Library_DockerMode(t *testing.T) {
186
214
}
187
215
188
216
func TestFanal_Library_TarMode (t * testing.T ) {
189
- t .Parallel ()
190
217
for _ , tc := range testCases {
191
- tc := tc // save a copy of tc for use in t.Run https://gist.github.com/posener/92a55c4cd441fc5e5e85f27bca008721
218
+ tc := tc
192
219
t .Run (tc .name , func (t * testing.T ) {
193
220
t .Parallel ()
194
221
ctx := context .Background ()
195
- d , _ := ioutil .TempDir ("" , "TestFanal_Library_ " )
222
+ d , _ := ioutil .TempDir ("" , "TestFanal_Library_TarMode_* " )
196
223
defer os .RemoveAll (d )
197
224
198
225
c , err := cache .NewFSCache (d )
@@ -236,18 +263,28 @@ func commonChecks(t *testing.T, detail types.ImageDetail, tc testCase) {
236
263
func checkPackages (t * testing.T , detail types.ImageDetail , tc testCase ) {
237
264
r := strings .NewReplacer ("/" , "-" , ":" , "-" )
238
265
goldenFile := fmt .Sprintf ("testdata/goldens/packages/%s.json.golden" , r .Replace (tc .imageName ))
266
+ data , err := ioutil .ReadFile (goldenFile )
267
+ require .NoError (t , err , tc .name )
239
268
240
- data , _ := ioutil .ReadFile (goldenFile )
241
269
var expectedPkgs []types.Package
242
- err : = json .Unmarshal (data , & expectedPkgs )
270
+ err = json .Unmarshal (data , & expectedPkgs )
243
271
require .NoError (t , err )
244
- assert .ElementsMatch (t , expectedPkgs , detail .Packages , tc .name )
272
+
273
+ require .Equal (t , len (expectedPkgs ), len (detail .Packages ), tc .name )
274
+ sort .Slice (expectedPkgs , func (i , j int ) bool { return expectedPkgs [i ].Name < expectedPkgs [j ].Name })
275
+ sort .Slice (detail .Packages , func (i , j int ) bool { return detail .Packages [i ].Name < detail .Packages [j ].Name })
276
+
277
+ for i := 0 ; i < len (expectedPkgs ); i ++ {
278
+ require .Equal (t , expectedPkgs [i ].Name , detail .Packages [i ].Name , tc .name )
279
+ require .Equal (t , expectedPkgs [i ].Version , detail .Packages [i ].Version , tc .name )
280
+ }
245
281
}
246
282
247
283
func checkLibraries (detail types.ImageDetail , t * testing.T , tc testCase ) {
248
284
if tc .expectedLibraries != "" {
249
285
data , _ := ioutil .ReadFile (tc .expectedLibraries )
250
286
var expectedLibraries map [types.FilePath ][]godeptypes.Library
287
+
251
288
json .Unmarshal (data , & expectedLibraries )
252
289
require .Equal (t , len (expectedLibraries ), len (detail .Applications ), tc .name )
253
290
} else {
@@ -259,6 +296,7 @@ func checkPackageFromCommands(t *testing.T, detail types.ImageDetail, tc testCas
259
296
if tc .expectedPkgsFromCmds != "" {
260
297
data , _ := ioutil .ReadFile (tc .expectedPkgsFromCmds )
261
298
var expectedPkgsFromCmds []types.Package
299
+
262
300
json .Unmarshal (data , & expectedPkgsFromCmds )
263
301
assert .ElementsMatch (t , expectedPkgsFromCmds , detail .HistoryPackages , tc .name )
264
302
} else {
0 commit comments