From 2d4ad13349fdcbef0290a7231aa5c6b10851936e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Garc=C3=ADa=20Veytia=20=28Puerco=29?= Date: Tue, 8 Mar 2022 23:31:22 -0600 Subject: [PATCH] Add integration and final unit tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Adolfo GarcĂ­a Veytia (Puerco) --- pkg/sbom/generator/generator.go | 4 + .../generatorfakes/fake_generator.go | 244 ++++++++++++ pkg/sbom/sbom.go | 44 +-- pkg/sbom/sbom_test.go | 144 +++++++ pkg/sbom/sbom_unit_test.go | 83 ++++- .../sbomfakes/fake_sbom_implementation.go | 351 ++++++++++++++++++ 6 files changed, 843 insertions(+), 27 deletions(-) create mode 100644 pkg/sbom/generator/generatorfakes/fake_generator.go create mode 100644 pkg/sbom/sbom_test.go create mode 100644 pkg/sbom/sbomfakes/fake_sbom_implementation.go diff --git a/pkg/sbom/generator/generator.go b/pkg/sbom/generator/generator.go index 33fc58d53..df8a61279 100644 --- a/pkg/sbom/generator/generator.go +++ b/pkg/sbom/generator/generator.go @@ -14,11 +14,15 @@ package generator +//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate + import ( "chainguard.dev/apko/pkg/sbom/generator/cyclonedx" "chainguard.dev/apko/pkg/sbom/options" ) +//counterfeiter:generate . Generator + type Generator interface { Key() string Ext() string diff --git a/pkg/sbom/generator/generatorfakes/fake_generator.go b/pkg/sbom/generator/generatorfakes/fake_generator.go new file mode 100644 index 000000000..5a0eba264 --- /dev/null +++ b/pkg/sbom/generator/generatorfakes/fake_generator.go @@ -0,0 +1,244 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package generatorfakes + +import ( + "sync" + + "chainguard.dev/apko/pkg/sbom/generator" + "chainguard.dev/apko/pkg/sbom/options" +) + +type FakeGenerator struct { + ExtStub func() string + extMutex sync.RWMutex + extArgsForCall []struct { + } + extReturns struct { + result1 string + } + extReturnsOnCall map[int]struct { + result1 string + } + GenerateStub func(*options.Options, string) error + generateMutex sync.RWMutex + generateArgsForCall []struct { + arg1 *options.Options + arg2 string + } + generateReturns struct { + result1 error + } + generateReturnsOnCall map[int]struct { + result1 error + } + KeyStub func() string + keyMutex sync.RWMutex + keyArgsForCall []struct { + } + keyReturns struct { + result1 string + } + keyReturnsOnCall map[int]struct { + result1 string + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeGenerator) Ext() string { + fake.extMutex.Lock() + ret, specificReturn := fake.extReturnsOnCall[len(fake.extArgsForCall)] + fake.extArgsForCall = append(fake.extArgsForCall, struct { + }{}) + stub := fake.ExtStub + fakeReturns := fake.extReturns + fake.recordInvocation("Ext", []interface{}{}) + fake.extMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeGenerator) ExtCallCount() int { + fake.extMutex.RLock() + defer fake.extMutex.RUnlock() + return len(fake.extArgsForCall) +} + +func (fake *FakeGenerator) ExtCalls(stub func() string) { + fake.extMutex.Lock() + defer fake.extMutex.Unlock() + fake.ExtStub = stub +} + +func (fake *FakeGenerator) ExtReturns(result1 string) { + fake.extMutex.Lock() + defer fake.extMutex.Unlock() + fake.ExtStub = nil + fake.extReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeGenerator) ExtReturnsOnCall(i int, result1 string) { + fake.extMutex.Lock() + defer fake.extMutex.Unlock() + fake.ExtStub = nil + if fake.extReturnsOnCall == nil { + fake.extReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.extReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeGenerator) Generate(arg1 *options.Options, arg2 string) error { + fake.generateMutex.Lock() + ret, specificReturn := fake.generateReturnsOnCall[len(fake.generateArgsForCall)] + fake.generateArgsForCall = append(fake.generateArgsForCall, struct { + arg1 *options.Options + arg2 string + }{arg1, arg2}) + stub := fake.GenerateStub + fakeReturns := fake.generateReturns + fake.recordInvocation("Generate", []interface{}{arg1, arg2}) + fake.generateMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeGenerator) GenerateCallCount() int { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + return len(fake.generateArgsForCall) +} + +func (fake *FakeGenerator) GenerateCalls(stub func(*options.Options, string) error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = stub +} + +func (fake *FakeGenerator) GenerateArgsForCall(i int) (*options.Options, string) { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + argsForCall := fake.generateArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeGenerator) GenerateReturns(result1 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + fake.generateReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeGenerator) GenerateReturnsOnCall(i int, result1 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + if fake.generateReturnsOnCall == nil { + fake.generateReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.generateReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeGenerator) Key() string { + fake.keyMutex.Lock() + ret, specificReturn := fake.keyReturnsOnCall[len(fake.keyArgsForCall)] + fake.keyArgsForCall = append(fake.keyArgsForCall, struct { + }{}) + stub := fake.KeyStub + fakeReturns := fake.keyReturns + fake.recordInvocation("Key", []interface{}{}) + fake.keyMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeGenerator) KeyCallCount() int { + fake.keyMutex.RLock() + defer fake.keyMutex.RUnlock() + return len(fake.keyArgsForCall) +} + +func (fake *FakeGenerator) KeyCalls(stub func() string) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = stub +} + +func (fake *FakeGenerator) KeyReturns(result1 string) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = nil + fake.keyReturns = struct { + result1 string + }{result1} +} + +func (fake *FakeGenerator) KeyReturnsOnCall(i int, result1 string) { + fake.keyMutex.Lock() + defer fake.keyMutex.Unlock() + fake.KeyStub = nil + if fake.keyReturnsOnCall == nil { + fake.keyReturnsOnCall = make(map[int]struct { + result1 string + }) + } + fake.keyReturnsOnCall[i] = struct { + result1 string + }{result1} +} + +func (fake *FakeGenerator) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.extMutex.RLock() + defer fake.extMutex.RUnlock() + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + fake.keyMutex.RLock() + defer fake.keyMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeGenerator) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ generator.Generator = new(FakeGenerator) diff --git a/pkg/sbom/sbom.go b/pkg/sbom/sbom.go index 2bd3f900d..549086180 100644 --- a/pkg/sbom/sbom.go +++ b/pkg/sbom/sbom.go @@ -67,8 +67,12 @@ func NewWithWorkDir(path string) *SBOM { return s } +func (s *SBOM) SetImplementation(impl sbomImplementation) { + s.impl = impl +} + func (s *SBOM) ReadReleaseData() error { - if err := s.impl.readReleaseData( + if err := s.impl.ReadReleaseData( &s.Options, filepath.Join(s.Options.WorkDir, osReleasePath), ); err != nil { return fmt.Errorf("reading release data: %w", err) @@ -79,7 +83,7 @@ func (s *SBOM) ReadReleaseData() error { // ReadPackageIndex parses the package index in the working directory // and returns a slice of the installed packages func (s *SBOM) ReadPackageIndex() ([]*repository.Package, error) { - pks, err := s.impl.readPackageIndex( + pks, err := s.impl.ReadPackageIndex( &s.Options, filepath.Join(s.Options.WorkDir, packageIndexPath), ) if err != nil { @@ -90,12 +94,12 @@ func (s *SBOM) ReadPackageIndex() ([]*repository.Package, error) { // Generate creates the sboms according to the options set func (s *SBOM) Generate() ([]string, error) { - if err := s.impl.checkGenerators( + if err := s.impl.CheckGenerators( &s.Options, s.Generators, ); err != nil { return nil, err } - files, err := s.impl.generate(&s.Options, s.Generators) + files, err := s.impl.Generate(&s.Options, s.Generators) if err != nil { return nil, fmt.Errorf("generating sboms: %w", err) } @@ -104,16 +108,16 @@ func (s *SBOM) Generate() ([]string, error) { //counterfeiter:generate . sbomImplementation type sbomImplementation interface { - readReleaseData(*options.Options, string) error - readPackageIndex(*options.Options, string) ([]*repository.Package, error) - generate(*options.Options, map[string]generator.Generator) ([]string, error) - checkGenerators(*options.Options, map[string]generator.Generator) error + ReadReleaseData(*options.Options, string) error + ReadPackageIndex(*options.Options, string) ([]*repository.Package, error) + Generate(*options.Options, map[string]generator.Generator) ([]string, error) + CheckGenerators(*options.Options, map[string]generator.Generator) error } type defaultSBOMImplementation struct{} // readReleaseDataInternal reads the information from /etc/os-release -func (di *defaultSBOMImplementation) readReleaseData(opts *options.Options, path string) error { +func (di *defaultSBOMImplementation) ReadReleaseData(opts *options.Options, path string) error { osReleaseData, err := os.ReadFile(path) if err != nil { return fmt.Errorf("reading os-release: %w", err) @@ -129,7 +133,7 @@ func (di *defaultSBOMImplementation) readReleaseData(opts *options.Options, path } // readPackageIndex parses the apk database passed in the path -func (di *defaultSBOMImplementation) readPackageIndex( +func (di *defaultSBOMImplementation) ReadPackageIndex( opts *options.Options, path string, ) (packages []*repository.Package, err error) { installedDB, err := os.Open(path) @@ -147,20 +151,10 @@ func (di *defaultSBOMImplementation) readPackageIndex( } // generate creates the documents according to the specified options -func (di *defaultSBOMImplementation) generate( +func (di *defaultSBOMImplementation) Generate( opts *options.Options, generators map[string]generator.Generator, ) ([]string, error) { - // Check the generators before running - for _, format := range opts.Formats { - if _, ok := generators[format]; !ok { - return nil, fmt.Errorf( - "unable to generate sboms: no generator available for format %s", format, - ) - } - } - files := []string{} - for _, format := range opts.Formats { path := filepath.Join( opts.OutputDir, opts.FileName+"."+generators[format].Ext(), @@ -175,9 +169,15 @@ func (di *defaultSBOMImplementation) generate( // checkGenerators verifies we have generators available for the // formats specified in the options -func (di *defaultSBOMImplementation) checkGenerators( +func (di *defaultSBOMImplementation) CheckGenerators( opts *options.Options, generators map[string]generator.Generator, ) error { + if len(generators) == 0 { + return fmt.Errorf("no generators defined") + } + if len(opts.Formats) == 0 { + return fmt.Errorf("no sbom format enabled in options") + } for _, format := range opts.Formats { if _, ok := generators[format]; !ok { return fmt.Errorf( diff --git a/pkg/sbom/sbom_test.go b/pkg/sbom/sbom_test.go new file mode 100644 index 000000000..5e4cdef2f --- /dev/null +++ b/pkg/sbom/sbom_test.go @@ -0,0 +1,144 @@ +// Copyright 2022 Chainguard, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sbom_test + +import ( + "fmt" + "testing" + + "chainguard.dev/apko/pkg/sbom" + "chainguard.dev/apko/pkg/sbom/sbomfakes" + "github.com/stretchr/testify/require" + "gitlab.alpinelinux.org/alpine/go/pkg/repository" +) + +var errFake = fmt.Errorf("synthetic error") + +func TestGenerate(t *testing.T) { + for _, tc := range []struct { + prepare func(*sbomfakes.FakeSbomImplementation) + assert func([]string, error) + }{ + { + // CheckGenerators errors + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.CheckGeneratorsReturns(errFake) + }, + assert: func(s []string, err error) { + require.Error(t, err) + }, + }, + { + // Generate fails + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.CheckGeneratorsReturns(nil) + fsi.GenerateReturns(nil, errFake) + }, + assert: func(s []string, err error) { + require.Error(t, err) + }, + }, + { + // Success + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.GenerateReturns([]string{"/path/to/sbom.cdx"}, nil) + }, + assert: func(s []string, err error) { + require.GreaterOrEqual(t, len(s), 1) + require.NoError(t, err) + }, + }, + } { + mock := &sbomfakes.FakeSbomImplementation{} + tc.prepare(mock) + + sut := sbom.SBOM{} + sut.SetImplementation(mock) + + obj, err := sut.Generate() + tc.assert(obj, err) + } +} + +func TestReadPackageIndes(t *testing.T) { + for _, tc := range []struct { + prepare func(*sbomfakes.FakeSbomImplementation) + assert func([]*repository.Package, error) + }{ + { + // ReadPackageIndex fails + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.ReadPackageIndexReturns(nil, errFake) + }, + assert: func(pkgs []*repository.Package, err error) { + require.Error(t, err) + }, + }, + { + // Success + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.ReadPackageIndexReturns([]*repository.Package{{}}, nil) + }, + assert: func(pkgs []*repository.Package, err error) { + require.GreaterOrEqual(t, len(pkgs), 1) + require.NoError(t, err) + }, + }, + } { + mock := &sbomfakes.FakeSbomImplementation{} + tc.prepare(mock) + + sut := sbom.SBOM{} + sut.SetImplementation(mock) + + obj, err := sut.ReadPackageIndex() + tc.assert(obj, err) + } +} + +func TestReadReleaseData(t *testing.T) { + for _, tc := range []struct { + prepare func(*sbomfakes.FakeSbomImplementation) + assert func(error) + }{ + { + // ReadReleaseData fails + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.ReadReleaseDataReturns(errFake) + }, + assert: func(err error) { + require.Error(t, err) + }, + }, + { + // Success + prepare: func(fsi *sbomfakes.FakeSbomImplementation) { + fsi.ReadReleaseDataReturns(nil) + }, + assert: func(err error) { + require.NoError(t, err) + }, + }, + } { + mock := &sbomfakes.FakeSbomImplementation{} + tc.prepare(mock) + + sut := sbom.SBOM{} + sut.SetImplementation(mock) + + err := sut.ReadReleaseData() + tc.assert(err) + } +} diff --git a/pkg/sbom/sbom_unit_test.go b/pkg/sbom/sbom_unit_test.go index c25df59ee..822b1f378 100644 --- a/pkg/sbom/sbom_unit_test.go +++ b/pkg/sbom/sbom_unit_test.go @@ -15,14 +15,20 @@ package sbom import ( + "fmt" "os" "path/filepath" "testing" + "chainguard.dev/apko/pkg/sbom/generator" + "chainguard.dev/apko/pkg/sbom/generator/generatorfakes" + "chainguard.dev/apko/pkg/sbom/options" "github.com/stretchr/testify/require" ) +var errFake = fmt.Errorf("synthetic error") + func TestReadReleaseData(t *testing.T) { osinfoData := `NAME="Alpine Linux" ID=alpine @@ -40,9 +46,9 @@ BUG_REPORT_URL="https://bugs.alpinelinux.org/" di := defaultSBOMImplementation{} // Non existent file, should err - require.Error(t, di.readReleaseData(&options.Options{}, filepath.Join(tdir, "non-existent"))) + require.Error(t, di.ReadReleaseData(&options.Options{}, filepath.Join(tdir, "non-existent"))) opts := options.Options{} - require.NoError(t, di.readReleaseData(&opts, filepath.Join(tdir, "os-release"))) + require.NoError(t, di.ReadReleaseData(&opts, filepath.Join(tdir, "os-release"))) require.Equal(t, "alpine", opts.OS.ID) require.Equal(t, "Alpine Linux", opts.OS.Name) require.Equal(t, "3.15.0", opts.OS.Version) @@ -117,12 +123,79 @@ Z:Q1/KAM0XSmA+YShex9ZKehdaf+mjw= // Non existent file must fail opts := &options.Options{} - _, err := di.readPackageIndex(opts, filepath.Join(tdir, "non-existent")) + _, err := di.ReadPackageIndex(opts, filepath.Join(tdir, "non-existent")) require.Error(t, err) - _, err = di.readPackageIndex(opts, filepath.Join(tdir, "installed-corrupt")) + _, err = di.ReadPackageIndex(opts, filepath.Join(tdir, "installed-corrupt")) require.Error(t, err) - pkg, err := di.readPackageIndex(opts, filepath.Join(tdir, "installed")) + pkg, err := di.ReadPackageIndex(opts, filepath.Join(tdir, "installed")) require.NoError(t, err) require.NotNil(t, pkg) require.Len(t, pkg, 2) } + +func TestCheckGenerators(t *testing.T) { + di := defaultSBOMImplementation{} + gen := generatorfakes.FakeGenerator{} + + // No generators set + require.Error(t, di.CheckGenerators( + &options.Options{Formats: []string{"cyclonedx"}}, + map[string]generator.Generator{}, + )) + // No generators enabled in the options + require.Error(t, di.CheckGenerators( + &options.Options{Formats: []string{}}, + map[string]generator.Generator{"fake": &gen}, + )) + // No generator for specified format + require.Error(t, di.CheckGenerators( + &options.Options{Formats: []string{"cyclonedx"}}, + map[string]generator.Generator{"fake": &gen}, + )) + // Success + require.NoError(t, di.CheckGenerators( + &options.Options{Formats: []string{"fake"}}, + map[string]generator.Generator{"fake": &gen}, + )) +} + +func TestGenerate(t *testing.T) { + di := defaultSBOMImplementation{} + outputDir := "/path/to/sbom" + formats := []string{"fake"} + + for _, tc := range []struct { + prepare func(*generatorfakes.FakeGenerator) + opts options.Options + assert func([]string, error) + }{ + { + // Success + prepare: func(fg *generatorfakes.FakeGenerator) { + fg.GenerateReturns(nil) + }, + opts: options.Options{OutputDir: outputDir, Formats: formats}, + assert: func(sboms []string, err error) { + require.NoError(t, err) + require.GreaterOrEqual(t, len(sboms), 1) + }, + }, + { + // Generate fails + prepare: func(fg *generatorfakes.FakeGenerator) { + fg.GenerateReturns(errFake) + }, + opts: options.Options{OutputDir: outputDir, Formats: formats}, + assert: func(s []string, err error) { + require.Error(t, err) + }, + }, + } { + mock := &generatorfakes.FakeGenerator{} + tc.prepare(mock) + res, err := di.Generate( + &tc.opts, map[string]generator.Generator{"fake": mock}, + ) + tc.assert(res, err) + } +} diff --git a/pkg/sbom/sbomfakes/fake_sbom_implementation.go b/pkg/sbom/sbomfakes/fake_sbom_implementation.go new file mode 100644 index 000000000..6b923315b --- /dev/null +++ b/pkg/sbom/sbomfakes/fake_sbom_implementation.go @@ -0,0 +1,351 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package sbomfakes + +import ( + "sync" + + "chainguard.dev/apko/pkg/sbom/generator" + "chainguard.dev/apko/pkg/sbom/options" + "gitlab.alpinelinux.org/alpine/go/pkg/repository" +) + +type FakeSbomImplementation struct { + CheckGeneratorsStub func(*options.Options, map[string]generator.Generator) error + checkGeneratorsMutex sync.RWMutex + checkGeneratorsArgsForCall []struct { + arg1 *options.Options + arg2 map[string]generator.Generator + } + checkGeneratorsReturns struct { + result1 error + } + checkGeneratorsReturnsOnCall map[int]struct { + result1 error + } + GenerateStub func(*options.Options, map[string]generator.Generator) ([]string, error) + generateMutex sync.RWMutex + generateArgsForCall []struct { + arg1 *options.Options + arg2 map[string]generator.Generator + } + generateReturns struct { + result1 []string + result2 error + } + generateReturnsOnCall map[int]struct { + result1 []string + result2 error + } + ReadPackageIndexStub func(*options.Options, string) ([]*repository.Package, error) + readPackageIndexMutex sync.RWMutex + readPackageIndexArgsForCall []struct { + arg1 *options.Options + arg2 string + } + readPackageIndexReturns struct { + result1 []*repository.Package + result2 error + } + readPackageIndexReturnsOnCall map[int]struct { + result1 []*repository.Package + result2 error + } + ReadReleaseDataStub func(*options.Options, string) error + readReleaseDataMutex sync.RWMutex + readReleaseDataArgsForCall []struct { + arg1 *options.Options + arg2 string + } + readReleaseDataReturns struct { + result1 error + } + readReleaseDataReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeSbomImplementation) CheckGenerators(arg1 *options.Options, arg2 map[string]generator.Generator) error { + fake.checkGeneratorsMutex.Lock() + ret, specificReturn := fake.checkGeneratorsReturnsOnCall[len(fake.checkGeneratorsArgsForCall)] + fake.checkGeneratorsArgsForCall = append(fake.checkGeneratorsArgsForCall, struct { + arg1 *options.Options + arg2 map[string]generator.Generator + }{arg1, arg2}) + stub := fake.CheckGeneratorsStub + fakeReturns := fake.checkGeneratorsReturns + fake.recordInvocation("CheckGenerators", []interface{}{arg1, arg2}) + fake.checkGeneratorsMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeSbomImplementation) CheckGeneratorsCallCount() int { + fake.checkGeneratorsMutex.RLock() + defer fake.checkGeneratorsMutex.RUnlock() + return len(fake.checkGeneratorsArgsForCall) +} + +func (fake *FakeSbomImplementation) CheckGeneratorsCalls(stub func(*options.Options, map[string]generator.Generator) error) { + fake.checkGeneratorsMutex.Lock() + defer fake.checkGeneratorsMutex.Unlock() + fake.CheckGeneratorsStub = stub +} + +func (fake *FakeSbomImplementation) CheckGeneratorsArgsForCall(i int) (*options.Options, map[string]generator.Generator) { + fake.checkGeneratorsMutex.RLock() + defer fake.checkGeneratorsMutex.RUnlock() + argsForCall := fake.checkGeneratorsArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSbomImplementation) CheckGeneratorsReturns(result1 error) { + fake.checkGeneratorsMutex.Lock() + defer fake.checkGeneratorsMutex.Unlock() + fake.CheckGeneratorsStub = nil + fake.checkGeneratorsReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeSbomImplementation) CheckGeneratorsReturnsOnCall(i int, result1 error) { + fake.checkGeneratorsMutex.Lock() + defer fake.checkGeneratorsMutex.Unlock() + fake.CheckGeneratorsStub = nil + if fake.checkGeneratorsReturnsOnCall == nil { + fake.checkGeneratorsReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.checkGeneratorsReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeSbomImplementation) Generate(arg1 *options.Options, arg2 map[string]generator.Generator) ([]string, error) { + fake.generateMutex.Lock() + ret, specificReturn := fake.generateReturnsOnCall[len(fake.generateArgsForCall)] + fake.generateArgsForCall = append(fake.generateArgsForCall, struct { + arg1 *options.Options + arg2 map[string]generator.Generator + }{arg1, arg2}) + stub := fake.GenerateStub + fakeReturns := fake.generateReturns + fake.recordInvocation("Generate", []interface{}{arg1, arg2}) + fake.generateMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSbomImplementation) GenerateCallCount() int { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + return len(fake.generateArgsForCall) +} + +func (fake *FakeSbomImplementation) GenerateCalls(stub func(*options.Options, map[string]generator.Generator) ([]string, error)) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = stub +} + +func (fake *FakeSbomImplementation) GenerateArgsForCall(i int) (*options.Options, map[string]generator.Generator) { + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + argsForCall := fake.generateArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSbomImplementation) GenerateReturns(result1 []string, result2 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + fake.generateReturns = struct { + result1 []string + result2 error + }{result1, result2} +} + +func (fake *FakeSbomImplementation) GenerateReturnsOnCall(i int, result1 []string, result2 error) { + fake.generateMutex.Lock() + defer fake.generateMutex.Unlock() + fake.GenerateStub = nil + if fake.generateReturnsOnCall == nil { + fake.generateReturnsOnCall = make(map[int]struct { + result1 []string + result2 error + }) + } + fake.generateReturnsOnCall[i] = struct { + result1 []string + result2 error + }{result1, result2} +} + +func (fake *FakeSbomImplementation) ReadPackageIndex(arg1 *options.Options, arg2 string) ([]*repository.Package, error) { + fake.readPackageIndexMutex.Lock() + ret, specificReturn := fake.readPackageIndexReturnsOnCall[len(fake.readPackageIndexArgsForCall)] + fake.readPackageIndexArgsForCall = append(fake.readPackageIndexArgsForCall, struct { + arg1 *options.Options + arg2 string + }{arg1, arg2}) + stub := fake.ReadPackageIndexStub + fakeReturns := fake.readPackageIndexReturns + fake.recordInvocation("ReadPackageIndex", []interface{}{arg1, arg2}) + fake.readPackageIndexMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeSbomImplementation) ReadPackageIndexCallCount() int { + fake.readPackageIndexMutex.RLock() + defer fake.readPackageIndexMutex.RUnlock() + return len(fake.readPackageIndexArgsForCall) +} + +func (fake *FakeSbomImplementation) ReadPackageIndexCalls(stub func(*options.Options, string) ([]*repository.Package, error)) { + fake.readPackageIndexMutex.Lock() + defer fake.readPackageIndexMutex.Unlock() + fake.ReadPackageIndexStub = stub +} + +func (fake *FakeSbomImplementation) ReadPackageIndexArgsForCall(i int) (*options.Options, string) { + fake.readPackageIndexMutex.RLock() + defer fake.readPackageIndexMutex.RUnlock() + argsForCall := fake.readPackageIndexArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSbomImplementation) ReadPackageIndexReturns(result1 []*repository.Package, result2 error) { + fake.readPackageIndexMutex.Lock() + defer fake.readPackageIndexMutex.Unlock() + fake.ReadPackageIndexStub = nil + fake.readPackageIndexReturns = struct { + result1 []*repository.Package + result2 error + }{result1, result2} +} + +func (fake *FakeSbomImplementation) ReadPackageIndexReturnsOnCall(i int, result1 []*repository.Package, result2 error) { + fake.readPackageIndexMutex.Lock() + defer fake.readPackageIndexMutex.Unlock() + fake.ReadPackageIndexStub = nil + if fake.readPackageIndexReturnsOnCall == nil { + fake.readPackageIndexReturnsOnCall = make(map[int]struct { + result1 []*repository.Package + result2 error + }) + } + fake.readPackageIndexReturnsOnCall[i] = struct { + result1 []*repository.Package + result2 error + }{result1, result2} +} + +func (fake *FakeSbomImplementation) ReadReleaseData(arg1 *options.Options, arg2 string) error { + fake.readReleaseDataMutex.Lock() + ret, specificReturn := fake.readReleaseDataReturnsOnCall[len(fake.readReleaseDataArgsForCall)] + fake.readReleaseDataArgsForCall = append(fake.readReleaseDataArgsForCall, struct { + arg1 *options.Options + arg2 string + }{arg1, arg2}) + stub := fake.ReadReleaseDataStub + fakeReturns := fake.readReleaseDataReturns + fake.recordInvocation("ReadReleaseData", []interface{}{arg1, arg2}) + fake.readReleaseDataMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeSbomImplementation) ReadReleaseDataCallCount() int { + fake.readReleaseDataMutex.RLock() + defer fake.readReleaseDataMutex.RUnlock() + return len(fake.readReleaseDataArgsForCall) +} + +func (fake *FakeSbomImplementation) ReadReleaseDataCalls(stub func(*options.Options, string) error) { + fake.readReleaseDataMutex.Lock() + defer fake.readReleaseDataMutex.Unlock() + fake.ReadReleaseDataStub = stub +} + +func (fake *FakeSbomImplementation) ReadReleaseDataArgsForCall(i int) (*options.Options, string) { + fake.readReleaseDataMutex.RLock() + defer fake.readReleaseDataMutex.RUnlock() + argsForCall := fake.readReleaseDataArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeSbomImplementation) ReadReleaseDataReturns(result1 error) { + fake.readReleaseDataMutex.Lock() + defer fake.readReleaseDataMutex.Unlock() + fake.ReadReleaseDataStub = nil + fake.readReleaseDataReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeSbomImplementation) ReadReleaseDataReturnsOnCall(i int, result1 error) { + fake.readReleaseDataMutex.Lock() + defer fake.readReleaseDataMutex.Unlock() + fake.ReadReleaseDataStub = nil + if fake.readReleaseDataReturnsOnCall == nil { + fake.readReleaseDataReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.readReleaseDataReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeSbomImplementation) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.checkGeneratorsMutex.RLock() + defer fake.checkGeneratorsMutex.RUnlock() + fake.generateMutex.RLock() + defer fake.generateMutex.RUnlock() + fake.readPackageIndexMutex.RLock() + defer fake.readPackageIndexMutex.RUnlock() + fake.readReleaseDataMutex.RLock() + defer fake.readReleaseDataMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeSbomImplementation) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +}