github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/util/datetime/date_time_test.go (about)

     1  // Copyright 2019 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // This file incorporates work covered by the following copyright and
    16  // permission notice:
    17  //
    18  // Copyright 2017 Attic Labs, Inc. All rights reserved.
    19  // Licensed under the Apache License, version 2.0:
    20  // http://www.apache.org/licenses/LICENSE-2.0
    21  
    22  package datetime
    23  
    24  import (
    25  	"context"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  
    32  	"github.com/dolthub/dolt/go/store/chunks"
    33  	"github.com/dolthub/dolt/go/store/d"
    34  	"github.com/dolthub/dolt/go/store/marshal"
    35  	"github.com/dolthub/dolt/go/store/types"
    36  )
    37  
    38  func TestBasics(t *testing.T) {
    39  	assert := assert.New(t)
    40  
    41  	vs := newTestValueStore()
    42  	defer vs.Close()
    43  
    44  	// Since we are using float64 in noms we cannot represent all possible times.
    45  	dt := DateTime{time.Unix(1234567, 1234567)}
    46  
    47  	nomsValue, err := marshal.Marshal(context.Background(), vs, dt)
    48  	assert.NoError(err)
    49  
    50  	var dt2 DateTime
    51  	err = marshal.Unmarshal(context.Background(), types.Format_Default, nomsValue, &dt2)
    52  	assert.NoError(err)
    53  
    54  	assert.True(dt.Equal(dt2.Time))
    55  }
    56  
    57  func mustStruct(st types.Struct, err error) types.Struct {
    58  	d.PanicIfError(err)
    59  	return st
    60  }
    61  
    62  func TestUnmarshal(t *testing.T) {
    63  	assert := assert.New(t)
    64  
    65  	test := func(v types.Struct, t time.Time) {
    66  		var dt DateTime
    67  		err := marshal.Unmarshal(context.Background(), types.Format_Default, v, &dt)
    68  		assert.NoError(err)
    69  		assert.True(dt.Equal(t))
    70  	}
    71  
    72  	for _, name := range []string{"DateTime", "Date", "xxx", ""} {
    73  		test(mustStruct(types.NewStruct(types.Format_Default, name, types.StructData{
    74  			"secSinceEpoch": types.Float(42),
    75  		})), time.Unix(42, 0))
    76  	}
    77  
    78  	test(mustStruct(types.NewStruct(types.Format_Default, "", types.StructData{
    79  		"secSinceEpoch": types.Float(42),
    80  		"extra":         types.String("field"),
    81  	})), time.Unix(42, 0))
    82  }
    83  
    84  func TestUnmarshalInvalid(t *testing.T) {
    85  	assert := assert.New(t)
    86  
    87  	test := func(v types.Value) {
    88  		var dt DateTime
    89  		err := marshal.Unmarshal(context.Background(), types.Format_Default, v, &dt)
    90  		assert.Error(err)
    91  	}
    92  
    93  	test(types.Float(42))
    94  	test(mustStruct(types.NewStruct(types.Format_Default, "DateTime", types.StructData{})))
    95  	test(mustStruct(types.NewStruct(types.Format_Default, "DateTime", types.StructData{
    96  		"secSinceEpoch": types.String("42"),
    97  	})))
    98  	test(mustStruct(types.NewStruct(types.Format_Default, "DateTime", types.StructData{
    99  		"SecSinceEpoch": types.Float(42),
   100  	})))
   101  	test(mustStruct(types.NewStruct(types.Format_Default, "DateTime", types.StructData{
   102  		"msSinceEpoch": types.Float(42),
   103  	})))
   104  }
   105  
   106  func TestMarshal(t *testing.T) {
   107  	assert := assert.New(t)
   108  
   109  	vs := newTestValueStore()
   110  	defer vs.Close()
   111  
   112  	test := func(dt DateTime, expected float64) {
   113  		v, err := marshal.Marshal(context.Background(), vs, dt)
   114  		assert.NoError(err)
   115  		st, err := types.NewStruct(types.Format_Default, "DateTime", types.StructData{
   116  			"secSinceEpoch": types.Float(expected),
   117  		})
   118  		assert.NoError(err)
   119  		assert.True(st.Equals(v))
   120  	}
   121  
   122  	test(DateTime{time.Unix(0, 0)}, 0)
   123  	test(DateTime{time.Unix(42, 0)}, 42)
   124  	test(DateTime{time.Unix(42, 123456789)}, 42.123456789)
   125  	test(DateTime{time.Unix(123456789, 123456789)}, 123456789.123456789)
   126  	test(DateTime{time.Unix(-42, 0)}, -42)
   127  	test(DateTime{time.Unix(-42, -123456789)}, -42.123456789)
   128  	test(DateTime{time.Unix(-123456789, -123456789)}, -123456789.123456789)
   129  }
   130  
   131  func TestMarshalType(t *testing.T) {
   132  	assert := assert.New(t)
   133  
   134  	vs := newTestValueStore()
   135  	defer vs.Close()
   136  
   137  	dt := DateTime{time.Unix(0, 0)}
   138  	typ, err := marshal.MarshalType(types.Format_Default, dt)
   139  	assert.NoError(err)
   140  	assert.Equal(DateTimeType, typ)
   141  
   142  	v, err := marshal.Marshal(context.Background(), vs, dt)
   143  	assert.NoError(err)
   144  	typ2, err := types.TypeOf(v)
   145  	assert.NoError(err)
   146  	assert.Equal(typ, typ2)
   147  }
   148  
   149  func newTestValueStore() *types.ValueStore {
   150  	st := &chunks.TestStorage{}
   151  	return types.NewValueStore(st.NewViewWithDefaultFormat())
   152  }
   153  
   154  func TestZeroValues(t *testing.T) {
   155  	assert := assert.New(t)
   156  
   157  	vs := newTestValueStore()
   158  	defer vs.Close()
   159  
   160  	dt1 := DateTime{}
   161  	assert.True(dt1.IsZero())
   162  
   163  	nomsDate, _ := dt1.MarshalNoms(vs)
   164  
   165  	dt2 := DateTime{}
   166  	marshal.Unmarshal(context.Background(), types.Format_Default, nomsDate, &dt2)
   167  	assert.True(dt2.IsZero())
   168  
   169  	dt3 := DateTime{}
   170  	dt3.UnmarshalNoms(context.Background(), types.Format_Default, nomsDate)
   171  	assert.True(dt3.IsZero())
   172  }
   173  
   174  func TestString(t *testing.T) {
   175  	assert := assert.New(t)
   176  	dt := DateTime{time.Unix(1234567, 1234567)}
   177  	// Don't test the actual output since that
   178  	assert.IsType(dt.String(), "s")
   179  }
   180  
   181  func TestEpoch(t *testing.T) {
   182  	assert := assert.New(t)
   183  	assert.Equal(Epoch, DateTime{time.Unix(0, 0)})
   184  }
   185  
   186  func TestHRSComment(t *testing.T) {
   187  	a := assert.New(t)
   188  	vs := newTestValueStore()
   189  
   190  	dt := Now()
   191  	mdt, err := marshal.Marshal(context.Background(), vs, dt)
   192  	a.NoError(err)
   193  
   194  	exp := dt.Format(time.RFC3339)
   195  	s1, err := types.EncodedValue(context.Background(), mdt)
   196  	a.NoError(err)
   197  	a.True(strings.Contains(s1, "{ // "+exp))
   198  
   199  	RegisterHRSCommenter(time.UTC)
   200  	exp = dt.In(time.UTC).Format((time.RFC3339))
   201  	s1, err = types.EncodedValue(context.Background(), mdt)
   202  	a.NoError(err)
   203  	a.True(strings.Contains(s1, "{ // "+exp))
   204  
   205  	types.UnregisterHRSCommenter(datetypename, hrsEncodingName)
   206  	s1, err = types.EncodedValue(context.Background(), mdt)
   207  	a.NoError(err)
   208  	a.False(strings.Contains(s1, "{ // 20"))
   209  }