Skip to content

Commit 6da1ee7

Browse files
Add tests for Boolean DataType (#92)
* Add tests for Boolean DataType * Increase test coverage * Add tests for Boolean datatype * Disable Nullable Test * Use t.skip instead of commenting * Merge with main * Remove timestamp tests
1 parent bf6e164 commit 6da1ee7

File tree

1 file changed

+282
-0
lines changed

1 file changed

+282
-0
lines changed

tests/boolean_test.go

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
/*
2+
** Copyright (c) 2025 Oracle and/or its affiliates.
3+
**
4+
** The Universal Permissive License (UPL), Version 1.0
5+
**
6+
** Subject to the condition set forth below, permission is hereby granted to any
7+
** person obtaining a copy of this software, associated documentation and/or data
8+
** (collectively the "Software"), free of charge and under any and all copyright
9+
** rights in the Software, and any and all patent rights owned or freely
10+
** licensable by each licensor hereunder covering either (i) the unmodified
11+
** Software as contributed to or provided by such licensor, or (ii) the Larger
12+
** Works (as defined below), to deal in both
13+
**
14+
** (a) the Software, and
15+
** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
** one is included with the Software (each a "Larger Work" to which the Software
17+
** is contributed by such licensors),
18+
**
19+
** without restriction, including without limitation the rights to copy, create
20+
** derivative works of, display, perform, and distribute the Software and make,
21+
** use, sell, offer for sale, import, export, have made, and have sold the
22+
** Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
** either these or other terms.
24+
**
25+
** This license is subject to the following condition:
26+
** The above copyright notice and either this complete permission notice or at
27+
** a minimum a reference to the UPL must be included in all copies or
28+
** substantial portions of the Software.
29+
**
30+
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31+
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32+
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33+
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34+
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35+
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36+
** SOFTWARE.
37+
*/
38+
39+
package tests
40+
41+
import (
42+
"database/sql"
43+
"testing"
44+
"strings"
45+
)
46+
47+
type BooleanTest struct {
48+
ID uint `gorm:"column:ID;primaryKey"`
49+
Flag bool `gorm:"column:FLAG"`
50+
Nullable *bool `gorm:"column:NULLABLE"`
51+
SQLBool sql.NullBool `gorm:"column:SQL_BOOL"`
52+
}
53+
54+
func (BooleanTest) TableName() string {
55+
return "BOOLEAN_TESTS"
56+
}
57+
58+
func TestBooleanBasicInsert(t *testing.T) {
59+
DB.Migrator().DropTable(&BooleanTest{})
60+
if err := DB.AutoMigrate(&BooleanTest{}); err != nil {
61+
t.Fatalf("failed to migrate: %v", err)
62+
}
63+
64+
valTrue := true
65+
valFalse := false
66+
67+
// Insert true
68+
bt1 := BooleanTest{Flag: true, Nullable: &valTrue}
69+
if err := DB.Create(&bt1).Error; err != nil {
70+
t.Fatalf("insert true failed: %v", err)
71+
}
72+
73+
// Insert false
74+
bt2 := BooleanTest{Flag: false, Nullable: &valFalse}
75+
if err := DB.Create(&bt2).Error; err != nil {
76+
t.Fatalf("insert false failed: %v", err)
77+
}
78+
79+
// Verify fetch
80+
var got1, got2 BooleanTest
81+
if err := DB.First(&got1, bt1.ID).Error; err != nil {
82+
t.Fatal(err)
83+
}
84+
if got1.Flag != true {
85+
t.Errorf("expected true, got %v", got1.Flag)
86+
}
87+
88+
if err := DB.First(&got2, bt2.ID).Error; err != nil {
89+
t.Fatal(err)
90+
}
91+
if got2.Flag != false {
92+
t.Errorf("expected false, got %v", got2.Flag)
93+
}
94+
}
95+
96+
func TestBooleanUpdate(t *testing.T) {
97+
DB.Migrator().DropTable(&BooleanTest{})
98+
DB.AutoMigrate(&BooleanTest{})
99+
100+
bt := BooleanTest{Flag: false}
101+
DB.Create(&bt)
102+
103+
if err := DB.Model(&bt).Update("Flag", true).Error; err != nil {
104+
t.Fatalf("update failed: %v", err)
105+
}
106+
107+
var got BooleanTest
108+
DB.First(&got, bt.ID)
109+
if got.Flag != true {
110+
t.Errorf("expected true after update, got %v", got.Flag)
111+
}
112+
}
113+
114+
func TestBooleanQueryFilters(t *testing.T) {
115+
DB.Migrator().DropTable(&BooleanTest{})
116+
DB.AutoMigrate(&BooleanTest{})
117+
118+
DB.Create(&BooleanTest{Flag: true})
119+
DB.Create(&BooleanTest{Flag: false})
120+
121+
var trues []BooleanTest
122+
if err := DB.Where("FLAG = ?", true).Find(&trues).Error; err != nil {
123+
t.Fatal(err)
124+
}
125+
126+
if len(trues) == 0 {
127+
t.Fatalf("expected at least 1 row, got 0")
128+
}
129+
130+
for _, row := range trues {
131+
if !row.Flag {
132+
t.Errorf("expected only true rows, got false")
133+
}
134+
}
135+
}
136+
137+
func TestBooleanNegativeInvalidDBValue(t *testing.T) {
138+
DB.Migrator().DropTable(&BooleanTest{})
139+
DB.AutoMigrate(&BooleanTest{})
140+
141+
if err := DB.Exec(`INSERT INTO "BOOLEAN_TESTS" ("ID","FLAG") VALUES (2001, 2)`).Error; err != nil {
142+
t.Fatalf("failed to insert invalid bool: %v", err)
143+
}
144+
145+
var got BooleanTest
146+
err := DB.First(&got, 2001).Error
147+
if err == nil {
148+
t.Fatal("expected invalid boolean scan error, got nil")
149+
}
150+
151+
if !strings.Contains(err.Error(), "invalid") &&
152+
!strings.Contains(err.Error(), "convert") {
153+
t.Fatalf("expected boolean conversion error, got: %v", err)
154+
}
155+
}
156+
157+
func TestBooleanInsertWithIntValues(t *testing.T) {
158+
DB.Migrator().DropTable(&BooleanTest{})
159+
DB.AutoMigrate(&BooleanTest{})
160+
161+
if err := DB.Exec("INSERT INTO BOOLEAN_TESTS (ID, FLAG) VALUES (1001, 1)").Error; err != nil {
162+
t.Fatalf("failed to insert int 1 as boolean: %v", err)
163+
}
164+
if err := DB.Exec("INSERT INTO BOOLEAN_TESTS (ID, FLAG) VALUES (1002, 0)").Error; err != nil {
165+
t.Fatalf("failed to insert int 0 as boolean: %v", err)
166+
}
167+
168+
var gotTrue, gotFalse BooleanTest
169+
if err := DB.First(&gotTrue, 1001).Error; err != nil {
170+
t.Fatalf("fetch failed: %v", err)
171+
}
172+
if gotTrue.Flag != true {
173+
t.Errorf("expected true for 1, got %v", gotTrue.Flag)
174+
}
175+
176+
if err := DB.First(&gotFalse, 1002).Error; err != nil {
177+
t.Fatalf("fetch failed: %v", err)
178+
}
179+
if gotFalse.Flag != false {
180+
t.Errorf("expected false for 0, got %v", gotFalse.Flag)
181+
}
182+
}
183+
184+
func TestBooleanSQLNullBool(t *testing.T) {
185+
DB.Migrator().DropTable(&BooleanTest{})
186+
DB.AutoMigrate(&BooleanTest{})
187+
188+
bt := BooleanTest{SQLBool: sql.NullBool{Bool: true, Valid: true}}
189+
DB.Create(&bt)
190+
191+
var got BooleanTest
192+
DB.First(&got, bt.ID)
193+
if !got.SQLBool.Valid || got.SQLBool.Bool != true {
194+
t.Errorf("expected sql.NullBool true/valid, got %+v", got.SQLBool)
195+
}
196+
}
197+
198+
func TestBooleanDefaultValue(t *testing.T) {
199+
DB.Migrator().DropTable(&BooleanTest{})
200+
DB.AutoMigrate(&BooleanTest{})
201+
202+
bt := BooleanTest{}
203+
if err := DB.Create(&bt).Error; err != nil {
204+
t.Fatalf("insert default failed: %v", err)
205+
}
206+
207+
var got BooleanTest
208+
DB.First(&got, bt.ID)
209+
210+
if got.Flag != false {
211+
t.Errorf("expected default false, got %v", got.Flag)
212+
}
213+
}
214+
215+
func TestBooleanQueryMixedComparisons(t *testing.T) {
216+
DB.Migrator().DropTable(&BooleanTest{})
217+
DB.AutoMigrate(&BooleanTest{})
218+
219+
DB.Create(&BooleanTest{Flag: true})
220+
DB.Create(&BooleanTest{Flag: false})
221+
222+
var gotNum []BooleanTest
223+
224+
// FILTER USING NUMBER
225+
if err := DB.Where("FLAG = 1").Find(&gotNum).Error; err != nil {
226+
t.Fatal(err)
227+
}
228+
if len(gotNum) == 0 {
229+
t.Errorf("expected at least 1 row for FLAG=1")
230+
}
231+
232+
var gotStr []BooleanTest
233+
if err := DB.Where("FLAG = 'true'").Find(&gotStr).Error; err == nil {
234+
t.Errorf("expected ORA-01722 when comparing NUMBER to string literal")
235+
}
236+
}
237+
238+
func TestBooleanStringCoercion(t *testing.T) {
239+
DB.Migrator().DropTable(&BooleanTest{})
240+
DB.AutoMigrate(&BooleanTest{})
241+
242+
// Insert using string literals
243+
if err := DB.Exec("INSERT INTO BOOLEAN_TESTS (ID, FLAG) VALUES (2001, '1')").Error; err != nil {
244+
t.Fatalf("failed to insert '1': %v", err)
245+
}
246+
if err := DB.Exec("INSERT INTO BOOLEAN_TESTS (ID, FLAG) VALUES (2002, '0')").Error; err != nil {
247+
t.Fatalf("failed to insert '0': %v", err)
248+
}
249+
250+
var got1, got2 BooleanTest
251+
DB.First(&got1, 2001)
252+
DB.First(&got2, 2002)
253+
254+
if got1.Flag != true {
255+
t.Errorf("expected true for '1', got %v", got1.Flag)
256+
}
257+
if got2.Flag != false {
258+
t.Errorf("expected false for '0', got %v", got2.Flag)
259+
}
260+
}
261+
262+
263+
func TestBooleanNullableColumn(t *testing.T) {
264+
t.Skip("Skipping until nullable bool bug is resolved")
265+
DB.Migrator().DropTable(&BooleanTest{})
266+
DB.AutoMigrate(&BooleanTest{})
267+
268+
// Insert a row with NULL value for Nullable column
269+
bt := BooleanTest{Flag: true, Nullable: nil}
270+
if err := DB.Create(&bt).Error; err != nil {
271+
t.Fatalf("failed to insert NULL bool: %v", err)
272+
}
273+
274+
var got BooleanTest
275+
if err := DB.First(&got, bt.ID).Error; err != nil {
276+
t.Fatal(err)
277+
}
278+
279+
if got.Nullable != nil {
280+
t.Errorf("expected NULL, got %v", *got.Nullable)
281+
}
282+
}

0 commit comments

Comments
 (0)