Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions pkg/lockfile/location_role_invariant_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package lockfile_test

import (
"os"
"path/filepath"
"testing"

"github.com/DataDog/datadog-sbom-generator/internal/utility/fileposition"
"github.com/DataDog/datadog-sbom-generator/pkg/lockfile"
"github.com/DataDog/datadog-sbom-generator/pkg/lockfile/internal/testutil"
_ "github.com/DataDog/datadog-sbom-generator/pkg/lockfile/parsers" // Register all extractors
)

// TestLocationRoleSetWhenBlockLocationIsValid verifies that every extractor sets
// LocationRole whenever it also sets a valid BlockLocation.
//
// This is an invariant that the reporter relies on: vulnerability_result.go uses
// LocationRole to populate the "role" field in the emitted PackageLocation. If an
// extractor populates BlockLocation but leaves LocationRole empty, the role will be
// blank in the SBOM output even though the location is meaningful.
//
// The test walks pkg/lockfile/fixtures/, runs the registered extractor for each
// fixture file, and fails if any returned PackageDetails has a valid BlockLocation
// but an empty LocationRole.
func TestLocationRoleSetWhenBlockLocationIsValid(t *testing.T) {
t.Parallel()

fixturesRoot := "fixtures"
context := testutil.GetTestContext()

// Enable all registered parsers so FindExtractor can match fixture files.
// An empty map disables every parser (FindExtractor checks enabledParsers[name] == true).
allParsers := make(map[string]bool)
for name := range lockfile.ListSupportedExtractors() {
allParsers[name] = true
}

err := filepath.WalkDir(fixturesRoot, func(path string, d os.DirEntry, err error) error {
if err != nil || d.IsDir() {
return err
}

extractor, _ := lockfile.FindExtractor(path, allParsers)
if extractor == nil {
return nil
}

f, err := lockfile.OpenLocalDepFile(path)
if err != nil {
return nil // skip unreadable files
}
defer f.Close()

packages, err := extractor.Extract(f, context)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exercise matcher-enriched package locations

For extractors that add source-file locations via matchers, this check is bypassed because it calls extractor.Extract directly. Production extraction then runs any ExtractorWithMatcher matchers (see ExtractFromFileWithContext), and those matchers are exactly where several manifest BlockLocation/LocationRole fields are populated. If a matcher regresses and starts setting a valid BlockLocation without LocationRole, this invariant still passes, so use the same extraction path that applies matchers for each fixture.

Useful? React with 👍 / 👎.

if err != nil {
return nil // skip files that fail to parse (invalid fixtures are intentional)
}

for _, pkg := range packages {
if fileposition.IsFilePositionExtractedSuccessfully(pkg.BlockLocation) && pkg.LocationRole == "" {
t.Errorf(
"extractor for %q returned package %s@%s with a valid BlockLocation but empty LocationRole",
path, pkg.Name, pkg.Version,
)
}
}

return nil
})

if err != nil {
t.Fatalf("error walking fixtures: %v", err)
}
}
Loading