func TestParseValue(t *testing.T) { // Because parsing JSON sucks. testcases := []struct { input string expected interface{} }{ {"42", int64(42)}, {"-42", int64(-42)}, {"42.42", float64(42.42)}, {"-42.42", float64(-42.42)}, {`"foo"`, nil}, {"9223372036854775807", int64(math.MaxInt64)}, {"-9223372036854775808", int64(math.MinInt64)}, {"9223372036854775808", uint64(math.MaxInt64) + 1}, } for i, tcase := range testcases { actual := parseValue(&openconfig.Update{ Value: &openconfig.Value{ Value: []byte(tcase.input), }, }) if d := test.Diff(tcase.expected, actual); d != "" { t.Errorf("#%d: %s: %#v vs %#v", i, d, tcase.expected, actual) } } }
func TestConfig(t *testing.T) { cfg, err := loadConfig("/nonexistent.json") if err == nil { t.Fatal("Managed to load a nonexistent config!") } cfg, err = loadConfig("sampleconfig.json") testcases := []struct { path string metric string tags map[string]string }{{ path: "/Sysdb/environment/cooling/status/fan/Fan1/1/speed/value", metric: "eos.environment.fan.speed", tags: map[string]string{"fan": "Fan1/1"}, }, { path: "/Sysdb/environment/power/status/powerSupply/PowerSupply2/outputPower/value", metric: "eos.environment.power.output", tags: map[string]string{"sensor": "PowerSupply2"}, }, { path: "/Sysdb/environment/power/status/voltageSensor/VoltageSensor23/voltage/value", metric: "eos.environment.voltage", tags: map[string]string{"sensor": "VoltageSensor23"}, }, { path: "/Sysdb/environment/power/status/currentSensor/CurrentSensorP2/1/current/value", metric: "eos.environment.current", tags: map[string]string{"sensor": "CurrentSensorP2/1"}, }, { path: "/Sysdb/environment/temperature/status/tempSensor/" + "TempSensorP2/1/maxTemperature/value", metric: "eos.environment.maxtemperature", tags: map[string]string{"sensor": "TempSensorP2/1"}, }, { path: "/Sysdb/interface/counter/eth/lag/intfCounterDir/" + "Port-Channel201/intfCounter/current/statistics/outUcastPkts", metric: "eos.interface.pkt", tags: map[string]string{"intf": "Port-Channel201", "direction": "out", "type": "Ucast"}, }, { path: "/Sysdb/interface/counter/eth/slice/phy/1/intfCounterDir/" + "Ethernet42/intfCounter/current/statistics/inUcastPkts", metric: "eos.interface.pkt", tags: map[string]string{"intf": "Ethernet42", "direction": "in", "type": "Ucast"}, }, { path: "/Sysdb/interface/counter/eth/slice/phy/1/intfCounterDir/" + "Ethernet42/intfCounter/lastClear/statistics/inErrors", }} for i, tcase := range testcases { actualMetric, actualTags := cfg.Match(tcase.path) if actualMetric != tcase.metric { t.Errorf("#%d expected metric %q but got %q", i, tcase.metric, actualMetric) } if d := test.Diff(tcase.tags, actualTags); actualMetric != "" && d != "" { t.Errorf("#%d expected tags %q but got %q: %s", i, tcase.tags, actualTags, d) } } }
func TestJsonify(t *testing.T) { var tests = []struct { notification *pb.Notification document map[string]interface{} }{{ notification: &pb.Notification{ Prefix: &pb.Path{Element: []string{"Sysdb", "a"}}, Update: []*pb.Update{ { Path: &pb.Path{Element: []string{"b"}}, Value: &pb.Value{ Value: []byte{52, 50}, Type: pb.Type_JSON, }, }, }, }, document: map[string]interface{}{ "timestamp": int64(0), "dataset": "foo", "update": map[string]interface{}{ "Sysdb": map[string]interface{}{ "a": map[string]interface{}{ "b": 42, }, }, }, }, }, } for _, jsonTest := range tests { expected, err := json.Marshal(jsonTest.document) if err != nil { t.Fatal(err) } actual, err := openconfig.NotificationToJSONDocument("foo", jsonTest.notification, nil) if err != nil { t.Error(err) } diff := test.Diff(actual, expected) if len(diff) > 0 { t.Errorf("Unexpected diff: %s", diff) } } }
func TestVisitPrefix(t *testing.T) { m := New() m.Set([]string{}, 0) m.Set([]string{"foo"}, 1) m.Set([]string{"foo", "bar"}, 2) m.Set([]string{"foo", "bar", "baz"}, 3) m.Set([]string{"foo", "bar", "baz", "quux"}, 4) m.Set([]string{"quux", "bar"}, 5) m.Set([]string{"foo", "quux"}, 6) m.Set([]string{"*"}, 7) m.Set([]string{"foo", "*"}, 8) m.Set([]string{"*", "bar"}, 9) m.Set([]string{"*", "quux"}, 10) m.Set([]string{"quux", "quux", "quux", "quux"}, 11) testCases := []struct { path []string expected map[int]int }{{ path: []string{"foo", "bar", "baz"}, expected: map[int]int{0: 1, 1: 1, 2: 1, 3: 1, 7: 1, 8: 1, 9: 1}, }, { path: []string{"zip", "zap"}, expected: map[int]int{0: 1, 7: 1}, }, { path: []string{"foo", "zap"}, expected: map[int]int{0: 1, 1: 1, 8: 1, 7: 1}, }, { path: []string{"quux", "quux", "quux"}, expected: map[int]int{0: 1, 7: 1, 10: 1}, }} for _, tc := range testCases { result := make(map[int]int, len(tc.expected)) m.VisitPrefix(tc.path, accumulator(result)) if diff := test.Diff(tc.expected, result); diff != "" { t.Errorf("Test case %v: %s", tc.path, diff) } } }
func TestDelete(t *testing.T) { m := New() m.Set([]string{}, 0) m.Set([]string{"*"}, 1) m.Set([]string{"foo", "bar"}, 2) m.Set([]string{"foo", "*"}, 3) n := countNodes(m.(*node)) if n != 5 { t.Errorf("Initial count wrong. Expected: 5, Got: %d", n) } testCases := []struct { del []string // Path to delete expected bool // expected return value of Delete visit []string // Path to Visit before map[int]int // Expected to find items before deletion after map[int]int // Expected to find items after deletion count int // Count of nodes }{{ del: []string{"zap"}, // A no-op Delete expected: false, visit: []string{"foo", "bar"}, before: map[int]int{2: 1, 3: 1}, after: map[int]int{2: 1, 3: 1}, count: 5, }, { del: []string{"foo", "bar"}, expected: true, visit: []string{"foo", "bar"}, before: map[int]int{2: 1, 3: 1}, after: map[int]int{3: 1}, count: 4, }, { del: []string{"*"}, expected: true, visit: []string{"foo"}, before: map[int]int{1: 1}, after: map[int]int{}, count: 3, }, { del: []string{"*"}, expected: false, visit: []string{"foo"}, before: map[int]int{}, after: map[int]int{}, count: 3, }, { del: []string{"foo", "*"}, expected: true, visit: []string{"foo", "bar"}, before: map[int]int{3: 1}, after: map[int]int{}, count: 1, // Should have deleted "foo" and "bar" nodes }, { del: []string{}, expected: true, visit: []string{}, before: map[int]int{0: 1}, after: map[int]int{}, count: 1, // Root node can't be deleted }} for i, tc := range testCases { beforeResult := make(map[int]int, len(tc.before)) m.Visit(tc.visit, accumulator(beforeResult)) if diff := test.Diff(tc.before, beforeResult); diff != "" { t.Errorf("Test case %d (%v): %s", i, tc.del, diff) } if got := m.Delete(tc.del); got != tc.expected { t.Errorf("Test case %d (%v): Unexpected return. Expected %t, Got: %t", i, tc.del, tc.expected, got) } afterResult := make(map[int]int, len(tc.after)) m.Visit(tc.visit, accumulator(afterResult)) if diff := test.Diff(tc.after, afterResult); diff != "" { t.Errorf("Test case %d (%v): %s", i, tc.del, diff) } } }
func TestNotificationToMap(t *testing.T) { value := map[string]interface{}{ "239.255.255.250_0.0.0.0": map[string]interface{}{ "creationTime": 4.567969230573434e+06, }, } valueJSON, err := json.Marshal(value) if err != nil { t.Fatal(err) } tests := []struct { notification openconfig.Notification json map[string]interface{} }{{ notification: openconfig.Notification{ Prefix: &openconfig.Path{ Element: []string{ "foo", }, }, Update: []*openconfig.Update{ { Path: &openconfig.Path{ Element: []string{ "route1", }, }, Value: &openconfig.Value{ Value: valueJSON, }, }, { Path: &openconfig.Path{ Element: []string{ "route2", }, }, Value: &openconfig.Value{ Value: valueJSON, }, }}, }, json: map[string]interface{}{ "timestamp": int64(0), "dataset": "cairo", "update": map[string]interface{}{ "foo": map[string]interface{}{ "route1": map[string]interface{}{ "239.255.255.250_0.0.0.0": map[string]interface{}{ "creationTime": 4.567969230573434e+06, }, }, "route2": map[string]interface{}{ "239.255.255.250_0.0.0.0": map[string]interface{}{ "creationTime": 4.567969230573434e+06, }, }, }, }, }, }, { notification: openconfig.Notification{ Prefix: &openconfig.Path{ Element: []string{ "foo", "bar", }, }, Delete: []*openconfig.Path{ &openconfig.Path{ Element: []string{ "route", "237.255.255.250_0.0.0.0", }}, &openconfig.Path{ Element: []string{ "route", "238.255.255.250_0.0.0.0", }, }, }, Update: []*openconfig.Update{{ Path: &openconfig.Path{ Element: []string{ "route", }, }, Value: &openconfig.Value{ Value: valueJSON, }, }}, }, json: map[string]interface{}{ "timestamp": int64(0), "dataset": "cairo", "delete": map[string]interface{}{ "foo": map[string]interface{}{ "bar": map[string]interface{}{ "route": map[string]interface{}{ "237.255.255.250_0.0.0.0": map[string]interface{}{}, "238.255.255.250_0.0.0.0": map[string]interface{}{}, }, }, }, }, "update": map[string]interface{}{ "foo": map[string]interface{}{ "bar": map[string]interface{}{ "route": map[string]interface{}{ "239.255.255.250_0.0.0.0": map[string]interface{}{ "creationTime": 4.567969230573434e+06, }, }, }, }, }, }, }} for _, tcase := range tests { actual, err := NotificationToMap("cairo", &tcase.notification, nil) if err != nil { t.Fatal(err) } diff := test.Diff(tcase.json, actual) if len(diff) > 0 { expectedJSON, _ := json.Marshal(tcase.json) actualJSON, _ := json.Marshal(actual) t.Fatalf("Unexpected diff: %s\nExpected:\n%s\nGot:\n%s\n)", diff, expectedJSON, actualJSON) } } }