mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
286 lines
5.8 KiB
Go
286 lines
5.8 KiB
Go
package unicode
|
||
|
||
import (
|
||
"errors"
|
||
"slices"
|
||
"testing"
|
||
|
||
"github.com/ncruces/go-sqlite3"
|
||
_ "github.com/ncruces/go-sqlite3/embed"
|
||
_ "github.com/ncruces/go-sqlite3/internal/testcfg"
|
||
)
|
||
|
||
func TestRegister(t *testing.T) {
|
||
t.Parallel()
|
||
|
||
db, err := sqlite3.Open(":memory:")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
exec := func(fn string) string {
|
||
stmt, _, err := db.Prepare(`SELECT ` + fn)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer stmt.Close()
|
||
|
||
if !stmt.Step() {
|
||
t.Fatal(stmt.Err())
|
||
}
|
||
return stmt.ColumnText(0)
|
||
}
|
||
|
||
Register(db)
|
||
|
||
tests := []struct {
|
||
test string
|
||
want string
|
||
}{
|
||
{`upper('hello')`, "HELLO"},
|
||
{`lower('HELLO')`, "hello"},
|
||
{`upper('привет')`, "ПРИВЕТ"},
|
||
{`lower('ПРИВЕТ')`, "привет"},
|
||
{`upper('istanbul')`, "ISTANBUL"},
|
||
{`upper('istanbul', 'tr-TR')`, "İSTANBUL"},
|
||
{`lower('Dünyanın İlk Borsası', 'tr-TR')`, "dünyanın ilk borsası"},
|
||
{`upper('Dünyanın İlk Borsası', 'tr-TR')`, "DÜNYANIN İLK BORSASI"},
|
||
{`initcap('Kad je hladno Marko nosi džemper')`, "Kad Je Hladno Marko Nosi Džemper"},
|
||
{`initcap('Kad je hladno Marko nosi džemper', 'hr-HR')`, "Kad Je Hladno Marko Nosi Džemper"},
|
||
{`normalize(X'61cc88')`, "ä"},
|
||
{`normalize(X'61cc88', 'NFC' )`, "ä"},
|
||
{`normalize(X'61cc88', 'NFKC')`, "ä"},
|
||
{`normalize('ä', 'NFD' )`, "\x61\xcc\x88"},
|
||
{`normalize('ä', 'NFKD')`, "\x61\xcc\x88"},
|
||
{`casefold('Maße')`, "masse"},
|
||
{`unaccent('Hôtel')`, "Hotel"},
|
||
{`'Hello' REGEXP 'ell'`, "1"},
|
||
{`'Hello' REGEXP 'el.'`, "1"},
|
||
{`'Hello' LIKE 'hel_'`, "0"},
|
||
{`'Hello' LIKE 'hel%'`, "1"},
|
||
{`'Hello' LIKE 'h_llo'`, "1"},
|
||
{`'Hello' LIKE 'hello'`, "1"},
|
||
{`'Привет' LIKE 'ПРИВЕТ'`, "1"},
|
||
{`'100%' LIKE '100|%' ESCAPE '|'`, "1"},
|
||
}
|
||
|
||
for _, tt := range tests {
|
||
t.Run(tt.test, func(t *testing.T) {
|
||
if got := exec(tt.test); got != tt.want {
|
||
t.Errorf("exec(%q) = %q, want %q", tt.test, got, tt.want)
|
||
}
|
||
})
|
||
}
|
||
|
||
err = db.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestRegister_collation(t *testing.T) {
|
||
t.Parallel()
|
||
|
||
db, err := sqlite3.Open(":memory:")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
Register(db)
|
||
|
||
err = db.Exec(`CREATE TABLE words (word VARCHAR(10))`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
err = db.Exec(`INSERT INTO words (word) VALUES ('côte'), ('cote'), ('coter'), ('coté'), ('cotée'), ('côté')`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT icu_load_collation('fr-FR', 'french')`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE french`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer stmt.Close()
|
||
|
||
got, want := []string{}, []string{"cote", "coté", "côte", "côté", "cotée", "coter"}
|
||
|
||
for stmt.Step() {
|
||
got = append(got, stmt.ColumnText(0))
|
||
}
|
||
if err := stmt.Err(); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if !slices.Equal(got, want) {
|
||
t.Error("not equal")
|
||
}
|
||
|
||
err = stmt.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
err = db.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestRegisterCollationsNeeded(t *testing.T) {
|
||
t.Parallel()
|
||
|
||
db, err := sqlite3.Open(":memory:")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
RegisterCollationsNeeded(db)
|
||
|
||
err = db.Exec(`CREATE TABLE words (word VARCHAR(10))`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
err = db.Exec(`INSERT INTO words (word) VALUES ('côte'), ('cote'), ('coter'), ('coté'), ('cotée'), ('côté')`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE fr_FR`)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer stmt.Close()
|
||
|
||
got, want := []string{}, []string{"cote", "coté", "côte", "côté", "cotée", "coter"}
|
||
|
||
for stmt.Step() {
|
||
got = append(got, stmt.ColumnText(0))
|
||
}
|
||
if err := stmt.Err(); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
if !slices.Equal(got, want) {
|
||
t.Error("not equal")
|
||
}
|
||
|
||
err = stmt.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
|
||
err = db.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func TestRegister_error(t *testing.T) {
|
||
t.Parallel()
|
||
|
||
db, err := sqlite3.Open(":memory:")
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
defer db.Close()
|
||
|
||
Register(db)
|
||
|
||
err = db.Exec(`SELECT upper('hello', 'enUS')`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT lower('hello', 'enUS')`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT normalize('', 'NF')`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT 'hello' REGEXP '\'`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT 'hello' LIKE 'HELLO' ESCAPE '\\'`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT icu_load_collation('enUS', 'error')`)
|
||
if err == nil {
|
||
t.Error("want error")
|
||
}
|
||
if !errors.Is(err, sqlite3.ERROR) {
|
||
t.Errorf("got %v, want sqlite3.ERROR", err)
|
||
}
|
||
|
||
err = db.Exec(`SELECT icu_load_collation('enUS', '')`)
|
||
if err != nil {
|
||
t.Error(err)
|
||
}
|
||
|
||
err = db.Close()
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
}
|
||
|
||
func Test_like2regex(t *testing.T) {
|
||
t.Parallel()
|
||
|
||
const prefix = `(?is)\A`
|
||
const sufix = `\z`
|
||
tests := []struct {
|
||
pattern string
|
||
escape rune
|
||
want string
|
||
}{
|
||
{`a`, -1, `a`},
|
||
{`a.`, -1, `a\.`},
|
||
{`a%`, -1, `a.*`},
|
||
{`a\`, -1, `a\\`},
|
||
{`a_b`, -1, `a.b`},
|
||
{`a|b`, '|', `ab`},
|
||
{`a|_`, '|', `a_`},
|
||
}
|
||
for _, tt := range tests {
|
||
t.Run(tt.pattern, func(t *testing.T) {
|
||
want := prefix + tt.want + sufix
|
||
if got := like2regex(tt.pattern, tt.escape); got != want {
|
||
t.Errorf("like2regex() = %q, want %q", got, want)
|
||
}
|
||
})
|
||
}
|
||
}
|