diff --git a/types/binary_literal_test.go b/types/binary_literal_test.go index a8788ecd422bc..b1547fec5f24f 100644 --- a/types/binary_literal_test.go +++ b/types/binary_literal_test.go @@ -106,6 +106,9 @@ func (s *testBinaryLiteralSuite) TestParseBitStr(c *C) { c.Assert([]byte(b), DeepEquals, t.Expected, Commentf("%#v", t)) } } + b, err := ParseBitStr("") + c.Assert(b, IsNil) + c.Assert(err, ErrorMatches, "invalid empty .*") } func (s *testBinaryLiteralSuite) TestParseHexStr(c *C) { @@ -139,6 +142,9 @@ func (s *testBinaryLiteralSuite) TestParseHexStr(c *C) { c.Assert([]byte(hex), DeepEquals, t.Expected, Commentf("%#v", t)) } } + hex, err := ParseHexStr("") + c.Assert(hex, IsNil) + c.Assert(err, ErrorMatches, "invalid empty .*") } func (s *testBinaryLiteralSuite) TestString(c *C) { @@ -243,6 +249,12 @@ func (s *testBinaryLiteralSuite) TestNewBinaryLiteralFromUint(c *C) { hex := NewBinaryLiteralFromUint(t.Input, t.ByteSize) c.Assert([]byte(hex), DeepEquals, t.Expected, Commentf("%#v", t)) } + + defer func() { + r := recover() + c.Assert(r, NotNil) + }() + NewBinaryLiteralFromUint(0x123, -2) } func (s *testBinaryLiteralSuite) TestCompare(c *C) { diff --git a/types/convert_test.go b/types/convert_test.go index 6398b9b87eeac..262b76862cb9c 100644 --- a/types/convert_test.go +++ b/types/convert_test.go @@ -884,3 +884,22 @@ func (s *testTypeConvertSuite) TestNumberToDuration(c *C) { c.Assert(dur.Duration, Equals, tc.dur) } } + +func (s *testTypeConvertSuite) TestStrToDuration(c *C) { + sc := new(stmtctx.StatementContext) + var tests = []struct { + str string + fsp int + isDuration bool + }{ + {"20190412120000", 4, false}, + {"20190101180000", 6, false}, + {"20190101180000", 1, false}, + {"20190101181234", 3, false}, + } + for _, tt := range tests { + _, _, isDuration, err := StrToDuration(sc, tt.str, tt.fsp) + c.Assert(err, IsNil) + c.Assert(isDuration, Equals, tt.isDuration) + } +} diff --git a/types/datum_test.go b/types/datum_test.go index 3e67866bfe1a5..a5a145ba55e4e 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -40,9 +40,13 @@ func (ts *testDatumSuite) TestDatum(c *C) { } for _, val := range values { var d Datum + d.SetMinNotNull() d.SetValue(val) x := d.GetValue() c.Assert(x, DeepEquals, val) + d.SetCollation(d.Collation()) + c.Assert(d.Collation(), NotNil) + c.Assert(d.Length(), Equals, int(d.length)) } } @@ -194,6 +198,34 @@ func (ts *testTypeConvertSuite) TestToFloat32(c *C) { c.Assert(converted.GetFloat64(), Equals, datum.GetFloat64()) } +func (ts *testTypeConvertSuite) TestToFloat64(c *C) { + testCases := []struct { + d Datum + errMsg string + result float64 + }{ + {NewDatum(float32(3.00)), "", 3.00}, + {NewDatum(float64(12345.678)), "", 12345.678}, + {NewDatum("12345.678"), "", 12345.678}, + {NewDatum([]byte("12345.678")), "", 12345.678}, + {NewDatum(int64(12345)), "", 12345}, + {NewDatum(uint64(123456)), "", 123456}, + {NewDatum(byte(123)), "cannot convert .*", 0}, + } + + sc := new(stmtctx.StatementContext) + sc.IgnoreTruncate = true + for _, t := range testCases { + converted, err := t.d.ToFloat64(sc) + if t.errMsg == "" { + c.Assert(err, IsNil) + } else { + c.Assert(err, ErrorMatches, t.errMsg) + } + c.Assert(converted, Equals, t.result) + } +} + // mustParseTimeIntoDatum is similar to ParseTime but panic if any error occurs. func mustParseTimeIntoDatum(s string, tp byte, fsp int) (d Datum) { t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp) diff --git a/types/helper_test.go b/types/helper_test.go index fa39980252901..434a88c7d0e2f 100644 --- a/types/helper_test.go +++ b/types/helper_test.go @@ -26,6 +26,7 @@ type testTypeHelperSuite struct { } func (s *testTypeHelperSuite) TestStrToInt(c *C) { + c.Parallel() tests := []struct { input string output string @@ -44,3 +45,21 @@ func (s *testTypeHelperSuite) TestStrToInt(c *C) { c.Check(strconv.FormatInt(output, 10), Equals, tt.output) } } + +func (s *testTypeHelperSuite) TestTruncate(c *C) { + c.Parallel() + tests := []struct { + f float64 + dec int + expected float64 + }{ + {123.45, 0, 123}, + {123.45, 1, 123.4}, + {123.45, 2, 123.45}, + {123.45, 3, 123.450}, + } + for _, tt := range tests { + res := Truncate(tt.f, tt.dec) + c.Assert(res, Equals, tt.expected) + } +} diff --git a/types/json/binary_functions_test.go b/types/json/binary_functions_test.go new file mode 100644 index 0000000000000..1d63e880e8aae --- /dev/null +++ b/types/json/binary_functions_test.go @@ -0,0 +1,31 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. +package json + +import ( + . "github.com/pingcap/check" +) + +var _ = Suite(&testJSONFuncSuite{}) + +type testJSONFuncSuite struct{} + +func (s *testJSONFuncSuite) TestdecodeEscapedUnicode(c *C) { + c.Parallel() + in := "597d" + r, size, err := decodeEscapedUnicode([]byte(in)) + c.Assert(string(r[:]), Equals, "好\x00") + c.Assert(size, Equals, 3) + c.Assert(err, IsNil) + +} diff --git a/types/mytime_test.go b/types/mytime_test.go index 8d9d8d016a68f..f2897c878908b 100644 --- a/types/mytime_test.go +++ b/types/mytime_test.go @@ -14,6 +14,8 @@ package types import ( + "time" + . "github.com/pingcap/check" ) @@ -228,3 +230,44 @@ func (s *testMyTimeSuite) TestGetLastDay(c *C) { c.Assert(day, Equals, t.expectedDay) } } + +func (s *testMyTimeSuite) TestgetFixDays(c *C) { + tests := []struct { + year int + month int + day int + ot time.Time + expectedDay int + }{ + {2000, 1, 0, time.Date(2000, 1, 31, 0, 0, 0, 0, time.UTC), -2}, + {2000, 1, 12, time.Date(2000, 1, 31, 0, 0, 0, 0, time.UTC), 0}, + {2000, 1, 12, time.Date(2000, 1, 0, 0, 0, 0, 0, time.UTC), 0}, + {2000, 2, 24, time.Date(2000, 2, 10, 0, 0, 0, 0, time.UTC), 0}, + {2019, 04, 05, time.Date(2019, 04, 01, 1, 2, 3, 4, time.UTC), 0}, + } + + for _, t := range tests { + res := getFixDays(t.year, t.month, t.day, t.ot) + c.Assert(res, Equals, t.expectedDay) + } +} + +func (s *testMyTimeSuite) TestAddDate(c *C) { + tests := []struct { + year int + month int + day int + ot time.Time + }{ + {01, 1, 0, time.Date(2000, 1, 01, 0, 0, 0, 0, time.UTC)}, + {02, 1, 12, time.Date(2000, 1, 01, 0, 0, 0, 0, time.UTC)}, + {03, 1, 12, time.Date(2000, 1, 01, 0, 0, 0, 0, time.UTC)}, + {04, 2, 24, time.Date(2000, 2, 10, 0, 0, 0, 0, time.UTC)}, + {01, 04, 05, time.Date(2019, 04, 01, 1, 2, 3, 4, time.UTC)}, + } + + for _, t := range tests { + res := AddDate(int64(t.year), int64(t.month), int64(t.day), t.ot) + c.Assert(res.Year(), Equals, t.year+t.ot.Year()) + } +} diff --git a/types/overflow_test.go b/types/overflow_test.go index 0f2fb0fc435c0..43d6d84a88c9a 100644 --- a/types/overflow_test.go +++ b/types/overflow_test.go @@ -305,6 +305,7 @@ func (s *testOverflowSuite) TestDiv(c *C) { {1, -1, 0, true}, {math.MaxInt64, math.MinInt64, 0, false}, {math.MaxInt64, -1, 0, true}, + {100, 20, 5, false}, } for _, t := range tblInt { diff --git a/types/time_test.go b/types/time_test.go index e7cf071ea23ee..d5a88c7c25c59 100644 --- a/types/time_test.go +++ b/types/time_test.go @@ -758,6 +758,21 @@ func (s *testTimeSuite) TestRoundFrac(c *C) { c.Assert(err, IsNil) c.Assert(nv.String(), Equals, t.Except) } + + cols := []struct { + input time.Time + fsp int + output time.Time + }{ + {time.Date(2011, 11, 11, 10, 10, 10, 888888, time.UTC), 0, time.Date(2011, 11, 11, 10, 10, 10, 11, time.UTC)}, + {time.Date(2011, 11, 11, 10, 10, 10, 111111, time.UTC), 0, time.Date(2011, 11, 11, 10, 10, 10, 10, time.UTC)}, + } + + for _, col := range cols { + res, err := types.RoundFrac(col.input, col.fsp) + c.Assert(res.Second(), Equals, col.output.Second()) + c.Assert(err, IsNil) + } } func (s *testTimeSuite) TestConvert(c *C) { @@ -832,6 +847,12 @@ func (s *testTimeSuite) TestCompare(c *C) { c.Assert(ret, Equals, t.Ret) } + v1, err := types.ParseTime(nil, "2011-10-10 11:11:11", mysql.TypeDatetime, types.MaxFsp) + c.Assert(err, IsNil) + res, err := v1.CompareString(nil, "Test should error") + c.Assert(err, NotNil) + c.Assert(res, Equals, 0) + tbl = []struct { Arg1 string Arg2 string @@ -1337,3 +1358,74 @@ func (s *testTimeSuite) TestgetFracIndex(c *C) { c.Assert(index, Equals, testCase.expectIndex) } } + +func (s *testTimeSuite) TestTimeOverflow(c *C) { + sc := mock.NewContext().GetSessionVars().StmtCtx + sc.IgnoreZeroInDate = true + defer testleak.AfterTest(c)() + table := []struct { + Input string + Output bool + }{ + {"2012-12-31 11:30:45", false}, + {"12-12-31 11:30:45", false}, + {"2012-12-31", false}, + {"20121231", false}, + {"2012-02-29", false}, + {"2018-01-01 18", false}, + {"18-01-01 18", false}, + {"2018.01.01", false}, + {"2018.01.01 00:00:00", false}, + {"2018/01/01-00:00:00", false}, + } + + for _, test := range table { + t, err := types.ParseDatetime(sc, test.Input) + c.Assert(err, IsNil) + isOverflow, err := types.DateTimeIsOverflow(sc, t) + c.Assert(err, IsNil) + c.Assert(isOverflow, Equals, test.Output) + } +} + +func (s *testTimeSuite) TestTruncateFrac(c *C) { + cols := []struct { + input time.Time + fsp int + output time.Time + }{ + {time.Date(2011, 11, 11, 10, 10, 10, 888888, time.UTC), 0, time.Date(2011, 11, 11, 10, 10, 10, 11, time.UTC)}, + {time.Date(2011, 11, 11, 10, 10, 10, 111111, time.UTC), 0, time.Date(2011, 11, 11, 10, 10, 10, 10, time.UTC)}, + } + + for _, col := range cols { + res, err := types.TruncateFrac(col.input, col.fsp) + c.Assert(res.Second(), Equals, col.output.Second()) + c.Assert(err, IsNil) + } +} +func (s *testTimeSuite) TestTimeSub(c *C) { + tbl := []struct { + Arg1 string + Arg2 string + Ret string + }{ + {"2017-01-18 01:01:01", "2017-01-18 00:00:01", "01:01:00"}, + {"2017-01-18 01:01:01", "2017-01-18 01:01:01", "00:00:00"}, + {"2019-04-12 18:20:00", "2019-04-12 14:00:00", "04:20:00"}, + } + + sc := &stmtctx.StatementContext{ + TimeZone: time.UTC, + } + for _, t := range tbl { + v1, err := types.ParseTime(nil, t.Arg1, mysql.TypeDatetime, types.MaxFsp) + c.Assert(err, IsNil) + v2, err := types.ParseTime(nil, t.Arg2, mysql.TypeDatetime, types.MaxFsp) + c.Assert(err, IsNil) + dur, err := types.ParseDuration(sc, t.Ret, types.MaxFsp) + c.Assert(err, IsNil) + rec := v1.Sub(sc, &v2) + c.Assert(rec, Equals, dur) + } +}