github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/ext/unicode/unicode_test.go (about) 1 package unicode 2 3 import ( 4 "errors" 5 "reflect" 6 "testing" 7 8 "github.com/ncruces/go-sqlite3" 9 _ "github.com/ncruces/go-sqlite3/embed" 10 _ "github.com/ncruces/go-sqlite3/tests/testcfg" 11 ) 12 13 func TestRegister(t *testing.T) { 14 t.Parallel() 15 16 db, err := sqlite3.Open(":memory:") 17 if err != nil { 18 t.Fatal(err) 19 } 20 defer db.Close() 21 22 exec := func(fn string) string { 23 stmt, _, err := db.Prepare(`SELECT ` + fn) 24 if err != nil { 25 t.Fatal(err) 26 } 27 defer stmt.Close() 28 29 if stmt.Step() { 30 return stmt.ColumnText(0) 31 } 32 t.Fatal(stmt.Err()) 33 return "" 34 } 35 36 Register(db) 37 38 tests := []struct { 39 test string 40 want string 41 }{ 42 {`upper('hello')`, "HELLO"}, 43 {`lower('HELLO')`, "hello"}, 44 {`upper('привет')`, "ПРИВЕТ"}, 45 {`lower('ПРИВЕТ')`, "привет"}, 46 {`upper('istanbul')`, "ISTANBUL"}, 47 {`upper('istanbul', 'tr-TR')`, "İSTANBUL"}, 48 {`lower('Dünyanın İlk Borsası', 'tr-TR')`, "dünyanın ilk borsası"}, 49 {`upper('Dünyanın İlk Borsası', 'tr-TR')`, "DÜNYANIN İLK BORSASI"}, 50 {`'Hello' REGEXP 'ell'`, "1"}, 51 {`'Hello' REGEXP 'el.'`, "1"}, 52 {`'Hello' LIKE 'hel_'`, "0"}, 53 {`'Hello' LIKE 'hel%'`, "1"}, 54 {`'Hello' LIKE 'h_llo'`, "1"}, 55 {`'Hello' LIKE 'hello'`, "1"}, 56 {`'Привет' LIKE 'ПРИВЕТ'`, "1"}, 57 {`'100%' LIKE '100|%' ESCAPE '|'`, "1"}, 58 } 59 60 for _, tt := range tests { 61 t.Run(tt.test, func(t *testing.T) { 62 if got := exec(tt.test); got != tt.want { 63 t.Errorf("exec(%q) = %q, want %q", tt.test, got, tt.want) 64 } 65 }) 66 } 67 68 err = db.Close() 69 if err != nil { 70 t.Fatal(err) 71 } 72 } 73 74 func TestRegister_collation(t *testing.T) { 75 t.Parallel() 76 77 db, err := sqlite3.Open(":memory:") 78 if err != nil { 79 t.Fatal(err) 80 } 81 defer db.Close() 82 83 Register(db) 84 85 err = db.Exec(`CREATE TABLE words (word VARCHAR(10))`) 86 if err != nil { 87 t.Fatal(err) 88 } 89 90 err = db.Exec(`INSERT INTO words (word) VALUES ('côte'), ('cote'), ('coter'), ('coté'), ('cotée'), ('côté')`) 91 if err != nil { 92 t.Fatal(err) 93 } 94 95 err = db.Exec(`SELECT icu_load_collation('fr_FR', 'french')`) 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE french`) 101 if err != nil { 102 t.Fatal(err) 103 } 104 defer stmt.Close() 105 106 got, want := []string{}, []string{"cote", "coté", "côte", "côté", "cotée", "coter"} 107 108 for stmt.Step() { 109 got = append(got, stmt.ColumnText(0)) 110 } 111 if err := stmt.Err(); err != nil { 112 t.Fatal(err) 113 } 114 115 if !reflect.DeepEqual(got, want) { 116 t.Error("not equal") 117 } 118 119 err = stmt.Close() 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 err = db.Close() 125 if err != nil { 126 t.Fatal(err) 127 } 128 } 129 130 func TestRegister_error(t *testing.T) { 131 t.Parallel() 132 133 db, err := sqlite3.Open(":memory:") 134 if err != nil { 135 t.Fatal(err) 136 } 137 defer db.Close() 138 139 Register(db) 140 141 err = db.Exec(`SELECT upper('hello', 'enUS')`) 142 if err == nil { 143 t.Error("want error") 144 } 145 if !errors.Is(err, sqlite3.ERROR) { 146 t.Errorf("got %v, want sqlite3.ERROR", err) 147 } 148 149 err = db.Exec(`SELECT lower('hello', 'enUS')`) 150 if err == nil { 151 t.Error("want error") 152 } 153 if !errors.Is(err, sqlite3.ERROR) { 154 t.Errorf("got %v, want sqlite3.ERROR", err) 155 } 156 157 err = db.Exec(`SELECT 'hello' REGEXP '\'`) 158 if err == nil { 159 t.Error("want error") 160 } 161 if !errors.Is(err, sqlite3.ERROR) { 162 t.Errorf("got %v, want sqlite3.ERROR", err) 163 } 164 165 err = db.Exec(`SELECT 'hello' LIKE 'HELLO' ESCAPE '\\'`) 166 if err == nil { 167 t.Error("want error") 168 } 169 if !errors.Is(err, sqlite3.ERROR) { 170 t.Errorf("got %v, want sqlite3.ERROR", err) 171 } 172 173 err = db.Exec(`SELECT icu_load_collation('enUS', 'error')`) 174 if err == nil { 175 t.Error("want error") 176 } 177 if !errors.Is(err, sqlite3.ERROR) { 178 t.Errorf("got %v, want sqlite3.ERROR", err) 179 } 180 181 err = db.Exec(`SELECT icu_load_collation('enUS', '')`) 182 if err != nil { 183 t.Error(err) 184 } 185 186 err = db.Close() 187 if err != nil { 188 t.Fatal(err) 189 } 190 } 191 192 func Test_like2regex(t *testing.T) { 193 t.Parallel() 194 195 const prefix = `(?is)\A` 196 const sufix = `\z` 197 tests := []struct { 198 pattern string 199 escape rune 200 want string 201 }{ 202 {`a`, -1, `a`}, 203 {`a.`, -1, `a\.`}, 204 {`a%`, -1, `a.*`}, 205 {`a\`, -1, `a\\`}, 206 {`a_b`, -1, `a.b`}, 207 {`a|b`, '|', `ab`}, 208 {`a|_`, '|', `a_`}, 209 } 210 for _, tt := range tests { 211 t.Run(tt.pattern, func(t *testing.T) { 212 want := prefix + tt.want + sufix 213 if got := like2regex(tt.pattern, tt.escape); got != want { 214 t.Errorf("like2regex() = %q, want %q", got, want) 215 } 216 }) 217 } 218 }