| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package symbols |
| |
| import ( |
| "context" |
| "fmt" |
| "testing" |
| |
| "github.com/go-git/go-git/v5" |
| "github.com/google/go-cmp/cmp" |
| "golang.org/x/vulndb/internal/osv" |
| "golang.org/x/vulndb/internal/report" |
| ) |
| |
| func TestPopulate(t *testing.T) { |
| for _, tc := range []struct { |
| name string |
| update bool |
| input *report.Report |
| want *report.Report |
| }{ |
| { |
| name: "basic", |
| update: true, |
| input: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| }}, |
| References: []*report.Reference{{ |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }}, |
| }, |
| want: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| Packages: []*report.Package{{ |
| Package: "example.com/module/package", |
| Symbols: []string{"symbol1", "symbol2"}, |
| }}, |
| FixLinks: []string{"https://example.com/module/commit/1234"}, |
| }}, |
| References: []*report.Reference{ |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }, |
| }, |
| }, |
| }, |
| { |
| name: "multiple_fixes", |
| update: false, |
| input: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| }}, |
| References: []*report.Reference{ |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }, |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/5678", |
| }, |
| }, |
| }, |
| want: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| Packages: []*report.Package{{ |
| Package: "example.com/module/package", |
| Symbols: []string{"symbol1", "symbol2", "symbol3"}, |
| }}, |
| }}, |
| References: []*report.Reference{ |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }, |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/5678", |
| }, |
| }, |
| }, |
| }, { |
| name: "multiple_fixes_update", |
| update: true, |
| input: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| }}, |
| References: []*report.Reference{ |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }, |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/5678", |
| }, |
| }, |
| }, |
| want: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| Packages: []*report.Package{{ |
| Package: "example.com/module/package", |
| // We don't yet dedupe the symbols. |
| Symbols: []string{"symbol1", "symbol2", "symbol3"}, |
| }}, |
| // Both links are added because they both contain vulnerable symbols |
| FixLinks: []string{"https://example.com/module/commit/1234", "https://example.com/module/commit/5678"}, |
| }}, |
| References: []*report.Reference{ |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/1234", |
| }, |
| { |
| Type: osv.ReferenceTypeFix, |
| URL: "https://example.com/module/commit/5678", |
| }, |
| }, |
| }, |
| }, |
| { |
| name: "has fix link", |
| update: false, |
| input: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| FixLinks: []string{"https://example.com/module/commit/1234", "https://example.com/module/commit/5678"}, |
| }}, |
| }, |
| want: &report.Report{ |
| Modules: []*report.Module{{ |
| Module: "example.com/module", |
| Packages: []*report.Package{{ |
| Package: "example.com/module/package", |
| Symbols: []string{"symbol1", "symbol2", "symbol3"}, |
| }}, |
| FixLinks: []string{"https://example.com/module/commit/1234", "https://example.com/module/commit/5678"}, |
| }}, |
| }, |
| }, |
| } { |
| t.Run(tc.name, func(t *testing.T) { |
| if err := populate(tc.input, tc.update, mockClone, patchedFake); err != nil { |
| t.Fatal(err) |
| } |
| got := tc.input |
| if diff := cmp.Diff(tc.want, got); diff != "" { |
| t.Errorf("populate mismatch (-want, +got):\n%s", diff) |
| } |
| }) |
| } |
| } |
| |
| func patchedFake(module string, hash string, repo *repository) (map[string][]string, error) { |
| if module == "example.com/module" && repo.url == "https://example.com/module" && hash == "1234" { |
| return map[string][]string{ |
| "example.com/module/package": {"symbol1", "symbol2"}, |
| }, nil |
| } |
| if module == "example.com/module" && repo.url == "https://example.com/module" && hash == "5678" { |
| return map[string][]string{ |
| "example.com/module/package": {"symbol1", "symbol2", "symbol3"}, |
| }, nil |
| } |
| return nil, fmt.Errorf("unrecognized inputs: module=%s,repo=%s,hash=%s", module, repo.url, hash) |
| } |
| |
| func mockClone(ctx context.Context, dir, repoURL string) (repo *git.Repository, err error) { |
| return nil, err |
| } |