aboutsummaryrefslogtreecommitdiff
path: root/dbstore/dbstore_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'dbstore/dbstore_test.go')
-rw-r--r--dbstore/dbstore_test.go420
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)
+ }
+ })
+ }
+}