packer-cn/builder/vmware/common/driver_parser_test.go

859 lines
23 KiB
Go

package common
import (
"testing"
"bytes"
"encoding/hex"
"os"
"path/filepath"
)
func consumeString(s string) (out chan byte) {
out = make(chan byte)
go func() {
for _, ch := range s {
out <- byte(ch)
}
close(out)
}()
return
}
func uncommentFromString(s string) string {
inCh := consumeString(s)
out := uncomment(inCh)
result := ""
for reading := true; reading; {
if item, ok := <-out; !ok {
break
} else {
result += string(item)
}
}
return result
}
func TestParserUncomment(t *testing.T) {
var result string
test_0 := "this is a straight-up line"
result_0 := test_0
result = uncommentFromString(test_0)
if result != result_0 {
t.Errorf("Expected %#v, received %#v", result_0, result)
}
test_1 := "this is a straight-up line with a newline\n"
result_1 := test_1
result = uncommentFromString(test_1)
if result != result_1 {
t.Errorf("Expected %#v, received %#v", result_1, result)
}
test_2 := "this line has a comment # at its end"
result_2 := "this line has a comment "
result = uncommentFromString(test_2)
if result != result_2 {
t.Errorf("Expected %#v, received %#v", result_2, result)
}
test_3 := "# this whole line is commented"
result_3 := ""
result = uncommentFromString(test_3)
if result != result_3 {
t.Errorf("Expected %#v, received %#v", result_3, result)
}
test_4 := "this\nhas\nmultiple\nlines"
result_4 := test_4
result = uncommentFromString(test_4)
if result != result_4 {
t.Errorf("Expected %#v, received %#v", result_4, result)
}
test_5 := "this only has\n# one line"
result_5 := "this only has\n"
result = uncommentFromString(test_5)
if result != result_5 {
t.Errorf("Expected %#v, received %#v", result_5, result)
}
test_6 := "this is\npartially # commented"
result_6 := "this is\npartially "
result = uncommentFromString(test_6)
if result != result_6 {
t.Errorf("Expected %#v, received %#v", result_6, result)
}
test_7 := "this # has\nmultiple # lines\ncommented # out"
result_7 := "this \nmultiple \ncommented "
result = uncommentFromString(test_7)
if result != result_7 {
t.Errorf("Expected %#v, received %#v", result_7, result)
}
}
func tokenizeDhcpConfigFromString(s string) []string {
inCh := consumeString(s)
out := tokenizeDhcpConfig(inCh)
result := make([]string, 0)
for {
if item, ok := <-out; !ok {
break
} else {
result = append(result, item)
}
}
return result
}
func TestParserTokenizeDhcp(t *testing.T) {
test_1 := `
subnet 127.0.0.0 netmask 255.255.255.252 {
item 1234 5678;
tabbed item-1 1234;
quoted item-2 "hola mundo.";
}
`
expected := []string{
"subnet", "127.0.0.0", "netmask", "255.255.255.252", "{",
"item", "1234", "5678", ";",
"tabbed", "item-1", "1234", ";",
"quoted", "item-2", "\"hola mundo.\"", ";",
"}",
}
result := tokenizeDhcpConfigFromString(test_1)
t.Logf("testing for: %v", expected)
t.Logf("checking out: %v", result)
if len(result) != len(expected) {
t.Fatalf("length of token lists do not match (%d != %d)", len(result), len(expected))
}
for index := range expected {
if expected[index] != result[index] {
t.Errorf("unexpected token at index %d: %v != %v", index, expected[index], result[index])
}
}
}
func consumeTokens(tokes []string) chan string {
out := make(chan string)
go func() {
for _, item := range tokes {
out <- item
}
out <- ";"
close(out)
}()
return out
}
func TestParserDhcpParameters(t *testing.T) {
var ch chan string
test_1 := []string{"option", "whee", "whooo"}
ch = consumeTokens(test_1)
result := parseTokenParameter(ch)
if result.name != "option" {
t.Errorf("expected name %s, got %s", test_1[0], result.name)
}
if len(result.operand) == 2 {
if result.operand[0] != "whee" {
t.Errorf("expected operand[%d] as %s, got %s", 0, "whee", result.operand[0])
}
if result.operand[1] != "whooo" {
t.Errorf("expected operand[%d] as %s, got %s", 0, "whooo", result.operand[1])
}
} else {
t.Errorf("expected %d operands, got %d", 2, len(result.operand))
}
test_2 := []string{"whaaa", "whoaaa", ";", "wooops"}
ch = consumeTokens(test_2)
result = parseTokenParameter(ch)
if result.name != "whaaa" {
t.Errorf("expected name %s, got %s", test_2[0], result.name)
}
if len(result.operand) == 1 {
if result.operand[0] != "whoaaa" {
t.Errorf("expected operand[%d] as %s, got %s", 0, "whoaaa", result.operand[0])
}
} else {
t.Errorf("expected %d operands, got %d", 1, len(result.operand))
}
test_3 := []string{"optionz", "only", "{", "culled"}
ch = consumeTokens(test_3)
result = parseTokenParameter(ch)
if result.name != "optionz" {
t.Errorf("expected name %s, got %s", test_3[0], result.name)
}
if len(result.operand) == 1 {
if result.operand[0] != "only" {
t.Errorf("expected operand[%d] as %s, got %s", 0, "only", result.operand[0])
}
} else {
t.Errorf("expected %d operands, got %d", 1, len(result.operand))
}
}
func consumeDhcpConfig(items []string) (tkGroup, error) {
out := make(chan string)
tch := consumeTokens(items)
go func() {
for item := range tch {
out <- item
}
close(out)
}()
return parseDhcpConfig(out)
}
func compareSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestParserDhcpConfigParse(t *testing.T) {
test_1 := []string{
"allow", "unused-option", ";",
"lease-option", "1234", ";",
"more", "options", "hi", ";",
}
result_1, err := consumeDhcpConfig(test_1)
if err != nil {
t.Fatalf("%s", err)
}
if len(result_1.params) != 4 {
t.Fatalf("expected %d params, got %d", 3, len(result_1.params))
}
if result_1.params[0].name != "allow" {
t.Errorf("expected %s, got %s", "allow", result_1.params[0].name)
}
if !compareSlice(result_1.params[0].operand, []string{"unused-option"}) {
t.Errorf("unexpected options parsed: %v", result_1.params[0].operand)
}
if result_1.params[1].name != "lease-option" {
t.Errorf("expected %s, got %s", "lease-option", result_1.params[1].name)
}
if !compareSlice(result_1.params[1].operand, []string{"1234"}) {
t.Errorf("unexpected options parsed: %v", result_1.params[1].operand)
}
if result_1.params[2].name != "more" {
t.Errorf("expected %s, got %s", "lease-option", result_1.params[2].name)
}
if !compareSlice(result_1.params[2].operand, []string{"options", "hi"}) {
t.Errorf("unexpected options parsed: %v", result_1.params[2].operand)
}
test_2 := []string{
"first-option", ";",
"child", "group", "{",
"blah", ";",
"meh", ";",
"}",
"hidden", "option", "57005", ";",
"host", "device", "two", "{",
"skipped", "option", ";",
"more", "skipped", "options", ";",
"}",
"last", "option", "but", "unterminated",
}
result_2, err := consumeDhcpConfig(test_2)
if err != nil {
t.Fatalf("%s", err)
}
if len(result_2.groups) != 2 {
t.Fatalf("expected %d groups, got %d", 2, len(result_2.groups))
}
if len(result_2.params) != 3 {
t.Errorf("expected %d options, got %d", 3, len(result_2.params))
}
group0 := result_2.groups[0]
if group0.id.name != "child" {
t.Errorf("expected group %s, got %s", "child", group0.id.name)
}
if len(group0.id.operand) != 1 {
t.Errorf("expected group operand %d, got %d", 1, len(group0.params))
}
if len(group0.params) != 2 {
t.Errorf("expected group params %d, got %d", 2, len(group0.params))
}
group1 := result_2.groups[1]
if group1.id.name != "host" {
t.Errorf("expected group %s, got %s", "host", group1.id.name)
}
if len(group1.id.operand) != 2 {
t.Errorf("expected group operand %d, got %d", 2, len(group1.params))
}
if len(group1.params) != 2 {
t.Errorf("expected group params %d, got %d", 2, len(group1.params))
}
}
func TestParserReadDhcpConfig(t *testing.T) {
expected := []string{
`{global}
grants : map[unknown-clients:0]
parameters : map[default-lease-time:1800 max-lease-time:7200]
`,
`{subnet4 172.33.33.0/24},{global}
address : range4:172.33.33.128-172.33.33.254
options : map[broadcast-address:172.33.33.255 routers:172.33.33.2]
grants : map[unknown-clients:0]
parameters : map[default-lease-time:2400 max-lease-time:9600]
`,
`{host name:vmnet8},{global}
address : hardware-address:ethernet[00:50:56:c0:00:08],fixed-address4:172.33.33.1
options : map[domain-name:"packer.test"]
grants : map[unknown-clients:0]
parameters : map[default-lease-time:1800 max-lease-time:7200]
`,
}
f, err := os.Open(filepath.Join("testdata", "dhcpd-example.conf"))
if err != nil {
t.Fatalf("Unable to open dhcpd.conf sample: %s", err)
}
defer f.Close()
config, err := ReadDhcpConfiguration(f)
if err != nil {
t.Fatalf("Unable to read dhcpd.conf samplpe: %s", err)
}
if len(config) != 3 {
t.Fatalf("expected %d entries, got %d", 3, len(config))
}
for index, item := range config {
if item.repr() != expected[index] {
t.Errorf("Parsing of declaration %d did not match what was expected", index)
t.Logf("Result from parsing:\n%s", item.repr())
t.Logf("Expected to parse:\n%s", expected[index])
}
}
}
func TestParserTokenizeNetworkMap(t *testing.T) {
test_1 := "group.attribute = \"string\""
expected := []string{
"group.attribute", "=", "\"string\"",
}
result := tokenizeDhcpConfigFromString(test_1)
if len(result) != len(expected) {
t.Fatalf("length of token lists do not match (%d != %d)", len(result), len(expected))
}
for index := range expected {
if expected[index] != result[index] {
t.Errorf("unexpected token at index %d: %v != %v", index, expected[index], result[index])
}
}
test_2 := "attribute == \""
expected = []string{
"attribute", "==", "\"",
}
result = tokenizeDhcpConfigFromString(test_2)
if len(result) != len(expected) {
t.Fatalf("length of token lists do not match (%d != %d)", len(result), len(expected))
}
test_3 := "attribute ....... ======\nnew lines should make no difference"
expected = []string{
"attribute", ".......", "======", "new", "lines", "should", "make", "no", "difference",
}
result = tokenizeDhcpConfigFromString(test_3)
if len(result) != len(expected) {
t.Fatalf("length of token lists do not match (%d != %d)", len(result), len(expected))
}
test_4 := "\t\t\t\t thishadwhitespacebeforebeingparsed\t \t \t \t\n\n"
expected = []string{
"thishadwhitespacebeforebeingparsed",
}
result = tokenizeDhcpConfigFromString(test_4)
if len(result) != len(expected) {
t.Fatalf("length of token lists do not match (%d != %d)", len(result), len(expected))
}
}
func TestParserReadNetworkMap(t *testing.T) {
f, err := os.Open(filepath.Join("testdata", "netmap-example.conf"))
if err != nil {
t.Fatalf("Unable to open netmap.conf sample: %s", err)
}
defer f.Close()
netmap, err := ReadNetworkMap(f)
if err != nil {
t.Fatalf("Unable to read netmap.conf samplpe: %s", err)
}
expected_keys := []string{"device", "name"}
for _, item := range netmap {
for _, name := range expected_keys {
_, ok := item[name]
if !ok {
t.Errorf("unable to find expected key %v in map: %v", name, item)
}
}
}
expected_vmnet0 := [][]string{
[]string{"device", "vmnet0"},
[]string{"name", "Bridged"},
}
for _, item := range netmap {
if item["device"] != "vmnet0" {
continue
}
for _, expectpair := range expected_vmnet0 {
name := expectpair[0]
value := expectpair[1]
if item[name] != value {
t.Errorf("expected value %v for attribute %v, got %v", value, name, item[name])
}
}
}
expected_vmnet1 := [][]string{
[]string{"device", "vmnet1"},
[]string{"name", "HostOnly"},
}
for _, item := range netmap {
if item["device"] != "vmnet1" {
continue
}
for _, expectpair := range expected_vmnet1 {
name := expectpair[0]
value := expectpair[1]
if item[name] != value {
t.Errorf("expected value %v for attribute %v, got %v", value, name, item[name])
}
}
}
expected_vmnet8 := [][]string{
[]string{"device", "vmnet8"},
[]string{"name", "NAT"},
}
for _, item := range netmap {
if item["device"] != "vmnet8" {
continue
}
for _, expectpair := range expected_vmnet8 {
name := expectpair[0]
value := expectpair[1]
if item[name] != value {
t.Errorf("expected value %v for attribute %v, got %v", value, name, item[name])
}
}
}
}
func collectIntoString(in chan byte) string {
result := ""
for item := range in {
result += string(item)
}
return result
}
func TestParserConsumeUntilSentinel(t *testing.T) {
test_1 := "consume until a semicolon; yeh?"
expected_1 := "consume until a semicolon"
ch := consumeString(test_1)
resultch, _ := consumeUntilSentinel(';', ch)
result := string(resultch)
if expected_1 != result {
t.Errorf("expected %#v, got %#v", expected_1, result)
}
test_2 := "; this is only a semi"
expected_2 := ""
ch = consumeString(test_2)
resultch, _ = consumeUntilSentinel(';', ch)
result = string(resultch)
if expected_2 != result {
t.Errorf("expected %#v, got %#v", expected_2, result)
}
}
func TestParserFilterCharacters(t *testing.T) {
test_1 := []string{" ", "ignore all spaces"}
expected_1 := "ignoreallspaces"
ch := consumeString(test_1[1])
outch := filterOutCharacters(bytes.NewBufferString(test_1[0]).Bytes(), ch)
result := collectIntoString(outch)
if result != expected_1 {
t.Errorf("expected %#v, got %#v", expected_1, result)
}
test_2 := []string{"\n\v\t\r ", "ignore\nall\rwhite\v\v space "}
expected_2 := "ignoreallwhitespace"
ch = consumeString(test_2[1])
outch = filterOutCharacters(bytes.NewBufferString(test_2[0]).Bytes(), ch)
result = collectIntoString(outch)
if result != expected_2 {
t.Errorf("expected %#v, got %#v", expected_2, result)
}
}
func TestParserConsumeOpenClosePair(t *testing.T) {
test_1 := "(everything)"
expected_1 := []string{"", test_1}
testch := consumeString(test_1)
prefix, ch := consumeOpenClosePair('(', ')', testch)
if string(prefix) != expected_1[0] {
t.Errorf("expected prefix %#v, got %#v", expected_1[0], prefix)
}
result := collectIntoString(ch)
if result != expected_1[1] {
t.Errorf("expected %#v, got %#v", expected_1[1], test_1)
}
test_2 := "prefixed (everything)"
expected_2 := []string{"prefixed ", "(everything)"}
testch = consumeString(test_2)
prefix, ch = consumeOpenClosePair('(', ')', testch)
if string(prefix) != expected_2[0] {
t.Errorf("expected prefix %#v, got %#v", expected_2[0], prefix)
}
result = collectIntoString(ch)
if result != expected_2[1] {
t.Errorf("expected %#v, got %#v", expected_2[1], test_2)
}
test_3 := "this(is()suffixed"
expected_3 := []string{"this", "(is()"}
testch = consumeString(test_3)
prefix, ch = consumeOpenClosePair('(', ')', testch)
if string(prefix) != expected_3[0] {
t.Errorf("expected prefix %#v, got %#v", expected_3[0], prefix)
}
result = collectIntoString(ch)
if result != expected_3[1] {
t.Errorf("expected %#v, got %#v", expected_3[1], test_2)
}
}
func TestParserCombinators(t *testing.T) {
test_1 := "across # ignore\nmultiple lines;"
expected_1 := "across multiple lines"
ch := consumeString(test_1)
inch := uncomment(ch)
whch := filterOutCharacters([]byte{'\n'}, inch)
resultch, _ := consumeUntilSentinel(';', whch)
result := string(resultch)
if expected_1 != result {
t.Errorf("expected %#v, got %#v", expected_1, result)
}
test_2 := "lease blah {\n blah\r\n# skipping this line\nblahblah # ignore semicolon;\n last item;\n\n };;;;;;"
expected_2 := []string{"lease blah ", "{ blahblahblah last item; }"}
ch = consumeString(test_2)
inch = uncomment(ch)
whch = filterOutCharacters([]byte{'\n', '\v', '\r'}, inch)
prefix, pairch := consumeOpenClosePair('{', '}', whch)
result = collectIntoString(pairch)
if string(prefix) != expected_2[0] {
t.Errorf("expected prefix %#v, got %#v", expected_2[0], prefix)
}
if result != expected_2[1] {
t.Errorf("expected %#v, got %#v", expected_2[1], result)
}
test_3 := "lease blah { # comment\n item 1;\n item 2;\n } not imortant"
expected_3_prefix := "lease blah "
expected_3 := []string{"{ item 1", " item 2", " }"}
sch := consumeString(test_3)
inch = uncomment(sch)
wch := filterOutCharacters([]byte{'\n', '\v', '\r'}, inch)
lease, itemch := consumeOpenClosePair('{', '}', wch)
if string(lease) != expected_3_prefix {
t.Errorf("expected %#v, got %#v", expected_3_prefix, string(lease))
}
result_3 := []string{}
for reading := true; reading; {
item, ok := consumeUntilSentinel(';', itemch)
result_3 = append(result_3, string(item))
if !ok {
reading = false
}
}
for index := range expected_3 {
if expected_3[index] != result_3[index] {
t.Errorf("expected index %d as %#v, got %#v", index, expected_3[index], result_3[index])
}
}
}
func TestParserDhcpdLeaseBytesDecoder(t *testing.T) {
test_1 := "00:0d:0e:0a:0d:00"
expected_1 := []byte{0, 13, 14, 10, 13, 0}
result, err := decodeDhcpdLeaseBytes(test_1)
if err != nil {
t.Errorf("unable to decode address: %s", err)
}
if !bytes.Equal(result, expected_1) {
t.Errorf("expected %v, got %v", expected_1, result)
}
test_2 := "11"
expected_2 := []byte{17}
result, err = decodeDhcpdLeaseBytes(test_2)
if err != nil {
t.Errorf("unable to decode address: %s", err)
}
if !bytes.Equal(result, expected_2) {
t.Errorf("expected %v, got %v", expected_2, result)
}
failtest_1 := ""
_, err = decodeDhcpdLeaseBytes(failtest_1)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_2 := "000000"
_, err = decodeDhcpdLeaseBytes(failtest_2)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_3 := "000:00"
_, err = decodeDhcpdLeaseBytes(failtest_3)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_4 := "00:00:"
_, err = decodeDhcpdLeaseBytes(failtest_4)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
}
func consumeLeaseString(s string) chan byte {
sch := consumeString(s)
uncommentedch := uncomment(sch)
return filterOutCharacters([]byte{'\n', '\r', '\v'}, uncommentedch)
}
func TestParserReadDhcpdLeaseEntry(t *testing.T) {
test_1 := "lease 127.0.0.1 {\nhardware ethernet 00:11:22:33 ;\nuid 00:11 ;\n }"
expected_1 := map[string]string{
"address": "127.0.0.1",
"ether": "00112233",
"uid": "0011",
}
result, err := readDhcpdLeaseEntry(consumeLeaseString(test_1))
if err != nil {
t.Errorf("error parsing entry: %v", err)
}
if result.address != expected_1["address"] {
t.Errorf("expected address %v, got %v", expected_1["address"], result.address)
}
if hex.EncodeToString(result.ether) != expected_1["ether"] {
t.Errorf("expected ether %v, got %v", expected_1["ether"], hex.EncodeToString(result.ether))
}
if hex.EncodeToString(result.uid) != expected_1["uid"] {
t.Errorf("expected uid %v, got %v", expected_1["uid"], hex.EncodeToString(result.uid))
}
test_2 := " \n\t lease 192.168.21.254{ hardware\n ethernet 44:55:66:77:88:99;uid 00:1\n1:22:3\r3:44;\n starts 57005 2006/01/02 15:04:05;ends 57005 2006/01/03 15:04:05;\tunknown item1; unknown item2; } "
expected_2 := map[string]string{
"address": "192.168.21.254",
"ether": "445566778899",
"uid": "0011223344",
"starts": "2006-01-02 15:04:05 +0000 UTC",
"ends": "2006-01-03 15:04:05 +0000 UTC",
}
result, err = readDhcpdLeaseEntry(consumeLeaseString(test_2))
if err != nil {
t.Errorf("error parsing entry: %v", err)
}
if result.address != expected_2["address"] {
t.Errorf("expected address %v, got %v", expected_2["address"], result.address)
}
if hex.EncodeToString(result.ether) != expected_2["ether"] {
t.Errorf("expected ether %v, got %v", expected_2["ether"], hex.EncodeToString(result.ether))
}
if hex.EncodeToString(result.uid) != expected_2["uid"] {
t.Errorf("expected uid %v, got %v", expected_2["uid"], hex.EncodeToString(result.uid))
}
if result.starts.String() != expected_2["starts"] {
t.Errorf("expected starts %v, got %v", expected_2["starts"], result.starts)
}
if result.ends.String() != expected_2["ends"] {
t.Errorf("expected ends %v, got %v", expected_2["ends"], result.ends)
}
if result.starts_weekday != 57005 {
t.Errorf("expected starts weekday %v, got %v", 57005, result.starts_weekday)
}
if result.ends_weekday != 57005 {
t.Errorf("expected ends weekday %v, got %v", 57005, result.ends_weekday)
}
}
func TestParserReadDhcpdLeases(t *testing.T) {
f, err := os.Open(filepath.Join("testdata", "dhcpd-example.leases"))
if err != nil {
t.Fatalf("Unable to open dhcpd.leases sample: %s", err)
}
defer f.Close()
results, err := ReadDhcpdLeaseEntries(f)
if err != nil {
t.Fatalf("Error reading lease: %s", err)
}
// some simple utilities
filter_address := func(address string, items []dhcpLeaseEntry) (result []dhcpLeaseEntry) {
for _, item := range items {
if item.address == address {
result = append(result, item)
}
}
return
}
find_uid := func(uid string, items []dhcpLeaseEntry) *dhcpLeaseEntry {
for _, item := range items {
if uid == hex.EncodeToString(item.uid) {
return &item
}
}
return nil
}
find_ether := func(ether string, items []dhcpLeaseEntry) *dhcpLeaseEntry {
for _, item := range items {
if ether == hex.EncodeToString(item.ether) {
return &item
}
}
return nil
}
// actual unit tests
test_1 := map[string]string{
"address": "127.0.0.19",
"uid": "010dead099aabb",
"ether": "0dead099aabb",
}
test_1_findings := filter_address(test_1["address"], results)
if len(test_1_findings) != 2 {
t.Errorf("expected %d matching entries, got %d", 2, len(test_1_findings))
} else {
res := find_ether(test_1["ether"], test_1_findings)
if res == nil {
t.Errorf("unable to find item with ether %v", test_1["ether"])
} else if hex.EncodeToString(res.uid) != test_1["uid"] {
t.Errorf("expected uid %s, got %s", test_1["uid"], hex.EncodeToString(res.uid))
}
}
test_2 := map[string]string{
"address": "127.0.0.19",
"uid": "010dead0667788",
"ether": "0dead0667788",
}
test_2_findings := filter_address(test_2["address"], results)
if len(test_2_findings) != 2 {
t.Errorf("expected %d matching entries, got %d", 2, len(test_2_findings))
} else {
res := find_ether(test_2["ether"], test_2_findings)
if res == nil {
t.Errorf("unable to find item with ether %v", test_2["ether"])
} else if hex.EncodeToString(res.uid) != test_2["uid"] {
t.Errorf("expected uid %s, got %s", test_2["uid"], hex.EncodeToString(res.uid))
}
}
test_3 := map[string]string{
"address": "127.0.0.17",
"uid": "010dead0334455",
"ether": "0dead0667788",
}
test_3_findings := filter_address(test_3["address"], results)
if len(test_3_findings) != 2 {
t.Errorf("expected %d matching entries, got %d", 2, len(test_3_findings))
} else {
res := find_uid(test_3["uid"], test_3_findings)
if res == nil {
t.Errorf("unable to find item with uid %v", test_3["uid"])
} else if hex.EncodeToString(res.ether) != test_3["ether"] {
t.Errorf("expected ethernet hardware %s, got %s", test_3["ether"], hex.EncodeToString(res.ether))
}
}
test_4 := map[string]string{
"address": "127.0.0.17",
"uid": "010dead0001122",
"ether": "0dead0667788",
}
test_4_findings := filter_address(test_4["address"], results)
if len(test_4_findings) != 2 {
t.Errorf("expected %d matching entries, got %d", 2, len(test_4_findings))
} else {
res := find_uid(test_4["uid"], test_4_findings)
if res == nil {
t.Errorf("unable to find item with uid %v", test_4["uid"])
} else if hex.EncodeToString(res.ether) != test_4["ether"] {
t.Errorf("expected ethernet hardware %s, got %s", test_4["ether"], hex.EncodeToString(res.ether))
}
}
}