Merge pull request #91 from anchore/issue-75

Recurse when creating a directory catalog
This commit is contained in:
Alfredo Deza 2020-07-21 11:26:03 -04:00 committed by GitHub
commit 380cd39514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 313 additions and 548 deletions

1
go.mod
View File

@ -6,6 +6,7 @@ require (
github.com/adrg/xdg v0.2.1 github.com/adrg/xdg v0.2.1
github.com/anchore/go-testutils v0.0.0-20200624184116-66aa578126db github.com/anchore/go-testutils v0.0.0-20200624184116-66aa578126db
github.com/anchore/stereoscope v0.0.0-20200706164556-7cf39d7f4639 github.com/anchore/stereoscope v0.0.0-20200706164556-7cf39d7f4639
github.com/bmatcuk/doublestar v1.3.1
github.com/go-test/deep v1.0.6 github.com/go-test/deep v1.0.6
github.com/google/go-containerregistry v0.1.1 // indirect github.com/google/go-containerregistry v0.1.1 // indirect
github.com/gookit/color v1.2.5 github.com/gookit/color v1.2.5

2
go.sum
View File

@ -161,6 +161,8 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmatcuk/doublestar v1.3.1 h1:rT8rxDPsavp9G+4ZULzqhhUSaI/OPsTZNG88Z3i0xvY=
github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U= github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U=
github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg= github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg=
github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc=

View File

@ -13,7 +13,7 @@ type Cataloger struct {
func NewCataloger() *Cataloger { func NewCataloger() *Cataloger {
globParsers := map[string]common.ParserFn{ globParsers := map[string]common.ParserFn{
"*/Gemfile.lock": parseGemfileLockEntries, "**/Gemfile.lock": parseGemfileLockEntries,
} }
return &Cataloger{ return &Cataloger{

View File

@ -12,12 +12,12 @@ type Cataloger struct {
} }
func NewCataloger() *Cataloger { func NewCataloger() *Cataloger {
pathParsers := map[string]common.ParserFn{ globParsers := map[string]common.ParserFn{
"/var/lib/dpkg/status": parseDpkgStatus, "**/var/lib/dpkg/status": parseDpkgStatus,
} }
return &Cataloger{ return &Cataloger{
cataloger: common.NewGenericCataloger(pathParsers, nil), cataloger: common.NewGenericCataloger(nil, globParsers),
} }
} }

View File

@ -11,11 +11,11 @@ import (
) )
var archiveFormatGlobs = []string{ var archiveFormatGlobs = []string{
"*.jar", "**/*.jar",
"*.war", "**/*.war",
"*.ear", "**/*.ear",
"*.jpi", "**/*.jpi",
"*.hpi", "**/*.hpi",
} }
type archiveParser struct { type archiveParser struct {

View File

@ -13,8 +13,8 @@ type Cataloger struct {
func NewCataloger() *Cataloger { func NewCataloger() *Cataloger {
globParsers := map[string]common.ParserFn{ globParsers := map[string]common.ParserFn{
"*egg-info/PKG-INFO": parseEggMetadata, "**/egg-info/PKG-INFO": parseEggMetadata,
"*dist-info/METADATA": parseWheelMetadata, "**/dist-info/METADATA": parseWheelMetadata,
} }
return &Cataloger{ return &Cataloger{

View File

@ -12,12 +12,12 @@ type Cataloger struct {
} }
func NewCataloger() *Cataloger { func NewCataloger() *Cataloger {
pathParsers := map[string]common.ParserFn{ globParsers := map[string]common.ParserFn{
"/var/lib/rpm/Packages": parseRpmDB, "**/var/lib/rpm/Packages": parseRpmDB,
} }
return &Cataloger{ return &Cataloger{
cataloger: common.NewGenericCataloger(pathParsers, nil), cataloger: common.NewGenericCataloger(nil, globParsers),
} }
} }

View File

@ -5,10 +5,10 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
"path/filepath"
"github.com/anchore/imgbom/internal/log" "github.com/anchore/imgbom/internal/log"
"github.com/anchore/stereoscope/pkg/file" "github.com/anchore/stereoscope/pkg/file"
"github.com/bmatcuk/doublestar"
) )
type DirectoryResolver struct { type DirectoryResolver struct {
@ -51,7 +51,7 @@ func (s DirectoryResolver) FilesByGlob(patterns ...string) ([]file.Reference, er
for _, pattern := range patterns { for _, pattern := range patterns {
pathPattern := path.Join(s.Path, pattern) pathPattern := path.Join(s.Path, pattern)
matches, err := filepath.Glob(pathPattern) matches, err := doublestar.Glob(pathPattern)
if err != nil { if err != nil {
return result, err return result, err
} }

View File

@ -138,6 +138,7 @@ func TestDirectoryResolver_FilesByGlobMultiple(t *testing.T) {
t.Run("finds multiple matching files", func(t *testing.T) { t.Run("finds multiple matching files", func(t *testing.T) {
resolver := DirectoryResolver{"test-fixtures"} resolver := DirectoryResolver{"test-fixtures"}
refs, err := resolver.FilesByGlob("image-symlinks/file*") refs, err := resolver.FilesByGlob("image-symlinks/file*")
if err != nil { if err != nil {
t.Fatalf("could not use resolver: %+v, %+v", err, refs) t.Fatalf("could not use resolver: %+v, %+v", err, refs)
} }
@ -149,6 +150,22 @@ func TestDirectoryResolver_FilesByGlobMultiple(t *testing.T) {
}) })
} }
func TestDirectoryResolver_FilesByGlobRecursive(t *testing.T) {
t.Run("finds multiple matching files", func(t *testing.T) {
resolver := DirectoryResolver{"test-fixtures"}
refs, err := resolver.FilesByGlob("**/*.txt")
if err != nil {
t.Fatalf("could not use resolver: %+v, %+v", err, refs)
}
if len(refs) != 4 {
t.Errorf("unexpected number of refs: %d != 4", len(refs))
}
})
}
func TestDirectoryResolver_FilesByGlobSingle(t *testing.T) { func TestDirectoryResolver_FilesByGlobSingle(t *testing.T) {
t.Run("finds multiple matching files", func(t *testing.T) { t.Run("finds multiple matching files", func(t *testing.T) {
resolver := DirectoryResolver{"test-fixtures"} resolver := DirectoryResolver{"test-fixtures"}

View File

@ -1,71 +0,0 @@
// +build integration
package integration
import (
"flag"
)
var update = flag.Bool("update", false, "update the *.golden files for json presenters")
// these tests are providing inconsistent results... we can fix in another PR
//func TestDirTextPresenter(t *testing.T) {
// var buffer bytes.Buffer
// protocol := imgbom.NewProtocol("dir://test-fixtures")
// if protocol.Type != imgbom.DirProtocol {
// t.Errorf("unexpected protocol returned: %v != %v", protocol.Type, imgbom.DirProtocol)
// }
//
// catalog, err := imgbom.CatalogDir(protocol.Value, scope.AllLayersScope)
// if err != nil {
// t.Errorf("could not produce catalog: %w", err)
// }
// presenterOpt := presenter.ParseOption("text")
// dirPresenter := presenter.GetDirPresenter(presenterOpt, protocol.Value, catalog)
//
// dirPresenter.Present(&buffer)
// actual := buffer.Bytes()
// if *update {
// testutils.UpdateGoldenFileContents(t, actual)
// }
//
// var expected = testutils.GetGoldenFileContents(t)
//
// if !bytes.Equal(expected, actual) {
// dmp := diffmatchpatch.New()
// diffs := dmp.DiffMain(string(actual), string(expected), true)
// t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs))
// }
//
//}
//
//func TestDirJsonPresenter(t *testing.T) {
// var buffer bytes.Buffer
// protocol := imgbom.NewProtocol("dir://test-fixtures")
// if protocol.Type != imgbom.DirProtocol {
// t.Errorf("unexpected protocol returned: %v != %v", protocol.Type, imgbom.DirProtocol)
// }
//
// catalog, err := imgbom.CatalogDir(protocol.Value, scope.AllLayersScope)
// if err != nil {
// t.Errorf("could not produce catalog: %w", err)
// }
// presenterOpt := presenter.ParseOption("json")
// dirPresenter := presenter.GetDirPresenter(presenterOpt, protocol.Value, catalog)
//
// dirPresenter.Present(&buffer)
// actual := buffer.Bytes()
// if *update {
// testutils.UpdateGoldenFileContents(t, actual)
// }
//
// var expected = testutils.GetGoldenFileContents(t)
//
// if !bytes.Equal(expected, actual) {
// dmp := diffmatchpatch.New()
// diffs := dmp.DiffMain(string(actual), string(expected), true)
// t.Errorf("mismatched output:\n%s", dmp.DiffPrettyText(diffs))
// }
//
//}

View File

@ -1,204 +0,0 @@
// +build integration
package integration
import (
"testing"
"github.com/anchore/imgbom/imgbom"
"github.com/anchore/imgbom/internal"
"github.com/anchore/go-testutils"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/imgbom/imgbom/scope"
)
func TestPkgCoverageImage(t *testing.T) {
fixtureImageName := "image-pkg-coverage"
_, cleanup := testutils.GetFixtureImage(t, "docker-archive", fixtureImageName)
tarPath := testutils.GetFixtureImageTarPath(t, fixtureImageName)
defer cleanup()
catalog, _, _, err := imgbom.Catalog("docker-archive://"+tarPath, scope.AllLayersScope)
if err != nil {
t.Fatalf("failed to catalog image: %+v", err)
}
cases := []struct {
name string
pkgType pkg.Type
pkgLanguage pkg.Language
pkgInfo map[string]string
}{
{
name: "find rpmdb packages",
pkgType: pkg.RpmPkg,
pkgInfo: map[string]string{
"dive": "0.9.2",
},
},
{
name: "find dpkg packages",
pkgType: pkg.DebPkg,
pkgInfo: map[string]string{
"apt": "1.8.2",
},
},
{
name: "find java packages",
pkgType: pkg.JavaPkg,
pkgLanguage: pkg.Java,
pkgInfo: map[string]string{
"example-java-app-maven": "0.1.0",
"example-jenkins-plugin": "1.0-SNAPSHOT", // the jeninks HPI file has a nested JAR of the same name
},
},
{
name: "find jenkins plugins",
pkgType: pkg.JenkinsPluginPkg,
pkgLanguage: pkg.Java,
pkgInfo: map[string]string{
"example-jenkins-plugin": "1.0-SNAPSHOT",
},
},
{
name: "find python wheel packages",
pkgType: pkg.WheelPkg,
pkgLanguage: pkg.Python,
pkgInfo: map[string]string{
"Pygments": "2.6.1",
},
},
{
name: "find python egg packages",
pkgType: pkg.EggPkg,
pkgLanguage: pkg.Python,
pkgInfo: map[string]string{
"requests": "2.22.0",
},
},
{
name: "find bundler packages",
pkgType: pkg.BundlerPkg,
pkgLanguage: pkg.Ruby,
pkgInfo: map[string]string{
"actionmailer": "4.1.1",
"actionpack": "4.1.1",
"actionview": "4.1.1",
"activemodel": "4.1.1",
"activerecord": "4.1.1",
"activesupport": "4.1.1",
"arel": "5.0.1.20140414130214",
"bootstrap-sass": "3.1.1.1",
"builder": "3.2.2",
"coffee-rails": "4.0.1",
"coffee-script": "2.2.0",
"coffee-script-source": "1.7.0",
"erubis": "2.7.0",
"execjs": "2.0.2",
"hike": "1.2.3",
"i18n": "0.6.9",
"jbuilder": "2.0.7",
"jquery-rails": "3.1.0",
"json": "1.8.1",
"kgio": "2.9.2",
"libv8": "3.16.14.3",
"mail": "2.5.4",
"mime-types": "1.25.1",
"minitest": "5.3.4",
"multi_json": "1.10.1",
"mysql2": "0.3.16",
"polyglot": "0.3.4",
"rack": "1.5.2",
"rack-test": "0.6.2",
"rails": "4.1.1",
"railties": "4.1.1",
"raindrops": "0.13.0",
"rake": "10.3.2",
"rdoc": "4.1.1",
"ref": "1.0.5",
"sass": "3.2.19",
"sass-rails": "4.0.3",
"sdoc": "0.4.0",
"spring": "1.1.3",
"sprockets": "2.11.0",
"sprockets-rails": "2.1.3",
"sqlite3": "1.3.9",
"therubyracer": "0.12.1",
"thor": "0.19.1",
"thread_safe": "0.3.3",
"tilt": "1.4.1",
"treetop": "1.4.15",
"turbolinks": "2.2.2",
"tzinfo": "1.2.0",
"uglifier": "2.5.0",
"unicorn": "4.8.3",
},
},
}
observedLanguages := internal.NewStringSet()
definedLanguages := internal.NewStringSet()
for _, l := range pkg.AllLanguages {
definedLanguages.Add(l.String())
}
observedPkgs := internal.NewStringSet()
definedPkgs := internal.NewStringSet()
for _, p := range pkg.AllPkgs {
definedPkgs.Add(p.String())
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pkgCount := 0
for a := range catalog.Enumerate(c.pkgType) {
observedLanguages.Add(a.Language.String())
observedPkgs.Add(a.Type.String())
expectedVersion, ok := c.pkgInfo[a.Name]
if !ok {
t.Errorf("unexpected package found: %s", a.Name)
}
if expectedVersion != a.Version {
t.Errorf("unexpected package version (pkg=%s): %s", a.Name, a.Version)
}
if a.Language != c.pkgLanguage {
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
}
if a.Type != c.pkgType {
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
}
pkgCount++
}
if pkgCount != len(c.pkgInfo) {
for a := range catalog.Enumerate(c.pkgType) {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
}
})
}
observedLanguages.Remove(pkg.UnknownLanguage.String())
definedLanguages.Remove(pkg.UnknownLanguage.String())
observedPkgs.Remove(pkg.UnknownPkg.String())
definedPkgs.Remove(pkg.UnknownPkg.String())
// ensure that integration test cases stay in sync with the available catalogers
if len(observedLanguages) < len(definedLanguages) {
t.Errorf("language coverage incomplete (languages=%d, coverage=%d)", len(definedLanguages), len(observedLanguages))
}
if len(observedPkgs) < len(definedPkgs) {
t.Errorf("package coverage incomplete (packages=%d, coverage=%d)", len(definedPkgs), len(observedPkgs))
}
}

View File

@ -0,0 +1,276 @@
// +build integration
package integration
import (
"testing"
"github.com/anchore/imgbom/imgbom"
"github.com/anchore/imgbom/internal"
"github.com/anchore/go-testutils"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/imgbom/imgbom/scope"
)
var cases = []struct {
name string
pkgType pkg.Type
pkgLanguage pkg.Language
pkgInfo map[string]string
}{
{
name: "find rpmdb packages",
pkgType: pkg.RpmPkg,
pkgInfo: map[string]string{
"dive": "0.9.2",
},
},
{
name: "find dpkg packages",
pkgType: pkg.DebPkg,
pkgInfo: map[string]string{
"apt": "1.8.2",
},
},
{
name: "find java packages",
pkgType: pkg.JavaPkg,
pkgLanguage: pkg.Java,
pkgInfo: map[string]string{
"example-java-app-maven": "0.1.0",
"example-jenkins-plugin": "1.0-SNAPSHOT", // the jenkins HPI file has a nested JAR of the same name
},
},
{
name: "find jenkins plugins",
pkgType: pkg.JenkinsPluginPkg,
pkgLanguage: pkg.Java,
pkgInfo: map[string]string{
"example-jenkins-plugin": "1.0-SNAPSHOT",
},
},
{
name: "find python wheel packages",
pkgType: pkg.WheelPkg,
pkgLanguage: pkg.Python,
pkgInfo: map[string]string{
"Pygments": "2.6.1",
},
},
{
name: "find python egg packages",
pkgType: pkg.EggPkg,
pkgLanguage: pkg.Python,
pkgInfo: map[string]string{
"requests": "2.22.0",
},
},
{
name: "find bundler packages",
pkgType: pkg.BundlerPkg,
pkgLanguage: pkg.Ruby,
pkgInfo: map[string]string{
"actionmailer": "4.1.1",
"actionpack": "4.1.1",
"actionview": "4.1.1",
"activemodel": "4.1.1",
"activerecord": "4.1.1",
"activesupport": "4.1.1",
"arel": "5.0.1.20140414130214",
"bootstrap-sass": "3.1.1.1",
"builder": "3.2.2",
"coffee-rails": "4.0.1",
"coffee-script": "2.2.0",
"coffee-script-source": "1.7.0",
"erubis": "2.7.0",
"execjs": "2.0.2",
"hike": "1.2.3",
"i18n": "0.6.9",
"jbuilder": "2.0.7",
"jquery-rails": "3.1.0",
"json": "1.8.1",
"kgio": "2.9.2",
"libv8": "3.16.14.3",
"mail": "2.5.4",
"mime-types": "1.25.1",
"minitest": "5.3.4",
"multi_json": "1.10.1",
"mysql2": "0.3.16",
"polyglot": "0.3.4",
"rack": "1.5.2",
"rack-test": "0.6.2",
"rails": "4.1.1",
"railties": "4.1.1",
"raindrops": "0.13.0",
"rake": "10.3.2",
"rdoc": "4.1.1",
"ref": "1.0.5",
"sass": "3.2.19",
"sass-rails": "4.0.3",
"sdoc": "0.4.0",
"spring": "1.1.3",
"sprockets": "2.11.0",
"sprockets-rails": "2.1.3",
"sqlite3": "1.3.9",
"therubyracer": "0.12.1",
"thor": "0.19.1",
"thread_safe": "0.3.3",
"tilt": "1.4.1",
"treetop": "1.4.15",
"turbolinks": "2.2.2",
"tzinfo": "1.2.0",
"uglifier": "2.5.0",
"unicorn": "4.8.3",
},
},
}
func TestPkgCoverageImage(t *testing.T) {
fixtureImageName := "image-pkg-coverage"
_, cleanup := testutils.GetFixtureImage(t, "docker-archive", fixtureImageName)
tarPath := testutils.GetFixtureImageTarPath(t, fixtureImageName)
defer cleanup()
catalog, _, _, err := imgbom.Catalog("docker-archive://"+tarPath, scope.AllLayersScope)
if err != nil {
t.Fatalf("failed to catalog image: %+v", err)
}
observedLanguages := internal.NewStringSet()
definedLanguages := internal.NewStringSet()
for _, l := range pkg.AllLanguages {
definedLanguages.Add(l.String())
}
observedPkgs := internal.NewStringSet()
definedPkgs := internal.NewStringSet()
for _, p := range pkg.AllPkgs {
definedPkgs.Add(p.String())
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pkgCount := 0
for a := range catalog.Enumerate(c.pkgType) {
observedLanguages.Add(a.Language.String())
observedPkgs.Add(a.Type.String())
expectedVersion, ok := c.pkgInfo[a.Name]
if !ok {
t.Errorf("unexpected package found: %s", a.Name)
}
if expectedVersion != a.Version {
t.Errorf("unexpected package version (pkg=%s): %s", a.Name, a.Version)
}
if a.Language != c.pkgLanguage {
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
}
if a.Type != c.pkgType {
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
}
pkgCount++
}
if pkgCount != len(c.pkgInfo) {
for a := range catalog.Enumerate(c.pkgType) {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
}
})
}
observedLanguages.Remove(pkg.UnknownLanguage.String())
definedLanguages.Remove(pkg.UnknownLanguage.String())
observedPkgs.Remove(pkg.UnknownPkg.String())
definedPkgs.Remove(pkg.UnknownPkg.String())
// ensure that integration test cases stay in sync with the available catalogers
if len(observedLanguages) < len(definedLanguages) {
t.Errorf("language coverage incomplete (languages=%d, coverage=%d)", len(definedLanguages), len(observedLanguages))
}
if len(observedPkgs) < len(definedPkgs) {
t.Errorf("package coverage incomplete (packages=%d, coverage=%d)", len(definedPkgs), len(observedPkgs))
}
}
func TestPkgCoverageDirectory(t *testing.T) {
catalog, _, _, err := imgbom.Catalog("dir://test-fixtures/image-pkg-coverage", scope.AllLayersScope)
if err != nil {
t.Errorf("unable to create scope from dir: %+v", err)
}
observedLanguages := internal.NewStringSet()
definedLanguages := internal.NewStringSet()
for _, l := range pkg.AllLanguages {
definedLanguages.Add(l.String())
}
observedPkgs := internal.NewStringSet()
definedPkgs := internal.NewStringSet()
for _, p := range pkg.AllPkgs {
definedPkgs.Add(p.String())
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pkgCount := 0
for a := range catalog.Enumerate(c.pkgType) {
observedLanguages.Add(a.Language.String())
observedPkgs.Add(a.Type.String())
expectedVersion, ok := c.pkgInfo[a.Name]
if !ok {
t.Errorf("unexpected package found: %s", a.Name)
}
if expectedVersion != a.Version {
t.Errorf("unexpected package version (pkg=%s): %s", a.Name, a.Version)
}
if a.Language != c.pkgLanguage {
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
}
if a.Type != c.pkgType {
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
}
pkgCount++
}
if pkgCount != len(c.pkgInfo) {
for a := range catalog.Enumerate(c.pkgType) {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=%d", pkgCount, len(c.pkgInfo))
}
})
}
observedLanguages.Remove(pkg.UnknownLanguage.String())
definedLanguages.Remove(pkg.UnknownLanguage.String())
observedPkgs.Remove(pkg.UnknownPkg.String())
definedPkgs.Remove(pkg.UnknownPkg.String())
// ensure that integration test cases stay in sync with the available catalogers
if len(observedLanguages) < len(definedLanguages) {
t.Errorf("language coverage incomplete (languages=%d, coverage=%d)", len(definedLanguages), len(observedLanguages))
}
if len(observedPkgs) < len(definedPkgs) {
t.Errorf("package coverage incomplete (packages=%d, coverage=%d)", len(definedPkgs), len(observedPkgs))
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,256 +0,0 @@
[Path: test-fixtures]
[actionmailer]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[actionpack]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[actionview]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[activemodel]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[activerecord]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[activesupport]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[arel]
Version: 5.0.1.20140414130214
Type: bundle
Found by: bundler-cataloger
[bootstrap-sass]
Version: 3.1.1.1
Type: bundle
Found by: bundler-cataloger
[builder]
Version: 3.2.2
Type: bundle
Found by: bundler-cataloger
[coffee-rails]
Version: 4.0.1
Type: bundle
Found by: bundler-cataloger
[coffee-script]
Version: 2.2.0
Type: bundle
Found by: bundler-cataloger
[coffee-script-source]
Version: 1.7.0
Type: bundle
Found by: bundler-cataloger
[erubis]
Version: 2.7.0
Type: bundle
Found by: bundler-cataloger
[execjs]
Version: 2.0.2
Type: bundle
Found by: bundler-cataloger
[hike]
Version: 1.2.3
Type: bundle
Found by: bundler-cataloger
[i18n]
Version: 0.6.9
Type: bundle
Found by: bundler-cataloger
[jbuilder]
Version: 2.0.7
Type: bundle
Found by: bundler-cataloger
[jquery-rails]
Version: 3.1.0
Type: bundle
Found by: bundler-cataloger
[json]
Version: 1.8.1
Type: bundle
Found by: bundler-cataloger
[kgio]
Version: 2.9.2
Type: bundle
Found by: bundler-cataloger
[libv8]
Version: 3.16.14.3
Type: bundle
Found by: bundler-cataloger
[mail]
Version: 2.5.4
Type: bundle
Found by: bundler-cataloger
[mime-types]
Version: 1.25.1
Type: bundle
Found by: bundler-cataloger
[minitest]
Version: 5.3.4
Type: bundle
Found by: bundler-cataloger
[multi_json]
Version: 1.10.1
Type: bundle
Found by: bundler-cataloger
[mysql2]
Version: 0.3.16
Type: bundle
Found by: bundler-cataloger
[polyglot]
Version: 0.3.4
Type: bundle
Found by: bundler-cataloger
[rack]
Version: 1.5.2
Type: bundle
Found by: bundler-cataloger
[rack-test]
Version: 0.6.2
Type: bundle
Found by: bundler-cataloger
[rails]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[railties]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[raindrops]
Version: 0.13.0
Type: bundle
Found by: bundler-cataloger
[rake]
Version: 10.3.2
Type: bundle
Found by: bundler-cataloger
[rdoc]
Version: 4.1.1
Type: bundle
Found by: bundler-cataloger
[ref]
Version: 1.0.5
Type: bundle
Found by: bundler-cataloger
[sass]
Version: 3.2.19
Type: bundle
Found by: bundler-cataloger
[sass-rails]
Version: 4.0.3
Type: bundle
Found by: bundler-cataloger
[sdoc]
Version: 0.4.0
Type: bundle
Found by: bundler-cataloger
[spring]
Version: 1.1.3
Type: bundle
Found by: bundler-cataloger
[sprockets]
Version: 2.11.0
Type: bundle
Found by: bundler-cataloger
[sprockets-rails]
Version: 2.1.3
Type: bundle
Found by: bundler-cataloger
[sqlite3]
Version: 1.3.9
Type: bundle
Found by: bundler-cataloger
[therubyracer]
Version: 0.12.1
Type: bundle
Found by: bundler-cataloger
[thor]
Version: 0.19.1
Type: bundle
Found by: bundler-cataloger
[thread_safe]
Version: 0.3.3
Type: bundle
Found by: bundler-cataloger
[tilt]
Version: 1.4.1
Type: bundle
Found by: bundler-cataloger
[treetop]
Version: 1.4.15
Type: bundle
Found by: bundler-cataloger
[turbolinks]
Version: 2.2.2
Type: bundle
Found by: bundler-cataloger
[tzinfo]
Version: 1.2.0
Type: bundle
Found by: bundler-cataloger
[uglifier]
Version: 2.5.0
Type: bundle
Found by: bundler-cataloger
[unicorn]
Version: 4.8.3
Type: bundle
Found by: bundler-cataloger