Merge pull request #640 from KeyboardNerd/sourcePackage

database: Replace Parent Feature with source metadata
This commit is contained in:
Sida Chen 2018-10-15 16:49:50 -04:00 committed by GitHub
commit 17539bda60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 341 additions and 419 deletions

View File

@ -40,8 +40,13 @@ func DeduplicateFeatures(features ...Feature) []Feature {
fSet.Add(f) fSet.Add(f)
} }
uniqueFeatures := make([]Feature, 0, fSet.Cardinality()) return ConvertFeatureSetToFeatures(fSet)
for f := range fSet.Iter() { }
// ConvertFeatureSetToFeatures converts a feature set to an array of features
func ConvertFeatureSetToFeatures(features mapset.Set) []Feature {
uniqueFeatures := make([]Feature, 0, features.Cardinality())
for f := range features.Iter() {
uniqueFeatures = append(uniqueFeatures, f.(Feature)) uniqueFeatures = append(uniqueFeatures, f.(Feature))
} }

View File

@ -158,19 +158,15 @@ type Namespace struct {
// Feature represents a package detected in a layer but the namespace is not // Feature represents a package detected in a layer but the namespace is not
// determined. // determined.
// //
// e.g. Name: OpenSSL, Version: 1.0, VersionFormat: dpkg. // e.g. Name: Libssl1.0, Version: 1.0, Name: Openssl, Version: 1.0, VersionFormat: dpkg.
// dpkg is the version format of the installer package manager, which in this // dpkg is the version format of the installer package manager, which in this
// case could be dpkg or apk. // case could be dpkg or apk.
type Feature struct { type Feature struct {
Name string Name string
Version string Version string
SourceName string
SourceVersion string
VersionFormat string VersionFormat string
// Parent feature indicates that the vulnerability affects parent feature
// will also affect this feature.
//
// e.g. A source package is the parent feature of a binary package.
Parent *Feature
} }
// NamespacedFeature is a feature with determined namespace and can be affected // NamespacedFeature is a feature with determined namespace and can be affected

View File

@ -26,10 +26,10 @@ import (
// int keys must be the consistent with the database ID. // int keys must be the consistent with the database ID.
var ( var (
realFeatures = map[int]database.Feature{ realFeatures = map[int]database.Feature{
1: {"ourchat", "0.5", "dpkg", nil}, 1: {"ourchat", "0.5", "ourchat", "0.5", "dpkg"},
2: {"openssl", "1.0", "dpkg", nil}, 2: {"openssl", "1.0", "openssl", "1.0", "dpkg"},
3: {"openssl", "2.0", "dpkg", nil}, 3: {"openssl", "2.0", "openssl", "2.0", "dpkg"},
4: {"fake", "2.0", "rpm", nil}, 4: {"fake", "2.0", "fake", "2.0", "rpm"},
} }
realNamespaces = map[int]database.Namespace{ realNamespaces = map[int]database.Namespace{

View File

@ -35,14 +35,8 @@ func init() {
type lister struct{} type lister struct{}
func valid(pkg *featurefmt.PackageInfo) bool { func valid(pkg *database.Feature) bool {
return pkg.PackageName != "" && pkg.PackageVersion != "" return pkg.Name != "" && pkg.Version != ""
}
func addSourceVersion(pkg *featurefmt.PackageInfo) {
if pkg.SourceName != "" {
pkg.SourceVersion = pkg.PackageVersion
}
} }
func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) { func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error) {
@ -55,23 +49,24 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
// package into a feature that will be stored in a set to guarantee // package into a feature that will be stored in a set to guarantee
// uniqueness. // uniqueness.
packages := mapset.NewSet() packages := mapset.NewSet()
pkg := featurefmt.PackageInfo{} pkg := database.Feature{VersionFormat: dpkg.ParserName}
scanner := bufio.NewScanner(bytes.NewBuffer(file)) scanner := bufio.NewScanner(bytes.NewBuffer(file))
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
if len(line) < 2 { if len(line) < 2 {
if valid(&pkg) { if valid(&pkg) {
addSourceVersion(&pkg)
packages.Add(pkg) packages.Add(pkg)
pkg.Reset() pkg = database.Feature{VersionFormat: dpkg.ParserName}
} }
continue continue
} }
// Parse the package name or version. // Parse the package name or version.
// Alpine package doesn't have specific source package. The "origin"
// package is sub package.
switch line[:2] { switch line[:2] {
case "P:": case "P:":
pkg.PackageName = line[2:] pkg.Name = line[2:]
case "V:": case "V:":
version := string(line[2:]) version := string(line[2:])
err := versionfmt.Valid(dpkg.ParserName, version) err := versionfmt.Valid(dpkg.ParserName, version)
@ -79,20 +74,17 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
log.WithError(err).WithField("version", version).Warning("could not parse package version. skipping") log.WithError(err).WithField("version", version).Warning("could not parse package version. skipping")
continue continue
} else { } else {
pkg.PackageVersion = version pkg.Version = version
} }
case "o:":
pkg.SourceName = line[2:]
} }
} }
// in case of no terminal line // in case of no terminal line
if valid(&pkg) { if valid(&pkg) {
addSourceVersion(&pkg)
packages.Add(pkg) packages.Add(pkg)
} }
return featurefmt.PackageSetToFeatures(dpkg.ParserName, packages), nil return database.ConvertFeatureSetToFeatures(packages), nil
} }
func (l lister) RequiredFilenames() []string { func (l lister) RequiredFilenames() []string {

View File

@ -17,6 +17,7 @@ package apk
import ( import (
"testing" "testing"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/featurefmt" "github.com/coreos/clair/ext/featurefmt"
"github.com/coreos/clair/ext/versionfmt/dpkg" "github.com/coreos/clair/ext/versionfmt/dpkg"
) )
@ -26,18 +27,18 @@ func TestAPKFeatureDetection(t *testing.T) {
{ {
"valid case", "valid case",
map[string]string{"lib/apk/db/installed": "apk/testdata/valid"}, map[string]string{"lib/apk/db/installed": "apk/testdata/valid"},
[]featurefmt.PackageInfo{ []database.Feature{
{"musl", "1.1.14-r10", "", ""}, {"musl", "1.1.14-r10", "", "", dpkg.ParserName},
{"busybox", "1.24.2-r9", "", ""}, {"busybox", "1.24.2-r9", "", "", dpkg.ParserName},
{"alpine-baselayout", "3.0.3-r0", "", ""}, {"alpine-baselayout", "3.0.3-r0", "", "", dpkg.ParserName},
{"alpine-keys", "1.1-r0", "", ""}, {"alpine-keys", "1.1-r0", "", "", dpkg.ParserName},
{"zlib", "1.2.8-r2", "", ""}, {"zlib", "1.2.8-r2", "", "", dpkg.ParserName},
{"libcrypto1.0", "1.0.2h-r1", "openssl", "1.0.2h-r1"}, {"libcrypto1.0", "1.0.2h-r1", "", "", dpkg.ParserName},
{"libssl1.0", "1.0.2h-r1", "openssl", "1.0.2h-r1"}, {"libssl1.0", "1.0.2h-r1", "", "", dpkg.ParserName},
{"apk-tools", "2.6.7-r0", "", ""}, {"apk-tools", "2.6.7-r0", "", "", dpkg.ParserName},
{"scanelf", "1.1.6-r0", "pax-utils", "1.1.6-r0"}, {"scanelf", "1.1.6-r0", "", "", dpkg.ParserName},
{"musl-utils", "1.1.14-r10", "musl", "1.1.14-r10"}, {"musl-utils", "1.1.14-r10", "", "", dpkg.ParserName},
{"libc-utils", "0.7-r0", "libc-dev", "0.7-r0"}, {"libc-utils", "0.7-r0", "", "", dpkg.ParserName},
}, },
}, },
} { } {

View File

@ -41,13 +41,17 @@ func init() {
featurefmt.RegisterLister("dpkg", "1.0", &lister{}) featurefmt.RegisterLister("dpkg", "1.0", &lister{})
} }
func valid(pkg *featurefmt.PackageInfo) bool { func valid(pkg *database.Feature) bool {
return pkg.PackageName != "" && pkg.PackageVersion != "" return pkg.Name != "" && pkg.Version != ""
} }
func addSourceVersion(pkg *featurefmt.PackageInfo) { func addSourcePackage(pkg *database.Feature) {
if pkg.SourceName != "" && pkg.SourceVersion == "" { if pkg.SourceName == "" {
pkg.SourceVersion = pkg.PackageVersion pkg.SourceName = pkg.Name
}
if pkg.SourceVersion == "" {
pkg.SourceVersion = pkg.Version
} }
} }
@ -58,7 +62,7 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
} }
var ( var (
pkg featurefmt.PackageInfo pkg = database.Feature{VersionFormat: dpkg.ParserName}
pkgs = mapset.NewSet() pkgs = mapset.NewSet()
err error err error
) )
@ -70,8 +74,8 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
// Package line // Package line
// Defines the name of the package // Defines the name of the package
pkg.PackageName = strings.TrimSpace(strings.TrimPrefix(line, "Package: ")) pkg.Name = strings.TrimSpace(strings.TrimPrefix(line, "Package: "))
pkg.PackageVersion = "" pkg.Version = ""
} else if strings.HasPrefix(line, "Source: ") { } else if strings.HasPrefix(line, "Source: ") {
// Source line (Optional) // Source line (Optional)
// Gives the name of the source package // Gives the name of the source package
@ -102,19 +106,19 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
if err = versionfmt.Valid(dpkg.ParserName, version); err != nil { if err = versionfmt.Valid(dpkg.ParserName, version); err != nil {
log.WithError(err).WithField("version", string(line[1])).Warning("could not parse package version. skipping") log.WithError(err).WithField("version", string(line[1])).Warning("could not parse package version. skipping")
} else { } else {
pkg.PackageVersion = version pkg.Version = version
} }
} else if line == "" { } else if line == "" {
pkg.Reset() pkg = database.Feature{VersionFormat: dpkg.ParserName}
} }
if valid(&pkg) { if valid(&pkg) {
addSourceVersion(&pkg) addSourcePackage(&pkg)
pkgs.Add(pkg) pkgs.Add(pkg)
} }
} }
return featurefmt.PackageSetToFeatures(dpkg.ParserName, pkgs), nil return database.ConvertFeatureSetToFeatures(pkgs), nil
} }
func (l lister) RequiredFilenames() []string { func (l lister) RequiredFilenames() []string {

View File

@ -17,6 +17,7 @@ package dpkg
import ( import (
"testing" "testing"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/featurefmt" "github.com/coreos/clair/ext/featurefmt"
"github.com/coreos/clair/ext/versionfmt/dpkg" "github.com/coreos/clair/ext/versionfmt/dpkg"
) )
@ -26,106 +27,106 @@ func TestListFeatures(t *testing.T) {
{ {
"valid status file", "valid status file",
map[string]string{"var/lib/dpkg/status": "dpkg/testdata/valid"}, map[string]string{"var/lib/dpkg/status": "dpkg/testdata/valid"},
[]featurefmt.PackageInfo{ []database.Feature{
{"adduser", "3.116ubuntu1", "", ""}, {"adduser", "3.116ubuntu1", "adduser", "3.116ubuntu1", dpkg.ParserName},
{"apt", "1.6.3ubuntu0.1", "", ""}, {"apt", "1.6.3ubuntu0.1", "apt", "1.6.3ubuntu0.1", dpkg.ParserName},
{"base-files", "10.1ubuntu2.2", "", ""}, {"base-files", "10.1ubuntu2.2", "base-files", "10.1ubuntu2.2", dpkg.ParserName},
{"base-passwd", "3.5.44", "", ""}, {"base-passwd", "3.5.44", "base-passwd", "3.5.44", dpkg.ParserName},
{"bash", "4.4.18-2ubuntu1", "", ""}, {"bash", "4.4.18-2ubuntu1", "bash", "4.4.18-2ubuntu1", dpkg.ParserName},
{"bsdutils", "1:2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"bsdutils", "1:2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"bzip2", "1.0.6-8.1", "", ""}, {"bzip2", "1.0.6-8.1", "bzip2", "1.0.6-8.1", dpkg.ParserName},
{"coreutils", "8.28-1ubuntu1", "", ""}, {"coreutils", "8.28-1ubuntu1", "coreutils", "8.28-1ubuntu1", dpkg.ParserName},
{"dash", "0.5.8-2.10", "", ""}, {"dash", "0.5.8-2.10", "dash", "0.5.8-2.10", dpkg.ParserName},
{"debconf", "1.5.66", "", ""}, {"debconf", "1.5.66", "debconf", "1.5.66", dpkg.ParserName},
{"debianutils", "4.8.4", "", ""}, {"debianutils", "4.8.4", "debianutils", "4.8.4", dpkg.ParserName},
{"diffutils", "1:3.6-1", "", ""}, {"diffutils", "1:3.6-1", "diffutils", "1:3.6-1", dpkg.ParserName},
{"dpkg", "1.19.0.5ubuntu2", "", ""}, {"dpkg", "1.19.0.5ubuntu2", "dpkg", "1.19.0.5ubuntu2", dpkg.ParserName},
{"e2fsprogs", "1.44.1-1", "", ""}, {"e2fsprogs", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName},
{"fdisk", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"fdisk", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"findutils", "4.6.0+git+20170828-2", "", ""}, {"findutils", "4.6.0+git+20170828-2", "findutils", "4.6.0+git+20170828-2", dpkg.ParserName},
{"gcc-8-base", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2"}, {"gcc-8-base", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName},
{"gpgv", "2.2.4-1ubuntu1.1", "gnupg2", "2.2.4-1ubuntu1.1"}, {"gpgv", "2.2.4-1ubuntu1.1", "gnupg2", "2.2.4-1ubuntu1.1", dpkg.ParserName},
{"grep", "3.1-2", "", ""}, {"grep", "3.1-2", "grep", "3.1-2", dpkg.ParserName},
{"gzip", "1.6-5ubuntu1", "", ""}, {"gzip", "1.6-5ubuntu1", "gzip", "1.6-5ubuntu1", dpkg.ParserName},
{"hostname", "3.20", "", ""}, {"hostname", "3.20", "hostname", "3.20", dpkg.ParserName},
{"init-system-helpers", "1.51", "", ""}, {"init-system-helpers", "1.51", "init-system-helpers", "1.51", dpkg.ParserName},
{"libacl1", "2.2.52-3build1", "acl", "2.2.52-3build1"}, {"libacl1", "2.2.52-3build1", "acl", "2.2.52-3build1", dpkg.ParserName},
{"libapt-pkg5.0", "1.6.3ubuntu0.1", "apt", "1.6.3ubuntu0.1"}, {"libapt-pkg5.0", "1.6.3ubuntu0.1", "apt", "1.6.3ubuntu0.1", dpkg.ParserName},
{"libattr1", "1:2.4.47-2build1", "attr", "1:2.4.47-2build1"}, {"libattr1", "1:2.4.47-2build1", "attr", "1:2.4.47-2build1", dpkg.ParserName},
{"libaudit-common", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1"}, {"libaudit-common", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1", dpkg.ParserName},
{"libaudit1", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1"}, {"libaudit1", "1:2.8.2-1ubuntu1", "audit", "1:2.8.2-1ubuntu1", dpkg.ParserName},
{"libblkid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"libblkid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"libbz2-1.0", "1.0.6-8.1", "bzip2", "1.0.6-8.1"}, {"libbz2-1.0", "1.0.6-8.1", "bzip2", "1.0.6-8.1", dpkg.ParserName},
{"libc-bin", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1"}, {"libc-bin", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1", dpkg.ParserName},
{"libc6", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1"}, {"libc6", "2.27-3ubuntu1", "glibc", "2.27-3ubuntu1", dpkg.ParserName},
{"libcap-ng0", "0.7.7-3.1", "libcap-ng", "0.7.7-3.1"}, {"libcap-ng0", "0.7.7-3.1", "libcap-ng", "0.7.7-3.1", dpkg.ParserName},
{"libcom-err2", "1.44.1-1", "e2fsprogs", "1.44.1-1"}, {"libcom-err2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName},
{"libdb5.3", "5.3.28-13.1ubuntu1", "db5.3", "5.3.28-13.1ubuntu1"}, {"libdb5.3", "5.3.28-13.1ubuntu1", "db5.3", "5.3.28-13.1ubuntu1", dpkg.ParserName},
{"libdebconfclient0", "0.213ubuntu1", "cdebconf", "0.213ubuntu1"}, {"libdebconfclient0", "0.213ubuntu1", "cdebconf", "0.213ubuntu1", dpkg.ParserName},
{"libext2fs2", "1.44.1-1", "e2fsprogs", "1.44.1-1"}, {"libext2fs2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName},
{"libfdisk1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"libfdisk1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"libffi6", "3.2.1-8", "libffi", "3.2.1-8"}, {"libffi6", "3.2.1-8", "libffi", "3.2.1-8", dpkg.ParserName},
{"libgcc1", "1:8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2"}, {"libgcc1", "1:8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName},
{"libgcrypt20", "1.8.1-4ubuntu1.1", "", ""}, {"libgcrypt20", "1.8.1-4ubuntu1.1", "libgcrypt20", "1.8.1-4ubuntu1.1", dpkg.ParserName},
{"libgmp10", "2:6.1.2+dfsg-2", "gmp", "2:6.1.2+dfsg-2"}, {"libgmp10", "2:6.1.2+dfsg-2", "gmp", "2:6.1.2+dfsg-2", dpkg.ParserName},
{"libgnutls30", "3.5.18-1ubuntu1", "gnutls28", "3.5.18-1ubuntu1"}, {"libgnutls30", "3.5.18-1ubuntu1", "gnutls28", "3.5.18-1ubuntu1", dpkg.ParserName},
{"libgpg-error0", "1.27-6", "libgpg-error", "1.27-6"}, {"libgpg-error0", "1.27-6", "libgpg-error", "1.27-6", dpkg.ParserName},
{"libhogweed4", "3.4-1", "nettle", "3.4-1"}, {"libhogweed4", "3.4-1", "nettle", "3.4-1", dpkg.ParserName},
{"libidn2-0", "2.0.4-1.1build2", "libidn2", "2.0.4-1.1build2"}, {"libidn2-0", "2.0.4-1.1build2", "libidn2", "2.0.4-1.1build2", dpkg.ParserName},
{"liblz4-1", "0.0~r131-2ubuntu3", "lz4", "0.0~r131-2ubuntu3"}, {"liblz4-1", "0.0~r131-2ubuntu3", "lz4", "0.0~r131-2ubuntu3", dpkg.ParserName},
{"liblzma5", "5.2.2-1.3", "xz-utils", "5.2.2-1.3"}, {"liblzma5", "5.2.2-1.3", "xz-utils", "5.2.2-1.3", dpkg.ParserName},
{"libmount1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"libmount1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"libncurses5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04"}, {"libncurses5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName},
{"libncursesw5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04"}, {"libncursesw5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName},
{"libnettle6", "3.4-1", "nettle", "3.4-1"}, {"libnettle6", "3.4-1", "nettle", "3.4-1", dpkg.ParserName},
{"libp11-kit0", "0.23.9-2", "p11-kit", "0.23.9-2"}, {"libp11-kit0", "0.23.9-2", "p11-kit", "0.23.9-2", dpkg.ParserName},
{"libpam-modules", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2"}, {"libpam-modules", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName},
{"libpam-modules-bin", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2"}, {"libpam-modules-bin", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName},
{"libpam-runtime", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2"}, {"libpam-runtime", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName},
{"libpam0g", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2"}, {"libpam0g", "1.1.8-3.6ubuntu2", "pam", "1.1.8-3.6ubuntu2", dpkg.ParserName},
{"libpcre3", "2:8.39-9", "pcre3", "2:8.39-9"}, {"libpcre3", "2:8.39-9", "pcre3", "2:8.39-9", dpkg.ParserName},
{"libprocps6", "2:3.3.12-3ubuntu1.1", "procps", "2:3.3.12-3ubuntu1.1"}, {"libprocps6", "2:3.3.12-3ubuntu1.1", "procps", "2:3.3.12-3ubuntu1.1", dpkg.ParserName},
{"libseccomp2", "2.3.1-2.1ubuntu4", "libseccomp", "2.3.1-2.1ubuntu4"}, {"libseccomp2", "2.3.1-2.1ubuntu4", "libseccomp", "2.3.1-2.1ubuntu4", dpkg.ParserName},
{"libselinux1", "2.7-2build2", "libselinux", "2.7-2build2"}, {"libselinux1", "2.7-2build2", "libselinux", "2.7-2build2", dpkg.ParserName},
{"libsemanage-common", "2.7-2build2", "libsemanage", "2.7-2build2"}, {"libsemanage-common", "2.7-2build2", "libsemanage", "2.7-2build2", dpkg.ParserName},
{"libsemanage1", "2.7-2build2", "libsemanage", "2.7-2build2"}, {"libsemanage1", "2.7-2build2", "libsemanage", "2.7-2build2", dpkg.ParserName},
{"libsepol1", "2.7-1", "libsepol", "2.7-1"}, {"libsepol1", "2.7-1", "libsepol", "2.7-1", dpkg.ParserName},
{"libsmartcols1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"libsmartcols1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"libss2", "1.44.1-1", "e2fsprogs", "1.44.1-1"}, {"libss2", "1.44.1-1", "e2fsprogs", "1.44.1-1", dpkg.ParserName},
{"libstdc++6", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2"}, {"libstdc++6", "8-20180414-1ubuntu2", "gcc-8", "8-20180414-1ubuntu2", dpkg.ParserName},
{"libsystemd0", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3"}, {"libsystemd0", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3", dpkg.ParserName},
{"libtasn1-6", "4.13-2", "", ""}, {"libtasn1-6", "4.13-2", "libtasn1-6", "4.13-2", dpkg.ParserName},
{"libtinfo5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04"}, {"libtinfo5", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName},
{"libudev1", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3"}, {"libudev1", "237-3ubuntu10.3", "systemd", "237-3ubuntu10.3", dpkg.ParserName},
{"libunistring2", "0.9.9-0ubuntu1", "libunistring", "0.9.9-0ubuntu1"}, {"libunistring2", "0.9.9-0ubuntu1", "libunistring", "0.9.9-0ubuntu1", dpkg.ParserName},
{"libuuid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"libuuid1", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"libzstd1", "1.3.3+dfsg-2ubuntu1", "libzstd", "1.3.3+dfsg-2ubuntu1"}, {"libzstd1", "1.3.3+dfsg-2ubuntu1", "libzstd", "1.3.3+dfsg-2ubuntu1", dpkg.ParserName},
{"login", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1"}, {"login", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1", dpkg.ParserName},
{"lsb-base", "9.20170808ubuntu1", "lsb", "9.20170808ubuntu1"}, {"lsb-base", "9.20170808ubuntu1", "lsb", "9.20170808ubuntu1", dpkg.ParserName},
{"mawk", "1.3.3-17ubuntu3", "", ""}, {"mawk", "1.3.3-17ubuntu3", "mawk", "1.3.3-17ubuntu3", dpkg.ParserName},
{"mount", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1"}, {"mount", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"ncurses-base", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04"}, {"ncurses-base", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName},
{"ncurses-bin", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04"}, {"ncurses-bin", "6.1-1ubuntu1.18.04", "ncurses", "6.1-1ubuntu1.18.04", dpkg.ParserName},
{"passwd", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1"}, {"passwd", "1:4.5-1ubuntu1", "shadow", "1:4.5-1ubuntu1", dpkg.ParserName},
{"perl-base", "5.26.1-6ubuntu0.2", "perl", "5.26.1-6ubuntu0.2"}, {"perl-base", "5.26.1-6ubuntu0.2", "perl", "5.26.1-6ubuntu0.2", dpkg.ParserName},
{"procps", "2:3.3.12-3ubuntu1.1", "", ""}, {"procps", "2:3.3.12-3ubuntu1.1", "procps", "2:3.3.12-3ubuntu1.1", dpkg.ParserName},
{"sed", "4.4-2", "", ""}, {"sed", "4.4-2", "sed", "4.4-2", dpkg.ParserName},
{"sensible-utils", "0.0.12", "", ""}, {"sensible-utils", "0.0.12", "sensible-utils", "0.0.12", dpkg.ParserName},
{"sysvinit-utils", "2.88dsf-59.10ubuntu1", "sysvinit", "2.88dsf-59.10ubuntu1"}, {"sysvinit-utils", "2.88dsf-59.10ubuntu1", "sysvinit", "2.88dsf-59.10ubuntu1", dpkg.ParserName},
{"tar", "1.29b-2", "", ""}, {"tar", "1.29b-2", "tar", "1.29b-2", dpkg.ParserName},
{"ubuntu-keyring", "2018.02.28", "", ""}, {"ubuntu-keyring", "2018.02.28", "ubuntu-keyring", "2018.02.28", dpkg.ParserName},
{"util-linux", "2.31.1-0.4ubuntu3.1", "", ""}, {"util-linux", "2.31.1-0.4ubuntu3.1", "util-linux", "2.31.1-0.4ubuntu3.1", dpkg.ParserName},
{"zlib1g", "1:1.2.11.dfsg-0ubuntu2", "zlib", "1:1.2.11.dfsg-0ubuntu2"}, {"zlib1g", "1:1.2.11.dfsg-0ubuntu2", "zlib", "1:1.2.11.dfsg-0ubuntu2", dpkg.ParserName},
}, },
}, },
{ {
"corrupted status file", "corrupted status file",
map[string]string{"var/lib/dpkg/status": "dpkg/testdata/corrupted"}, map[string]string{"var/lib/dpkg/status": "dpkg/testdata/corrupted"},
[]featurefmt.PackageInfo{ []database.Feature{
{"libpam-runtime", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3"}, {"libpam-runtime", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3", dpkg.ParserName},
{"libpam-modules-bin", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3"}, {"libpam-modules-bin", "1.1.8-3.1ubuntu3", "pam", "1.1.8-3.1ubuntu3", dpkg.ParserName},
{"makedev", "2.3.1-93ubuntu1", "", ""}, {"makedev", "2.3.1-93ubuntu1", "makedev", "2.3.1-93ubuntu1", dpkg.ParserName},
{"libgcc1", "1:5.1.1-12ubuntu1", "gcc-5", "5.1.1-12ubuntu1"}, {"libgcc1", "1:5.1.1-12ubuntu1", "gcc-5", "5.1.1-12ubuntu1", dpkg.ParserName},
}, },
}, },
} { } {

View File

@ -1,56 +0,0 @@
package featurefmt
import (
"github.com/coreos/clair/database"
"github.com/deckarep/golang-set"
)
// PackageInfo is the extracted raw information from the package managers that
// can be converted to a feature.
type PackageInfo struct {
PackageName string
PackageVersion string
SourceName string
SourceVersion string
}
// Reset defaults the internal string fields to empty strings.
func (pkg *PackageInfo) Reset() {
pkg.PackageName = ""
pkg.PackageVersion = ""
pkg.SourceName = ""
pkg.SourceVersion = ""
}
func (pkg *PackageInfo) asFeature(versionFormat string) database.Feature {
feature := database.Feature{
Name: pkg.PackageName,
Version: pkg.PackageVersion,
VersionFormat: versionFormat,
}
if pkg.SourceName != "" {
parent := database.Feature{
Name: pkg.SourceName,
Version: pkg.SourceVersion,
VersionFormat: versionFormat,
}
if parent != feature {
feature.Parent = &parent
}
}
return feature
}
// PackageSetToFeatures converts a package set to feature slice
func PackageSetToFeatures(versionFormat string, pkgs mapset.Set) []database.Feature {
features := make([]database.Feature, 0, pkgs.Cardinality())
for pkg := range pkgs.Iter() {
p := pkg.(PackageInfo)
features = append(features, p.asFeature(versionFormat))
}
return features
}

View File

@ -55,8 +55,8 @@ func isIgnored(packageName string) bool {
return false return false
} }
func valid(pkg *featurefmt.PackageInfo) bool { func valid(pkg *database.Feature) bool {
return pkg.PackageName != "" && pkg.PackageVersion != "" && return pkg.Name != "" && pkg.Version != "" &&
((pkg.SourceName == "" && pkg.SourceVersion != "") || ((pkg.SourceName == "" && pkg.SourceVersion != "") ||
(pkg.SourceName != "" && pkg.SourceVersion != "")) (pkg.SourceName != "" && pkg.SourceVersion != ""))
} }
@ -104,9 +104,9 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
continue continue
} }
pkg := featurefmt.PackageInfo{PackageName: line[0]} pkg := database.Feature{Name: line[0], VersionFormat: rpm.ParserName}
pkg.PackageVersion = strings.Replace(line[1], "(none):", "", -1) pkg.Version = strings.Replace(line[1], "(none):", "", -1)
if err := versionfmt.Valid(rpm.ParserName, pkg.PackageVersion); err != nil { if err := versionfmt.Valid(rpm.ParserName, pkg.Version); err != nil {
log.WithError(err).WithField("version", line[1]).Warning("skipped unparseable package") log.WithError(err).WithField("version", line[1]).Warning("skipped unparseable package")
continue continue
} }
@ -121,7 +121,7 @@ func (l lister) ListFeatures(files tarutil.FilesMap) ([]database.Feature, error)
} }
} }
return featurefmt.PackageSetToFeatures(rpm.ParserName, packages), nil return database.ConvertFeatureSetToFeatures(packages), nil
} }
func (l lister) RequiredFilenames() []string { func (l lister) RequiredFilenames() []string {
@ -140,7 +140,7 @@ const (
// parseSourceRPM parses the source rpm package representation string // parseSourceRPM parses the source rpm package representation string
// http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html // http://ftp.rpm.org/max-rpm/ch-rpm-file-format.html
func parseSourceRPM(sourceRPM string, pkg *featurefmt.PackageInfo) error { func parseSourceRPM(sourceRPM string, pkg *database.Feature) error {
state := parseRPM state := parseRPM
previousCheckPoint := len(sourceRPM) previousCheckPoint := len(sourceRPM)
release := "" release := ""

View File

@ -19,184 +19,185 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/featurefmt" "github.com/coreos/clair/ext/featurefmt"
"github.com/coreos/clair/ext/versionfmt/rpm" "github.com/coreos/clair/ext/versionfmt/rpm"
) )
var expectedBigCaseInfo = []featurefmt.PackageInfo{ var expectedBigCaseInfo = []database.Feature{
{"publicsuffix-list-dafsa", "20180514-1.fc28", "publicsuffix-list", "20180514-1.fc28"}, {"publicsuffix-list-dafsa", "20180514-1.fc28", "publicsuffix-list", "20180514-1.fc28", rpm.ParserName},
{"libreport-filesystem", "2.9.5-1.fc28", "libreport", "2.9.5-1.fc28"}, {"libreport-filesystem", "2.9.5-1.fc28", "libreport", "2.9.5-1.fc28", rpm.ParserName},
{"fedora-gpg-keys", "28-5", "fedora-repos", "28-5"}, {"fedora-gpg-keys", "28-5", "fedora-repos", "28-5", rpm.ParserName},
{"fedora-release", "28-2", "", ""}, {"fedora-release", "28-2", "fedora-release", "28-2", rpm.ParserName},
{"filesystem", "3.8-2.fc28", "", ""}, {"filesystem", "3.8-2.fc28", "filesystem", "3.8-2.fc28", rpm.ParserName},
{"tzdata", "2018e-1.fc28", "", ""}, {"tzdata", "2018e-1.fc28", "tzdata", "2018e-1.fc28", rpm.ParserName},
{"pcre2", "10.31-10.fc28", "", ""}, {"pcre2", "10.31-10.fc28", "pcre2", "10.31-10.fc28", rpm.ParserName},
{"glibc-minimal-langpack", "2.27-32.fc28", "glibc", "2.27-32.fc28"}, {"glibc-minimal-langpack", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName},
{"glibc-common", "2.27-32.fc28", "glibc", "2.27-32.fc28"}, {"glibc-common", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName},
{"bash", "4.4.23-1.fc28", "", ""}, {"bash", "4.4.23-1.fc28", "bash", "4.4.23-1.fc28", rpm.ParserName},
{"zlib", "1.2.11-8.fc28", "", ""}, {"zlib", "1.2.11-8.fc28", "zlib", "1.2.11-8.fc28", rpm.ParserName},
{"bzip2-libs", "1.0.6-26.fc28", "bzip2", "1.0.6-26.fc28"}, {"bzip2-libs", "1.0.6-26.fc28", "bzip2", "1.0.6-26.fc28", rpm.ParserName},
{"libcap", "2.25-9.fc28", "", ""}, {"libcap", "2.25-9.fc28", "libcap", "2.25-9.fc28", rpm.ParserName},
{"libgpg-error", "1.31-1.fc28", "", ""}, {"libgpg-error", "1.31-1.fc28", "libgpg-error", "1.31-1.fc28", rpm.ParserName},
{"libzstd", "1.3.5-1.fc28", "zstd", "1.3.5-1.fc28"}, {"libzstd", "1.3.5-1.fc28", "zstd", "1.3.5-1.fc28", rpm.ParserName},
{"expat", "2.2.5-3.fc28", "", ""}, {"expat", "2.2.5-3.fc28", "expat", "2.2.5-3.fc28", rpm.ParserName},
{"nss-util", "3.38.0-1.0.fc28", "", ""}, {"nss-util", "3.38.0-1.0.fc28", "nss-util", "3.38.0-1.0.fc28", rpm.ParserName},
{"libcom_err", "1.44.2-0.fc28", "e2fsprogs", "1.44.2-0.fc28"}, {"libcom_err", "1.44.2-0.fc28", "e2fsprogs", "1.44.2-0.fc28", rpm.ParserName},
{"libffi", "3.1-16.fc28", "", ""}, {"libffi", "3.1-16.fc28", "libffi", "3.1-16.fc28", rpm.ParserName},
{"libgcrypt", "1.8.3-1.fc28", "", ""}, {"libgcrypt", "1.8.3-1.fc28", "libgcrypt", "1.8.3-1.fc28", rpm.ParserName},
{"libxml2", "2.9.8-4.fc28", "", ""}, {"libxml2", "2.9.8-4.fc28", "libxml2", "2.9.8-4.fc28", rpm.ParserName},
{"libacl", "2.2.53-1.fc28", "acl", "2.2.53-1.fc28"}, {"libacl", "2.2.53-1.fc28", "acl", "2.2.53-1.fc28", rpm.ParserName},
{"sed", "4.5-1.fc28", "", ""}, {"sed", "4.5-1.fc28", "sed", "4.5-1.fc28", rpm.ParserName},
{"libmount", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28"}, {"libmount", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"p11-kit", "0.23.12-1.fc28", "", ""}, {"p11-kit", "0.23.12-1.fc28", "p11-kit", "0.23.12-1.fc28", rpm.ParserName},
{"libidn2", "2.0.5-1.fc28", "", ""}, {"libidn2", "2.0.5-1.fc28", "libidn2", "2.0.5-1.fc28", rpm.ParserName},
{"libcap-ng", "0.7.9-4.fc28", "", ""}, {"libcap-ng", "0.7.9-4.fc28", "libcap-ng", "0.7.9-4.fc28", rpm.ParserName},
{"lz4-libs", "1.8.1.2-4.fc28", "lz4", "1.8.1.2-4.fc28"}, {"lz4-libs", "1.8.1.2-4.fc28", "lz4", "1.8.1.2-4.fc28", rpm.ParserName},
{"libassuan", "2.5.1-3.fc28", "", ""}, {"libassuan", "2.5.1-3.fc28", "libassuan", "2.5.1-3.fc28", rpm.ParserName},
{"keyutils-libs", "1.5.10-6.fc28", "keyutils", "1.5.10-6.fc28"}, {"keyutils-libs", "1.5.10-6.fc28", "keyutils", "1.5.10-6.fc28", rpm.ParserName},
{"glib2", "2.56.1-4.fc28", "", ""}, {"glib2", "2.56.1-4.fc28", "glib2", "2.56.1-4.fc28", rpm.ParserName},
{"systemd-libs", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28"}, {"systemd-libs", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName},
{"dbus-libs", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28"}, {"dbus-libs", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28", rpm.ParserName},
{"libtasn1", "4.13-2.fc28", "", ""}, {"libtasn1", "4.13-2.fc28", "libtasn1", "4.13-2.fc28", rpm.ParserName},
{"ca-certificates", "2018.2.24-1.0.fc28", "", ""}, {"ca-certificates", "2018.2.24-1.0.fc28", "ca-certificates", "2018.2.24-1.0.fc28", rpm.ParserName},
{"libarchive", "3.3.1-4.fc28", "", ""}, {"libarchive", "3.3.1-4.fc28", "libarchive", "3.3.1-4.fc28", rpm.ParserName},
{"openssl", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28"}, {"openssl", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28", rpm.ParserName},
{"libusbx", "1.0.22-1.fc28", "", ""}, {"libusbx", "1.0.22-1.fc28", "libusbx", "1.0.22-1.fc28", rpm.ParserName},
{"libsemanage", "2.8-2.fc28", "", ""}, {"libsemanage", "2.8-2.fc28", "libsemanage", "2.8-2.fc28", rpm.ParserName},
{"libutempter", "1.1.6-14.fc28", "", ""}, {"libutempter", "1.1.6-14.fc28", "libutempter", "1.1.6-14.fc28", rpm.ParserName},
{"mpfr", "3.1.6-1.fc28", "", ""}, {"mpfr", "3.1.6-1.fc28", "mpfr", "3.1.6-1.fc28", rpm.ParserName},
{"gnutls", "3.6.3-4.fc28", "", ""}, {"gnutls", "3.6.3-4.fc28", "gnutls", "3.6.3-4.fc28", rpm.ParserName},
{"gzip", "1.9-3.fc28", "", ""}, {"gzip", "1.9-3.fc28", "gzip", "1.9-3.fc28", rpm.ParserName},
{"acl", "2.2.53-1.fc28", "", ""}, {"acl", "2.2.53-1.fc28", "acl", "2.2.53-1.fc28", rpm.ParserName},
{"nss-softokn-freebl", "3.38.0-1.0.fc28", "nss-softokn", "3.38.0-1.0.fc28"}, {"nss-softokn-freebl", "3.38.0-1.0.fc28", "nss-softokn", "3.38.0-1.0.fc28", rpm.ParserName},
{"nss", "3.38.0-1.0.fc28", "", ""}, {"nss", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName},
{"libmetalink", "0.1.3-6.fc28", "", ""}, {"libmetalink", "0.1.3-6.fc28", "libmetalink", "0.1.3-6.fc28", rpm.ParserName},
{"libdb-utils", "5.3.28-30.fc28", "libdb", "5.3.28-30.fc28"}, {"libdb-utils", "5.3.28-30.fc28", "libdb", "5.3.28-30.fc28", rpm.ParserName},
{"file-libs", "5.33-7.fc28", "file", "5.33-7.fc28"}, {"file-libs", "5.33-7.fc28", "file", "5.33-7.fc28", rpm.ParserName},
{"libsss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28"}, {"libsss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName},
{"libsigsegv", "2.11-5.fc28", "", ""}, {"libsigsegv", "2.11-5.fc28", "libsigsegv", "2.11-5.fc28", rpm.ParserName},
{"krb5-libs", "1.16.1-13.fc28", "krb5", "1.16.1-13.fc28"}, {"krb5-libs", "1.16.1-13.fc28", "krb5", "1.16.1-13.fc28", rpm.ParserName},
{"libnsl2", "1.2.0-2.20180605git4a062cf.fc28", "", ""}, {"libnsl2", "1.2.0-2.20180605git4a062cf.fc28", "libnsl2", "1.2.0-2.20180605git4a062cf.fc28", rpm.ParserName},
{"python3-pip", "9.0.3-2.fc28", "python-pip", "9.0.3-2.fc28"}, {"python3-pip", "9.0.3-2.fc28", "python-pip", "9.0.3-2.fc28", rpm.ParserName},
{"python3", "3.6.6-1.fc28", "", ""}, {"python3", "3.6.6-1.fc28", "python3", "3.6.6-1.fc28", rpm.ParserName},
{"pam", "1.3.1-1.fc28", "", ""}, {"pam", "1.3.1-1.fc28", "pam", "1.3.1-1.fc28", rpm.ParserName},
{"python3-gobject-base", "3.28.3-1.fc28", "pygobject3", "3.28.3-1.fc28"}, {"python3-gobject-base", "3.28.3-1.fc28", "pygobject3", "3.28.3-1.fc28", rpm.ParserName},
{"python3-smartcols", "0.3.0-2.fc28", "python-smartcols", "0.3.0-2.fc28"}, {"python3-smartcols", "0.3.0-2.fc28", "python-smartcols", "0.3.0-2.fc28", rpm.ParserName},
{"python3-iniparse", "0.4-30.fc28", "python-iniparse", "0.4-30.fc28"}, {"python3-iniparse", "0.4-30.fc28", "python-iniparse", "0.4-30.fc28", rpm.ParserName},
{"openldap", "2.4.46-3.fc28", "", ""}, {"openldap", "2.4.46-3.fc28", "openldap", "2.4.46-3.fc28", rpm.ParserName},
{"libseccomp", "2.3.3-2.fc28", "", ""}, {"libseccomp", "2.3.3-2.fc28", "libseccomp", "2.3.3-2.fc28", rpm.ParserName},
{"npth", "1.5-4.fc28", "", ""}, {"npth", "1.5-4.fc28", "npth", "1.5-4.fc28", rpm.ParserName},
{"gpgme", "1.10.0-4.fc28", "", ""}, {"gpgme", "1.10.0-4.fc28", "gpgme", "1.10.0-4.fc28", rpm.ParserName},
{"json-c", "0.13.1-2.fc28", "", ""}, {"json-c", "0.13.1-2.fc28", "json-c", "0.13.1-2.fc28", rpm.ParserName},
{"libyaml", "0.1.7-5.fc28", "", ""}, {"libyaml", "0.1.7-5.fc28", "libyaml", "0.1.7-5.fc28", rpm.ParserName},
{"libpkgconf", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28"}, {"libpkgconf", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName},
{"pkgconf-pkg-config", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28"}, {"pkgconf-pkg-config", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName},
{"iptables-libs", "1.6.2-3.fc28", "iptables", "1.6.2-3.fc28"}, {"iptables-libs", "1.6.2-3.fc28", "iptables", "1.6.2-3.fc28", rpm.ParserName},
{"device-mapper-libs", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28"}, {"device-mapper-libs", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28", rpm.ParserName},
{"systemd-pam", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28"}, {"systemd-pam", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName},
{"systemd", "238-9.git0e0aa59.fc28", "", ""}, {"systemd", "238-9.git0e0aa59.fc28", "systemd", "238-9.git0e0aa59.fc28", rpm.ParserName},
{"elfutils-default-yama-scope", "0.173-1.fc28", "elfutils", "0.173-1.fc28"}, {"elfutils-default-yama-scope", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName},
{"libcurl", "7.59.0-6.fc28", "curl", "7.59.0-6.fc28"}, {"libcurl", "7.59.0-6.fc28", "curl", "7.59.0-6.fc28", rpm.ParserName},
{"python3-librepo", "1.8.1-7.fc28", "librepo", "1.8.1-7.fc28"}, {"python3-librepo", "1.8.1-7.fc28", "librepo", "1.8.1-7.fc28", rpm.ParserName},
{"rpm-plugin-selinux", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"rpm-plugin-selinux", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"rpm", "4.14.1-9.fc28", "", ""}, {"rpm", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"libdnf", "0.11.1-3.fc28", "", ""}, {"libdnf", "0.11.1-3.fc28", "libdnf", "0.11.1-3.fc28", rpm.ParserName},
{"rpm-build-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"rpm-build-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"python3-rpm", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"python3-rpm", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"dnf", "2.7.5-12.fc28", "", ""}, {"dnf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName},
{"deltarpm", "3.6-25.fc28", "", ""}, {"deltarpm", "3.6-25.fc28", "deltarpm", "3.6-25.fc28", rpm.ParserName},
{"sssd-client", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28"}, {"sssd-client", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName},
{"cracklib-dicts", "2.9.6-13.fc28", "cracklib", "2.9.6-13.fc28"}, {"cracklib-dicts", "2.9.6-13.fc28", "cracklib", "2.9.6-13.fc28", rpm.ParserName},
{"tar", "2:1.30-3.fc28", "tar", "1.30-3.fc28"}, {"tar", "2:1.30-3.fc28", "tar", "1.30-3.fc28", rpm.ParserName},
{"diffutils", "3.6-4.fc28", "", ""}, {"diffutils", "3.6-4.fc28", "diffutils", "3.6-4.fc28", rpm.ParserName},
{"langpacks-en", "1.0-12.fc28", "langpacks", "1.0-12.fc28"}, {"langpacks-en", "1.0-12.fc28", "langpacks", "1.0-12.fc28", rpm.ParserName},
{"libgcc", "8.1.1-5.fc28", "gcc", "8.1.1-5.fc28"}, {"libgcc", "8.1.1-5.fc28", "gcc", "8.1.1-5.fc28", rpm.ParserName},
{"pkgconf-m4", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28"}, {"pkgconf-m4", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName},
{"dnf-conf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28"}, {"dnf-conf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName},
{"fedora-repos", "28-5", "", ""}, {"fedora-repos", "28-5", "fedora-repos", "28-5", rpm.ParserName},
{"setup", "2.11.4-1.fc28", "", ""}, {"setup", "2.11.4-1.fc28", "setup", "2.11.4-1.fc28", rpm.ParserName},
{"basesystem", "11-5.fc28", "", ""}, {"basesystem", "11-5.fc28", "basesystem", "11-5.fc28", rpm.ParserName},
{"ncurses-base", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28"}, {"ncurses-base", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28", rpm.ParserName},
{"libselinux", "2.8-1.fc28", "", ""}, {"libselinux", "2.8-1.fc28", "libselinux", "2.8-1.fc28", rpm.ParserName},
{"ncurses-libs", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28"}, {"ncurses-libs", "6.1-5.20180224.fc28", "ncurses", "6.1-5.20180224.fc28", rpm.ParserName},
{"glibc", "2.27-32.fc28", "", ""}, {"glibc", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName},
{"libsepol", "2.8-1.fc28", "", ""}, {"libsepol", "2.8-1.fc28", "libsepol", "2.8-1.fc28", rpm.ParserName},
{"xz-libs", "5.2.4-2.fc28", "xz", "5.2.4-2.fc28"}, {"xz-libs", "5.2.4-2.fc28", "xz", "5.2.4-2.fc28", rpm.ParserName},
{"info", "6.5-4.fc28", "texinfo", "6.5-4.fc28"}, {"info", "6.5-4.fc28", "texinfo", "6.5-4.fc28", rpm.ParserName},
{"libdb", "5.3.28-30.fc28", "", ""}, {"libdb", "5.3.28-30.fc28", "libdb", "5.3.28-30.fc28", rpm.ParserName},
{"elfutils-libelf", "0.173-1.fc28", "elfutils", "0.173-1.fc28"}, {"elfutils-libelf", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName},
{"popt", "1.16-14.fc28", "", ""}, {"popt", "1.16-14.fc28", "popt", "1.16-14.fc28", rpm.ParserName},
{"nspr", "4.19.0-1.fc28", "", ""}, {"nspr", "4.19.0-1.fc28", "nspr", "4.19.0-1.fc28", rpm.ParserName},
{"libxcrypt", "4.1.2-1.fc28", "", ""}, {"libxcrypt", "4.1.2-1.fc28", "libxcrypt", "4.1.2-1.fc28", rpm.ParserName},
{"lua-libs", "5.3.4-10.fc28", "lua", "5.3.4-10.fc28"}, {"lua-libs", "5.3.4-10.fc28", "lua", "5.3.4-10.fc28", rpm.ParserName},
{"libuuid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28"}, {"libuuid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"readline", "7.0-11.fc28", "", ""}, {"readline", "7.0-11.fc28", "readline", "7.0-11.fc28", rpm.ParserName},
{"libattr", "2.4.48-3.fc28", "attr", "2.4.48-3.fc28"}, {"libattr", "2.4.48-3.fc28", "attr", "2.4.48-3.fc28", rpm.ParserName},
{"coreutils-single", "8.29-7.fc28", "coreutils", "8.29-7.fc28"}, {"coreutils-single", "8.29-7.fc28", "coreutils", "8.29-7.fc28", rpm.ParserName},
{"libblkid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28"}, {"libblkid", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"gmp", "1:6.1.2-7.fc28", "gmp", "6.1.2-7.fc28"}, {"gmp", "1:6.1.2-7.fc28", "gmp", "6.1.2-7.fc28", rpm.ParserName},
{"libunistring", "0.9.10-1.fc28", "", ""}, {"libunistring", "0.9.10-1.fc28", "libunistring", "0.9.10-1.fc28", rpm.ParserName},
{"sqlite-libs", "3.22.0-4.fc28", "sqlite", "3.22.0-4.fc28"}, {"sqlite-libs", "3.22.0-4.fc28", "sqlite", "3.22.0-4.fc28", rpm.ParserName},
{"audit-libs", "2.8.4-2.fc28", "audit", "2.8.4-2.fc28"}, {"audit-libs", "2.8.4-2.fc28", "audit", "2.8.4-2.fc28", rpm.ParserName},
{"chkconfig", "1.10-4.fc28", "", ""}, {"chkconfig", "1.10-4.fc28", "chkconfig", "1.10-4.fc28", rpm.ParserName},
{"libsmartcols", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28"}, {"libsmartcols", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"pcre", "8.42-3.fc28", "", ""}, {"pcre", "8.42-3.fc28", "pcre", "8.42-3.fc28", rpm.ParserName},
{"grep", "3.1-5.fc28", "", ""}, {"grep", "3.1-5.fc28", "grep", "3.1-5.fc28", rpm.ParserName},
{"crypto-policies", "20180425-5.git6ad4018.fc28", "", ""}, {"crypto-policies", "20180425-5.git6ad4018.fc28", "crypto-policies", "20180425-5.git6ad4018.fc28", rpm.ParserName},
{"gdbm-libs", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28"}, {"gdbm-libs", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28", rpm.ParserName},
{"p11-kit-trust", "0.23.12-1.fc28", "p11-kit", "0.23.12-1.fc28"}, {"p11-kit-trust", "0.23.12-1.fc28", "p11-kit", "0.23.12-1.fc28", rpm.ParserName},
{"openssl-libs", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28"}, {"openssl-libs", "1:1.1.0h-3.fc28", "openssl", "1.1.0h-3.fc28", rpm.ParserName},
{"ima-evm-utils", "1.1-2.fc28", "", ""}, {"ima-evm-utils", "1.1-2.fc28", "ima-evm-utils", "1.1-2.fc28", rpm.ParserName},
{"gdbm", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28"}, {"gdbm", "1:1.14.1-4.fc28", "gdbm", "1.14.1-4.fc28", rpm.ParserName},
{"gobject-introspection", "1.56.1-1.fc28", "", ""}, {"gobject-introspection", "1.56.1-1.fc28", "gobject-introspection", "1.56.1-1.fc28", rpm.ParserName},
{"shadow-utils", "2:4.6-1.fc28", "shadow-utils", "4.6-1.fc28"}, {"shadow-utils", "2:4.6-1.fc28", "shadow-utils", "4.6-1.fc28", rpm.ParserName},
{"libpsl", "0.20.2-2.fc28", "", ""}, {"libpsl", "0.20.2-2.fc28", "libpsl", "0.20.2-2.fc28", rpm.ParserName},
{"nettle", "3.4-2.fc28", "", ""}, {"nettle", "3.4-2.fc28", "nettle", "3.4-2.fc28", rpm.ParserName},
{"libfdisk", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28"}, {"libfdisk", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"cracklib", "2.9.6-13.fc28", "", ""}, {"cracklib", "2.9.6-13.fc28", "cracklib", "2.9.6-13.fc28", rpm.ParserName},
{"libcomps", "0.1.8-11.fc28", "", ""}, {"libcomps", "0.1.8-11.fc28", "libcomps", "0.1.8-11.fc28", rpm.ParserName},
{"nss-softokn", "3.38.0-1.0.fc28", "", ""}, {"nss-softokn", "3.38.0-1.0.fc28", "nss-softokn", "3.38.0-1.0.fc28", rpm.ParserName},
{"nss-sysinit", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28"}, {"nss-sysinit", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName},
{"libksba", "1.3.5-7.fc28", "", ""}, {"libksba", "1.3.5-7.fc28", "libksba", "1.3.5-7.fc28", rpm.ParserName},
{"kmod-libs", "25-2.fc28", "kmod", "25-2.fc28"}, {"kmod-libs", "25-2.fc28", "kmod", "25-2.fc28", rpm.ParserName},
{"libsss_nss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28"}, {"libsss_nss_idmap", "1.16.3-2.fc28", "sssd", "1.16.3-2.fc28", rpm.ParserName},
{"libverto", "0.3.0-5.fc28", "", ""}, {"libverto", "0.3.0-5.fc28", "libverto", "0.3.0-5.fc28", rpm.ParserName},
{"gawk", "4.2.1-1.fc28", "", ""}, {"gawk", "4.2.1-1.fc28", "gawk", "4.2.1-1.fc28", rpm.ParserName},
{"libtirpc", "1.0.3-3.rc2.fc28", "", ""}, {"libtirpc", "1.0.3-3.rc2.fc28", "libtirpc", "1.0.3-3.rc2.fc28", rpm.ParserName},
{"python3-libs", "3.6.6-1.fc28", "python3", "3.6.6-1.fc28"}, {"python3-libs", "3.6.6-1.fc28", "python3", "3.6.6-1.fc28", rpm.ParserName},
{"python3-setuptools", "39.2.0-6.fc28", "python-setuptools", "39.2.0-6.fc28"}, {"python3-setuptools", "39.2.0-6.fc28", "python-setuptools", "39.2.0-6.fc28", rpm.ParserName},
{"libpwquality", "1.4.0-7.fc28", "", ""}, {"libpwquality", "1.4.0-7.fc28", "libpwquality", "1.4.0-7.fc28", rpm.ParserName},
{"util-linux", "2.32.1-1.fc28", "", ""}, {"util-linux", "2.32.1-1.fc28", "util-linux", "2.32.1-1.fc28", rpm.ParserName},
{"python3-libcomps", "0.1.8-11.fc28", "libcomps", "0.1.8-11.fc28"}, {"python3-libcomps", "0.1.8-11.fc28", "libcomps", "0.1.8-11.fc28", rpm.ParserName},
{"python3-six", "1.11.0-3.fc28", "python-six", "1.11.0-3.fc28"}, {"python3-six", "1.11.0-3.fc28", "python-six", "1.11.0-3.fc28", rpm.ParserName},
{"cyrus-sasl-lib", "2.1.27-0.2rc7.fc28", "cyrus-sasl", "2.1.27-0.2rc7.fc28"}, {"cyrus-sasl-lib", "2.1.27-0.2rc7.fc28", "cyrus-sasl", "2.1.27-0.2rc7.fc28", rpm.ParserName},
{"libssh", "0.8.2-1.fc28", "", ""}, {"libssh", "0.8.2-1.fc28", "libssh", "0.8.2-1.fc28", rpm.ParserName},
{"qrencode-libs", "3.4.4-5.fc28", "qrencode", "3.4.4-5.fc28"}, {"qrencode-libs", "3.4.4-5.fc28", "qrencode", "3.4.4-5.fc28", rpm.ParserName},
{"gnupg2", "2.2.8-1.fc28", "", ""}, {"gnupg2", "2.2.8-1.fc28", "gnupg2", "2.2.8-1.fc28", rpm.ParserName},
{"python3-gpg", "1.10.0-4.fc28", "gpgme", "1.10.0-4.fc28"}, {"python3-gpg", "1.10.0-4.fc28", "gpgme", "1.10.0-4.fc28", rpm.ParserName},
{"libargon2", "20161029-5.fc28", "argon2", "20161029-5.fc28"}, {"libargon2", "20161029-5.fc28", "argon2", "20161029-5.fc28", rpm.ParserName},
{"libmodulemd", "1.6.2-2.fc28", "", ""}, {"libmodulemd", "1.6.2-2.fc28", "libmodulemd", "1.6.2-2.fc28", rpm.ParserName},
{"pkgconf", "1.4.2-1.fc28", "", ""}, {"pkgconf", "1.4.2-1.fc28", "pkgconf", "1.4.2-1.fc28", rpm.ParserName},
{"libpcap", "14:1.9.0-1.fc28", "libpcap", "1.9.0-1.fc28"}, {"libpcap", "14:1.9.0-1.fc28", "libpcap", "1.9.0-1.fc28", rpm.ParserName},
{"device-mapper", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28"}, {"device-mapper", "1.02.146-5.fc28", "lvm2", "2.02.177-5.fc28", rpm.ParserName},
{"cryptsetup-libs", "2.0.4-1.fc28", "cryptsetup", "2.0.4-1.fc28"}, {"cryptsetup-libs", "2.0.4-1.fc28", "cryptsetup", "2.0.4-1.fc28", rpm.ParserName},
{"elfutils-libs", "0.173-1.fc28", "elfutils", "0.173-1.fc28"}, {"elfutils-libs", "0.173-1.fc28", "elfutils", "0.173-1.fc28", rpm.ParserName},
{"dbus", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28"}, {"dbus", "1:1.12.10-1.fc28", "dbus", "1.12.10-1.fc28", rpm.ParserName},
{"libnghttp2", "1.32.1-1.fc28", "nghttp2", "1.32.1-1.fc28"}, {"libnghttp2", "1.32.1-1.fc28", "nghttp2", "1.32.1-1.fc28", rpm.ParserName},
{"librepo", "1.8.1-7.fc28", "", ""}, {"librepo", "1.8.1-7.fc28", "librepo", "1.8.1-7.fc28", rpm.ParserName},
{"curl", "7.59.0-6.fc28", "", ""}, {"curl", "7.59.0-6.fc28", "curl", "7.59.0-6.fc28", rpm.ParserName},
{"rpm-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"rpm-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"libsolv", "0.6.35-1.fc28", "", ""}, {"libsolv", "0.6.35-1.fc28", "libsolv", "0.6.35-1.fc28", rpm.ParserName},
{"python3-hawkey", "0.11.1-3.fc28", "libdnf", "0.11.1-3.fc28"}, {"python3-hawkey", "0.11.1-3.fc28", "libdnf", "0.11.1-3.fc28", rpm.ParserName},
{"rpm-sign-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"rpm-sign-libs", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"python3-dnf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28"}, {"python3-dnf", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName},
{"dnf-yum", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28"}, {"dnf-yum", "2.7.5-12.fc28", "dnf", "2.7.5-12.fc28", rpm.ParserName},
{"rpm-plugin-systemd-inhibit", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28"}, {"rpm-plugin-systemd-inhibit", "4.14.1-9.fc28", "rpm", "4.14.1-9.fc28", rpm.ParserName},
{"nss-tools", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28"}, {"nss-tools", "3.38.0-1.0.fc28", "nss", "3.38.0-1.0.fc28", rpm.ParserName},
{"openssl-pkcs11", "0.4.8-1.fc28", "", ""}, {"openssl-pkcs11", "0.4.8-1.fc28", "openssl-pkcs11", "0.4.8-1.fc28", rpm.ParserName},
{"vim-minimal", "2:8.1.328-1.fc28", "vim", "8.1.328-1.fc28"}, {"vim-minimal", "2:8.1.328-1.fc28", "vim", "8.1.328-1.fc28", rpm.ParserName},
{"glibc-langpack-en", "2.27-32.fc28", "glibc", "2.27-32.fc28"}, {"glibc-langpack-en", "2.27-32.fc28", "glibc", "2.27-32.fc28", rpm.ParserName},
{"rootfiles", "8.1-22.fc28", "", ""}, {"rootfiles", "8.1-22.fc28", "rootfiles", "8.1-22.fc28", rpm.ParserName},
} }
func TestRpmFeatureDetection(t *testing.T) { func TestRpmFeatureDetection(t *testing.T) {
@ -204,9 +205,9 @@ func TestRpmFeatureDetection(t *testing.T) {
{ {
"valid small case", "valid small case",
map[string]string{"var/lib/rpm/Packages": "rpm/testdata/valid"}, map[string]string{"var/lib/rpm/Packages": "rpm/testdata/valid"},
[]featurefmt.PackageInfo{ []database.Feature{
{"centos-release", "7-1.1503.el7.centos.2.8", "", ""}, {"centos-release", "7-1.1503.el7.centos.2.8", "centos-release", "7-1.1503.el7.centos.2.8", rpm.ParserName},
{"filesystem", "3.2-18.el7", "", ""}, {"filesystem", "3.2-18.el7", "filesystem", "3.2-18.el7", rpm.ParserName},
}, },
}, },
{ {
@ -247,7 +248,7 @@ func TestParseSourceRPM(t *testing.T) {
// actual expected: name="lua", version="5.3.4", release="10.fc-28" // actual expected: name="lua", version="5.3.4", release="10.fc-28"
{"lua-5.3.4-10.fc-28.src.rpm", "lua-5.3.4", "10.fc-28", ""}, {"lua-5.3.4-10.fc-28.src.rpm", "lua-5.3.4", "10.fc-28", ""},
} { } {
pkg := featurefmt.PackageInfo{} pkg := database.Feature{}
err := parseSourceRPM(test.sourceRPM, &pkg) err := parseSourceRPM(test.sourceRPM, &pkg)
if test.expectedErr != "" { if test.expectedErr != "" {
require.EqualError(t, err, test.expectedErr) require.EqualError(t, err, test.expectedErr)

View File

@ -54,7 +54,7 @@ func loadTestFiles(testFilePaths map[string]string) tarutil.FilesMap {
type TestCase struct { type TestCase struct {
Name string Name string
FilePaths map[string]string FilePaths map[string]string
ExpectedResult []PackageInfo ExpectedResult []database.Feature
} }
// RunTest runs a featurefmt test by loading the package info database files and // RunTest runs a featurefmt test by loading the package info database files and
@ -65,7 +65,7 @@ func RunTest(t *testing.T, test TestCase, lister Lister, expectedVersionFormat s
expected := test.ExpectedResult expected := test.ExpectedResult
features, err := lister.ListFeatures(filesMap) features, err := lister.ListFeatures(filesMap)
require.Nil(t, err) require.Nil(t, err)
visited := map[PackageInfo]bool{} visited := map[database.Feature]bool{}
// we only enforce the unique packages to match, the result features // we only enforce the unique packages to match, the result features
// should be always deduplicated. // should be always deduplicated.
for _, pkg := range expected { for _, pkg := range expected {
@ -75,22 +75,16 @@ func RunTest(t *testing.T, test TestCase, lister Lister, expectedVersionFormat s
assert.Len(t, features, len(visited)) assert.Len(t, features, len(visited))
for _, f := range features { for _, f := range features {
assert.Equal(t, expectedVersionFormat, f.VersionFormat) assert.Equal(t, expectedVersionFormat, f.VersionFormat)
if f.Parent != nil { if ok, found := visited[f]; ok {
// currently we don't have more than 2 levels deep features. assert.Fail(t, "duplicated features is not allowed", "feature=%#v", f)
assert.Equal(t, expectedVersionFormat, f.Parent.VersionFormat)
}
pkg := convertToPackageInfo(&f)
if ok, found := visited[pkg]; ok {
assert.Fail(t, "duplicated features is not allowed", "feature=%#v", f, pkg)
} else if !found { } else if !found {
assert.Fail(t, "unexpected feature", "feature = %#v", pkg) assert.Fail(t, "unexpected feature", "feature = %#v", f)
} }
visited[pkg] = true visited[f] = true
} }
missingPackages := []PackageInfo{} missingPackages := []database.Feature{}
for pkg, ok := range visited { for pkg, ok := range visited {
if !ok { if !ok {
missingPackages = append(missingPackages, pkg) missingPackages = append(missingPackages, pkg)
@ -100,19 +94,3 @@ func RunTest(t *testing.T, test TestCase, lister Lister, expectedVersionFormat s
assert.Len(t, missingPackages, 0, "missing packages") assert.Len(t, missingPackages, 0, "missing packages")
}) })
} }
func convertToPackageInfo(feature *database.Feature) PackageInfo {
pkg := PackageInfo{
PackageName: feature.Name,
PackageVersion: feature.Version,
}
// Since in the actual package manager metadata file, there's no explicit
// tree structure, the features are converted to compare the metadata only.
if feature.Parent != nil {
pkg.SourceName = feature.Parent.Name
pkg.SourceVersion = feature.Parent.Version
}
return pkg
}