From 94b148ccdcb88f2544c222f73f5c734ac78ccd96 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Mon, 31 Jan 2022 23:28:22 -0500 Subject: internal/cvss: more tests --- internal/cvss/v2key_test.go | 18 ++ internal/cvss/v2metric_test.go | 9 + internal/cvss/v3key_test.go | 18 ++ internal/cvss/v3metric.go | 9 +- internal/cvss/v3metric_test.go | 366 +++++++++++++++++++++++++++++++++++++++++ internal/cvss/version_test.go | 24 +++ 6 files changed, 438 insertions(+), 6 deletions(-) create mode 100644 internal/cvss/v3metric_test.go create mode 100644 internal/cvss/version_test.go (limited to 'internal') diff --git a/internal/cvss/v2key_test.go b/internal/cvss/v2key_test.go index 76a3d79..a54f4e7 100644 --- a/internal/cvss/v2key_test.go +++ b/internal/cvss/v2key_test.go @@ -96,3 +96,21 @@ func TestV2KeyCategory(t *testing.T) { }) } } + +func TestInvalidV2KeyName(t *testing.T) { + exp := "invalid" + got := v2Key(255).Name() + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} + +func TestInvalidV2KeyCategory(t *testing.T) { + exp := InvalidCategory + got := v2Key(255).Category() + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} diff --git a/internal/cvss/v2metric_test.go b/internal/cvss/v2metric_test.go index b17d2ed..f606ed5 100644 --- a/internal/cvss/v2metric_test.go +++ b/internal/cvss/v2metric_test.go @@ -265,3 +265,12 @@ func TestV2MetricString(t *testing.T) { }) } } + +func TestInvalidV2MetricKey(t *testing.T) { + got := v2Metric(255).Key() + exp := v2InvalidKey + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} diff --git a/internal/cvss/v3key_test.go b/internal/cvss/v3key_test.go index ccf2b8f..517eebd 100644 --- a/internal/cvss/v3key_test.go +++ b/internal/cvss/v3key_test.go @@ -122,3 +122,21 @@ func TestV3KeyCategory(t *testing.T) { }) } } + +func TestInvalidV3KeyName(t *testing.T) { + exp := "invalid" + got := v3Key(255).Name() + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} + +func TestInvalidV3KeyCategory(t *testing.T) { + exp := InvalidCategory + got := v3Key(255).Category() + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} diff --git a/internal/cvss/v3metric.go b/internal/cvss/v3metric.go index e9a6763..fc4c860 100644 --- a/internal/cvss/v3metric.go +++ b/internal/cvss/v3metric.go @@ -323,12 +323,9 @@ func (m v3Metric) Key() Key { // Convert string to CVSS 3.1 metric. func getV3Metric(version Version, s string) (v3Metric, error) { - // get metric - m, ok := v3MetricStrLut[s] - if !ok { + if m, ok := v3MetricStrLut[s]; ok { + return m, nil + } else { return v3InvalidMetric, newBadMetric(version, s) } - - // return success - return m, nil } diff --git a/internal/cvss/v3metric_test.go b/internal/cvss/v3metric_test.go new file mode 100644 index 0000000..432d34a --- /dev/null +++ b/internal/cvss/v3metric_test.go @@ -0,0 +1,366 @@ +package cvss + +import "testing" + +func TestGetV3Metric(t *testing.T) { + tests := []struct { + val string + exp v3Metric + ok bool + } { + { "AV:N", v3AVNetwork, true }, + { "AV:A", v3AVAdjacentNetwork, true }, + { "AV:L", v3AVLocal, true }, + { "AV:P", v3AVPhysical, true }, + + { "AC:L", v3ACLow, true }, + { "AC:H", v3ACHigh, true }, + + { "PR:N", v3PRNone, true }, + { "PR:L", v3PRLow, true }, + { "PR:H", v3PRHigh, true }, + + { "UI:N", v3UINone, true }, + { "UI:R", v3UIRequired, true }, + + { "S:U", v3SUnchanged, true }, + { "S:C", v3SChanged, true }, + + { "C:H", v3CHigh, true }, + { "C:L", v3CLow, true }, + { "C:N", v3CNone, true }, + + { "I:H", v3IHigh, true }, + { "I:L", v3ILow, true }, + { "I:N", v3INone, true }, + + { "A:H", v3AHigh, true }, + { "A:L", v3ALow, true }, + { "A:N", v3ANone, true }, + + { "E:X", v3ENotDefined, true }, + { "E:H", v3EHigh, true }, + { "E:F", v3EFunctional, true }, + { "E:P", v3EProofOfConcept, true }, + { "E:U", v3EUnproven, true }, + + { "RL:X", v3RLNotDefined, true }, + { "RL:U", v3RLUnavailable, true }, + { "RL:W", v3RLWorkaround, true }, + { "RL:T", v3RLTemporaryFix, true }, + { "RL:O", v3RLOfficialFix, true }, + + { "RC:X", v3RCNotDefined, true }, + { "RC:C", v3RCConfirmed, true }, + { "RC:R", v3RCReasonable, true }, + { "RC:U", v3RCUnknown, true }, + + { "CR:X", v3CRNotDefined, true }, + { "CR:H", v3CRHigh, true }, + { "CR:M", v3CRMedium, true }, + { "CR:L", v3CRLow, true }, + + { "IR:X", v3IRNotDefined, true }, + { "IR:H", v3IRHigh, true }, + { "IR:M", v3IRMedium, true }, + { "IR:L", v3IRLow, true }, + + { "AR:X", v3ARNotDefined, true }, + { "AR:H", v3ARHigh, true }, + { "AR:M", v3ARMedium, true }, + { "AR:L", v3ARLow, true }, + + { "MAV:X", v3MAVNotDefined, true }, + { "MAV:N", v3MAVNetwork, true }, + { "MAV:A", v3MAVAdjacentNetwork, true }, + { "MAV:L", v3MAVLocal, true }, + { "MAV:P", v3MAVPhysical, true }, + + { "MAC:X", v3MACNotDefined, true }, + { "MAC:L", v3MACLow, true }, + { "MAC:H", v3MACHigh, true }, + + { "MPR:X", v3MMRNotDefined, true }, + { "MPR:L", v3MPRLow, true }, + { "MPR:H", v3MPRHigh, true }, + + { "MUI:X", v3MUINotDefined, true }, + { "MUI:N", v3MUINone, true }, + { "MUI:R", v3MUIRequired, true }, + + { "MMS:X", v3MSNotDefined, true }, + { "MMS:U", v3MSUnchanged, true }, + { "MMS:C", v3MSChanged, true }, + + { "MC:X", v3MCNotDefined, true }, + { "MC:H", v3MCHigh, true }, + { "MC:L", v3MCLow, true }, + { "MC:N", v3MCNone, true }, + + { "MI:X", v3MINotDefined, true }, + { "MI:H", v3MIHigh, true }, + { "MI:L", v3MILow, true }, + { "MI:N", v3MINone, true }, + + { "MA:X", v3MANotDefined, true }, + { "MA:H", v3MAHigh, true }, + { "MA:L", v3MALow, true }, + { "MA:N", v3MANone, true }, + + { "invalid", v3InvalidMetric, false }, + } + + for _, test := range(tests) { + t.Run(test.val, func(t *testing.T) { + got, err := getV3Metric(V31, 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 TestGetV3MetricKey(t *testing.T) { + tests := []struct { + val v3Metric + exp v3Key + } { + { v3AVNetwork, v3AttackVector }, // AV:N + { v3AVAdjacentNetwork, v3AttackVector }, // AV:A + { v3AVLocal, v3AttackVector }, // AV:L + { v3AVPhysical, v3AttackVector }, // AV:P + + { v3ACLow, v3AttackComplexity }, // AC:L + { v3ACHigh, v3AttackComplexity }, // AC:H + + { v3PRNone, v3PrivilegesRequired }, // PR:N + { v3PRLow, v3PrivilegesRequired }, // PR:L + { v3PRHigh, v3PrivilegesRequired }, // PR:H + + { v3UINone, v3UserInteraction }, // UI:N + { v3UIRequired, v3UserInteraction }, // UI:R + + { v3SUnchanged, v3Scope }, // S:U + { v3SChanged, v3Scope }, // S:C + + { v3CHigh, v3Confidentiality }, // C:H + { v3CLow, v3Confidentiality }, // C:L + { v3CNone, v3Confidentiality }, // C:N + + { v3IHigh, v3Integrity }, // I:H + { v3ILow, v3Integrity }, // I:L + { v3INone, v3Integrity }, // I:N + + { v3AHigh, v3Availability }, // A:H + { v3ALow, v3Availability }, // A:L + { v3ANone, v3Availability }, // A:N + + { v3ENotDefined, v3ExploitCodeMaturity }, // E:X + { v3EHigh, v3ExploitCodeMaturity }, // E:H + { v3EFunctional, v3ExploitCodeMaturity }, // E:F + { v3EProofOfConcept, v3ExploitCodeMaturity }, // E:P + { v3EUnproven, v3ExploitCodeMaturity }, // E:U + + { v3RLNotDefined, v3RemediationLevel }, // RL:X + { v3RLUnavailable, v3RemediationLevel }, // RL:U + { v3RLWorkaround, v3RemediationLevel }, // RL:W + { v3RLTemporaryFix, v3RemediationLevel }, // RL:T + { v3RLOfficialFix, v3RemediationLevel }, // RL:O + + { v3RCNotDefined, v3ReportConfidence }, // RC:X + { v3RCConfirmed, v3ReportConfidence }, // RC:C + { v3RCReasonable, v3ReportConfidence }, // RC:R + { v3RCUnknown, v3ReportConfidence }, // RC:U + + { v3CRNotDefined, v3ConfidentialityRequirement }, // CR:X + { v3CRHigh, v3ConfidentialityRequirement }, // CR:H + { v3CRMedium, v3ConfidentialityRequirement }, // CR:M + { v3CRLow, v3ConfidentialityRequirement }, // CR:L + + { v3IRNotDefined, v3IntegrityRequirement }, // IR:X + { v3IRHigh, v3IntegrityRequirement }, // IR:H + { v3IRMedium, v3IntegrityRequirement }, // IR:M + { v3IRLow, v3IntegrityRequirement }, // IR:L + + { v3ARNotDefined, v3AvailabilityRequirement }, // AR:X + { v3ARHigh, v3AvailabilityRequirement }, // AR:H + { v3ARMedium, v3AvailabilityRequirement }, // AR:M + { v3ARLow, v3AvailabilityRequirement }, // AR:L + + { v3MAVNotDefined, v3ModifiedAttackVector }, // MAV:X + { v3MAVNetwork, v3ModifiedAttackVector }, // MAV:N + { v3MAVAdjacentNetwork, v3ModifiedAttackVector }, // MAV:A + { v3MAVLocal, v3ModifiedAttackVector }, // MAV:L + { v3MAVPhysical, v3ModifiedAttackVector }, // MAV:P + + { v3MACNotDefined, v3ModifiedAttackComplexity }, // MAC:X + { v3MACLow, v3ModifiedAttackComplexity }, // MAC:L + { v3MACHigh, v3ModifiedAttackComplexity }, // MAC:H + + { v3MMRNotDefined, v3ModifiedPrivilegesRequired }, // MPR:X + { v3MPRLow, v3ModifiedPrivilegesRequired }, // MPR:L + { v3MPRHigh, v3ModifiedPrivilegesRequired }, // MPR:H + + { v3MUINotDefined, v3ModifiedUserInteraction }, // MUI:X + { v3MUINone, v3ModifiedUserInteraction }, // MUI:N + { v3MUIRequired, v3ModifiedUserInteraction }, // MUI:R + + { v3MSNotDefined, v3ModifiedScope }, // MMS:X + { v3MSUnchanged, v3ModifiedConfidentiality }, // MMS:U + { v3MSChanged, v3ModifiedIntegrity }, // MMS:C + + { v3MCNotDefined, v3ModifiedConfidentiality }, // MC:X + { v3MCHigh, v3ModifiedConfidentiality }, // MC:H + { v3MCLow, v3ModifiedConfidentiality }, // MC:L + { v3MCNone, v3ModifiedConfidentiality }, // MC:N + + { v3MINotDefined, v3ModifiedIntegrity }, // MI:X + { v3MIHigh, v3ModifiedIntegrity }, // MI:H + { v3MILow, v3ModifiedIntegrity }, // MI:L + { v3MINone, v3ModifiedIntegrity }, // MI:N + + { v3MANotDefined, v3ModifiedAvailability }, // MA:X + { v3MAHigh, v3ModifiedAvailability }, // MA:H + { v3MALow, v3ModifiedAvailability }, // MA:L + { v3MANone, v3ModifiedAvailability }, // MA:N + } + + 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 TestV3MetricString(t *testing.T) { + tests := []struct { + val v3Metric + exp string + } { + { v3AVNetwork, "AV:N" }, + { v3AVAdjacentNetwork, "AV:A" }, + { v3AVLocal, "AV:L" }, + { v3AVPhysical, "AV:P" }, + + { v3ACLow, "AC:L" }, + { v3ACHigh, "AC:H" }, + + { v3PRNone, "PR:N" }, + { v3PRLow, "PR:L" }, + { v3PRHigh, "PR:H" }, + + { v3UINone, "UI:N" }, + { v3UIRequired, "UI:R" }, + + { v3SUnchanged, "S:U" }, + { v3SChanged, "S:C" }, + + { v3CHigh, "C:H" }, + { v3CLow, "C:L" }, + { v3CNone, "C:N" }, + + { v3IHigh, "I:H" }, + { v3ILow, "I:L" }, + { v3INone, "I:N" }, + + { v3AHigh, "A:H" }, + { v3ALow, "A:L" }, + { v3ANone, "A:N" }, + + { v3ENotDefined, "E:X" }, + { v3EHigh, "E:H" }, + { v3EFunctional, "E:F" }, + { v3EProofOfConcept, "E:P" }, + { v3EUnproven, "E:U" }, + + { v3RLNotDefined, "RL:X" }, + { v3RLUnavailable, "RL:U" }, + { v3RLWorkaround, "RL:W" }, + { v3RLTemporaryFix, "RL:T" }, + { v3RLOfficialFix, "RL:O" }, + + { v3RCNotDefined, "RC:X" }, + { v3RCConfirmed, "RC:C" }, + { v3RCReasonable, "RC:R" }, + { v3RCUnknown, "RC:U" }, + + { v3CRNotDefined, "CR:X" }, + { v3CRHigh, "CR:H" }, + { v3CRMedium, "CR:M" }, + { v3CRLow, "CR:L" }, + + { v3IRNotDefined, "IR:X" }, + { v3IRHigh, "IR:H" }, + { v3IRMedium, "IR:M" }, + { v3IRLow, "IR:L" }, + + { v3ARNotDefined, "AR:X" }, + { v3ARHigh, "AR:H" }, + { v3ARMedium, "AR:M" }, + { v3ARLow, "AR:L" }, + + { v3MAVNotDefined, "MAV:X" }, + { v3MAVNetwork, "MAV:N" }, + { v3MAVAdjacentNetwork, "MAV:A" }, + { v3MAVLocal, "MAV:L" }, + { v3MAVPhysical, "MAV:P" }, + + { v3MACNotDefined, "MAC:X" }, + { v3MACLow, "MAC:L" }, + { v3MACHigh, "MAC:H" }, + + { v3MMRNotDefined, "MPR:X" }, + { v3MPRLow, "MPR:L" }, + { v3MPRHigh, "MPR:H" }, + + { v3MUINotDefined, "MUI:X" }, + { v3MUINone, "MUI:N" }, + { v3MUIRequired, "MUI:R" }, + + { v3MSNotDefined, "MMS:X" }, + { v3MSUnchanged, "MMS:U" }, + { v3MSChanged, "MMS:C" }, + + { v3MCNotDefined, "MC:X" }, + { v3MCHigh, "MC:H" }, + { v3MCLow, "MC:L" }, + { v3MCNone, "MC:N" }, + + { v3MINotDefined, "MI:X" }, + { v3MIHigh, "MI:H" }, + { v3MILow, "MI:L" }, + { v3MINone, "MI:N" }, + + { v3MANotDefined, "MA:X" }, + { v3MAHigh, "MA:H" }, + { v3MALow, "MA:L" }, + { v3MANone, "MA:N" }, + + { v3Metric(255), "v3Metric(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) + } + }) + } +} + +func TestInvalidV3MetricKey(t *testing.T) { + got := v3Metric(255).Key() + exp := v3InvalidKey + + if got != exp { + t.Errorf("got: \"%s\", exp: \"%s\"", got, exp) + } +} diff --git a/internal/cvss/version_test.go b/internal/cvss/version_test.go new file mode 100644 index 0000000..e010094 --- /dev/null +++ b/internal/cvss/version_test.go @@ -0,0 +1,24 @@ +package cvss + +import "testing" + +func TestVersionString(t *testing.T) { + tests := []struct { + val Version + exp string + } { + { V20, "2.0" }, + { V30, "3.0" }, + { V31, "3.1" }, + { Version(255), "Version(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) + } + }) + } +} -- cgit v1.2.3