From 5db2e66f30d671f334486ad3dfbb178f4fef6817 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 2 Feb 2022 22:38:49 -0500 Subject: internal/cpe: add avstring and tests --- internal/cpe/avstring.go | 54 +++++++++++++++++++++ internal/cpe/avstring_test.go | 95 +++++++++++++++++++++++++++++++++++++ internal/cpe/avstringtype_string.go | 25 ++++++++++ 3 files changed, 174 insertions(+) create mode 100644 internal/cpe/avstring.go create mode 100644 internal/cpe/avstring_test.go create mode 100644 internal/cpe/avstringtype_string.go diff --git a/internal/cpe/avstring.go b/internal/cpe/avstring.go new file mode 100644 index 0000000..46e16cf --- /dev/null +++ b/internal/cpe/avstring.go @@ -0,0 +1,54 @@ +package cpe + +//go:generate stringer -linecomment -type=AvStringType + +import ( + "fmt" +) + +// type of avstring. +type AvStringType byte + +const ( + AnyString AvStringType = iota // any + NaString // na + ValString // val +) + +// String value (NISTIR 7695, CPE 2.3 spec, Figure 6-3) +type AvString struct { + Type AvStringType // value type + Val string // value +} + +// token type to avstring type map +var avTypes = map[tokenType]AvStringType { + anyToken: AnyString, + naToken: NaString, + valToken: ValString, +} + +// create new AvString from token. +func newAvString(t token) (AvString, error) { + if at, ok := avTypes[t.Type]; ok { + return AvString { at, t.Val }, nil + } else { + err := fmt.Errorf("invalid token type: 0x%02x", byte(t.Type)) + return AvString { 0, "" }, err + } +} + +// Serialize as string. +func (s AvString) String() string { + switch s.Type { + case AnyString: + return "*" + case NaString: + return "-" + case ValString: + return s.Val + default: + // not sure what to return here + return "" + } +} diff --git a/internal/cpe/avstring_test.go b/internal/cpe/avstring_test.go new file mode 100644 index 0000000..8cbb14b --- /dev/null +++ b/internal/cpe/avstring_test.go @@ -0,0 +1,95 @@ +package cpe + +import ( + "testing" +) + +func TestNewAvString(t *testing.T) { + passTests := []struct { + name string + val token + exp AvString + } { + { "any", token { Type: anyToken }, AvString { Type: AnyString } }, + { "na", token { Type: naToken }, AvString { Type: NaString } }, + { "empty", token { Type: valToken }, AvString { ValString, "" } }, + { "foo", token { valToken, "foo" }, AvString { ValString, "foo" } }, + } + + for _, test := range(passTests) { + t.Run(test.name, func(t *testing.T) { + got, err := newAvString(test.val) + if err != nil { + t.Error(err) + } else if got.Type != test.exp.Type { + t.Errorf("token: got %s, exp %s", got.Type, test.exp.Type) + } else if got.Type == ValString && got.Val != test.exp.Val { + t.Errorf("value: got \"%s\", exp \"%s\"", got.Val, test.exp.Val) + } + }) + } + + failTests := []struct { + name string + val token + exp string + } {{ + name: "invalid token", + val: token { Type: tokenType(127), Val: "foo" }, + exp: "invalid token type: 0x7f", + }} + + for _, test := range(failTests) { + t.Run(test.name, func(t *testing.T) { + got, err := newAvString(test.val) + if err == nil { + t.Errorf("got %v, exp error", got) + } else if err.Error() != test.exp { + t.Errorf("got \"%s\", exp \"%s\"", err.Error(), test.exp) + } + }) + } +} + +func TestAvStringString(t *testing.T) { + tests := []struct { + name string + val AvString + exp string + } { + { "any", AvString { AnyString, "" }, "*" }, + { "na", AvString { NaString, "" }, "-" }, + { "foo", AvString { ValString, "foo" }, "foo" }, + { "junk", AvString { AvStringType(255), "foo" }, "" }, + } + + for _, test := range(tests) { + t.Run(test.name, func(t *testing.T) { + got := test.val.String() + if got != test.exp { + t.Errorf("value: got \"%s\", exp \"%s\"", got, test.exp) + } + }) + } +} + +func TestAvStringTypeString(t *testing.T) { + tests := []struct { + val AvStringType + exp string + } { + { AnyString, "any" }, + { NaString, "na" }, + { ValString, "val" }, + { AvStringType(255), "AvStringType(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) + } + }) + } +} diff --git a/internal/cpe/avstringtype_string.go b/internal/cpe/avstringtype_string.go new file mode 100644 index 0000000..6fb88e1 --- /dev/null +++ b/internal/cpe/avstringtype_string.go @@ -0,0 +1,25 @@ +// Code generated by "stringer -linecomment -type=AvStringType"; DO NOT EDIT. + +package cpe + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[AnyString-0] + _ = x[NaString-1] + _ = x[ValString-2] +} + +const _AvStringType_name = "anynaval" + +var _AvStringType_index = [...]uint8{0, 3, 5, 8} + +func (i AvStringType) String() string { + if i >= AvStringType(len(_AvStringType_index)-1) { + return "AvStringType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _AvStringType_name[_AvStringType_index[i]:_AvStringType_index[i+1]] +} -- cgit v1.2.3