1package zero
2
3import (
4	"encoding/json"
5	"testing"
6)
7
8var (
9	boolJSON     = []byte(`true`)
10	falseJSON    = []byte(`false`)
11	nullBoolJSON = []byte(`{"Bool":true,"Valid":true}`)
12)
13
14func TestBoolFrom(t *testing.T) {
15	b := BoolFrom(true)
16	assertBool(t, b, "BoolFrom()")
17
18	zero := BoolFrom(false)
19	if zero.Valid {
20		t.Error("BoolFrom(false)", "is valid, but should be invalid")
21	}
22}
23
24func TestBoolFromPtr(t *testing.T) {
25	v := true
26	bptr := &v
27	b := BoolFromPtr(bptr)
28	assertBool(t, b, "BoolFromPtr()")
29
30	null := BoolFromPtr(nil)
31	assertNullBool(t, null, "BoolFromPtr(nil)")
32}
33
34func TestUnmarshalBool(t *testing.T) {
35	var b Bool
36	err := json.Unmarshal(boolJSON, &b)
37	maybePanic(err)
38	assertBool(t, b, "float json")
39
40	var nb Bool
41	err = json.Unmarshal(nullBoolJSON, &nb)
42	maybePanic(err)
43	assertBool(t, nb, "sql.NullBool json")
44
45	var zero Bool
46	err = json.Unmarshal(falseJSON, &zero)
47	maybePanic(err)
48	assertNullBool(t, zero, "zero json")
49
50	var null Bool
51	err = json.Unmarshal(nullJSON, &null)
52	maybePanic(err)
53	assertNullBool(t, null, "null json")
54
55	var invalid Bool
56	err = invalid.UnmarshalJSON(invalidJSON)
57	if _, ok := err.(*json.SyntaxError); !ok {
58		t.Errorf("expected json.SyntaxError, not %T: %v", err, err)
59	}
60	assertNullBool(t, invalid, "invalid json")
61
62	var badType Bool
63	err = json.Unmarshal(intJSON, &badType)
64	if err == nil {
65		panic("err should not be nil")
66	}
67	assertNullBool(t, badType, "wrong type json")
68}
69
70func TestTextUnmarshalBool(t *testing.T) {
71	var b Bool
72	err := b.UnmarshalText(boolJSON)
73	maybePanic(err)
74	assertBool(t, b, "UnmarshalText() bool")
75
76	var zero Bool
77	err = zero.UnmarshalText(falseJSON)
78	maybePanic(err)
79	assertNullBool(t, zero, "UnmarshalText() zero bool")
80
81	var blank Bool
82	err = blank.UnmarshalText([]byte(""))
83	maybePanic(err)
84	assertNullBool(t, blank, "UnmarshalText() empty bool")
85
86	var null Bool
87	err = null.UnmarshalText(nullJSON)
88	maybePanic(err)
89	assertNullBool(t, null, `UnmarshalText() "null"`)
90
91	var invalid Bool
92	err = invalid.UnmarshalText(invalidJSON)
93	if err == nil {
94		panic("err should not be nil")
95	}
96}
97
98func TestMarshalBool(t *testing.T) {
99	b := BoolFrom(true)
100	data, err := json.Marshal(b)
101	maybePanic(err)
102	assertJSONEquals(t, data, "true", "non-empty json marshal")
103
104	// invalid values should be encoded as false
105	null := NewBool(false, false)
106	data, err = json.Marshal(null)
107	maybePanic(err)
108	assertJSONEquals(t, data, "false", "null json marshal")
109}
110
111func TestMarshalBoolText(t *testing.T) {
112	b := BoolFrom(true)
113	data, err := b.MarshalText()
114	maybePanic(err)
115	assertJSONEquals(t, data, "true", "non-empty text marshal")
116
117	// invalid values should be encoded as zero
118	null := NewBool(false, false)
119	data, err = null.MarshalText()
120	maybePanic(err)
121	assertJSONEquals(t, data, "false", "null text marshal")
122}
123
124func TestBoolPointer(t *testing.T) {
125	b := BoolFrom(true)
126	ptr := b.Ptr()
127	if *ptr != true {
128		t.Errorf("bad %s bool: %#v ≠ %v\n", "pointer", ptr, true)
129	}
130
131	null := NewBool(false, false)
132	ptr = null.Ptr()
133	if ptr != nil {
134		t.Errorf("bad %s bool: %#v ≠ %s\n", "nil pointer", ptr, "nil")
135	}
136}
137
138func TestBoolIsZero(t *testing.T) {
139	b := BoolFrom(true)
140	if b.IsZero() {
141		t.Errorf("IsZero() should be false")
142	}
143
144	null := NewBool(false, false)
145	if !null.IsZero() {
146		t.Errorf("IsZero() should be true")
147	}
148
149	zero := NewBool(false, true)
150	if !zero.IsZero() {
151		t.Errorf("IsZero() should be true")
152	}
153}
154
155func TestBoolSetValid(t *testing.T) {
156	change := NewBool(false, false)
157	assertNullBool(t, change, "SetValid()")
158	change.SetValid(true)
159	assertBool(t, change, "SetValid()")
160}
161
162func TestBoolScan(t *testing.T) {
163	var b Bool
164	err := b.Scan(true)
165	maybePanic(err)
166	assertBool(t, b, "scanned bool")
167
168	var null Bool
169	err = null.Scan(nil)
170	maybePanic(err)
171	assertNullBool(t, null, "scanned null")
172}
173
174func TestBoolValueOrZero(t *testing.T) {
175	valid := NewBool(true, true)
176	if valid.ValueOrZero() != true {
177		t.Error("unexpected ValueOrZero", valid.ValueOrZero())
178	}
179
180	invalid := NewBool(true, false)
181	if invalid.ValueOrZero() != false {
182		t.Error("unexpected ValueOrZero", invalid.ValueOrZero())
183	}
184}
185
186func TestBoolEqual(t *testing.T) {
187	b1 := NewBool(true, false)
188	b2 := NewBool(true, false)
189	assertBoolEqualIsTrue(t, b1, b2)
190
191	b1 = NewBool(true, false)
192	b2 = NewBool(false, false)
193	assertBoolEqualIsTrue(t, b1, b2)
194
195	b1 = NewBool(true, true)
196	b2 = NewBool(true, true)
197	assertBoolEqualIsTrue(t, b1, b2)
198
199	b1 = NewBool(true, false)
200	b2 = NewBool(false, true)
201	assertBoolEqualIsTrue(t, b1, b2)
202
203	b1 = NewBool(true, true)
204	b2 = NewBool(true, false)
205	assertBoolEqualIsFalse(t, b1, b2)
206
207	b1 = NewBool(true, false)
208	b2 = NewBool(true, true)
209	assertBoolEqualIsFalse(t, b1, b2)
210
211	b1 = NewBool(true, true)
212	b2 = NewBool(false, true)
213	assertBoolEqualIsFalse(t, b1, b2)
214}
215
216func assertBool(t *testing.T, b Bool, from string) {
217	if b.Bool != true {
218		t.Errorf("bad %s bool: %v ≠ %v\n", from, b.Bool, true)
219	}
220	if !b.Valid {
221		t.Error(from, "is invalid, but should be valid")
222	}
223}
224
225func assertNullBool(t *testing.T, b Bool, from string) {
226	if b.Valid {
227		t.Error(from, "is valid, but should be invalid")
228	}
229}
230
231func assertBoolEqualIsTrue(t *testing.T, a, b Bool) {
232	t.Helper()
233	if !a.Equal(b) {
234		t.Errorf("Equal() of Bool{%t, Valid:%t} and Bool{%t, Valid:%t} should return true", a.Bool, a.Valid, b.Bool, b.Valid)
235	}
236}
237
238func assertBoolEqualIsFalse(t *testing.T, a, b Bool) {
239	t.Helper()
240	if a.Equal(b) {
241		t.Errorf("Equal() of Bool{%t, Valid:%t} and Bool{%t, Valid:%t} should return false", a.Bool, a.Valid, b.Bool, b.Valid)
242	}
243}
244