diff options
Diffstat (limited to 'dbstore/dbstore_test.go')
-rw-r--r-- | dbstore/dbstore_test.go | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/dbstore/dbstore_test.go b/dbstore/dbstore_test.go index 1e03d72..628addb 100644 --- a/dbstore/dbstore_test.go +++ b/dbstore/dbstore_test.go @@ -10,8 +10,10 @@ import ( "fmt" _ "github.com/mattn/go-sqlite3" "github.com/pablotron/cvez/cpedict" + "github.com/pablotron/cvez/cpematch" io_fs "io/fs" "os" + "path/filepath" "reflect" "testing" "time" @@ -526,3 +528,421 @@ func TestCpeSearch(t *testing.T) { }) } } + +func TestAddCpeMatches(t *testing.T) { + // cache context, create temp dir + ctx := context.Background() + dir, err := os.MkdirTemp("", "") + if err != nil { + t.Error(err) + return + } + defer os.RemoveAll(dir) + + vuln := true + passTests := []struct { + name string // test name and path + seed string // db seed query + matches []cpematch.Match // matches + } {{ + name: "pass-basic", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + Vulnerable: &vuln, + + VersionStartIncluding: "1.0.0", + VersionEndIncluding: "1.6.3", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }, { + name: "pass-excluding", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + Vulnerable: &vuln, + + VersionStartExcluding: "1.0.0", + VersionEndExcluding: "1.6.3", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }} + + for _, test := range(passTests) { + t.Run(test.name, func(t *testing.T) { + // build test matches + matches := cpematch.Matches { Matches: test.matches } + // open db + db, err := Open(filepath.Join(dir, fmt.Sprintf("%s.db", test.name))) + if err != nil { + t.Error(err) + return + } + + // init db + if err := db.Init(ctx); err != nil { + t.Error(err) + return + } + + // seed db + if _, err = db.db.ExecContext(ctx, test.seed); err != nil { + t.Error(err) + return + } + + // add matches + if err = db.AddCpeMatches(ctx, matches); err != nil { + t.Error(err) + } + }) + } + + failTests := []struct { + name string // test name (path inferred) + seed string // db seed query + matches []cpematch.Match // matches + } {{ + name: "bad-match-cpe23", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:", + + VersionStartIncluding: "1.0.0", + VersionEndIncluding: "1.6.3", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }, { + name: "bad-cpe", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + VersionStartIncluding: "1.0.0", + VersionEndIncluding: "1.6.3", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }, { + name: "dup-versionstart", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + VersionStartIncluding: "1.0.0", + VersionStartExcluding: "1.1.0", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }, { + name: "dup-versionend", + + seed: ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + `, + + matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + VersionEndIncluding: "1.0.0", + VersionEndExcluding: "1.1.0", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + }} + + for _, test := range(failTests) { + t.Run(test.name, func(t *testing.T) { + // build test matches + matches := cpematch.Matches { Matches: test.matches } + // open db + db, err := Open(filepath.Join(dir, fmt.Sprintf("%s.db", test.name))) + if err != nil { + t.Error(err) + return + } + + // init db + if err := db.Init(ctx); err != nil { + t.Error(err) + return + } + + // seed db + if _, err = db.db.ExecContext(ctx, test.seed); err != nil { + t.Error(err) + return + } + + // add matches + if err = db.AddCpeMatches(ctx, matches); err == nil { + t.Error("got success, exp error") + } + }) + } +} + +func TestCpeMatchSearch(t *testing.T) { + // cache context, create temp dir + ctx := context.Background() + dir, err := os.MkdirTemp("", "") + if err != nil { + t.Error(err) + return + } + defer os.RemoveAll(dir) + + // db cpe seed query + seed := ` + INSERT INTO cpes(cpe_uri, cpe23) VALUES ( + 'cpe:/1', + 'cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/2', + 'cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*' + ), ( + 'cpe:/3', + 'cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*' + ); + ` + + matches := cpematch.Matches { + Matches: []cpematch.Match { + cpematch.Match { + Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + + VersionStartIncluding: "1.0.0", + VersionEndIncluding: "1.6.3", + + Names: []cpematch.Name { + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + }, + + cpematch.Name { + Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }, + }, + }, + } + + // build test matches + // open db + db, err := Open(filepath.Join(dir, "TestCpeMatchSearch.db")) + if err != nil { + t.Error(err) + return + } + + // init db + if err := db.Init(ctx); err != nil { + t.Error(err) + return + } + + // seed db + if _, err = db.db.ExecContext(ctx, seed); err != nil { + t.Error(err) + return + } + + // add matches + if err = db.AddCpeMatches(ctx, matches); err != nil { + t.Error(err) + return + } + + tests := []struct { + val string // search val + exp []string // expected results + } {{ + val: "nothing", + exp: []string {}, + }, { + val: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*", + exp: []string { + "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*", + "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*", + "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*", + }, + }} + + for _, test := range(tests) { + t.Run(test.val, func(t *testing.T) { + if got, err := db.CpeMatchSearch(ctx, test.val); err != nil { + t.Error(err) + } else if ((len(got) > 0) || (len(test.exp) > 0)) && + !reflect.DeepEqual(got, test.exp) { + t.Errorf("got %v, exp %v", got, test.exp) + } + }) + } +} |