github.com/openfga/openfga@v1.5.4-rc1/internal/condition/types/types_test.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/require"
     9  )
    10  
    11  func TestPrimitives(t *testing.T) {
    12  	var tests = []struct {
    13  		name          string
    14  		paramType     ParameterType
    15  		input         any
    16  		output        any
    17  		expectedError error
    18  		repr          string
    19  	}{
    20  		{
    21  			name:      "valid_any",
    22  			paramType: AnyParamType,
    23  			input:     "hello",
    24  			output:    "hello",
    25  			repr:      "any",
    26  		},
    27  		{
    28  			name:      "valid_bool",
    29  			paramType: BoolParamType,
    30  			input:     true,
    31  			output:    true,
    32  			repr:      "bool",
    33  		},
    34  		{
    35  			name:      "valid_int",
    36  			paramType: IntParamType,
    37  			input:     int64(10),
    38  			output:    int64(10),
    39  			repr:      "int",
    40  		},
    41  		{
    42  			name:      "invalid_int_to_string",
    43  			paramType: StringParamType,
    44  			input:     int64(10),
    45  			output:    nil,
    46  			repr:      "string",
    47  			expectedError: fmt.Errorf(
    48  				"expected type value 'string', but found 'int64'",
    49  			),
    50  		},
    51  		{
    52  			name:      "valid_uint",
    53  			paramType: UIntParamType,
    54  			input:     uint64(10),
    55  			output:    uint64(10),
    56  			repr:      "uint",
    57  		},
    58  		{
    59  			name:      "valid_double",
    60  			paramType: DoubleParamType,
    61  			input:     10.5,
    62  			output:    float64(10.5),
    63  			repr:      "double",
    64  		},
    65  		{
    66  			name:      "valid_double_to_uint",
    67  			paramType: UIntParamType,
    68  			input:     float64(10.0),
    69  			output:    uint64(10),
    70  			repr:      "uint",
    71  		},
    72  		{
    73  			name:      "valid_double_to_int",
    74  			paramType: IntParamType,
    75  			input:     float64(10.0),
    76  			output:    int64(10),
    77  			repr:      "int",
    78  		},
    79  		{
    80  			name:      "invalid_double_to_uint",
    81  			paramType: UIntParamType,
    82  			input:     float64(10.5),
    83  			output:    nil,
    84  			repr:      "uint",
    85  			expectedError: fmt.Errorf(
    86  				"expected a uint value, but found numeric value '10.5'",
    87  			),
    88  		},
    89  		{
    90  			name:      "invalid_negative_double_to_uint",
    91  			paramType: UIntParamType,
    92  			input:     float64(-10.5),
    93  			output:    nil,
    94  			repr:      "uint",
    95  			expectedError: fmt.Errorf(
    96  				"expected a uint value, but found numeric value '-10.5'",
    97  			),
    98  		},
    99  		{
   100  			name:      "invalid_double_to_int",
   101  			paramType: IntParamType,
   102  			input:     float64(10.5),
   103  			output:    nil,
   104  			repr:      "int",
   105  			expectedError: fmt.Errorf(
   106  				"expected an int value, but found numeric value '10.5'",
   107  			),
   108  		},
   109  		{
   110  			name:      "valid_string",
   111  			paramType: StringParamType,
   112  			input:     "hello",
   113  			output:    "hello",
   114  			repr:      "string",
   115  		},
   116  		{
   117  			name:      "valid_string_to_int",
   118  			paramType: IntParamType,
   119  			input:     "10",
   120  			output:    int64(10),
   121  			repr:      "int",
   122  		},
   123  		{
   124  			name:      "invalid_string_to_bool",
   125  			paramType: BoolParamType,
   126  			input:     "hello",
   127  			output:    nil,
   128  			repr:      "bool",
   129  			expectedError: fmt.Errorf(
   130  				"expected type value 'bool', but found 'string'",
   131  			),
   132  		},
   133  		{
   134  			name:      "invalid_string_to_double",
   135  			paramType: DoubleParamType,
   136  			input:     "invalid",
   137  			output:    nil,
   138  			repr:      "double",
   139  			expectedError: fmt.Errorf(
   140  				"expected a float64 value, but found invalid string value 'invalid'",
   141  			),
   142  		},
   143  		{
   144  			name:      "valid_duration",
   145  			paramType: DurationParamType,
   146  			input:     "1h",
   147  			output:    1 * time.Hour,
   148  			repr:      "duration",
   149  		},
   150  		{
   151  			name:      "invalid_duration",
   152  			paramType: DurationParamType,
   153  			input:     "2sm",
   154  			output:    nil,
   155  			repr:      "duration",
   156  			expectedError: fmt.Errorf(
   157  				"expected a valid duration string, but found: '2sm'",
   158  			),
   159  		},
   160  		{
   161  			name:      "valid_timestamp",
   162  			paramType: TimestampParamType,
   163  			input:     "1972-01-01T10:00:20.021Z",
   164  			output:    time.Date(1972, time.January, 1, 10, 0, 20, 21000000, time.UTC),
   165  			repr:      "timestamp",
   166  		},
   167  		{
   168  			name:      "invalid_timestamp",
   169  			paramType: TimestampParamType,
   170  			input:     "2023-0914",
   171  			output:    nil,
   172  			repr:      "timestamp",
   173  			expectedError: fmt.Errorf(
   174  				"expected RFC 3339 formatted timestamp string, but found '2023-0914'",
   175  			),
   176  		},
   177  		{
   178  			name:      "valid_ipaddress",
   179  			paramType: IPAddressType,
   180  			input:     "127.0.0.1",
   181  			output:    mustParseIPAddress("127.0.0.1"),
   182  			repr:      "ipaddress",
   183  		},
   184  		{
   185  			name:      "invalid_ipaddress",
   186  			paramType: IPAddressType,
   187  			input:     "invalid",
   188  			output:    nil,
   189  			repr:      "ipaddress",
   190  			expectedError: fmt.Errorf(
   191  				"expected a well-formed IP address, but found: 'invalid'",
   192  			),
   193  		},
   194  		{
   195  			name:      "valid_map_string",
   196  			paramType: mustMapParamType(StringParamType),
   197  			input:     map[string]any{"hello": "world"},
   198  			output:    map[string]any{"hello": "world"},
   199  			repr:      "TYPE_NAME_MAP<string>",
   200  		},
   201  		{
   202  			name:      "invalid_map",
   203  			paramType: mustMapParamType(StringParamType),
   204  			input:     map[int]any{123: "world"},
   205  			expectedError: fmt.Errorf(
   206  				"map requires a map, found: map[int]interface {}",
   207  			),
   208  			repr: "TYPE_NAME_MAP<string>",
   209  		},
   210  		{
   211  			name:      "invalid_map_string",
   212  			paramType: mustMapParamType(StringParamType),
   213  			input:     map[string]any{"hello": 1},
   214  			expectedError: fmt.Errorf(
   215  				"found an invalid value for key 'hello': expected type value 'string', but found 'int'",
   216  			),
   217  			repr: "TYPE_NAME_MAP<string>",
   218  		},
   219  		{
   220  			name:      "valid_list_string",
   221  			paramType: mustListParamType(StringParamType),
   222  			input:     []any{"hello", "world"},
   223  			output:    []any{"hello", "world"},
   224  			repr:      "TYPE_NAME_LIST<string>",
   225  		},
   226  		{
   227  			name:      "invalid_list",
   228  			paramType: mustListParamType(StringParamType),
   229  			input:     "hello",
   230  			expectedError: fmt.Errorf(
   231  				"list requires a list, found: string",
   232  			),
   233  			repr: "TYPE_NAME_LIST<string>",
   234  		},
   235  		{
   236  			name:      "invalid_list_string",
   237  			paramType: mustListParamType(StringParamType),
   238  			input:     []any{"hello", 1},
   239  			expectedError: fmt.Errorf(
   240  				"found an invalid list item at index `1`: expected type value 'string', but found 'int'",
   241  			),
   242  			repr: "TYPE_NAME_LIST<string>",
   243  		},
   244  	}
   245  
   246  	for _, test := range tests {
   247  		t.Run(test.name, func(t *testing.T) {
   248  			converted, err := test.paramType.ConvertValue(test.input)
   249  
   250  			if test.expectedError != nil {
   251  				require.Error(t, err)
   252  				require.EqualError(t, err, test.expectedError.Error())
   253  			} else {
   254  				require.NoError(t, err)
   255  			}
   256  
   257  			require.Equal(t, test.output, converted)
   258  			require.Equal(t, test.repr, test.paramType.String())
   259  		})
   260  	}
   261  }
   262  
   263  func mustParseIPAddress(ip string) IPAddress {
   264  	addr, err := ParseIPAddress(ip)
   265  	if err != nil {
   266  		panic(err)
   267  	}
   268  
   269  	return addr
   270  }
   271  
   272  func mustMapParamType(genericTypes ...ParameterType) ParameterType {
   273  	paramType, err := MapParamType(genericTypes...)
   274  	if err != nil {
   275  		panic(err)
   276  	}
   277  	return paramType
   278  }
   279  
   280  func mustListParamType(genericTypes ...ParameterType) ParameterType {
   281  	paramType, err := ListParamType(genericTypes...)
   282  	if err != nil {
   283  		panic(err)
   284  	}
   285  	return paramType
   286  }