aboutsummaryrefslogtreecommitdiff
path: root/internal/cvss
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2022-01-31 22:07:06 -0500
committerPaul Duncan <pabs@pablotron.org>2022-01-31 22:07:06 -0500
commitabcd9428d9eb6cc8ac0189e6443930a67ebcabda (patch)
treedbd3a1f78fe900514244588d50bab7d98eebe0ba /internal/cvss
parenta739c2c0116e3bbe3122ec08b13a38440a3f9b62 (diff)
downloadcvez-abcd9428d9eb6cc8ac0189e6443930a67ebcabda.tar.bz2
cvez-abcd9428d9eb6cc8ac0189e6443930a67ebcabda.zip
internal/cvss: add many tests
Diffstat (limited to 'internal/cvss')
-rw-r--r--internal/cvss/v2key_test.go98
-rw-r--r--internal/cvss/v2metric.go2
-rw-r--r--internal/cvss/v2metric_test.go267
-rw-r--r--internal/cvss/v2vector.go2
-rw-r--r--internal/cvss/v2vector_test.go48
-rw-r--r--internal/cvss/v30vector_test.go49
-rw-r--r--internal/cvss/v31vector_test.go52
-rw-r--r--internal/cvss/v3key_test.go124
8 files changed, 622 insertions, 20 deletions
diff --git a/internal/cvss/v2key_test.go b/internal/cvss/v2key_test.go
new file mode 100644
index 0000000..76a3d79
--- /dev/null
+++ b/internal/cvss/v2key_test.go
@@ -0,0 +1,98 @@
+package cvss
+
+import "testing"
+
+func TestV2KeyString(t *testing.T) {
+ tests := []struct {
+ key v2Key
+ exp string
+ } {
+ { v2AccessVector, "AV" },
+ { v2AccessComplexity, "AC" },
+ { v2Authentication, "Au" },
+ { v2ConfidentialityImpact, "C" },
+ { v2IntegrityImpact, "I" },
+ { v2AvailabilityImpact, "A" },
+ { v2Exploitability, "E" },
+ { v2RemediationLevel, "RL" },
+ { v2ReportConfidence, "RC" },
+ { v2CollateralDamagePotential, "CDP" },
+ { v2TargetDistribution, "TD" },
+ { v2ConfidentialityRequirement, "CR" },
+ { v2IntegrityRequirement, "IR" },
+ { v2AvailabilityRequirement, "AR" },
+
+ { v2Key(255), "v2Key(255)" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.exp, func(t *testing.T) {
+ got := test.key.String()
+ if got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestV2KeyName(t *testing.T) {
+ tests := []struct {
+ key v2Key
+ exp string
+ } {
+ { v2AccessVector, "Access Vector" },
+ { v2AccessComplexity, "Access Complexity" },
+ { v2Authentication, "Authentication" },
+ { v2ConfidentialityImpact, "Confidentiality Impact" },
+ { v2IntegrityImpact, "Integrity Impact" },
+ { v2AvailabilityImpact, "Availability Impact" },
+ { v2Exploitability, "Exploitability" },
+ { v2RemediationLevel, "Remediation Level" },
+ { v2ReportConfidence, "Report Confidence" },
+ { v2CollateralDamagePotential, "Collateral Damage Potential" },
+ { v2TargetDistribution, "Target Distribution" },
+ { v2ConfidentialityRequirement, "Confidentiality Requirement" },
+ { v2IntegrityRequirement, "Integrity Requirement" },
+ { v2AvailabilityRequirement, "Availability Requirement" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.exp, func(t *testing.T) {
+ got := test.key.Name()
+ if got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestV2KeyCategory(t *testing.T) {
+ tests := []struct {
+ key v2Key
+ exp Category
+ } {
+ { v2AccessVector, Base },
+ { v2AccessComplexity, Base },
+ { v2Authentication, Base },
+ { v2ConfidentialityImpact, Base },
+ { v2IntegrityImpact, Base },
+ { v2AvailabilityImpact, Base },
+ { v2Exploitability, Temporal },
+ { v2RemediationLevel, Temporal },
+ { v2ReportConfidence, Temporal },
+ { v2CollateralDamagePotential, Environmental },
+ { v2TargetDistribution, Environmental},
+ { v2ConfidentialityRequirement, Environmental},
+ { v2IntegrityRequirement, Environmental},
+ { v2AvailabilityRequirement, Environmental},
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.key.String(), func(t *testing.T) {
+ got := test.key.Category()
+ if got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
diff --git a/internal/cvss/v2metric.go b/internal/cvss/v2metric.go
index de8b52b..a80cf8a 100644
--- a/internal/cvss/v2metric.go
+++ b/internal/cvss/v2metric.go
@@ -223,7 +223,7 @@ var v2MetricStrLut = map[string]v2Metric {
}
// Convert string to CVSS 2.0 metric.
-func getV2MetricFromString(s string) (v2Metric, error) {
+func getV2Metric(s string) (v2Metric, error) {
// get metric
m, ok := v2MetricStrLut[s]
if !ok {
diff --git a/internal/cvss/v2metric_test.go b/internal/cvss/v2metric_test.go
new file mode 100644
index 0000000..b17d2ed
--- /dev/null
+++ b/internal/cvss/v2metric_test.go
@@ -0,0 +1,267 @@
+package cvss
+
+import "testing"
+
+func TestGetV2Metric(t *testing.T) {
+ tests := []struct {
+ val string
+ exp v2Metric
+ ok bool
+ } {
+ { "AV:N", v2AVNetwork, true },
+ { "AV:A", v2AVAdjacentNetwork, true },
+ { "AV:L", v2AVLocal, true },
+
+ { "AC:L", v2ACLow, true },
+ { "AC:M", v2ACMedium, true },
+ { "AC:H", v2ACHigh, true },
+
+ { "Au:M", v2AuMultiple, true },
+ { "Au:S", v2AuSingle, true },
+ { "Au:N", v2AuNone, true },
+
+ { "C:N", v2CNone, true },
+ { "C:P", v2CPartial, true },
+ { "C:C", v2CComplete, true },
+
+ { "I:N", v2INone, true },
+ { "I:P", v2IPartial, true },
+ { "I:C", v2IComplete, true },
+
+ { "A:N", v2ANone, true },
+ { "A:P", v2APartial, true },
+ { "A:C", v2AComplete, true },
+
+ { "E:ND", v2ENotDefined, true },
+ { "E:U", v2EUnproven, true },
+ { "E:POC", v2EProofOfConcept, true },
+ { "E:F", v2EFunctional, true },
+ { "E:H", v2EHigh, true },
+
+ { "RL:OF", v2RLOfficialFix, true },
+ { "RL:TF", v2RLTemporaryFix, true },
+ { "RL:W", v2RLWorkaround, true },
+ { "RL:U", v2RLUnavailable, true },
+ { "RL:ND", v2RLNotDefined, true },
+
+ { "RC:UC", v2RCUnconfirmed, true },
+ { "RC:UR", v2RCUncorroborated, true },
+ { "RC:C", v2RCConfirmed, true },
+ { "RC:ND", v2RCNotDefined, true },
+
+ { "CDP:N", v2CDPNone, true },
+ { "CDP:L", v2CDPLow, true },
+ { "CDP:LM", v2CDPLowMedium, true },
+ { "CDP:MH", v2CDPMediumHigh, true },
+ { "CDP:H", v2CDPHigh, true },
+ { "CDP:ND", v2CDPNotDefined, true },
+
+ { "TD:N", v2TDNone, true },
+ { "TD:L", v2TDLow, true },
+ { "TD:M", v2TDMedium, true },
+ { "TD:H", v2TDHigh, true },
+ { "TD:ND", v2TDNotDefined, true },
+
+ { "CR:L", v2CRLow, true },
+ { "CR:M", v2CRMedium, true },
+ { "CR:H", v2CRHigh, true },
+ { "CR:ND", v2CRNotDefined, true },
+
+ { "IR:L", v2IRLow, true },
+ { "IR:M", v2IRMedium, true },
+ { "IR:H", v2IRHigh, true },
+ { "IR:ND", v2IRNotDefined, true },
+
+ { "AR:L", v2ARLow, true },
+ { "AR:M", v2ARMedium, true },
+ { "AR:H", v2ARHigh, true },
+ { "AR:ND", v2ARNotDefined, true },
+
+ { "asdf", v2InvalidMetric, false },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.val, func(t *testing.T) {
+ got, err := getV2Metric(test.val)
+ if test.ok && err == nil && got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ } else if test.ok && err != nil {
+ t.Error(err)
+ } else if !test.ok && err == nil {
+ t.Errorf("got: \"%s\", exp: error", got)
+ }
+ })
+ }
+}
+
+func TestGetV2MetricKey(t *testing.T) {
+ tests := []struct {
+ val v2Metric
+ exp v2Key
+ } {
+ { v2AVNetwork, v2AccessVector },
+ { v2AVAdjacentNetwork, v2AccessVector },
+ { v2AVLocal, v2AccessVector },
+
+ { v2ACLow, v2AccessComplexity },
+ { v2ACMedium, v2AccessComplexity },
+ { v2ACHigh, v2AccessComplexity },
+
+ { v2AuMultiple, v2Authentication },
+ { v2AuSingle, v2Authentication },
+ { v2AuNone, v2Authentication },
+
+ { v2CNone, v2ConfidentialityImpact },
+ { v2CPartial, v2ConfidentialityImpact },
+ { v2CComplete, v2ConfidentialityImpact },
+
+ { v2INone, v2IntegrityImpact },
+ { v2IPartial, v2IntegrityImpact },
+ { v2IComplete, v2IntegrityImpact },
+
+ { v2ANone, v2AvailabilityImpact },
+ { v2APartial, v2AvailabilityImpact },
+ { v2AComplete, v2AvailabilityImpact },
+
+ { v2ENotDefined, v2Exploitability },
+ { v2EUnproven, v2Exploitability },
+ { v2EProofOfConcept, v2Exploitability },
+ { v2EFunctional, v2Exploitability },
+ { v2EHigh, v2Exploitability },
+
+ { v2RLOfficialFix, v2RemediationLevel },
+ { v2RLTemporaryFix, v2RemediationLevel },
+ { v2RLWorkaround, v2RemediationLevel },
+ { v2RLUnavailable, v2RemediationLevel },
+ { v2RLNotDefined, v2RemediationLevel },
+
+ { v2RCUnconfirmed, v2ReportConfidence },
+ { v2RCUncorroborated, v2ReportConfidence },
+ { v2RCConfirmed, v2ReportConfidence },
+ { v2RCNotDefined, v2ReportConfidence },
+
+ { v2CDPNone, v2CollateralDamagePotential },
+ { v2CDPLow, v2CollateralDamagePotential },
+ { v2CDPLowMedium, v2CollateralDamagePotential },
+ { v2CDPMediumHigh, v2CollateralDamagePotential },
+ { v2CDPHigh, v2CollateralDamagePotential },
+ { v2CDPNotDefined, v2CollateralDamagePotential },
+
+ { v2TDNone, v2TargetDistribution },
+ { v2TDLow, v2TargetDistribution },
+ { v2TDMedium, v2TargetDistribution },
+ { v2TDHigh, v2TargetDistribution },
+ { v2TDNotDefined, v2TargetDistribution },
+
+ { v2CRLow, v2ConfidentialityRequirement },
+ { v2CRMedium, v2ConfidentialityRequirement },
+ { v2CRHigh, v2ConfidentialityRequirement },
+ { v2CRNotDefined, v2ConfidentialityRequirement },
+
+ { v2IRLow, v2IntegrityRequirement },
+ { v2IRMedium, v2IntegrityRequirement },
+ { v2IRHigh, v2IntegrityRequirement },
+ { v2IRNotDefined, v2IntegrityRequirement },
+
+ { v2ARLow, v2AvailabilityRequirement },
+ { v2ARMedium, v2AvailabilityRequirement },
+ { v2ARHigh, v2AvailabilityRequirement },
+ { v2ARNotDefined, v2AvailabilityRequirement },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.val.String(), func(t *testing.T) {
+ got := test.val.Key()
+ if got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestV2MetricString(t *testing.T) {
+ tests := []struct {
+ val v2Metric
+ exp string
+ } {
+ { v2AVNetwork, "AV:N" },
+ { v2AVAdjacentNetwork, "AV:A" },
+ { v2AVLocal, "AV:L" },
+
+ { v2ACLow, "AC:L" },
+ { v2ACMedium, "AC:M" },
+ { v2ACHigh, "AC:H" },
+
+ { v2AuMultiple, "Au:M" },
+ { v2AuSingle, "Au:S" },
+ { v2AuNone, "Au:N" },
+
+ { v2CNone, "C:N" },
+ { v2CPartial, "C:P" },
+ { v2CComplete, "C:C" },
+
+ { v2INone, "I:N" },
+ { v2IPartial, "I:P" },
+ { v2IComplete, "I:C" },
+
+ { v2ANone, "A:N" },
+ { v2APartial, "A:P" },
+ { v2AComplete, "A:C" },
+
+ { v2ENotDefined, "E:ND" },
+ { v2EUnproven, "E:U" },
+ { v2EProofOfConcept, "E:POC" },
+ { v2EFunctional, "E:F" },
+ { v2EHigh, "E:H" },
+
+ { v2RLOfficialFix, "RL:OF" },
+ { v2RLTemporaryFix, "RL:TF" },
+ { v2RLWorkaround, "RL:W" },
+ { v2RLUnavailable, "RL:U" },
+ { v2RLNotDefined, "RL:ND" },
+
+ { v2RCUnconfirmed, "RC:UC" },
+ { v2RCUncorroborated, "RC:UR" },
+ { v2RCConfirmed, "RC:C" },
+ { v2RCNotDefined, "RC:ND" },
+
+ { v2CDPNone, "CDP:N" },
+ { v2CDPLow, "CDP:L" },
+ { v2CDPLowMedium, "CDP:LM" },
+ { v2CDPMediumHigh, "CDP:MH" },
+ { v2CDPHigh, "CDP:H" },
+ { v2CDPNotDefined, "CDP:ND" },
+
+ { v2TDNone, "TD:N" },
+ { v2TDLow, "TD:L" },
+ { v2TDMedium, "TD:M" },
+ { v2TDHigh, "TD:H" },
+ { v2TDNotDefined, "TD:ND" },
+
+ { v2CRLow, "CR:L" },
+ { v2CRMedium, "CR:M" },
+ { v2CRHigh, "CR:H" },
+ { v2CRNotDefined, "CR:ND" },
+
+ { v2IRLow, "IR:L" },
+ { v2IRMedium, "IR:M" },
+ { v2IRHigh, "IR:H" },
+ { v2IRNotDefined, "IR:ND" },
+
+ { v2ARLow, "AR:L" },
+ { v2ARMedium, "AR:M" },
+ { v2ARHigh, "AR:H" },
+ { v2ARNotDefined, "AR:ND" },
+
+ { v2Metric(255), "v2Metric(255)" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.val.String(), func(t *testing.T) {
+ got := test.val.String()
+ if got != test.exp {
+ t.Errorf("got: \"%s\", exp: \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
diff --git a/internal/cvss/v2vector.go b/internal/cvss/v2vector.go
index efa2444..909bca6 100644
--- a/internal/cvss/v2vector.go
+++ b/internal/cvss/v2vector.go
@@ -47,7 +47,7 @@ func newV2Vector(s string) (Vector, error) {
// walk metric strings
for i, ms := range(strs) {
// convert string to vector
- m, err := getV2MetricFromString(ms)
+ m, err := getV2Metric(ms)
if err != nil {
return nil, err
}
diff --git a/internal/cvss/v2vector_test.go b/internal/cvss/v2vector_test.go
index 3ef4194..a943957 100644
--- a/internal/cvss/v2vector_test.go
+++ b/internal/cvss/v2vector_test.go
@@ -1,17 +1,51 @@
package cvss
-import "testing"
+import (
+ "testing"
+)
-// test v2 vector
-var testCvssV2 = "AV:L/AC:L/Au:N/C:N/I:N/A:P"
-
-// Test cvss v2 parser
+// Test cvss v2
func TestCvssV2Parser(t *testing.T) {
+ // test v2 vector
+ test := "AV:L/AC:L/Au:N/C:N/I:N/A:P"
+ expMetrics := []string { "AV:L", "AC:L", "Au:N", "C:N", "I:N", "A:P" }
+
t.Run("TestV2Parser", func(t *testing.T) {
- // parse vector, check for error
- _, err := NewVector(testCvssV2)
+ // parse vector
+ vec, err := NewVector(test)
if err != nil {
t.Error(err)
+ return
+ }
+
+ // check version
+ if vec.Version() != V20 {
+ t.Errorf("got %s, exp %s", vec.Version(), V20)
+ return
+ }
+
+ for i, m := range(vec.Metrics()) {
+ got := m.String()
+ if got != expMetrics[i] {
+ t.Errorf("got %s, exp %s", got, expMetrics[i])
+ }
}
})
}
+
+// Test cvss v2
+func TestInvalidV2Vector(t *testing.T) {
+ // test invalid vector
+ test := "AV:L/junk/Au:N/C:N/I:N/A:P"
+ exp := "invalid CVSS 2.0 metric: junk"
+
+ // parse vector
+ got, err := NewVector(test)
+ if err != nil && err.Error() != exp {
+ t.Errorf("got \"%s\", exp \"%s\"", err.Error(), err)
+ return
+ } else if err == nil {
+ t.Errorf("got \"%s\", exp badMetric", got)
+ return
+ }
+}
diff --git a/internal/cvss/v30vector_test.go b/internal/cvss/v30vector_test.go
new file mode 100644
index 0000000..fae3436
--- /dev/null
+++ b/internal/cvss/v30vector_test.go
@@ -0,0 +1,49 @@
+package cvss
+
+import (
+ "testing"
+)
+
+func TestV30Vector(t *testing.T) {
+ // test v3 vector
+ test := "CVSS:3.0/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N"
+ expMetrics := []string { "AV:L", "AC:H", "PR:L", "UI:N", "S:U", "C:H", "I:N", "A:N" }
+
+ t.Run("TestV30Vector", func(t *testing.T) {
+ // parse vector
+ vec, err := NewVector(test)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // check version
+ if vec.Version() != V30 {
+ t.Errorf("got %s, exp %s", vec.Version(), V30)
+ return
+ }
+
+ for i, m := range(vec.Metrics()) {
+ got := m.String()
+ if got != expMetrics[i] {
+ t.Errorf("got %s, exp %s", got, expMetrics[i])
+ }
+ }
+ })
+}
+
+func TestInvalidV30Vector(t *testing.T) {
+ // test invalid vector
+ test := "CVSS:3.0/AV:L/junk/PR:L/UI:N/S:U/C:H/I:N/A:N"
+ exp := "invalid CVSS 3.0 metric: junk"
+
+ // parse vector
+ got, err := NewVector(test)
+ if err != nil && err.Error() != exp {
+ t.Errorf("got \"%s\", exp \"%s\"", err.Error(), err)
+ return
+ } else if err == nil {
+ t.Errorf("got \"%s\", exp badMetric", got)
+ return
+ }
+}
diff --git a/internal/cvss/v31vector_test.go b/internal/cvss/v31vector_test.go
index 8340123..ba82edb 100644
--- a/internal/cvss/v31vector_test.go
+++ b/internal/cvss/v31vector_test.go
@@ -1,19 +1,49 @@
package cvss
-import "testing"
+import (
+ "testing"
+)
-// test cvss v3.1 vector
-var testCvssV3 = "CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H"
+func TestV31Vector(t *testing.T) {
+ // test v3 vector
+ test := "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N"
+ expMetrics := []string { "AV:L", "AC:H", "PR:L", "UI:N", "S:U", "C:H", "I:N", "A:N" }
-// Test CVSS v3 parser.
-func TestCvssV3Parser(t *testing.T) {
- t.Run("TestV3", func(t *testing.T) {
- // parse vector, check for error
- if _, err := NewVector(testCvssV3); err != nil {
- t.Fatal(err)
+ t.Run("TestV31Vector", func(t *testing.T) {
+ // parse vector
+ vec, err := NewVector(test)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ // check version
+ if vec.Version() != V31 {
+ t.Errorf("got %s, exp %s", vec.Version(), V31)
+ return
+ }
+
+ for i, m := range(vec.Metrics()) {
+ got := m.String()
+ if got != expMetrics[i] {
+ t.Errorf("got %s, exp %s", got, expMetrics[i])
+ }
}
})
+}
+
+func TestInvalidV31Vector(t *testing.T) {
+ // test invalid vector
+ test := "CVSS:3.1/AV:L/junk/PR:L/UI:N/S:U/C:H/I:N/A:N"
+ exp := "invalid CVSS 3.1 metric: junk"
- // fmt.Println(v.Metrics())
- // fmt.Println(v)
+ // parse vector
+ got, err := NewVector(test)
+ if err != nil && err.Error() != exp {
+ t.Errorf("got \"%s\", exp \"%s\"", err.Error(), err)
+ return
+ } else if err == nil {
+ t.Errorf("got \"%s\", exp badMetric", got)
+ return
+ }
}
diff --git a/internal/cvss/v3key_test.go b/internal/cvss/v3key_test.go
new file mode 100644
index 0000000..ccf2b8f
--- /dev/null
+++ b/internal/cvss/v3key_test.go
@@ -0,0 +1,124 @@
+package cvss
+
+import (
+ "testing"
+)
+
+func TestV3KeyString(t *testing.T) {
+ tests := []struct {
+ val v3Key
+ exp string
+ } {
+ { v3AttackVector, "AV" },
+ { v3AttackComplexity, "AC" },
+ { v3PrivilegesRequired, "PR" },
+ { v3UserInteraction, "UI" },
+ { v3Scope, "S" },
+ { v3Confidentiality, "C" },
+ { v3Integrity, "I" },
+ { v3Availability, "A" },
+ { v3ExploitCodeMaturity, "E" },
+ { v3RemediationLevel, "RL" },
+ { v3ReportConfidence, "RC" },
+ { v3ConfidentialityRequirement, "CR" },
+ { v3IntegrityRequirement, "IR" },
+ { v3AvailabilityRequirement, "AR" },
+ { v3ModifiedAttackVector, "MAV" },
+ { v3ModifiedAttackComplexity, "MAC" },
+ { v3ModifiedPrivilegesRequired, "MPR" },
+ { v3ModifiedUserInteraction, "MUI" },
+ { v3ModifiedScope, "MS" },
+ { v3ModifiedConfidentiality, "MC" },
+ { v3ModifiedIntegrity, "MI" },
+ { v3ModifiedAvailability, "MA" },
+
+ { v3Key(255), "v3Key(255)" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.exp, func(t *testing.T) {
+ got := test.val.String()
+ if got != test.exp {
+ t.Errorf("got \"%s\", exp \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestV3KeyName(t *testing.T) {
+ tests := []struct {
+ val v3Key
+ exp string
+ } {
+ { v3AttackVector, "Attack Vector" },
+ { v3AttackComplexity, "Attack Complexity" },
+ { v3PrivilegesRequired, "Privileges Required" },
+ { v3UserInteraction, "User Interaction" },
+ { v3Scope, "Scope" },
+ { v3Confidentiality, "Confidentiality" },
+ { v3Integrity, "Integrity" },
+ { v3Availability, "Availability" },
+ { v3ExploitCodeMaturity, "Exploit Code Maturity" },
+ { v3RemediationLevel, "Remediation Level" },
+ { v3ReportConfidence, "Report Confidence" },
+ { v3ConfidentialityRequirement, "Confidentiality Requirement" },
+ { v3IntegrityRequirement, "Integrity Requirement" },
+ { v3AvailabilityRequirement, "Availability Requirement" },
+ { v3ModifiedAttackVector, "Modified Attack Vector" },
+ { v3ModifiedAttackComplexity, "Modified Attack Complexity" },
+ { v3ModifiedPrivilegesRequired, "Modified Privileges Required" },
+ { v3ModifiedUserInteraction, "Modified User Interaction" },
+ { v3ModifiedScope, "Modified Scope" },
+ { v3ModifiedConfidentiality, "Modified Confidentiality" },
+ { v3ModifiedIntegrity, "Modified Integrity" },
+ { v3ModifiedAvailability, "Modified Availability" },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.exp, func(t *testing.T) {
+ got := test.val.Name()
+ if got != test.exp {
+ t.Errorf("got \"%s\", exp \"%s\"", got, test.exp)
+ }
+ })
+ }
+}
+
+func TestV3KeyCategory(t *testing.T) {
+ tests := []struct {
+ val v3Key
+ exp Category
+ } {
+ { v3AttackVector, Base },
+ { v3AttackComplexity, Base },
+ { v3PrivilegesRequired, Base },
+ { v3UserInteraction, Base },
+ { v3Scope, Base },
+ { v3Confidentiality, Base },
+ { v3Integrity, Base },
+ { v3Availability, Base },
+ { v3ExploitCodeMaturity, Temporal },
+ { v3RemediationLevel, Temporal },
+ { v3ReportConfidence, Temporal },
+ { v3ConfidentialityRequirement, Environmental },
+ { v3IntegrityRequirement, Environmental },
+ { v3AvailabilityRequirement, Environmental },
+ { v3ModifiedAttackVector, Environmental },
+ { v3ModifiedAttackComplexity, Environmental },
+ { v3ModifiedPrivilegesRequired, Environmental },
+ { v3ModifiedUserInteraction, Environmental },
+ { v3ModifiedScope, Environmental },
+ { v3ModifiedConfidentiality, Environmental },
+ { v3ModifiedIntegrity, Environmental },
+ { v3ModifiedAvailability, Environmental },
+ }
+
+ for _, test := range(tests) {
+ t.Run(test.val.String(), func(t *testing.T) {
+ got := test.val.Category()
+ if got != test.exp {
+ t.Errorf("got \"%s\", exp \"%s\"", got, test.exp)
+ }
+ })
+ }
+}