port ruby cataloger to new generic cataloger pattern (#1322)

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2022-11-04 11:33:55 -04:00 committed by GitHub
parent 3048382bbd
commit 41464bbd7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 182 additions and 177 deletions

View File

@ -4,23 +4,17 @@ Package ruby bundler provides a concrete Cataloger implementation for Ruby Gemfi
package ruby package ruby
import ( import (
"github.com/anchore/syft/syft/pkg/cataloger/common" "github.com/anchore/syft/syft/pkg/cataloger/generic"
) )
// NewGemFileLockCataloger returns a new Bundler cataloger object tailored for parsing index-oriented files (e.g. Gemfile.lock). // NewGemFileLockCataloger returns a new Bundler cataloger object tailored for parsing index-oriented files (e.g. Gemfile.lock).
func NewGemFileLockCataloger() *common.GenericCataloger { func NewGemFileLockCataloger() *generic.Cataloger {
globParsers := map[string]common.ParserFn{ return generic.NewCataloger("ruby-gemfile-cataloger").
"**/Gemfile.lock": parseGemFileLockEntries, WithParserByGlobs(parseGemFileLockEntries, "**/Gemfile.lock")
}
return common.NewGenericCataloger(nil, globParsers, "ruby-gemfile-cataloger")
} }
// NewGemSpecCataloger returns a new Bundler cataloger object tailored for detecting installations of gems (e.g. Gemspec). // NewGemSpecCataloger returns a new Bundler cataloger object tailored for detecting installations of gems (e.g. Gemspec).
func NewGemSpecCataloger() *common.GenericCataloger { func NewGemSpecCataloger() *generic.Cataloger {
globParsers := map[string]common.ParserFn{ return generic.NewCataloger("ruby-gemspec-cataloger").
"**/specifications/**/*.gemspec": parseGemSpecEntries, WithParserByGlobs(parseGemSpecEntries, "**/specifications/**/*.gemspec")
}
return common.NewGenericCataloger(nil, globParsers, "ruby-gemspec-cataloger")
} }

View File

@ -0,0 +1,53 @@
package ruby
import (
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/source"
)
func newGemfileLockPackage(name, version string, locations ...source.Location) pkg.Package {
p := pkg.Package{
Name: name,
Version: version,
PURL: packageURL(name, version),
Locations: source.NewLocationSet(locations...),
Language: pkg.Ruby,
Type: pkg.GemPkg,
}
p.SetID()
return p
}
func newGemspecPackage(m pkg.GemMetadata, locations ...source.Location) pkg.Package {
p := pkg.Package{
Name: m.Name,
Version: m.Version,
Locations: source.NewLocationSet(locations...),
PURL: packageURL(m.Name, m.Version),
Licenses: m.Licenses,
Language: pkg.Ruby,
Type: pkg.GemPkg,
MetadataType: pkg.GemMetadataType,
Metadata: m,
}
p.SetID()
return p
}
func packageURL(name, version string) string {
var qualifiers packageurl.Qualifiers
return packageurl.NewPackageURL(
packageurl.TypeGem,
"",
name,
version,
qualifiers,
"",
).ToString()
}

View File

@ -0,0 +1,31 @@
package ruby
import (
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
)
func Test_packageURL(t *testing.T) {
tests := []struct {
name string
version string
expected string
}{
{
name: "p",
version: "v",
expected: "pkg:gem/p@v",
},
}
for _, test := range tests {
t.Run(fmt.Sprintf("%s@%s", test.name, test.version), func(t *testing.T) {
actual := packageURL(test.name, test.version)
if diff := cmp.Diff(test.expected, actual); diff != "" {
t.Errorf("unexpected packageURL (-want +got):\n%s", diff)
}
})
}
}

View File

@ -2,23 +2,22 @@ package ruby
import ( import (
"bufio" "bufio"
"io"
"strings" "strings"
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/common" "github.com/anchore/syft/syft/pkg/cataloger/generic"
"github.com/anchore/syft/syft/source"
) )
// integrity check var _ generic.Parser = parseGemFileLockEntries
var _ common.ParserFn = parseGemFileLockEntries
var sectionsOfInterest = internal.NewStringSet("GEM") var sectionsOfInterest = internal.NewStringSet("GEM")
// parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered. // parseGemFileLockEntries is a parser function for Gemfile.lock contents, returning all Gems discovered.
func parseGemFileLockEntries(_ string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { func parseGemFileLockEntries(_ source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
pkgs := make([]*pkg.Package, 0) var pkgs []pkg.Package
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
var currentSection string var currentSection string
@ -41,12 +40,13 @@ func parseGemFileLockEntries(_ string, reader io.Reader) ([]*pkg.Package, []arti
if len(candidate) != 2 { if len(candidate) != 2 {
continue continue
} }
pkgs = append(pkgs, &pkg.Package{ pkgs = append(pkgs,
Name: candidate[0], newGemfileLockPackage(
Version: strings.Trim(candidate[1], "()"), candidate[0],
Language: pkg.Ruby, strings.Trim(candidate[1], "()"),
Type: pkg.GemPkg, reader.Location,
}) ),
)
} }
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {

View File

@ -1,102 +1,69 @@
package ruby package ruby
import ( import (
"os"
"testing" "testing"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
"github.com/anchore/syft/syft/source"
) )
func TestParseGemfileLockEntries(t *testing.T) { func TestParseGemfileLockEntries(t *testing.T) {
fixture := "test-fixtures/Gemfile.lock"
var expectedGems = map[string]string{ locations := source.NewLocationSet(source.NewLocation(fixture))
"actionmailer": "4.1.1", var expectedPkgs = []pkg.Package{
"actionpack": "4.1.1", {Name: "actionmailer", Version: "4.1.1", PURL: "pkg:gem/actionmailer@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"actionview": "4.1.1", {Name: "actionpack", Version: "4.1.1", PURL: "pkg:gem/actionpack@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"activemodel": "4.1.1", {Name: "actionview", Version: "4.1.1", PURL: "pkg:gem/actionview@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"activerecord": "4.1.1", {Name: "activemodel", Version: "4.1.1", PURL: "pkg:gem/activemodel@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"activesupport": "4.1.1", {Name: "activerecord", Version: "4.1.1", PURL: "pkg:gem/activerecord@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"arel": "5.0.1.20140414130214", {Name: "activesupport", Version: "4.1.1", PURL: "pkg:gem/activesupport@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"bootstrap-sass": "3.1.1.1", {Name: "arel", Version: "5.0.1.20140414130214", PURL: "pkg:gem/arel@5.0.1.20140414130214", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"builder": "3.2.2", {Name: "bootstrap-sass", Version: "3.1.1.1", PURL: "pkg:gem/bootstrap-sass@3.1.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"coffee-rails": "4.0.1", {Name: "builder", Version: "3.2.2", PURL: "pkg:gem/builder@3.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"coffee-script": "2.2.0", {Name: "coffee-rails", Version: "4.0.1", PURL: "pkg:gem/coffee-rails@4.0.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"coffee-script-source": "1.7.0", {Name: "coffee-script", Version: "2.2.0", PURL: "pkg:gem/coffee-script@2.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"erubis": "2.7.0", {Name: "coffee-script-source", Version: "1.7.0", PURL: "pkg:gem/coffee-script-source@1.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"execjs": "2.0.2", {Name: "erubis", Version: "2.7.0", PURL: "pkg:gem/erubis@2.7.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"hike": "1.2.3", {Name: "execjs", Version: "2.0.2", PURL: "pkg:gem/execjs@2.0.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"i18n": "0.6.9", {Name: "hike", Version: "1.2.3", PURL: "pkg:gem/hike@1.2.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"jbuilder": "2.0.7", {Name: "i18n", Version: "0.6.9", PURL: "pkg:gem/i18n@0.6.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"jquery-rails": "3.1.0", {Name: "jbuilder", Version: "2.0.7", PURL: "pkg:gem/jbuilder@2.0.7", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"json": "1.8.1", {Name: "jquery-rails", Version: "3.1.0", PURL: "pkg:gem/jquery-rails@3.1.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"kgio": "2.9.2", {Name: "json", Version: "1.8.1", PURL: "pkg:gem/json@1.8.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"libv8": "3.16.14.3", {Name: "kgio", Version: "2.9.2", PURL: "pkg:gem/kgio@2.9.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"mail": "2.5.4", {Name: "libv8", Version: "3.16.14.3", PURL: "pkg:gem/libv8@3.16.14.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"mime-types": "1.25.1", {Name: "mail", Version: "2.5.4", PURL: "pkg:gem/mail@2.5.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"minitest": "5.3.4", {Name: "mime-types", Version: "1.25.1", PURL: "pkg:gem/mime-types@1.25.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"multi_json": "1.10.1", {Name: "minitest", Version: "5.3.4", PURL: "pkg:gem/minitest@5.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"mysql2": "0.3.16", {Name: "multi_json", Version: "1.10.1", PURL: "pkg:gem/multi_json@1.10.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"polyglot": "0.3.4", {Name: "mysql2", Version: "0.3.16", PURL: "pkg:gem/mysql2@0.3.16", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"rack": "1.5.2", {Name: "polyglot", Version: "0.3.4", PURL: "pkg:gem/polyglot@0.3.4", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"rack-test": "0.6.2", {Name: "rack", Version: "1.5.2", PURL: "pkg:gem/rack@1.5.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"rails": "4.1.1", {Name: "rack-test", Version: "0.6.2", PURL: "pkg:gem/rack-test@0.6.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"railties": "4.1.1", {Name: "rails", Version: "4.1.1", PURL: "pkg:gem/rails@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"raindrops": "0.13.0", {Name: "railties", Version: "4.1.1", PURL: "pkg:gem/railties@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"rake": "10.3.2", {Name: "raindrops", Version: "0.13.0", PURL: "pkg:gem/raindrops@0.13.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"rdoc": "4.1.1", {Name: "rake", Version: "10.3.2", PURL: "pkg:gem/rake@10.3.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"ref": "1.0.5", {Name: "rdoc", Version: "4.1.1", PURL: "pkg:gem/rdoc@4.1.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sass": "3.2.19", {Name: "ref", Version: "1.0.5", PURL: "pkg:gem/ref@1.0.5", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sass-rails": "4.0.3", {Name: "sass", Version: "3.2.19", PURL: "pkg:gem/sass@3.2.19", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sdoc": "0.4.0", {Name: "sass-rails", Version: "4.0.3", PURL: "pkg:gem/sass-rails@4.0.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"spring": "1.1.3", {Name: "sdoc", Version: "0.4.0", PURL: "pkg:gem/sdoc@0.4.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sprockets": "2.11.0", {Name: "spring", Version: "1.1.3", PURL: "pkg:gem/spring@1.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sprockets-rails": "2.1.3", {Name: "sprockets", Version: "2.11.0", PURL: "pkg:gem/sprockets@2.11.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"sqlite3": "1.3.9", {Name: "sprockets-rails", Version: "2.1.3", PURL: "pkg:gem/sprockets-rails@2.1.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"therubyracer": "0.12.1", {Name: "sqlite3", Version: "1.3.9", PURL: "pkg:gem/sqlite3@1.3.9", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"thor": "0.19.1", {Name: "therubyracer", Version: "0.12.1", PURL: "pkg:gem/therubyracer@0.12.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"thread_safe": "0.3.3", {Name: "thor", Version: "0.19.1", PURL: "pkg:gem/thor@0.19.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"tilt": "1.4.1", {Name: "thread_safe", Version: "0.3.3", PURL: "pkg:gem/thread_safe@0.3.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"treetop": "1.4.15", {Name: "tilt", Version: "1.4.1", PURL: "pkg:gem/tilt@1.4.1", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"turbolinks": "2.2.2", {Name: "treetop", Version: "1.4.15", PURL: "pkg:gem/treetop@1.4.15", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"tzinfo": "1.2.0", {Name: "turbolinks", Version: "2.2.2", PURL: "pkg:gem/turbolinks@2.2.2", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"uglifier": "2.5.0", {Name: "tzinfo", Version: "1.2.0", PURL: "pkg:gem/tzinfo@1.2.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
"unicorn": "4.8.3", {Name: "uglifier", Version: "2.5.0", PURL: "pkg:gem/uglifier@2.5.0", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
{Name: "unicorn", Version: "4.8.3", PURL: "pkg:gem/unicorn@4.8.3", Locations: locations, Language: pkg.Ruby, Type: pkg.GemPkg},
} }
fixture, err := os.Open("test-fixtures/Gemfile.lock") pkgtest.TestFileParser(t, fixture, parseGemFileLockEntries, expectedPkgs, nil)
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}
// TODO: no relationships are under test yet
actual, _, err := parseGemFileLockEntries(fixture.Name(), fixture)
if err != nil {
t.Fatalf("failed to parse gemfile lock: %+v", err)
}
if len(actual) != len(expectedGems) {
for _, a := range actual {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=%d", len(actual), len(expectedGems))
}
for _, a := range actual {
expectedVersion, ok := expectedGems[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 != pkg.Ruby {
t.Errorf("bad language (pkg=%+v): %+v", a.Name, a.Language)
}
if a.Type != pkg.GemPkg {
t.Errorf("bad package type (pkg=%+v): %+v", a.Name, a.Type)
}
}
} }

View File

@ -4,7 +4,6 @@ import (
"bufio" "bufio"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"regexp" "regexp"
"strings" "strings"
@ -13,11 +12,11 @@ import (
"github.com/anchore/syft/internal" "github.com/anchore/syft/internal"
"github.com/anchore/syft/syft/artifact" "github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/common" "github.com/anchore/syft/syft/pkg/cataloger/generic"
"github.com/anchore/syft/syft/source"
) )
// integrity check var _ generic.Parser = parseGemFileLockEntries
var _ common.ParserFn = parseGemFileLockEntries
type postProcessor func(string) []string type postProcessor func(string) []string
@ -36,14 +35,14 @@ var patterns = map[string]*regexp.Regexp{
"homepage": regexp.MustCompile(`.*\.homepage\s*=\s*["']{1}(?P<homepage>.*)["']{1} *`), "homepage": regexp.MustCompile(`.*\.homepage\s*=\s*["']{1}(?P<homepage>.*)["']{1} *`),
// match example: files = ["exe/bundle".freeze, "exe/bundler".freeze] ---> "exe/bundle".freeze, "exe/bundler".freeze // match example: files = ["exe/bundle".freeze, "exe/bundler".freeze] ---> "exe/bundle".freeze, "exe/bundler".freeze
"files": regexp.MustCompile(`.*\.files\s*=\s*\[(?P<files>.*)\] *`), "files": regexp.MustCompile(`.*\.files\s*=\s*\[(?P<files>.*)] *`),
// match example: authors = ["Andr\u00E9 Arko".freeze, "Samuel Giddins".freeze, "Colby Swandale".freeze, // match example: authors = ["Andr\u00E9 Arko".freeze, "Samuel Giddins".freeze, "Colby Swandale".freeze,
// "Hiroshi Shibata".freeze, "David Rodr\u00EDguez".freeze, "Grey Baker".freeze...] // "Hiroshi Shibata".freeze, "David Rodr\u00EDguez".freeze, "Grey Baker".freeze...]
"authors": regexp.MustCompile(`.*\.authors\s*=\s*\[(?P<authors>.*)\] *`), "authors": regexp.MustCompile(`.*\.authors\s*=\s*\[(?P<authors>.*)] *`),
// match example: licenses = ["MIT".freeze] ----> "MIT".freeze // match example: licenses = ["MIT".freeze] ----> "MIT".freeze
"licenses": regexp.MustCompile(`.*\.licenses\s*=\s*\[(?P<licenses>.*)\] *`), "licenses": regexp.MustCompile(`.*\.licenses\s*=\s*\[(?P<licenses>.*)] *`),
} }
var postProcessors = map[string]postProcessor{ var postProcessors = map[string]postProcessor{
@ -60,8 +59,8 @@ func processList(s string) []string {
return results return results
} }
func parseGemSpecEntries(_ string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) { func parseGemSpecEntries(_ source.FileResolver, _ *generic.Environment, reader source.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
var pkgs []*pkg.Package var pkgs []pkg.Package
var fields = make(map[string]interface{}) var fields = make(map[string]interface{})
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
@ -79,8 +78,8 @@ func parseGemSpecEntries(_ string, reader io.Reader) ([]*pkg.Package, []artifact
for field, pattern := range patterns { for field, pattern := range patterns {
matchMap := internal.MatchNamedCaptureGroups(pattern, sanitizedLine) matchMap := internal.MatchNamedCaptureGroups(pattern, sanitizedLine)
if value := matchMap[field]; value != "" { if value := matchMap[field]; value != "" {
if postProcessor := postProcessors[field]; postProcessor != nil { if pp := postProcessors[field]; pp != nil {
fields[field] = postProcessor(value) fields[field] = pp(value)
} else { } else {
fields[field] = value fields[field] = value
} }
@ -96,15 +95,7 @@ func parseGemSpecEntries(_ string, reader io.Reader) ([]*pkg.Package, []artifact
return nil, nil, fmt.Errorf("unable to decode gem metadata: %w", err) return nil, nil, fmt.Errorf("unable to decode gem metadata: %w", err)
} }
pkgs = append(pkgs, &pkg.Package{ pkgs = append(pkgs, newGemspecPackage(metadata, reader.Location))
Name: metadata.Name,
Version: metadata.Version,
Licenses: metadata.Licenses,
Language: pkg.Ruby,
Type: pkg.GemPkg,
MetadataType: pkg.GemMetadataType,
Metadata: metadata,
})
} }
return pkgs, nil, nil return pkgs, nil, nil

View File

@ -1,18 +1,23 @@
package ruby package ruby
import ( import (
"os"
"testing" "testing"
"github.com/go-test/deep"
"github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
"github.com/anchore/syft/syft/source"
) )
func TestParseGemspec(t *testing.T) { func TestParseGemspec(t *testing.T) {
fixture := "test-fixtures/bundler.gemspec"
locations := source.NewLocationSet(source.NewLocation(fixture))
var expectedPkg = pkg.Package{ var expectedPkg = pkg.Package{
Name: "bundler", Name: "bundler",
Version: "2.1.4", Version: "2.1.4",
PURL: "pkg:gem/bundler@2.1.4",
Locations: locations,
Type: pkg.GemPkg, Type: pkg.GemPkg,
Licenses: []string{"MIT"}, Licenses: []string{"MIT"},
Language: pkg.Ruby, Language: pkg.Ruby,
@ -27,25 +32,5 @@ func TestParseGemspec(t *testing.T) {
}, },
} }
fixture, err := os.Open("test-fixtures/bundler.gemspec") pkgtest.TestFileParser(t, fixture, parseGemSpecEntries, []pkg.Package{expectedPkg}, nil)
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}
// TODO: no relationships are under test yet
actual, _, err := parseGemSpecEntries(fixture.Name(), fixture)
if err != nil {
t.Fatalf("failed to parse gemspec: %+v", err)
}
if len(actual) != 1 {
for _, a := range actual {
t.Log(" ", a)
}
t.Fatalf("unexpected package count: %d!=1", len(actual))
}
for _, d := range deep.Equal(actual[0], &expectedPkg) {
t.Errorf("diff: %+v", d)
}
} }

View File

@ -17,24 +17,6 @@ func TestPackageURL(t *testing.T) {
distro *linux.Release distro *linux.Release
expected string expected string
}{ }{
{
name: "gem",
pkg: Package{
Name: "name",
Version: "v0.1.0",
Type: GemPkg,
},
expected: "pkg:gem/name@v0.1.0",
},
{
name: "npm",
pkg: Package{
Name: "name",
Version: "v0.1.0",
Type: NpmPkg,
},
expected: "pkg:npm/name@v0.1.0",
},
{ {
name: "cargo", name: "cargo",
pkg: Package{ pkg: Package{
@ -109,6 +91,8 @@ func TestPackageURL(t *testing.T) {
expectedTypes.Remove(string(PhpComposerPkg)) expectedTypes.Remove(string(PhpComposerPkg))
expectedTypes.Remove(string(PythonPkg)) expectedTypes.Remove(string(PythonPkg))
expectedTypes.Remove(string(RpmPkg)) expectedTypes.Remove(string(RpmPkg))
expectedTypes.Remove(string(GemPkg))
expectedTypes.Remove(string(NpmPkg))
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {