From 5dbf57134000f5ff2c5c12342ac4439b6d395603 Mon Sep 17 00:00:00 2001
From: Paul Duncan <pabs@pablotron.org>
Date: Tue, 1 Feb 2022 07:56:12 -0500
Subject: internal/feed: add nodeop tests

---
 internal/feed/feed.go          | 31 +----------------
 internal/feed/nodeop.go        | 39 +++++++++++++++++++++
 internal/feed/nodeop_string.go | 24 +++++++++++++
 internal/feed/nodeop_test.go   | 77 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 141 insertions(+), 30 deletions(-)
 create mode 100644 internal/feed/nodeop.go
 create mode 100644 internal/feed/nodeop_string.go
 create mode 100644 internal/feed/nodeop_test.go

(limited to 'internal/feed')

diff --git a/internal/feed/feed.go b/internal/feed/feed.go
index cf0fd2d..93a4a8f 100644
--- a/internal/feed/feed.go
+++ b/internal/feed/feed.go
@@ -7,10 +7,7 @@ import (
 )
 
 const (
-  OrNodeOp = iota // OR operator
-  AndNodeOp       // And operator
-
-  AdjacentNetwork // Adjacent Network attack vector.
+  AdjacentNetwork = iota // Adjacent Network attack vector.
   Network         // Network attack vector.
   Local           // Local attack vector.
   Physical        // Physical attack vector.
@@ -38,32 +35,6 @@ const (
 
 // TODO: parse cpe
 
-// Configuration node boolean operator.
-type NodeOp int
-
-// Unmarshal DataVersion from JSON.
-func (me *NodeOp) UnmarshalJSON(b []byte) error {
-  // decode string, check for error
-  var s string
-  if err := json.Unmarshal(b, &s); err != nil {
-    return err
-  }
-
-  // check value
-  switch s {
-  case "AND":
-    *me = AndNodeOp
-  case "OR":
-    *me = OrNodeOp
-  default:
-    // return error
-    return fmt.Errorf("unknown operator: %s", s)
-  }
-
-  // return success
-  return nil
-}
-
 // CVSS attack vector
 type AttackVector int
 
diff --git a/internal/feed/nodeop.go b/internal/feed/nodeop.go
new file mode 100644
index 0000000..8bfa0a0
--- /dev/null
+++ b/internal/feed/nodeop.go
@@ -0,0 +1,39 @@
+package feed
+
+//go:generate stringer -linecomment -type=NodeOp
+
+import (
+  "encoding/json"
+  "fmt"
+)
+
+// Node boolean operator.
+type NodeOp byte
+
+const (
+  OrOp NodeOp = iota  // OR
+  AndOp               // AND
+)
+
+// Unmarshal DataVersion from JSON.
+func (me *NodeOp) UnmarshalJSON(b []byte) error {
+  // decode string, check for error
+  var s string
+  if err := json.Unmarshal(b, &s); err != nil {
+    return err
+  }
+
+  // check value
+  switch s {
+  case "AND":
+    *me = AndOp
+  case "OR":
+    *me = OrOp
+  default:
+    // return error
+    return fmt.Errorf("unknown operator: %s", s)
+  }
+
+  // return success
+  return nil
+}
diff --git a/internal/feed/nodeop_string.go b/internal/feed/nodeop_string.go
new file mode 100644
index 0000000..2c120d4
--- /dev/null
+++ b/internal/feed/nodeop_string.go
@@ -0,0 +1,24 @@
+// Code generated by "stringer -linecomment -type=NodeOp"; DO NOT EDIT.
+
+package feed
+
+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[OrOp-0]
+	_ = x[AndOp-1]
+}
+
+const _NodeOp_name = "ORAND"
+
+var _NodeOp_index = [...]uint8{0, 2, 5}
+
+func (i NodeOp) String() string {
+	if i >= NodeOp(len(_NodeOp_index)-1) {
+		return "NodeOp(" + strconv.FormatInt(int64(i), 10) + ")"
+	}
+	return _NodeOp_name[_NodeOp_index[i]:_NodeOp_index[i+1]]
+}
diff --git a/internal/feed/nodeop_test.go b/internal/feed/nodeop_test.go
new file mode 100644
index 0000000..dd538e5
--- /dev/null
+++ b/internal/feed/nodeop_test.go
@@ -0,0 +1,77 @@
+package feed
+
+import (
+  "encoding/json"
+  "testing"
+)
+
+func TestNodeOpUnmarshalInvalidData(t *testing.T) {
+  test := []byte(`{}`)
+  var val NodeOp
+
+  if err := json.Unmarshal(test, &val); err == nil {
+    t.Errorf("got \"%s\", exp error", val)
+  }
+}
+
+func TestNodeOpUnmarshalUnknown(t *testing.T) {
+  test := []byte(`"foo"`)
+  exp := "unknown operator: foo"
+  var val NodeOp
+
+  err := json.Unmarshal(test, &val)
+  if err == nil {
+    t.Errorf("got \"%s\", exp error", val)
+    return
+  }
+
+  if err.Error() != exp {
+    t.Errorf("got \"%s\", exp \"%s\"", err.Error(), exp)
+  }
+}
+
+func TestNodeOpUnmarshalValid(t *testing.T) {
+  tests := []struct {
+    val string
+    exp NodeOp
+  } {
+    { "\"AND\"", AndOp },
+    { "\"OR\"", OrOp },
+  }
+
+  for _, test := range(tests) {
+    t.Run(test.val, func(t *testing.T) {
+      var got NodeOp
+      if err := json.Unmarshal([]byte(test.val), &got); err != nil {
+        t.Error(err)
+        return
+      }
+
+      if got != test.exp {
+        t.Errorf("got \"%s\", exp \"%s\"", got, test.exp)
+      }
+    })
+  }
+}
+
+func TestNodeOpString(t *testing.T) {
+  tests := []struct {
+    val NodeOp
+    exp string
+  } {
+    { AndOp, "AND" },
+    { OrOp, "OR" },
+
+    { NodeOp(255), "NodeOp(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)
+      }
+    })
+  }
+}
-- 
cgit v1.2.3