Skip to content
Merged
Changes from 1 commit
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
67 changes: 67 additions & 0 deletions pkg/lockfile/location_role_invariant_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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()

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

extractor, _ := lockfile.FindExtractor(path, map[string]bool{})
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 Enable parsers before using FindExtractor

In this test, FindExtractor only returns an extractor when enabledParsers[name] is true (see pkg/lockfile/extract.go), so passing an empty map disables every registered parser. As a result extractor is nil for every fixture and the new invariant test passes without exercising any extractor, including the future package.json case it is meant to catch. Populate the map from the registered extractor names before walking fixtures, or use a helper that matches all registered extractors.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 4be1fa3. The test now populates allParsers from lockfile.ListSupportedExtractors() before passing it to FindExtractor, so every registered extractor is exercised against its fixture files.

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