Lots of progress made on the decoding side, we can parse a single line in to several types. Left to do: Encoding, better errors, and formally define valid attribute characters.

This commit is contained in:
David Arroyo
2013-07-14 11:27:12 -04:00
parent 751b403e15
commit a19bd721cd
7 changed files with 665 additions and 281 deletions

223
read_test.go Normal file
View File

@@ -0,0 +1,223 @@
package ndb
import (
"testing"
"fmt"
)
type screenCfg struct {
Title string
Width, Height uint16
R,G,B,A uint16
}
type netCfg struct {
Host string `ndb:"hostname"`
Vlan []int `ndb:"vlan"`
Native int `ndb:"nativevlan"`
}
var multiMap = []struct {
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"},
},
},
}
var advancedTests = []struct {
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,
},
},
}
var structTests = []struct {
in string
out screenCfg
}{
{
in: "Title='Hollywood movie' Width=640 Height=400 A=8",
out: screenCfg {
Title: "Hollywood movie",
Width: 640,
Height: 400,
A: 8,
},
},
}
var mapTests = []struct {
in string
out map[string] string
}{
{
in: "ipnet=murrayhill 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",
},
},
}
func TestStruct(t *testing.T) {
var cfg screenCfg
for _,tt := range structTests {
if err := Parse([]byte(tt.in), &cfg); err != nil {
t.Error(err)
} else if cfg != tt.out {
t.Errorf("Got %v, wanted %v", cfg, tt.out)
}
t.Logf("%s == %v", tt.in, cfg)
}
}
func TestMap(t *testing.T) {
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)
}
t.Logf("%s == %v", tt.in, net)
}
}
func TestAdvanced(t *testing.T) {
var net netCfg
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) {
t.Errorf("Got %v, wanted %v", net, tt.out)
}
t.Logf("%s == %v", tt.in, net)
}
}
func TestMultiMap(t *testing.T) {
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) {
t.Errorf("Got %v, wanted %v", m, tt.out)
}
t.Logf("%s == %v", tt.in, m)
}
}
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
out []pair
}{
{
in: []byte("key1=val1 key2=val2 key3=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")}},
},
{
in: []byte("title='Dave''s pasta' sq=Davis cost=$$"),
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")}},
},
{
in: []byte("action=reload key='' mod=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")}},
},
{
in: []byte("esc='Use '''' to escape a '''"),
out: []pair {
{[]byte("esc"),[]byte("Use '' to escape a '")}},
},
}
func Test_parsing(t *testing.T) {
for i,tt := range parseTests {
d := NewDecoder(bytes.NewReader(tt.in))
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)
t.FailNow()
}
}
}
}
}
func match(p1, p2 pair) bool {
return (bytes.Compare(p1.attr, p2.attr) == 0) && (bytes.Compare(p1.val, p2.val) == 0)
}