github.com/weaviate/weaviate@v1.24.6/usecases/objects/validation/properties_validation_test.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package validation
    13  
    14  import (
    15  	"context"
    16  	"encoding/json"
    17  	"fmt"
    18  	"reflect"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/go-openapi/strfmt"
    23  	"github.com/google/uuid"
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  	"github.com/weaviate/weaviate/entities/additional"
    27  	"github.com/weaviate/weaviate/entities/models"
    28  	"github.com/weaviate/weaviate/entities/schema"
    29  	"github.com/weaviate/weaviate/usecases/config"
    30  )
    31  
    32  func TestValidator_extractAndValidateProperty(t *testing.T) {
    33  	type fields struct {
    34  		schema schema.Schema
    35  		exists exists
    36  		config *config.WeaviateConfig
    37  	}
    38  	type args struct {
    39  		ctx          context.Context
    40  		propertyName string
    41  		pv           interface{}
    42  		className    string
    43  		dataType     *schema.DataType
    44  	}
    45  	validatorFields := fields{
    46  		schema: schema.Schema{
    47  			Objects: &models.Schema{
    48  				Classes: []*models.Class{
    49  					{
    50  						Class: "BlobClass",
    51  						Properties: []*models.Property{
    52  							{
    53  								DataType: []string{"blob"},
    54  								Name:     "blobProperty",
    55  							},
    56  						},
    57  					},
    58  				},
    59  			},
    60  		},
    61  	}
    62  	tests := []struct {
    63  		name    string
    64  		fields  fields
    65  		args    args
    66  		want    interface{}
    67  		wantErr bool
    68  	}{
    69  		{
    70  			name:   "Validate blob - empty base64 encoded image string",
    71  			fields: validatorFields,
    72  			args: args{
    73  				ctx:          context.Background(),
    74  				propertyName: "blobProperty",
    75  				pv:           "",
    76  				className:    "BlobClass",
    77  				dataType:     getDataType(schema.DataTypeBlob),
    78  			},
    79  			want:    nil,
    80  			wantErr: true,
    81  		},
    82  		{
    83  			name:   "Validate blob - invalid base64 encoded image string",
    84  			fields: validatorFields,
    85  			args: args{
    86  				ctx:          context.Background(),
    87  				propertyName: "blobProperty",
    88  				pv:           "image",
    89  				className:    "BlobClass",
    90  				dataType:     getDataType(schema.DataTypeBlob),
    91  			},
    92  			want:    nil,
    93  			wantErr: true,
    94  		},
    95  		{
    96  			name:   "Validate blob - valid base64 encoded string but with type definition before image string",
    97  			fields: validatorFields,
    98  			args: args{
    99  				ctx:          context.Background(),
   100  				propertyName: "blobProperty",
   101  				pv:           "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAAA/CAYAAAAfQM0aAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRjQ5NEM3RDI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRjQ5NEM3RTI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJGNDk0QzdCMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJGNDk0QzdDMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+WeGRxAAAB2hJREFUeNrUXFts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",
   102  				className:    "BlobClass",
   103  				dataType:     getDataType(schema.DataTypeBlob),
   104  			},
   105  			want:    nil,
   106  			wantErr: true,
   107  		},
   108  		{
   109  			name:   "Validate blob - valid base64 encoded string",
   110  			fields: validatorFields,
   111  			args: args{
   112  				ctx:          context.Background(),
   113  				propertyName: "blobProperty",
   114  				pv:           "iVBORw0KGgoAAAANSUhEUgAAAGAAAAA/CAYAAAAfQM0aAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRjQ5NEM3RDI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRjQ5NEM3RTI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJGNDk0QzdCMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJGNDk0QzdDMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+WeGRxAAAB2hJREFUeNrUXFts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",
   115  				className:    "BlobClass",
   116  				dataType:     getDataType(schema.DataTypeBlob),
   117  			},
   118  			want:    "iVBORw0KGgoAAAANSUhEUgAAAGAAAAA/CAYAAAAfQM0aAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRjQ5NEM3RDI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRjQ5NEM3RTI5QTkxMUUyOTc1NENCMzI4N0QwNDNCOSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJGNDk0QzdCMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJGNDk0QzdDMjlBOTExRTI5NzU0Q0IzMjg3RDA0M0I5Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+WeGRxAAAB2hJREFUeNrUXFts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",
   119  			wantErr: false,
   120  		},
   121  		{
   122  			name:   "Validate blob - nil entry",
   123  			fields: validatorFields,
   124  			args: args{
   125  				ctx:          context.Background(),
   126  				propertyName: "blobProperty",
   127  				pv:           nil,
   128  				className:    "BlobClass",
   129  				dataType:     getDataType(schema.DataTypeBlob),
   130  			},
   131  			want:    nil,
   132  			wantErr: true,
   133  		},
   134  	}
   135  	for _, tt := range tests {
   136  		t.Run(tt.name, func(t *testing.T) {
   137  			v := &Validator{
   138  				exists: tt.fields.exists,
   139  				config: tt.fields.config,
   140  			}
   141  			got, err := v.extractAndValidateProperty(tt.args.ctx, tt.args.propertyName, tt.args.pv, tt.args.className, tt.args.dataType, "")
   142  			if (err != nil) != tt.wantErr {
   143  				t.Errorf("Validator.extractAndValidateProperty() error = %v, wantErr %v", err, tt.wantErr)
   144  				return
   145  			}
   146  			if !reflect.DeepEqual(got, tt.want) {
   147  				t.Errorf("Validator.extractAndValidateProperty() = %v, want %v", got, tt.want)
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  func getDataType(dataType schema.DataType) *schema.DataType {
   154  	return &dataType
   155  }
   156  
   157  func TestProperties(t *testing.T) {
   158  	const myBeacon = "weaviate://localhost/things/8e555f0d-8590-48c2-a9a6-70772ed14c0a"
   159  	myJournalClass := &models.Class{
   160  		Properties: []*models.Property{{Name: "inJournal", DataType: []string{"Journal"}}},
   161  	}
   162  	specs := map[string]struct {
   163  		class     *models.Class
   164  		obj       *models.Object
   165  		expErr    bool
   166  		expBeacon strfmt.URI
   167  	}{
   168  		"incorrect cref body - example from issue #1253": {
   169  			class: myJournalClass,
   170  			obj: &models.Object{
   171  				Properties: map[string]any{"inJournal": []any{map[string]any{
   172  					"beacon": map[string]any{"beacon": myBeacon},
   173  				}}},
   174  			},
   175  			expErr: true,
   176  		},
   177  		"complete beacon": {
   178  			class: myJournalClass,
   179  			obj: &models.Object{
   180  				Properties: map[string]any{"inJournal": []any{map[string]any{
   181  					"beacon": myBeacon,
   182  				}}},
   183  			},
   184  			expBeacon: myBeacon,
   185  		},
   186  		"beacon without class": {
   187  			class: myJournalClass,
   188  			obj: &models.Object{
   189  				Properties: map[string]any{"inJournal": []any{map[string]any{
   190  					"beacon": "weaviate://foo/8e555f0d-8590-48c2-a9a6-70772ed14c0a",
   191  				}}},
   192  			},
   193  			expBeacon: "weaviate://localhost/Journal/8e555f0d-8590-48c2-a9a6-70772ed14c0a",
   194  		},
   195  	}
   196  	for name, spec := range specs {
   197  		t.Run(name, func(t *testing.T) {
   198  			validator := &Validator{exists: func(_ context.Context, class string, _ strfmt.UUID, _ *additional.ReplicationProperties, _ string) (bool, error) {
   199  				return true, nil
   200  			}}
   201  			gotErr := validator.properties(context.Background(), spec.class, spec.obj, nil)
   202  			if spec.expErr {
   203  				require.Error(t, gotErr)
   204  				return
   205  			}
   206  			require.NoError(t, gotErr)
   207  			props := spec.obj.Properties
   208  			gotBeacon := extractBeacon(t, props)
   209  			assert.Equal(t, spec.expBeacon, gotBeacon)
   210  		})
   211  	}
   212  }
   213  
   214  func extractBeacon(t *testing.T, props models.PropertySchema) strfmt.URI {
   215  	require.IsType(t, map[string]any{}, props)
   216  	require.Contains(t, props.(map[string]any), "inJournal")
   217  	journalProp := props.(map[string]any)["inJournal"]
   218  	require.IsType(t, models.MultipleRef{}, journalProp)
   219  	require.Len(t, journalProp.(models.MultipleRef), 1)
   220  	gotBeacon := journalProp.(models.MultipleRef)[0].Beacon
   221  	return gotBeacon
   222  }
   223  
   224  func TestValidator_ValuesCasting(t *testing.T) {
   225  	t.Run("int(s)", func(t *testing.T) {
   226  		type testCase struct {
   227  			value         interface{}
   228  			expectedValue float64
   229  			expectedErr   bool
   230  		}
   231  
   232  		testCases := []testCase{
   233  			{
   234  				value:         json.Number("123"),
   235  				expectedValue: float64(123),
   236  				expectedErr:   false,
   237  			},
   238  			{
   239  				value:         int64(123),
   240  				expectedValue: float64(123),
   241  				expectedErr:   false,
   242  			},
   243  			{
   244  				value:         float64(123),
   245  				expectedValue: float64(123),
   246  				expectedErr:   false,
   247  			},
   248  
   249  			{
   250  				value:         json.Number("123.5"),
   251  				expectedValue: float64(0),
   252  				expectedErr:   true,
   253  			},
   254  			{
   255  				value:         float64(123.5),
   256  				expectedValue: float64(0),
   257  				expectedErr:   true,
   258  			},
   259  			{
   260  				value:         "123.5",
   261  				expectedValue: float64(0),
   262  				expectedErr:   true,
   263  			},
   264  			{
   265  				value:         "something",
   266  				expectedValue: float64(0),
   267  				expectedErr:   true,
   268  			},
   269  			{
   270  				value:         true,
   271  				expectedValue: float64(0),
   272  				expectedErr:   true,
   273  			},
   274  		}
   275  
   276  		for i, tc := range testCases {
   277  			t.Run(fmt.Sprintf("int #%d", i), func(t *testing.T) {
   278  				value, err := intVal(tc.value)
   279  
   280  				if tc.expectedErr {
   281  					assert.Error(t, err)
   282  				} else {
   283  					assert.NoError(t, err)
   284  				}
   285  				assert.Equal(t, tc.expectedValue, value)
   286  			})
   287  		}
   288  		for i, tc := range testCases {
   289  			t.Run(fmt.Sprintf("ints (single) #%d", i), func(t *testing.T) {
   290  				value, err := intArrayVal(tc.value)
   291  
   292  				assert.Error(t, err)
   293  				assert.Nil(t, value)
   294  			})
   295  			t.Run(fmt.Sprintf("ints (array) #%d", i), func(t *testing.T) {
   296  				value, err := intArrayVal([]interface{}{tc.value})
   297  
   298  				if tc.expectedErr {
   299  					assert.Error(t, err)
   300  					assert.Nil(t, value)
   301  				} else {
   302  					assert.NoError(t, err)
   303  					assert.Equal(t, []float64{tc.expectedValue}, value)
   304  				}
   305  			})
   306  		}
   307  	})
   308  
   309  	t.Run("number(s)", func(t *testing.T) {
   310  		type testCase struct {
   311  			value         interface{}
   312  			expectedValue float64
   313  			expectedErr   bool
   314  		}
   315  
   316  		testCases := []testCase{
   317  			{
   318  				value:         json.Number("123"),
   319  				expectedValue: float64(123),
   320  				expectedErr:   false,
   321  			},
   322  			{
   323  				value:         int64(123),
   324  				expectedValue: float64(123),
   325  				expectedErr:   false,
   326  			},
   327  			{
   328  				value:         float64(123),
   329  				expectedValue: float64(123),
   330  				expectedErr:   false,
   331  			},
   332  			{
   333  				value:         json.Number("123.5"),
   334  				expectedValue: float64(123.5),
   335  				expectedErr:   false,
   336  			},
   337  			{
   338  				value:         float64(123.5),
   339  				expectedValue: float64(123.5),
   340  				expectedErr:   false,
   341  			},
   342  
   343  			{
   344  				value:         "123.5",
   345  				expectedValue: float64(0),
   346  				expectedErr:   true,
   347  			},
   348  			{
   349  				value:         "something",
   350  				expectedValue: float64(0),
   351  				expectedErr:   true,
   352  			},
   353  			{
   354  				value:         true,
   355  				expectedValue: float64(0),
   356  				expectedErr:   true,
   357  			},
   358  		}
   359  
   360  		for i, tc := range testCases {
   361  			t.Run(fmt.Sprintf("number #%d", i), func(t *testing.T) {
   362  				value, err := numberVal(tc.value)
   363  
   364  				if tc.expectedErr {
   365  					assert.Error(t, err)
   366  				} else {
   367  					assert.NoError(t, err)
   368  				}
   369  				assert.Equal(t, tc.expectedValue, value)
   370  			})
   371  		}
   372  		for i, tc := range testCases {
   373  			t.Run(fmt.Sprintf("numbers (single) #%d", i), func(t *testing.T) {
   374  				value, err := numberArrayVal(tc.value)
   375  
   376  				assert.Error(t, err)
   377  				assert.Nil(t, value)
   378  			})
   379  			t.Run(fmt.Sprintf("numbers (array) #%d", i), func(t *testing.T) {
   380  				value, err := numberArrayVal([]interface{}{tc.value})
   381  
   382  				if tc.expectedErr {
   383  					assert.Error(t, err)
   384  					assert.Nil(t, value)
   385  				} else {
   386  					assert.NoError(t, err)
   387  					assert.Equal(t, []float64{tc.expectedValue}, value)
   388  				}
   389  			})
   390  		}
   391  	})
   392  
   393  	t.Run("string(s)", func(t *testing.T) {
   394  		type testCase struct {
   395  			value         interface{}
   396  			expectedValue string
   397  			expectedErr   bool
   398  		}
   399  
   400  		testCases := []testCase{
   401  			{
   402  				value:         "123.5",
   403  				expectedValue: "123.5",
   404  				expectedErr:   false,
   405  			},
   406  			{
   407  				value:         "something",
   408  				expectedValue: "something",
   409  				expectedErr:   false,
   410  			},
   411  
   412  			{
   413  				value:         json.Number("123"),
   414  				expectedValue: "",
   415  				expectedErr:   true,
   416  			},
   417  			{
   418  				value:         int64(123),
   419  				expectedValue: "",
   420  				expectedErr:   true,
   421  			},
   422  			{
   423  				value:         float64(123),
   424  				expectedValue: "",
   425  				expectedErr:   true,
   426  			},
   427  			{
   428  				value:         []byte("something"),
   429  				expectedValue: "",
   430  				expectedErr:   true,
   431  			},
   432  			{
   433  				value:         true,
   434  				expectedValue: "",
   435  				expectedErr:   true,
   436  			},
   437  		}
   438  
   439  		for i, tc := range testCases {
   440  			t.Run(fmt.Sprintf("string #%d", i), func(t *testing.T) {
   441  				value, err := stringVal(tc.value)
   442  
   443  				if tc.expectedErr {
   444  					assert.Error(t, err)
   445  				} else {
   446  					assert.NoError(t, err)
   447  				}
   448  				assert.Equal(t, tc.expectedValue, value)
   449  			})
   450  		}
   451  		for i, tc := range testCases {
   452  			t.Run(fmt.Sprintf("strings (single) #%d", i), func(t *testing.T) {
   453  				value, err := stringArrayVal(tc.value, "text")
   454  
   455  				assert.Error(t, err)
   456  				assert.Nil(t, value)
   457  			})
   458  			t.Run(fmt.Sprintf("strings (array) #%d", i), func(t *testing.T) {
   459  				value, err := stringArrayVal([]interface{}{tc.value}, "text")
   460  
   461  				if tc.expectedErr {
   462  					assert.Error(t, err)
   463  					assert.Nil(t, value)
   464  				} else {
   465  					assert.NoError(t, err)
   466  					assert.Equal(t, []string{tc.expectedValue}, value)
   467  				}
   468  			})
   469  		}
   470  	})
   471  
   472  	t.Run("bool(s)", func(t *testing.T) {
   473  		type testCase struct {
   474  			value         interface{}
   475  			expectedValue bool
   476  			expectedErr   bool
   477  		}
   478  
   479  		testCases := []testCase{
   480  			{
   481  				value:         true,
   482  				expectedValue: true,
   483  				expectedErr:   false,
   484  			},
   485  			{
   486  				value:         false,
   487  				expectedValue: false,
   488  				expectedErr:   false,
   489  			},
   490  
   491  			{
   492  				value:         float64(1),
   493  				expectedValue: false,
   494  				expectedErr:   true,
   495  			},
   496  			{
   497  				value:         int64(1),
   498  				expectedValue: false,
   499  				expectedErr:   true,
   500  			},
   501  			{
   502  				value:         "1",
   503  				expectedValue: false,
   504  				expectedErr:   true,
   505  			},
   506  			{
   507  				value:         "true",
   508  				expectedValue: false,
   509  				expectedErr:   true,
   510  			},
   511  			{
   512  				value:         "something",
   513  				expectedValue: false,
   514  				expectedErr:   true,
   515  			},
   516  		}
   517  
   518  		for i, tc := range testCases {
   519  			t.Run(fmt.Sprintf("bool #%d", i), func(t *testing.T) {
   520  				value, err := boolVal(tc.value)
   521  
   522  				if tc.expectedErr {
   523  					assert.Error(t, err)
   524  				} else {
   525  					assert.NoError(t, err)
   526  				}
   527  				assert.Equal(t, tc.expectedValue, value)
   528  			})
   529  		}
   530  		for i, tc := range testCases {
   531  			t.Run(fmt.Sprintf("bools (single) #%d", i), func(t *testing.T) {
   532  				value, err := boolArrayVal(tc.value)
   533  
   534  				assert.Error(t, err)
   535  				assert.Nil(t, value)
   536  			})
   537  			t.Run(fmt.Sprintf("bools (array) #%d", i), func(t *testing.T) {
   538  				value, err := boolArrayVal([]interface{}{tc.value})
   539  
   540  				if tc.expectedErr {
   541  					assert.Error(t, err)
   542  					assert.Nil(t, value)
   543  				} else {
   544  					assert.NoError(t, err)
   545  					assert.Equal(t, []bool{tc.expectedValue}, value)
   546  				}
   547  			})
   548  		}
   549  	})
   550  
   551  	t.Run("uuid(s)", func(t *testing.T) {
   552  		type testCase struct {
   553  			value         interface{}
   554  			expectedValue uuid.UUID
   555  			expectedErr   bool
   556  		}
   557  
   558  		testCases := []testCase{
   559  			{
   560  				value:         "e780b0a4-8d0e-4c09-898e-19d6b81e1e63",
   561  				expectedValue: uuid.MustParse("e780b0a4-8d0e-4c09-898e-19d6b81e1e63"),
   562  				expectedErr:   false,
   563  			},
   564  			{
   565  				value:         "e780b0a48d0e4c09898e19d6b81e1e63",
   566  				expectedValue: uuid.MustParse("e780b0a4-8d0e-4c09-898e-19d6b81e1e63"),
   567  				expectedErr:   false,
   568  			},
   569  
   570  			{
   571  				value:         float64(123),
   572  				expectedValue: [16]byte{},
   573  				expectedErr:   true,
   574  			},
   575  			{
   576  				value:         int64(123),
   577  				expectedValue: [16]byte{},
   578  				expectedErr:   true,
   579  			},
   580  			{
   581  				value:         "123",
   582  				expectedValue: [16]byte{},
   583  				expectedErr:   true,
   584  			},
   585  			{
   586  				value:         "something",
   587  				expectedValue: [16]byte{},
   588  				expectedErr:   true,
   589  			},
   590  			{
   591  				value:         true,
   592  				expectedValue: [16]byte{},
   593  				expectedErr:   true,
   594  			},
   595  		}
   596  
   597  		for i, tc := range testCases {
   598  			t.Run(fmt.Sprintf("uuid #%d", i), func(t *testing.T) {
   599  				value, err := uuidVal(tc.value)
   600  
   601  				if tc.expectedErr {
   602  					assert.Error(t, err)
   603  				} else {
   604  					assert.NoError(t, err)
   605  				}
   606  				assert.Equal(t, tc.expectedValue, value)
   607  			})
   608  		}
   609  		for i, tc := range testCases {
   610  			t.Run(fmt.Sprintf("uuids (single) #%d", i), func(t *testing.T) {
   611  				value, err := uuidArrayVal(tc.value)
   612  
   613  				assert.Error(t, err)
   614  				assert.Nil(t, value)
   615  			})
   616  			t.Run(fmt.Sprintf("uuids (array) #%d", i), func(t *testing.T) {
   617  				value, err := uuidArrayVal([]interface{}{tc.value})
   618  
   619  				if tc.expectedErr {
   620  					assert.Error(t, err)
   621  					assert.Nil(t, value)
   622  				} else {
   623  					assert.NoError(t, err)
   624  					assert.Equal(t, []uuid.UUID{tc.expectedValue}, value)
   625  				}
   626  			})
   627  		}
   628  	})
   629  
   630  	t.Run("date(s)", func(t *testing.T) {
   631  		type testCase struct {
   632  			value         interface{}
   633  			expectedValue time.Time
   634  			expectedErr   bool
   635  		}
   636  
   637  		testCases := []testCase{
   638  			{
   639  				value:         "2024-01-02T03:04:05.00Z",
   640  				expectedValue: time.Unix(1704164645, 0).UTC(),
   641  				expectedErr:   false,
   642  			},
   643  
   644  			{
   645  				value:         float64(123),
   646  				expectedValue: time.Time{},
   647  				expectedErr:   true,
   648  			},
   649  			{
   650  				value:         int64(123),
   651  				expectedValue: time.Time{},
   652  				expectedErr:   true,
   653  			},
   654  			{
   655  				value:         "123",
   656  				expectedValue: time.Time{},
   657  				expectedErr:   true,
   658  			},
   659  			{
   660  				value:         "something",
   661  				expectedValue: time.Time{},
   662  				expectedErr:   true,
   663  			},
   664  			{
   665  				value:         true,
   666  				expectedValue: time.Time{},
   667  				expectedErr:   true,
   668  			},
   669  		}
   670  
   671  		for i, tc := range testCases {
   672  			t.Run(fmt.Sprintf("date #%d", i), func(t *testing.T) {
   673  				value, err := dateVal(tc.value)
   674  
   675  				if tc.expectedErr {
   676  					assert.Error(t, err)
   677  				} else {
   678  					assert.NoError(t, err)
   679  				}
   680  				assert.Equal(t, tc.expectedValue, value)
   681  			})
   682  		}
   683  		for i, tc := range testCases {
   684  			t.Run(fmt.Sprintf("dates (single) #%d", i), func(t *testing.T) {
   685  				value, err := dateArrayVal(tc.value)
   686  
   687  				assert.Error(t, err)
   688  				assert.Nil(t, value)
   689  			})
   690  			t.Run(fmt.Sprintf("dates (array) #%d", i), func(t *testing.T) {
   691  				value, err := dateArrayVal([]interface{}{tc.value})
   692  
   693  				if tc.expectedErr {
   694  					assert.Error(t, err)
   695  					assert.Nil(t, value)
   696  				} else {
   697  					assert.NoError(t, err)
   698  					assert.Equal(t, []time.Time{tc.expectedValue}, value)
   699  				}
   700  			})
   701  		}
   702  	})
   703  }