1package main
2
3import (
4	"bytes"
5	"encoding/json"
6	"reflect"
7	"sort"
8	"testing"
9)
10
11func statementsFromStringSlice(strs []string) statements {
12	ss := make(statements, len(strs))
13	for i, str := range strs {
14		ss[i] = statementFromString(str)
15	}
16	return ss
17}
18
19func TestStatementsSimple(t *testing.T) {
20
21	j := []byte(`{
22		"dotted": "A dotted value",
23		"a quoted": "value",
24		"bool1": true,
25		"bool2": false,
26		"anull": null,
27		"anarr": [1, 1.5],
28		"anob": {
29			"foo": "bar"
30		},
31		"else": 1,
32		"id": 66912849,
33		"": 2
34	}`)
35
36	ss, err := statementsFromJSON(bytes.NewReader(j), statement{{"json", typBare}})
37
38	if err != nil {
39		t.Errorf("Want nil error from makeStatementsFromJSON() but got %s", err)
40	}
41
42	wants := statementsFromStringSlice([]string{
43		`json = {};`,
44		`json.dotted = "A dotted value";`,
45		`json["a quoted"] = "value";`,
46		`json.bool1 = true;`,
47		`json.bool2 = false;`,
48		`json.anull = null;`,
49		`json.anarr = [];`,
50		`json.anarr[0] = 1;`,
51		`json.anarr[1] = 1.5;`,
52		`json.anob = {};`,
53		`json.anob.foo = "bar";`,
54		`json["else"] = 1;`,
55		`json.id = 66912849;`,
56		`json[""] = 2;`,
57	})
58
59	t.Logf("Have: %#v", ss)
60	for _, want := range wants {
61		if !ss.Contains(want) {
62			t.Errorf("Statement group should contain `%s` but doesn't", want)
63		}
64	}
65
66}
67
68func TestStatementsSorting(t *testing.T) {
69	want := statementsFromStringSlice([]string{
70		`json.a = true;`,
71		`json.b = true;`,
72		`json.c[0] = true;`,
73		`json.c[2] = true;`,
74		`json.c[10] = true;`,
75		`json.c[11] = true;`,
76		`json.c[21][2] = true;`,
77		`json.c[21][11] = true;`,
78	})
79
80	have := statementsFromStringSlice([]string{
81		`json.c[11] = true;`,
82		`json.c[21][2] = true;`,
83		`json.c[0] = true;`,
84		`json.c[2] = true;`,
85		`json.b = true;`,
86		`json.c[10] = true;`,
87		`json.c[21][11] = true;`,
88		`json.a = true;`,
89	})
90
91	sort.Sort(have)
92
93	for i := range want {
94		if !reflect.DeepEqual(have[i], want[i]) {
95			t.Errorf("Statements sorted incorrectly; want `%s` at index %d, have `%s`", want[i], i, have[i])
96		}
97	}
98}
99
100func BenchmarkStatementsLess(b *testing.B) {
101	ss := statementsFromStringSlice([]string{
102		`json.c[21][2] = true;`,
103		`json.c[21][11] = true;`,
104	})
105
106	for i := 0; i < b.N; i++ {
107		_ = ss.Less(0, 1)
108	}
109}
110
111func BenchmarkFill(b *testing.B) {
112	j := []byte(`{
113		"dotted": "A dotted value",
114		"a quoted": "value",
115		"bool1": true,
116		"bool2": false,
117		"anull": null,
118		"anarr": [1, 1.5],
119		"anob": {
120			"foo": "bar"
121		},
122		"else": 1
123	}`)
124
125	var top interface{}
126	err := json.Unmarshal(j, &top)
127	if err != nil {
128		b.Fatalf("Failed to unmarshal test file: %s", err)
129	}
130
131	for i := 0; i < b.N; i++ {
132		ss := make(statements, 0)
133		ss.fill(statement{{"json", typBare}}, top)
134	}
135}
136
137func TestUngronStatementsSimple(t *testing.T) {
138	in := statementsFromStringSlice([]string{
139		`json.contact = {};`,
140		`json.contact["e-mail"][0] = "mail@tomnomnom.com";`,
141		`json.contact["e-mail"][1] = "test@tomnomnom.com";`,
142		`json.contact["e-mail"][3] = "foo@tomnomnom.com";`,
143		`json.contact.twitter = "@TomNomNom";`,
144	})
145
146	want := map[string]interface{}{
147		"json": map[string]interface{}{
148			"contact": map[string]interface{}{
149				"e-mail": []interface{}{
150					0: "mail@tomnomnom.com",
151					1: "test@tomnomnom.com",
152					3: "foo@tomnomnom.com",
153				},
154				"twitter": "@TomNomNom",
155			},
156		},
157	}
158
159	have, err := in.toInterface()
160
161	if err != nil {
162		t.Fatalf("want nil error but have: %s", err)
163	}
164
165	t.Logf("Have: %#v", have)
166	t.Logf("Want: %#v", want)
167
168	eq := reflect.DeepEqual(have, want)
169	if !eq {
170		t.Errorf("have and want are not equal")
171	}
172}
173
174func TestUngronStatementsInvalid(t *testing.T) {
175	cases := []statements{
176		statementsFromStringSlice([]string{``}),
177		statementsFromStringSlice([]string{`this isn't a statement at all`}),
178		statementsFromStringSlice([]string{`json[0] = 1;`, `json.bar = 1;`}),
179	}
180
181	for _, c := range cases {
182		_, err := c.toInterface()
183		if err == nil {
184			t.Errorf("want non-nil error; have nil")
185		}
186	}
187}
188
189func TestStatement(t *testing.T) {
190	s := statement{
191		token{"json", typBare},
192		token{".", typDot},
193		token{"foo", typBare},
194		token{"=", typEquals},
195		token{"2", typNumber},
196		token{";", typSemi},
197	}
198
199	have := s.String()
200	want := "json.foo = 2;"
201	if have != want {
202		t.Errorf("have: `%s` want: `%s`", have, want)
203	}
204}
205