Skip to content

Commit 985442d

Browse files
committed
analyzer_test: Adding seams for testability
Signed-off-by: Simarpreet Singh <simar@linux.com>
1 parent 95e89a4 commit 985442d

File tree

5 files changed

+68
-26
lines changed

5 files changed

+68
-26
lines changed

analyzer/analyzer.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"context"
66
"io"
77
"os"
8-
"time"
98

109
"github.com/aquasecurity/fanal/utils"
1110

@@ -33,6 +32,10 @@ var (
3332
ErrNoPkgsDetected = xerrors.New("No packages detected")
3433
)
3534

35+
type AnalyzerConfig struct {
36+
Extractor extractor.Extractor
37+
}
38+
3639
type OSAnalyzer interface {
3740
Analyze(extractor.FileMap) (OS, error)
3841
RequiredFiles() []string
@@ -113,28 +116,19 @@ func RequiredFilenames() []string {
113116
return filenames
114117
}
115118

116-
func Analyze(ctx context.Context, imageName string, opts ...types.DockerOption) (fileMap extractor.FileMap, err error) {
117-
// default docker option
118-
opt := types.DockerOption{
119-
Timeout: 600 * time.Second,
120-
SkipPing: true,
121-
}
122-
if len(opts) > 0 {
123-
opt = opts[0]
124-
}
125-
126-
e := docker.NewDockerExtractor(opt)
127-
r, err := e.SaveLocalImage(ctx, imageName)
119+
// TODO: Remove opts as they're no longer needed
120+
func (ac AnalyzerConfig) Analyze(ctx context.Context, imageName string, opts ...types.DockerOption) (fileMap extractor.FileMap, err error) {
121+
r, err := ac.Extractor.SaveLocalImage(ctx, imageName)
128122
if err != nil {
129123
// when no docker daemon is installed or no image exists in the local machine
130-
fileMap, err = e.Extract(ctx, imageName, RequiredFilenames())
124+
fileMap, err = ac.Extractor.Extract(ctx, imageName, RequiredFilenames())
131125
if err != nil {
132126
return nil, xerrors.Errorf("failed to extract files: %w", err)
133127
}
134128
return fileMap, nil
135129
}
136130

137-
fileMap, err = e.ExtractFromFile(ctx, r, RequiredFilenames())
131+
fileMap, err = ac.Extractor.ExtractFromFile(ctx, r, RequiredFilenames())
138132
if err != nil {
139133
return nil, xerrors.Errorf("failed to extract files from saved tar: %w", err)
140134
}

analyzer/analyzer_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package analyzer
2+
3+
import (
4+
"context"
5+
"io"
6+
"testing"
7+
8+
"github.com/aquasecurity/fanal/extractor"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
type mockDockerExtractor struct {
14+
saveLocalImage func(ctx context.Context, imageName string) (io.Reader, error)
15+
extractFromFile func(ctx context.Context, r io.Reader, filenames []string) (extractor.FileMap, error)
16+
}
17+
18+
func (mde mockDockerExtractor) Extract(ctx context.Context, imageName string, filenames []string) (extractor.FileMap, error) {
19+
panic("implement me")
20+
}
21+
22+
func (mde mockDockerExtractor) ExtractFromFile(ctx context.Context, r io.Reader, filenames []string) (extractor.FileMap, error) {
23+
if mde.extractFromFile != nil {
24+
return mde.extractFromFile(ctx, r, filenames)
25+
}
26+
return extractor.FileMap{}, nil
27+
}
28+
29+
func (mde mockDockerExtractor) SaveLocalImage(ctx context.Context, imageName string) (io.Reader, error) {
30+
if mde.saveLocalImage != nil {
31+
return mde.saveLocalImage(ctx, imageName)
32+
}
33+
return nil, nil
34+
}
35+
36+
func (mde mockDockerExtractor) ExtractFiles(layer io.Reader, filenames []string) (extractor.FileMap, extractor.OPQDirs, error) {
37+
panic("implement me")
38+
}
39+
40+
func TestAnalyze(t *testing.T) {
41+
ac := AnalyzerConfig{Extractor: mockDockerExtractor{}}
42+
fm, err := ac.Analyze(context.TODO(), "foo")
43+
assert.NoError(t, err)
44+
assert.NotNil(t, fm)
45+
}

extractor/docker/docker.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,19 +60,17 @@ type layer struct {
6060
Content io.ReadCloser
6161
}
6262

63-
type opqDirs []string
64-
6563
type DockerExtractor struct {
6664
Option types.DockerOption
6765
}
6866

69-
func NewDockerExtractor(option types.DockerOption) DockerExtractor {
67+
func NewDockerExtractor(option types.DockerOption) extractor.Extractor {
7068
RegisterRegistry(&gcr.GCR{})
7169
RegisterRegistry(&ecr.ECR{})
7270
return DockerExtractor{Option: option}
7371
}
7472

75-
func applyLayers(layerPaths []string, filesInLayers map[string]extractor.FileMap, opqInLayers map[string]opqDirs) (extractor.FileMap, error) {
73+
func applyLayers(layerPaths []string, filesInLayers map[string]extractor.FileMap, opqInLayers map[string]extractor.OPQDirs) (extractor.FileMap, error) {
7674
sep := "/"
7775
nestedMap := nested.Nested{}
7876
for _, layerPath := range layerPaths {
@@ -190,7 +188,8 @@ func (d DockerExtractor) Extract(ctx context.Context, imageName string, filename
190188

191189
ch := make(chan layer)
192190
errCh := make(chan error)
193-
layerIDs := []string{}
191+
var layerIDs []string
192+
194193
for _, ref := range m.Manifest.Layers {
195194
layerIDs = append(layerIDs, string(ref.Digest))
196195
go func(d digest.Digest) {
@@ -203,6 +202,7 @@ func (d DockerExtractor) Extract(ctx context.Context, imageName string, filename
203202
errCh <- xerrors.Errorf("failed to download the layer(%s): %w", d, err)
204203
return
205204
}
205+
206206
rc, err = cache.Set(string(d), rc)
207207
if err != nil {
208208
log.Print(err)
@@ -218,7 +218,7 @@ func (d DockerExtractor) Extract(ctx context.Context, imageName string, filename
218218
}
219219

220220
filesInLayers := make(map[string]extractor.FileMap)
221-
opqInLayers := make(map[string]opqDirs)
221+
opqInLayers := make(map[string]extractor.OPQDirs)
222222
for i := 0; i < len(m.Manifest.Layers); i++ {
223223
var l layer
224224
select {
@@ -262,7 +262,7 @@ func (d DockerExtractor) Extract(ctx context.Context, imageName string, filename
262262
func (d DockerExtractor) ExtractFromFile(ctx context.Context, r io.Reader, filenames []string) (extractor.FileMap, error) {
263263
manifests := make([]manifest, 0)
264264
filesInLayers := map[string]extractor.FileMap{}
265-
opqInLayers := make(map[string]opqDirs)
265+
opqInLayers := make(map[string]extractor.OPQDirs)
266266

267267
tarFiles := make(map[string][]byte)
268268

@@ -330,9 +330,9 @@ func (d DockerExtractor) ExtractFromFile(ctx context.Context, r io.Reader, filen
330330
return fileMap, nil
331331
}
332332

333-
func (d DockerExtractor) ExtractFiles(layer io.Reader, filenames []string) (extractor.FileMap, opqDirs, error) {
333+
func (d DockerExtractor) ExtractFiles(layer io.Reader, filenames []string) (extractor.FileMap, extractor.OPQDirs, error) {
334334
data := make(map[string][]byte)
335-
opqDirs := opqDirs{}
335+
opqDirs := extractor.OPQDirs{}
336336

337337
tr := tar.NewReader(layer)
338338
for {

extractor/docker/docker_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func TestExtractFiles(t *testing.T) {
122122
file string // Test input file
123123
filenames []string // Target files
124124
FileMap extractor.FileMap // Expected output
125-
opqDirs opqDirs // Expected output
125+
opqDirs OPQDirs // Expected output
126126
err error // Expected error to occur
127127
}{
128128
{
@@ -167,7 +167,7 @@ func TestExtractFiles(t *testing.T) {
167167
t.Errorf("err: got %v, want %v", v.err, err)
168168
}
169169
if !reflect.DeepEqual(opqDirs, v.opqDirs) {
170-
t.Errorf("opqDirs: got %v, want %v", opqDirs, v.opqDirs)
170+
t.Errorf("OPQDirs: got %v, want %v", opqDirs, v.opqDirs)
171171
}
172172
if !reflect.DeepEqual(fm, v.FileMap) {
173173
t.Errorf("FilesMap: got %v, want %v", fm, v.FileMap)

extractor/extractor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
)
77

88
type FileMap map[string][]byte
9+
type OPQDirs []string
910

1011
type Extractor interface {
1112
Extract(ctx context.Context, imageName string, filenames []string) (FileMap, error)
1213
ExtractFromFile(ctx context.Context, r io.Reader, filenames []string) (FileMap, error)
14+
SaveLocalImage(ctx context.Context, imageName string) (io.Reader, error)
15+
ExtractFiles(layer io.Reader, filenames []string) (FileMap, OPQDirs, error)
1316
}

0 commit comments

Comments
 (0)