mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 05:59:14 +00:00
168 lines
4.8 KiB
Go
168 lines
4.8 KiB
Go
package sql3util_test
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ncruces/go-sqlite3"
|
|
_ "github.com/ncruces/go-sqlite3/embed"
|
|
"github.com/ncruces/go-sqlite3/util/sql3util"
|
|
)
|
|
|
|
func TestUnquote(t *testing.T) {
|
|
tests := []struct {
|
|
val string
|
|
want string
|
|
}{
|
|
{"a", "a"},
|
|
{"abc", "abc"},
|
|
{"abba", "abba"},
|
|
{"`ab``c`", "ab`c"},
|
|
{"'ab''c'", "ab'c"},
|
|
{"'ab``c'", "ab``c"},
|
|
{"[ab``c]", "ab``c"},
|
|
{`"ab""c"`, `ab"c`},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.val, func(t *testing.T) {
|
|
if got := sql3util.Unquote(tt.val); got != tt.want {
|
|
t.Errorf("Unquote(%s) = %s, want %s", tt.val, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseBool(t *testing.T) {
|
|
tests := []struct {
|
|
str string
|
|
val bool
|
|
ok bool
|
|
}{
|
|
{"", false, false},
|
|
{"0", false, true},
|
|
{"1", true, true},
|
|
{"9", true, true},
|
|
{"T", false, false},
|
|
{"true", true, true},
|
|
{"FALSE", false, true},
|
|
{"false?", false, false},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.str, func(t *testing.T) {
|
|
gotVal, gotOK := sql3util.ParseBool(tt.str)
|
|
if gotVal != tt.val || gotOK != tt.ok {
|
|
t.Errorf("ParseBool(%q) = (%v, %v) want (%v, %v)", tt.str, gotVal, gotOK, tt.val, tt.ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseTimeShift(t *testing.T) {
|
|
epoch := time.Unix(0, 0)
|
|
tests := []struct {
|
|
str string
|
|
val time.Time
|
|
ok bool
|
|
}{
|
|
{"", epoch, false},
|
|
{"0001-11-30", epoch, false},
|
|
{"+_001-11-30", epoch, false},
|
|
{"+0001-_1-30", epoch.AddDate(1, 0, 0), false},
|
|
{"+0001-11-_0", epoch.AddDate(1, 11, 0), false},
|
|
{"+0001-11-30", epoch.AddDate(1, 11, 30), true},
|
|
{"-0001-11-30", epoch.AddDate(-1, -11, -30), true},
|
|
{"+0001-11-30T", epoch.AddDate(1, 11, 30), false},
|
|
{"+0001-11-30 12", epoch.AddDate(1, 11, 30), false},
|
|
{"+0001-11-30 _2:30", epoch.AddDate(1, 11, 30), false},
|
|
{"+0001-11-30 12:_0", epoch.AddDate(1, 11, 30), false},
|
|
{"+0001-11-30 12:30", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute), true},
|
|
{"+0001-11-30 12:30:", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute), false},
|
|
{"+0001-11-30 12:30:_0", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute), false},
|
|
{"+0001-11-30 12:30:59", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second), true},
|
|
{"+0001-11-30 12:30:59.", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second), false},
|
|
{"+0001-11-30 12:30:59._", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second), false},
|
|
{"+0001-11-30 12:30:59.1", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second + 100*time.Millisecond), true},
|
|
{"+0001-11-30 12:30:59.123456789_", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second + 123456789), false},
|
|
{"+0001-11-30 12:30:59.1234567890", epoch.AddDate(1, 11, 30).Add(12*time.Hour + 30*time.Minute + 59*time.Second + 123456789), true},
|
|
{"-12:30:59.1234567890", epoch.Add(-12*time.Hour - 30*time.Minute - 59*time.Second - 123456789), true},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.str, func(t *testing.T) {
|
|
years, months, days, duration, gotOK := sql3util.ParseTimeShift(tt.str)
|
|
gotVal := epoch.AddDate(years, months, days).Add(duration)
|
|
if !gotVal.Equal(tt.val) || gotOK != tt.ok {
|
|
t.Errorf("ParseTimeShift(%q) = (%v, %v) want (%v, %v)", tt.str, gotVal, gotOK, tt.val, tt.ok)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func FuzzParseTimeShift(f *testing.F) {
|
|
f.Add("")
|
|
f.Add("0001-12-30")
|
|
f.Add("+_001-12-30")
|
|
f.Add("+0001-_2-30")
|
|
f.Add("+0001-12-_0")
|
|
f.Add("+0001-12-30")
|
|
f.Add("-0001-12-30")
|
|
f.Add("+0001-12-30T")
|
|
f.Add("+0001-12-30 12")
|
|
f.Add("+0001-12-30 _2:30")
|
|
f.Add("+0001-12-30 12:_0")
|
|
f.Add("+0001-12-30 12:30")
|
|
f.Add("+0001-12-30 12:30:")
|
|
f.Add("+0001-12-30 12:30:_0")
|
|
f.Add("+0001-12-30 12:30:60")
|
|
f.Add("+0001-12-30 12:30:60.")
|
|
f.Add("+0001-12-30 12:30:60._")
|
|
f.Add("+0001-12-30 12:30:60.1")
|
|
f.Add("+0001-12-30 12:30:60.123456789_")
|
|
f.Add("+0001-12-30 12:30:60.1234567890")
|
|
f.Add("-12:30:60.1234567890")
|
|
|
|
c, err := sqlite3.Open(":memory:")
|
|
if err != nil {
|
|
f.Fatal(err)
|
|
}
|
|
defer c.Close()
|
|
|
|
s, _, err := c.Prepare(`SELECT julianday('00:00', ?)`)
|
|
if err != nil {
|
|
f.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
|
|
// Default SQLite date.
|
|
epoch := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
|
|
|
|
f.Fuzz(func(t *testing.T, str string) {
|
|
years, months, days, duration, ok := sql3util.ParseTimeShift(str)
|
|
|
|
// Account for a full 400 year cycle.
|
|
if years < -200 || years > +200 {
|
|
t.Skip()
|
|
}
|
|
// SQLite only tracks milliseconds.
|
|
if duration != duration.Truncate(time.Millisecond) {
|
|
t.Skip()
|
|
}
|
|
|
|
if ok {
|
|
s.Reset()
|
|
s.BindText(1, str)
|
|
if !s.Step() {
|
|
t.Fail()
|
|
}
|
|
|
|
got := epoch.AddDate(years, months, days).Add(duration)
|
|
|
|
// Julian day introduces floating point inaccuracy.
|
|
want := s.ColumnTime(0, sqlite3.TimeFormatJulianDay)
|
|
want = want.Round(time.Millisecond)
|
|
if !got.Equal(want) {
|
|
t.Fatalf("with %q, got %v, want %v", str, got, want)
|
|
}
|
|
}
|
|
})
|
|
}
|