Feature complete. I may change the names, and error-handling needs to be more robust. I feel pretty good about resisting bad input, but not so good about saving to or writing from complex data structures, or maps with interface{} elements.
This commit is contained in:
182
read_test.go
182
read_test.go
@@ -1,72 +1,73 @@
|
||||
package ndb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type screenCfg struct {
|
||||
Title string
|
||||
Title string
|
||||
Width, Height uint16
|
||||
R,G,B,A uint16
|
||||
R, G, B, A uint16
|
||||
}
|
||||
|
||||
type netCfg struct {
|
||||
Host string `ndb:"hostname"`
|
||||
Vlan []int `ndb:"vlan"`
|
||||
Native int `ndb:"nativevlan"`
|
||||
Host string `ndb:"host-name"`
|
||||
Vlan []int `ndb:"vlan"`
|
||||
Native int `ndb:"native-vlan"`
|
||||
}
|
||||
|
||||
var multiMap = []struct {
|
||||
in string
|
||||
out map[string] []string
|
||||
in string
|
||||
out map[string][]string
|
||||
}{
|
||||
{
|
||||
{
|
||||
in: "user=clive user=david user=trenton group=dirty-dozen",
|
||||
out: map[string] []string {
|
||||
"user": []string {"clive", "david", "trenton"},
|
||||
"group": []string {"dirty-dozen"},
|
||||
out: map[string][]string{
|
||||
"user": []string{"clive", "david", "trenton"},
|
||||
"group": []string{"dirty-dozen"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
var advancedTests = []struct {
|
||||
in string
|
||||
in string
|
||||
out netCfg
|
||||
}{
|
||||
{ in: "hostname=p2-jbs537 vlan=66 vlan=35 nativevlan=218",
|
||||
out: netCfg {
|
||||
Host: "p2-jbs537",
|
||||
Vlan: []int {66, 35},
|
||||
Native: 218,
|
||||
},
|
||||
{in: "host-name=p2-jbs537 vlan=66 vlan=35 native-vlan=218",
|
||||
out: netCfg{
|
||||
Host: "p2-jbs537",
|
||||
Vlan: []int{66, 35},
|
||||
Native: 218,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var structTests = []struct {
|
||||
in string
|
||||
in string
|
||||
out screenCfg
|
||||
}{
|
||||
{
|
||||
in: "Title='Hollywood movie' Width=640 Height=400 A=8",
|
||||
out: screenCfg {
|
||||
Title: "Hollywood movie",
|
||||
Width: 640,
|
||||
out: screenCfg{
|
||||
Title: "Hollywood movie",
|
||||
Width: 640,
|
||||
Height: 400,
|
||||
A: 8,
|
||||
A: 8,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var mapTests = []struct {
|
||||
in string
|
||||
out map[string] string
|
||||
in string
|
||||
out map[string]string
|
||||
}{
|
||||
{
|
||||
in: "ipnet=murray–hill ip=135.104.0.0 ipmask=255.255.0.0",
|
||||
out: map[string] string {
|
||||
"ipnet": "murray-hill",
|
||||
"ip": "135.104.0.0",
|
||||
in: "ipnet=murray-hill ip=135.104.0.0 ipmask=255.255.0.0",
|
||||
out: map[string]string{
|
||||
"ipnet": "murray-hill",
|
||||
"ip": "135.104.0.0",
|
||||
"ipmask": "255.255.0.0",
|
||||
},
|
||||
},
|
||||
@@ -74,8 +75,8 @@ var mapTests = []struct {
|
||||
|
||||
func TestStruct(t *testing.T) {
|
||||
var cfg screenCfg
|
||||
|
||||
for _,tt := range structTests {
|
||||
|
||||
for _, tt := range structTests {
|
||||
if err := Parse([]byte(tt.in), &cfg); err != nil {
|
||||
t.Error(err)
|
||||
} else if cfg != tt.out {
|
||||
@@ -85,20 +86,34 @@ func TestStruct(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func TestMap(t *testing.T) {
|
||||
var net map[string] string
|
||||
for _,tt := range mapTests {
|
||||
var net map[string]string
|
||||
for _, tt := range mapTests {
|
||||
if err := Parse([]byte(tt.in), &net); err != nil {
|
||||
t.Error(err)
|
||||
} else if fmt.Sprint(net) != fmt.Sprint(tt.out) {
|
||||
t.Errorf("Got %v, wanted %v", net, tt.out)
|
||||
} else if !mapEquals(tt.out, net) {
|
||||
t.Errorf("Got `%v`, wanted `%v`", net, tt.out)
|
||||
}
|
||||
t.Logf("%s == %v", tt.in, net)
|
||||
}
|
||||
}
|
||||
|
||||
func mapEquals(m1, m2 map[string] string) bool {
|
||||
for k := range m1 {
|
||||
if m1[k] != m2[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for k := range m2 {
|
||||
if m1[k] != m2[k] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestAdvanced(t *testing.T) {
|
||||
var net netCfg
|
||||
for _,tt := range advancedTests {
|
||||
for _, tt := range advancedTests {
|
||||
if err := Parse([]byte(tt.in), &net); err != nil {
|
||||
t.Error(err)
|
||||
} else if fmt.Sprint(tt.out) != fmt.Sprint(net) {
|
||||
@@ -109,8 +124,8 @@ func TestAdvanced(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMultiMap(t *testing.T) {
|
||||
var m map[string] []string
|
||||
for _,tt := range multiMap {
|
||||
var m map[string][]string
|
||||
for _, tt := range multiMap {
|
||||
if err := Parse([]byte(tt.in), &m); err != nil {
|
||||
t.Error(err)
|
||||
} else if fmt.Sprint(tt.out) != fmt.Sprint(m) {
|
||||
@@ -120,97 +135,68 @@ func TestMultiMap(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func netEqual(t *testing.T, n1, n2 netCfg) bool {
|
||||
if len(n1.Vlan) != len(n2.Vlan) {
|
||||
return false
|
||||
}
|
||||
for i := range n1.Vlan {
|
||||
if n1.Vlan[i] != n2.Vlan[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return n1.Host == n2.Host && n1.Native == n2.Native
|
||||
}
|
||||
|
||||
func mapEqual(t *testing.T, m1, m2 map[string] string) bool {
|
||||
for k := range m1 {
|
||||
if m1[k] != m2[k] {
|
||||
t.Logf("%v != %v", m1[k], m2[k])
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
package ndb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
var parseTests = []struct {
|
||||
in []byte
|
||||
in []byte
|
||||
out []pair
|
||||
}{
|
||||
{
|
||||
in: []byte("key1=val1 key2=val2 key3=val3"),
|
||||
out: []pair {
|
||||
{[]byte("key1"),[]byte("val1")},
|
||||
{[]byte("key2"),[]byte("val2")},
|
||||
{[]byte("key3"),[]byte("val3")}},
|
||||
out: []pair{
|
||||
{[]byte("key1"), []byte("val1")},
|
||||
{[]byte("key2"), []byte("val2")},
|
||||
{[]byte("key3"), []byte("val3")}},
|
||||
},
|
||||
{
|
||||
in: []byte("title='Some value with spaces' width=340 height=200"),
|
||||
out: []pair {
|
||||
{[]byte("title"),[]byte("Some value with spaces")},
|
||||
{[]byte("width"),[]byte("340")},
|
||||
{[]byte("height"),[]byte("200")}},
|
||||
out: []pair{
|
||||
{[]byte("title"), []byte("Some value with spaces")},
|
||||
{[]byte("width"), []byte("340")},
|
||||
{[]byte("height"), []byte("200")}},
|
||||
},
|
||||
{
|
||||
in: []byte("title='Dave''s pasta' sq=Davis cost=$$"),
|
||||
out: []pair {
|
||||
{[]byte("title"),[]byte("Dave's pasta")},
|
||||
{[]byte("sq"),[]byte("Davis")},
|
||||
{[]byte("cost"),[]byte("$$")}},
|
||||
out: []pair{
|
||||
{[]byte("title"), []byte("Dave's pasta")},
|
||||
{[]byte("sq"), []byte("Davis")},
|
||||
{[]byte("cost"), []byte("$$")}},
|
||||
},
|
||||
{
|
||||
in: []byte("action=''bradley key=jay mod=ctrl+alt+shift"),
|
||||
out: []pair {
|
||||
{[]byte("action"),[]byte("'bradley")},
|
||||
{[]byte("key"),[]byte("jay")},
|
||||
{[]byte("mod"),[]byte("ctrl+alt+shift")}},
|
||||
out: []pair{
|
||||
{[]byte("action"), []byte("'bradley")},
|
||||
{[]byte("key"), []byte("jay")},
|
||||
{[]byte("mod"), []byte("ctrl+alt+shift")}},
|
||||
},
|
||||
{
|
||||
in: []byte("action=reload key='' mod=ctrl+alt+shift"),
|
||||
out: []pair {
|
||||
{[]byte("action"),[]byte("reload")},
|
||||
{[]byte("key"),[]byte("'")},
|
||||
{[]byte("mod"),[]byte("ctrl+alt+shift")}},
|
||||
out: []pair{
|
||||
{[]byte("action"), []byte("reload")},
|
||||
{[]byte("key"), []byte("'")},
|
||||
{[]byte("mod"), []byte("ctrl+alt+shift")}},
|
||||
},
|
||||
{
|
||||
in: []byte("s='spaces and '' quotes'"),
|
||||
out: []pair {
|
||||
{[]byte("s"),[]byte("spaces and ' quotes")}},
|
||||
out: []pair{
|
||||
{[]byte("s"), []byte("spaces and ' quotes")}},
|
||||
},
|
||||
{
|
||||
in: []byte("esc='Use '''' to escape a '''"),
|
||||
out: []pair {
|
||||
{[]byte("esc"),[]byte("Use '' to escape a '")}},
|
||||
out: []pair{
|
||||
{[]byte("esc"), []byte("Use '' to escape a '")}},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
func Test_parsing(t *testing.T) {
|
||||
for i,tt := range parseTests {
|
||||
for i, tt := range parseTests {
|
||||
d := NewDecoder(bytes.NewReader(tt.in))
|
||||
p,err := d.getPairs()
|
||||
p, err := d.getPairs()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
t.FailNow()
|
||||
} else {
|
||||
for j := range tt.out {
|
||||
if j > len(p) || !match(p[j],tt.out[j]) {
|
||||
t.Errorf("%d: getPairs %s => %v, want %v",i, tt.in, p, tt.out)
|
||||
if j > len(p) || !match(p[j], tt.out[j]) {
|
||||
t.Errorf("%d: getPairs %s => %v, want %v", i, tt.in, p, tt.out)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user