From 16cb69c3a3e45eb25bcbcb4f18b65e48ab72b07e Mon Sep 17 00:00:00 2001 From: Spiegel Date: Sun, 24 Feb 2019 18:46:22 +0900 Subject: [PATCH] Testing --- README.md | 71 ++++++++++++++++--------- cvsserr/errors.go | 15 ++++-- cvsserr/errors_test.go | 104 +++++++++++++++++++++++++++++++++++++ v3/base/base.go | 28 ++++------ v3/base/base_test.go | 41 ++++++++------- v3/cvss_test.go | 13 ++--- v3/version/version_test.go | 5 +- version.go | 5 ++ version_test.go | 10 ++++ 9 files changed, 219 insertions(+), 73 deletions(-) create mode 100644 cvsserr/errors_test.go create mode 100644 version.go create mode 100644 version_test.go diff --git a/README.md b/README.md index dc623fa..4ed2b83 100644 --- a/README.md +++ b/README.md @@ -4,33 +4,56 @@ [![GitHub license](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/spiegel-im-spiegel/go-cvss/master/LICENSE) [![GitHub release](http://img.shields.io/github/release/spiegel-im-spiegel/go-cvss.svg)](https://github.com/spiegel-im-spiegel/go-cvss/releases/latest) -### Usage +### Sample Code ```go -m := cvssv3.New() -if err := m.ImportBaseVector("CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H"); err != nil { - fmt.Fprintln(os.Stderr, err) - return -} -severity := m.Base.GetSeverity() -fmt.Printf("%s: %v (%.1f)\n\n", severity.Title(language.English), severity, m.Base.Score()) -if r, err := m.Base.Report(nil, language.English); err != nil { //output with CSV format - fmt.Fprintln(os.Stderr, err) -} else { - io.Copy(os.Stdout, r) +package main + +import ( + "flag" + "fmt" + "io" + "os" + + cvssv3 "github.com/spiegel-im-spiegel/go-cvss/v3" + "golang.org/x/text/language" +) + +func main() { + tf := flag.String("t", "", "template file") + flag.Parse() + if flag.NArg() != 1 { + fmt.Fprintln(os.Stderr, os.ErrInvalid) + return + } + vector := flag.Arg(0) + var tr io.Reader + if len(*tf) > 0 { + file, err := os.Open(*tf) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + defer file.Close() + tr = file + } + + m := cvssv3.New() + if err := m.ImportBaseVector(vector); err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + severity := m.Base.GetSeverity() + //lang := language.English + lang := language.Japanese + fmt.Printf("%s: %v (%.1f)\n\n", severity.Title(lang), severity.NameOfValue(lang), m.Base.Score()) + + if r, err := m.Base.Report(tr, lang); err != nil { + fmt.Fprintln(os.Stderr, err) + } else { + io.Copy(os.Stdout, r) + } } -// Output: -//Severity: Critical (9.9) -// -//Base Metrics,Metric Value -//Attack Vector,Network -//Attack Complexity,Low -//Privileges Required,Low -//User Interaction,None -//Scope,Changed -//Confidentiality Impact,High -//Integrity Impact,High -//Availability Impact,High ``` ref: [sample.go](https://github.com/spiegel-im-spiegel/go-cvss/blob/master/sample/sample.go) diff --git a/cvsserr/errors.go b/cvsserr/errors.go index d67d765..eaebd36 100644 --- a/cvsserr/errors.go +++ b/cvsserr/errors.go @@ -28,6 +28,18 @@ func (n Num) Error() string { return fmt.Sprintf("unknown error (%d)", int(n)) } +func (n Num) Is(target error) bool { + var t1 *wrapError + if errors.As(target, &t1) { + return n == t1.Num + } + var t2 Num + if errors.As(target, &t2) { + return n == t2 + } + return false +} + type wrapError struct { Num frame errors.Frame @@ -48,9 +60,6 @@ func (we *wrapError) FormatError(p errors.Printer) error { } func (we *wrapError) Is(target error) bool { - if we == nil || target == nil { - return we == target - } var t1 *wrapError if errors.As(target, &t1) { return we.Num == t1.Num diff --git a/cvsserr/errors_test.go b/cvsserr/errors_test.go new file mode 100644 index 0000000..29badc7 --- /dev/null +++ b/cvsserr/errors_test.go @@ -0,0 +1,104 @@ +package cvsserr + +import ( + "fmt" + "os" + "testing" + + "golang.org/x/xerrors" +) + +func TestNumError(t *testing.T) { + testCases := []struct { + err error + str string + }{ + {err: ErrUndefinedMetric, str: "undefined metric"}, + {err: ErrInvalidVector, str: "invalid vector"}, + {err: ErrNotSupportVer, str: "not support version"}, + {err: Num(4), str: "unknown error (4)"}, + } + + for _, tc := range testCases { + errStr := tc.err.Error() + if errStr != tc.str { + t.Errorf("\"%v\" != \"%v\"", errStr, tc.str) + } + fmt.Printf("Info(TestNumError): %+v\n", tc.err) + } +} + +func TestWrapError(t *testing.T) { + testCases := []struct { + err error + str string + }{ + {err: New(ErrUndefinedMetric), str: "undefined metric"}, + {err: New(ErrInvalidVector), str: "invalid vector"}, + {err: New(ErrNotSupportVer), str: "not support version"}, + {err: New(Num(4)), str: "unknown error (4)"}, + } + + for _, tc := range testCases { + errStr := tc.err.Error() + if errStr != tc.str { + t.Errorf("\"%v\" != \"%v\"", errStr, tc.str) + } + fmt.Printf("Info(TestWrapError): %+v\n", tc.err) + } +} + +func TestErrorEquality(t *testing.T) { + testCases := []struct { + err1 error + err2 error + res bool + }{ + {err1: New(ErrUndefinedMetric), err2: ErrUndefinedMetric, res: true}, + {err1: New(ErrInvalidVector), err2: ErrInvalidVector, res: true}, + {err1: New(ErrNotSupportVer), err2: ErrNotSupportVer, res: true}, + {err1: New(ErrUndefinedMetric), err2: New(ErrUndefinedMetric), res: true}, + {err1: New(ErrInvalidVector), err2: New(ErrInvalidVector), res: true}, + {err1: New(ErrNotSupportVer), err2: New(ErrNotSupportVer), res: true}, + {err1: New(ErrUndefinedMetric), err2: nil, res: false}, + {err1: New(ErrInvalidVector), err2: nil, res: false}, + {err1: New(ErrNotSupportVer), err2: nil, res: false}, + {err1: New(ErrUndefinedMetric), err2: os.ErrInvalid, res: false}, + {err1: New(ErrInvalidVector), err2: os.ErrInvalid, res: false}, + {err1: New(ErrNotSupportVer), err2: os.ErrInvalid, res: false}, + {err1: ErrUndefinedMetric, err2: New(ErrUndefinedMetric), res: true}, + {err1: ErrInvalidVector, err2: New(ErrInvalidVector), res: true}, + {err1: ErrNotSupportVer, err2: New(ErrNotSupportVer), res: true}, + {err1: ErrUndefinedMetric, err2: ErrUndefinedMetric, res: true}, + {err1: ErrInvalidVector, err2: ErrInvalidVector, res: true}, + {err1: ErrNotSupportVer, err2: ErrNotSupportVer, res: true}, + {err1: ErrUndefinedMetric, err2: nil, res: false}, + {err1: ErrInvalidVector, err2: nil, res: false}, + {err1: ErrNotSupportVer, err2: nil, res: false}, + {err1: ErrUndefinedMetric, err2: os.ErrInvalid, res: false}, + {err1: ErrInvalidVector, err2: os.ErrInvalid, res: false}, + {err1: ErrNotSupportVer, err2: os.ErrInvalid, res: false}, + } + + for _, tc := range testCases { + res := xerrors.Is(tc.err1, tc.err2) + if res != tc.res { + t.Errorf("\"%v\" == \"%v\" ? %v, want %v", tc.err1, tc.err2, res, tc.res) + } + } +} + +/* Copyright 2019 Spiegel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/v3/base/base.go b/v3/base/base.go index c7ff7f2..66fe770 100644 --- a/v3/base/base.go +++ b/v3/base/base.go @@ -6,18 +6,10 @@ import ( "math" "strings" - cvss "github.com/spiegel-im-spiegel/go-cvss" + "github.com/spiegel-im-spiegel/go-cvss/cvsserr" "github.com/spiegel-im-spiegel/go-cvss/v3/version" ) -//Error instances -// var ( -// ErrNilData = errors.New("nil data") -// ErrUndefinedMetric = errors.New("undefined metric") -// ErrInvalidVector = errors.New("invalid vector") -// ErrNotSupportVer = errors.New("not support version") -// ) - //Metrics is Base Metrics for CVSSv3 type Metrics struct { AV AttackVector @@ -48,7 +40,7 @@ func NewMetrics() *Metrics { func Decode(vector string) (*Metrics, error) { values := strings.Split(vector, "/") if len(values) < 9 { - return nil, cvss.ErrInvalidVector + return nil, cvsserr.New(cvsserr.ErrInvalidVector) } //CVSS version (CVSS 3.0 only) if _, err := checkVersion(values[0]); err != nil { @@ -59,7 +51,7 @@ func Decode(vector string) (*Metrics, error) { for _, value := range values[1:] { metric := strings.Split(value, ":") if len(metric) != 2 { - return nil, cvss.ErrInvalidVector + return nil, cvsserr.New(cvsserr.ErrInvalidVector) } switch strings.ToUpper(metric[0]) { case "AV": //Attack Vector @@ -79,7 +71,7 @@ func Decode(vector string) (*Metrics, error) { case "A": //Availability Impact metrics.A = GetAvailabilityImpact(metric[1]) default: - return nil, cvss.ErrInvalidVector + return nil, cvsserr.New(cvsserr.ErrInvalidVector) } } return metrics, metrics.GetError() @@ -87,13 +79,13 @@ func Decode(vector string) (*Metrics, error) { func checkVersion(ver string) (string, error) { v := strings.Split(ver, ":") if len(v) != 2 { - return "", cvss.ErrInvalidVector + return "", cvsserr.New(cvsserr.ErrInvalidVector) } if strings.ToUpper(v[0]) != "CVSS" { - return "", cvss.ErrInvalidVector + return "", cvsserr.New(cvsserr.ErrInvalidVector) } if v[1] != version.Version { - return "", cvss.ErrNotSupportVer + return "", cvsserr.New(cvsserr.ErrNotSupportVer) } return v[1], nil } @@ -119,11 +111,11 @@ func (m *Metrics) Encode() (string, error) { //GetError returns error instance if undefined metric func (m *Metrics) GetError() error { if m == nil { - return cvss.ErrUndefinedMetric + return cvsserr.New(cvsserr.ErrUndefinedMetric) } switch true { case !m.AV.IsDefined(), !m.AC.IsDefined(), !m.PR.IsDefined(), !m.UI.IsDefined(), !m.S.IsDefined(), !m.C.IsDefined(), !m.I.IsDefined(), !m.A.IsDefined(): - return cvss.ErrUndefinedMetric + return cvsserr.New(cvsserr.ErrUndefinedMetric) default: return nil } @@ -175,7 +167,7 @@ func (m *Metrics) GetSeverity() Severity { } } -/* Copyright 2018 Spiegel +/* Copyright 2018,2019 Spiegel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/v3/base/base_test.go b/v3/base/base_test.go index 5cc480f..fb526a5 100644 --- a/v3/base/base_test.go +++ b/v3/base/base_test.go @@ -4,7 +4,8 @@ import ( "fmt" "testing" - cvss "github.com/spiegel-im-spiegel/go-cvss" + "github.com/spiegel-im-spiegel/go-cvss/cvsserr" + "golang.org/x/xerrors" ) func TestDecodeError(t *testing.T) { @@ -13,25 +14,25 @@ func TestDecodeError(t *testing.T) { err error }{ {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: nil}, - {vector: "XXX:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrInvalidVector}, - {vector: "CVSS:2.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrNotSupportVer}, - {vector: "CVSS:3.0", err: cvss.ErrInvalidVector}, - {vector: "CVSS3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrInvalidVector}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A-N", err: cvss.ErrInvalidVector}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/X:N", err: cvss.ErrInvalidVector}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:X", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:X/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:X/I:N/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:X/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:X/S:U/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:H/PR:X/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:P/AC:X/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, - {vector: "CVSS:3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, + {vector: "XXX:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS:2.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrNotSupportVer}, + {vector: "CVSS:3.0", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A-N", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/X:N", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:X", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:X/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:X/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:X/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:X/S:U/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:H/PR:X/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:P/AC:X/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, } for _, tc := range testCases { _, err := Decode(tc.vector) - if err != tc.err { + if !xerrors.Is(err, tc.err) { t.Errorf("NewMetrics(%s) = \"%v\", want \"%v\".", tc.vector, err, tc.err) } } @@ -42,7 +43,7 @@ func TestDecodeEncode(t *testing.T) { vector string err error }{ - {vector: "CVSS:3.0/AV:X/AC:X/PR:X/UI:X/S:X/C:X/I:X/A:X", err: cvss.ErrUndefinedMetric}, + {vector: "CVSS:3.0/AV:X/AC:X/PR:X/UI:X/S:X/C:X/I:X/A:X", err: cvsserr.ErrUndefinedMetric}, {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: nil}, {vector: "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:L", err: nil}, {vector: "CVSS:3.0/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", err: nil}, @@ -51,11 +52,11 @@ func TestDecodeEncode(t *testing.T) { for _, tc := range testCases { m, err := Decode(tc.vector) - if err != tc.err { + if !xerrors.Is(err, tc.err) { t.Errorf("Decode(%s) = \"%v\", want \"%v\".", tc.vector, err, tc.err) } v, err := m.Encode() - if err != tc.err { + if !xerrors.Is(err, tc.err) { t.Errorf("Encode() = \"%v\", want \"%v\".", err, tc.err) } if err == nil { @@ -121,7 +122,7 @@ func ExampleMetrics() { //Severity = High } -/* Copyright 2018 Spiegel +/* Copyright 2018,2019 Spiegel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/v3/cvss_test.go b/v3/cvss_test.go index 1a00552..8480767 100644 --- a/v3/cvss_test.go +++ b/v3/cvss_test.go @@ -6,8 +6,9 @@ import ( "os" "testing" - cvss "github.com/spiegel-im-spiegel/go-cvss" + "github.com/spiegel-im-spiegel/go-cvss/cvsserr" "golang.org/x/text/language" + "golang.org/x/xerrors" ) func TestImportBaseVector(t *testing.T) { @@ -16,13 +17,13 @@ func TestImportBaseVector(t *testing.T) { err error }{ {vector: "CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: nil}, - {vector: "XXX:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrInvalidVector}, - {vector: "CVSS:2.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrNotSupportVer}, - {vector: "CVSS:3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvss.ErrUndefinedMetric}, + {vector: "XXX:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrInvalidVector}, + {vector: "CVSS:2.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrNotSupportVer}, + {vector: "CVSS:3.0/AV:X/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N", err: cvsserr.ErrUndefinedMetric}, } for _, tc := range testCases { err := New().ImportBaseVector(tc.vector) - if err != tc.err { + if !xerrors.Is(err, tc.err) { t.Errorf("CVSS.ImportBaseVector(%s) = \"%v\", want \"%v\".", tc.vector, err, tc.err) } } @@ -55,7 +56,7 @@ func ExampleCVSS() { //Availability Impact,High } -/* Copyright 2018 Spiegel +/* Copyright 2018,2019 Spiegel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/v3/version/version_test.go b/v3/version/version_test.go index 5499f4b..bac1501 100644 --- a/v3/version/version_test.go +++ b/v3/version/version_test.go @@ -3,7 +3,8 @@ package version import "testing" func TestVersion(t *testing.T) { - if Version != "3.0" { - t.Errorf("Version = %v, want %v.", Version, "3.0") + v := "3.0" + if Version != v { + t.Errorf("Version = %v, want %v.", Version, v) } } diff --git a/version.go b/version.go new file mode 100644 index 0000000..4a5d554 --- /dev/null +++ b/version.go @@ -0,0 +1,5 @@ +package cvss + +const ( + LatestVersion = "v3" +) diff --git a/version_test.go b/version_test.go new file mode 100644 index 0000000..4da6c90 --- /dev/null +++ b/version_test.go @@ -0,0 +1,10 @@ +package cvss + +import "testing" + +func TestVersion(t *testing.T) { + v := "v3" + if LatestVersion != v { + t.Errorf("Version = %v, want %v.", LatestVersion, v) + } +}