github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/value/cast_test.go (about)

     1  package value
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
    11  )
    12  
    13  func ptr[T any]() interface{} {
    14  	var zeroValue T
    15  
    16  	return &zeroValue
    17  }
    18  
    19  func value2ptr[T any](v T) *T {
    20  	return &v
    21  }
    22  
    23  func unwrapPtr(v interface{}) interface{} {
    24  	return reflect.ValueOf(v).Elem().Interface()
    25  }
    26  
    27  func loadLocation(T *testing.T, name string) *time.Location {
    28  	loc, err := time.LoadLocation(name)
    29  	require.NoError(T, err)
    30  
    31  	return loc
    32  }
    33  
    34  func TestCastTo(t *testing.T) {
    35  	testsCases := []struct {
    36  		name  string
    37  		value Value
    38  		dst   interface{}
    39  		exp   interface{}
    40  		err   error
    41  	}{
    42  		{
    43  			name:  xtest.CurrentFileLine(),
    44  			value: TextValue("test"),
    45  			dst:   (interface{})(nil),
    46  			err:   errNilDestination,
    47  		},
    48  
    49  		{
    50  			name:  xtest.CurrentFileLine(),
    51  			value: TextValue("test"),
    52  			dst:   ptr[Value](),
    53  			exp:   TextValue("test"),
    54  			err:   nil,
    55  		},
    56  		{
    57  			name:  xtest.CurrentFileLine(),
    58  			value: OptionalValue(TextValue("test")),
    59  			dst:   ptr[Value](),
    60  			exp:   OptionalValue(TextValue("test")),
    61  			err:   nil,
    62  		},
    63  		{
    64  			name:  xtest.CurrentFileLine(),
    65  			value: TextValue("test"),
    66  			dst:   ptr[string](),
    67  			exp:   "test",
    68  			err:   nil,
    69  		},
    70  		{
    71  			name:  xtest.CurrentFileLine(),
    72  			value: OptionalValue(TextValue("test")),
    73  			dst:   ptr[*string](),
    74  			exp:   value2ptr("test"),
    75  			err:   nil,
    76  		},
    77  		{
    78  			name:  xtest.CurrentFileLine(),
    79  			value: TextValue("test"),
    80  			dst:   ptr[[]byte](),
    81  			exp:   []byte("test"),
    82  			err:   nil,
    83  		},
    84  		{
    85  			name:  xtest.CurrentFileLine(),
    86  			value: OptionalValue(TextValue("test")),
    87  			dst:   ptr[*[]byte](),
    88  			exp:   value2ptr([]byte("test")),
    89  			err:   nil,
    90  		},
    91  		{
    92  			name:  xtest.CurrentFileLine(),
    93  			value: TextValue("test"),
    94  			dst:   ptr[[]byte](),
    95  			exp:   []byte("test"),
    96  			err:   nil,
    97  		},
    98  		{
    99  			name:  xtest.CurrentFileLine(),
   100  			value: TextValue("test"),
   101  			dst:   ptr[int](),
   102  			err:   ErrCannotCast,
   103  		},
   104  
   105  		{
   106  			name:  xtest.CurrentFileLine(),
   107  			value: BytesValue([]byte("test")),
   108  			dst:   ptr[Value](),
   109  			exp:   BytesValue([]byte("test")),
   110  			err:   nil,
   111  		},
   112  		{
   113  			name:  xtest.CurrentFileLine(),
   114  			value: BytesValue([]byte("test")),
   115  			dst:   ptr[string](),
   116  			exp:   "test",
   117  			err:   nil,
   118  		},
   119  		{
   120  			name:  xtest.CurrentFileLine(),
   121  			value: BytesValue([]byte("test")),
   122  			dst:   ptr[[]byte](),
   123  			exp:   []byte("test"),
   124  			err:   nil,
   125  		},
   126  		{
   127  			name:  xtest.CurrentFileLine(),
   128  			value: BytesValue([]byte("test")),
   129  			dst:   ptr[[]byte](),
   130  			exp:   []byte("test"),
   131  			err:   nil,
   132  		},
   133  		{
   134  			name:  xtest.CurrentFileLine(),
   135  			value: BytesValue([]byte("test")),
   136  			dst:   ptr[int](),
   137  			err:   ErrCannotCast,
   138  		},
   139  
   140  		{
   141  			name:  xtest.CurrentFileLine(),
   142  			value: JSONDocumentValue(`{"test": "text"}"`),
   143  			dst:   ptr[string](),
   144  			exp:   `{"test": "text"}"`,
   145  			err:   nil,
   146  		},
   147  		{
   148  			name:  xtest.CurrentFileLine(),
   149  			value: JSONDocumentValue(`{"test":"text"}"`),
   150  			dst:   ptr[Value](),
   151  			exp:   JSONDocumentValue(`{"test":"text"}"`),
   152  			err:   nil,
   153  		},
   154  		{
   155  			name:  xtest.CurrentFileLine(),
   156  			value: OptionalValue(JSONDocumentValue(`{"test": "text"}"`)),
   157  			dst:   ptr[*[]byte](),
   158  			exp:   value2ptr([]byte(`{"test": "text"}"`)),
   159  			err:   nil,
   160  		},
   161  		{
   162  			name:  xtest.CurrentFileLine(),
   163  			value: JSONDocumentValue(`{"test":"text"}"`),
   164  			dst:   ptr[[]byte](),
   165  			exp:   []byte(`{"test":"text"}"`),
   166  			err:   nil,
   167  		},
   168  
   169  		{
   170  			name:  xtest.CurrentFileLine(),
   171  			value: BoolValue(true),
   172  			dst:   ptr[bool](),
   173  			exp:   true,
   174  			err:   nil,
   175  		},
   176  		{
   177  			name:  xtest.CurrentFileLine(),
   178  			value: BoolValue(true),
   179  			dst:   ptr[Value](),
   180  			exp:   BoolValue(true),
   181  			err:   nil,
   182  		},
   183  		{
   184  			name:  xtest.CurrentFileLine(),
   185  			value: OptionalValue(BoolValue(true)),
   186  			dst:   ptr[*bool](),
   187  			exp:   value2ptr(true),
   188  			err:   nil,
   189  		},
   190  
   191  		{
   192  			name:  xtest.CurrentFileLine(),
   193  			value: Int32Value(123),
   194  			dst:   ptr[int32](),
   195  			exp:   int32(123),
   196  			err:   nil,
   197  		},
   198  		{
   199  			name:  xtest.CurrentFileLine(),
   200  			value: Int32Value(123),
   201  			dst:   ptr[Value](),
   202  			exp:   Int32Value(123),
   203  			err:   nil,
   204  		},
   205  		{
   206  			name:  xtest.CurrentFileLine(),
   207  			value: Int32Value(123),
   208  			dst:   ptr[int64](),
   209  			exp:   int64(123),
   210  			err:   nil,
   211  		},
   212  		{
   213  			name:  xtest.CurrentFileLine(),
   214  			value: Int32Value(123),
   215  			dst:   ptr[float32](),
   216  			exp:   float32(123),
   217  			err:   nil,
   218  		},
   219  		{
   220  			name:  xtest.CurrentFileLine(),
   221  			value: Int32Value(123),
   222  			dst:   ptr[float64](),
   223  			exp:   float64(123),
   224  			err:   nil,
   225  		},
   226  		{
   227  			name:  xtest.CurrentFileLine(),
   228  			value: OptionalValue(Int32Value(123)),
   229  			dst:   ptr[*int32](),
   230  			exp:   value2ptr(int32(123)),
   231  			err:   nil,
   232  		},
   233  		{
   234  			name:  xtest.CurrentFileLine(),
   235  			value: Int32Value(123),
   236  			dst:   ptr[string](),
   237  			exp:   "123",
   238  			err:   nil,
   239  		},
   240  		{
   241  			name:  xtest.CurrentFileLine(),
   242  			value: Int32Value(123),
   243  			dst:   ptr[[]byte](),
   244  			exp:   []byte("123"),
   245  			err:   nil,
   246  		},
   247  
   248  		{
   249  			name:  xtest.CurrentFileLine(),
   250  			value: Int64Value(123),
   251  			dst:   ptr[int64](),
   252  			exp:   int64(123),
   253  			err:   nil,
   254  		},
   255  		{
   256  			name:  xtest.CurrentFileLine(),
   257  			value: Int64Value(123),
   258  			dst:   ptr[Value](),
   259  			exp:   Int64Value(123),
   260  			err:   nil,
   261  		},
   262  		{
   263  			name:  xtest.CurrentFileLine(),
   264  			value: OptionalValue(Int64Value(123)),
   265  			dst:   ptr[*int64](),
   266  			exp:   value2ptr(int64(123)),
   267  			err:   nil,
   268  		},
   269  		{
   270  			name:  xtest.CurrentFileLine(),
   271  			value: Int64Value(123),
   272  			dst:   ptr[float64](),
   273  			exp:   float64(123),
   274  			err:   nil,
   275  		},
   276  		{
   277  			name:  xtest.CurrentFileLine(),
   278  			value: Int64Value(123),
   279  			dst:   ptr[string](),
   280  			exp:   "123",
   281  			err:   nil,
   282  		},
   283  		{
   284  			name:  xtest.CurrentFileLine(),
   285  			value: Int64Value(123),
   286  			dst:   ptr[[]byte](),
   287  			exp:   []byte("123"),
   288  			err:   nil,
   289  		},
   290  
   291  		{
   292  			name:  xtest.CurrentFileLine(),
   293  			value: DoubleValue(1.23),
   294  			dst:   ptr[float64](),
   295  			exp:   1.23,
   296  			err:   nil,
   297  		},
   298  		{
   299  			name:  xtest.CurrentFileLine(),
   300  			value: DoubleValue(1.23),
   301  			dst:   ptr[Value](),
   302  			exp:   DoubleValue(1.23),
   303  			err:   nil,
   304  		},
   305  		{
   306  			name:  xtest.CurrentFileLine(),
   307  			value: OptionalValue(DoubleValue(1.23)),
   308  			dst:   ptr[*float64](),
   309  			exp:   value2ptr(1.23),
   310  			err:   nil,
   311  		},
   312  
   313  		{
   314  			name:  xtest.CurrentFileLine(),
   315  			value: IntervalValueFromDuration(time.Second),
   316  			dst:   ptr[time.Duration](),
   317  			exp:   time.Second,
   318  			err:   nil,
   319  		},
   320  		{
   321  			name:  xtest.CurrentFileLine(),
   322  			value: IntervalValueFromDuration(time.Second),
   323  			dst:   ptr[Value](),
   324  			exp:   IntervalValueFromDuration(time.Second),
   325  			err:   nil,
   326  		},
   327  
   328  		// nanoseconds are ignored in YDB timestamps
   329  		{
   330  			name:  xtest.CurrentFileLine(),
   331  			value: TimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local)),
   332  			dst:   ptr[time.Time](),
   333  			exp:   time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local),
   334  			err:   nil,
   335  		},
   336  		{
   337  			name:  xtest.CurrentFileLine(),
   338  			value: TimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local)),
   339  			dst:   ptr[Value](),
   340  			exp:   TimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local)),
   341  			err:   nil,
   342  		},
   343  		{
   344  			name:  xtest.CurrentFileLine(),
   345  			value: TimestampValue(uint64(time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local).Unix())),
   346  			dst:   ptr[uint64](),
   347  			exp:   uint64(time.Date(2024, 1, 2, 3, 4, 5, 0, time.Local).Unix()),
   348  			err:   nil,
   349  		},
   350  
   351  		// nanoseconds are ignored in YDB timestamps
   352  		{
   353  			name:  xtest.CurrentFileLine(),
   354  			value: TzTimestampValue("2024-01-02T03:04:05.000000,Europe/Moscow"),
   355  			dst:   ptr[time.Time](),
   356  			exp:   time.Date(2024, 1, 2, 3, 4, 5, 0, loadLocation(t, "Europe/Moscow")),
   357  			err:   nil,
   358  		},
   359  		{
   360  			name:  xtest.CurrentFileLine(),
   361  			value: TzTimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)),
   362  			dst:   ptr[string](),
   363  			exp:   "2024-01-02T03:04:05.000000Z",
   364  			err:   nil,
   365  		},
   366  		{
   367  			name:  xtest.CurrentFileLine(),
   368  			value: TzTimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)),
   369  			dst:   ptr[[]byte](),
   370  			exp:   []byte("2024-01-02T03:04:05.000000Z"),
   371  			err:   nil,
   372  		},
   373  		{
   374  			name:  xtest.CurrentFileLine(),
   375  			value: TzTimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)),
   376  			dst:   ptr[Value](),
   377  			exp:   TzTimestampValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)),
   378  			err:   nil,
   379  		},
   380  
   381  		{
   382  			name:  xtest.CurrentFileLine(),
   383  			value: DateValue(uint32(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC).Unix())),
   384  			dst:   ptr[int32](),
   385  			exp:   int32(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC).Unix()),
   386  			err:   nil,
   387  		},
   388  		{
   389  			name:  xtest.CurrentFileLine(),
   390  			value: DateValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC)),
   391  			dst:   ptr[uint64](),
   392  			exp:   uint64(DateValueFromTime(time.Date(2024, 1, 2, 3, 4, 5, 0, time.UTC))),
   393  			err:   nil,
   394  		},
   395  		{
   396  			name:  xtest.CurrentFileLine(),
   397  			value: DateValueFromTime(time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC)),
   398  			dst:   ptr[int64](),
   399  			exp:   int64(DateValueFromTime(time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC))),
   400  			err:   nil,
   401  		},
   402  		{
   403  			name:  xtest.CurrentFileLine(),
   404  			value: DateValueFromTime(time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC)),
   405  			dst:   ptr[time.Time](),
   406  			exp:   time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC),
   407  			err:   nil,
   408  		},
   409  		{
   410  			name:  xtest.CurrentFileLine(),
   411  			value: DateValueFromTime(time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC)),
   412  			dst:   ptr[Value](),
   413  			exp:   DateValueFromTime(time.Date(2024, 1, 2, 0, 0, 0, 0, time.UTC)),
   414  			err:   nil,
   415  		},
   416  	}
   417  	for _, tt := range testsCases {
   418  		t.Run(tt.name, func(t *testing.T) {
   419  			if tt.err == nil {
   420  				require.NoError(t, CastTo(tt.value, tt.dst))
   421  				require.Equal(t, tt.exp, unwrapPtr(tt.dst))
   422  			} else {
   423  				require.ErrorIs(t, CastTo(tt.value, tt.dst), tt.err)
   424  			}
   425  		})
   426  	}
   427  }