github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/driver/time_test.go (about) 1 package driver 2 3 import ( 4 "testing" 5 "time" 6 ) 7 8 // This checks that any string can be recovered as the same string. 9 func Fuzz_stringOrTime_1(f *testing.F) { 10 f.Add("") 11 f.Add(" ") 12 f.Add("SQLite") 13 f.Add(time.RFC3339) 14 f.Add(time.RFC3339Nano) 15 f.Add(time.Layout) 16 f.Add(time.DateTime) 17 f.Add(time.DateOnly) 18 f.Add(time.TimeOnly) 19 f.Add("2006-01-02T15:04:05Z") 20 f.Add("2006-01-02T15:04:05.000Z") 21 f.Add("2006-01-02T15:04:05.9999999999Z") 22 f.Add("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") 23 24 f.Fuzz(func(t *testing.T, str string) { 25 v, ok := maybeTime(str) 26 if ok { 27 // Make sure times round-trip to the same string: 28 // https://pkg.go.dev/database/sql#Rows.Scan 29 if v.Format(time.RFC3339Nano) != str { 30 t.Fatalf("did not round-trip: %q", str) 31 } 32 } else { 33 date, err := time.Parse(time.RFC3339Nano, str) 34 if err == nil && date.Format(time.RFC3339Nano) == str { 35 t.Fatalf("would round-trip: %q", str) 36 } 37 } 38 }) 39 } 40 41 // This checks that any [time.Time] can be recovered as a [time.Time], 42 // with nanosecond accuracy, and preserving any timezone offset. 43 func Fuzz_stringOrTime_2(f *testing.F) { 44 f.Add(int64(0), int64(0)) 45 f.Add(int64(0), int64(1)) 46 f.Add(int64(0), int64(-1)) 47 f.Add(int64(0), int64(999_999_999)) 48 f.Add(int64(0), int64(1_000_000_000)) 49 f.Add(int64(7956915742), int64(222_222_222)) // twosday 50 f.Add(int64(639095955742), int64(222_222_222)) // twosday, year 22222AD 51 f.Add(int64(-763421161058), int64(222_222_222)) // twosday, year 22222BC 52 53 checkTime := func(t testing.TB, date time.Time) { 54 v, ok := maybeTime(date.Format(time.RFC3339Nano)) 55 if ok { 56 // Make sure times round-trip to the same time: 57 if !v.Equal(date) { 58 t.Fatalf("did not round-trip: %v", date) 59 } 60 // With the same zone offset: 61 _, off1 := v.Zone() 62 _, off2 := date.Zone() 63 if off1 != off2 { 64 t.Fatalf("did not round-trip: %v", date) 65 } 66 } else { 67 t.Fatalf("was not recovered: %v", date) 68 } 69 } 70 71 f.Fuzz(func(t *testing.T, sec, nsec int64) { 72 // Reduce the search space. 73 if 1e12 < sec || sec < -1e12 { 74 // Dates before 29000BC and after 33000AD; I think we're safe. 75 return 76 } 77 if 0 < nsec || nsec > 1e10 { 78 // Out of range nsec: [time.Time.Unix] handles these. 79 return 80 } 81 82 unix := time.Unix(sec, nsec) 83 checkTime(t, unix) 84 checkTime(t, unix.UTC()) 85 checkTime(t, unix.In(time.FixedZone("", -8*3600))) 86 checkTime(t, unix.In(time.FixedZone("", +8*3600))) 87 }) 88 }