...
1
2
3
4 package tomltest
5
6 import (
7 "math"
8 "reflect"
9 )
10
11
12
13
14
15
16
17
18
19 func (r Test) CompareTOML(want, have interface{}) Test {
20 if isTomlValue(want) {
21 if !isTomlValue(have) {
22 return r.fail("Type for key '%s' differs:\n"+
23 " Expected: %[2]v (%[2]T)\n"+
24 " Your encoder: %[3]v (%[3]T)",
25 r.Key, want, have)
26 }
27
28 if !deepEqual(want, have) {
29 return r.fail("Values for key '%s' differ:\n"+
30 " Expected: %[2]v (%[2]T)\n"+
31 " Your encoder: %[3]v (%[3]T)",
32 r.Key, want, have)
33 }
34 return r
35 }
36
37 switch w := want.(type) {
38 case map[string]interface{}:
39 return r.cmpTOMLMap(w, have)
40 case []interface{}:
41 return r.cmpTOMLArrays(w, have)
42 default:
43 return r.fail("Unrecognized TOML structure: %T", want)
44 }
45 }
46
47 func (r Test) cmpTOMLMap(want map[string]interface{}, have interface{}) Test {
48 haveMap, ok := have.(map[string]interface{})
49 if !ok {
50 return r.mismatch("table", want, haveMap)
51 }
52
53
54 for k := range want {
55 if _, ok := haveMap[k]; !ok {
56 bunk := r.kjoin(k)
57 return bunk.fail("Could not find key '%s' in encoder output", bunk.Key)
58 }
59 }
60 for k := range haveMap {
61 if _, ok := want[k]; !ok {
62 bunk := r.kjoin(k)
63 return bunk.fail("Could not find key '%s' in expected output", bunk.Key)
64 }
65 }
66
67
68 for k := range want {
69 if sub := r.kjoin(k).CompareTOML(want[k], haveMap[k]); sub.Failed() {
70 return sub
71 }
72 }
73 return r
74 }
75
76 func (r Test) cmpTOMLArrays(want []interface{}, have interface{}) Test {
77
78
79
80
81 haveSlice, ok := have.([]interface{})
82 if !ok {
83 tblArray, ok := have.([]map[string]interface{})
84 if !ok {
85 return r.mismatch("array", want, have)
86 }
87
88 haveSlice = make([]interface{}, len(tblArray))
89 for i := range tblArray {
90 haveSlice[i] = tblArray[i]
91 }
92 }
93
94 if len(want) != len(haveSlice) {
95 return r.fail("Array lengths differ for key '%s'"+
96 " Expected: %[2]v (len=%[4]d)\n"+
97 " Your encoder: %[3]v (len=%[5]d)",
98 r.Key, want, haveSlice, len(want), len(haveSlice))
99 }
100 for i := 0; i < len(want); i++ {
101 if sub := r.CompareTOML(want[i], haveSlice[i]); sub.Failed() {
102 return sub
103 }
104 }
105 return r
106 }
107
108
109 func deepEqual(want, have interface{}) bool {
110 var wantF, haveF float64
111 switch f := want.(type) {
112 case float32:
113 wantF = float64(f)
114 case float64:
115 wantF = f
116 }
117 switch f := have.(type) {
118 case float32:
119 haveF = float64(f)
120 case float64:
121 haveF = f
122 }
123 if math.IsNaN(wantF) && math.IsNaN(haveF) {
124 return true
125 }
126
127 return reflect.DeepEqual(want, have)
128 }
129
130 func isTomlValue(v interface{}) bool {
131 switch v.(type) {
132 case map[string]interface{}, []interface{}:
133 return false
134 }
135 return true
136 }
137
View as plain text