chore: validateAndCastValueData (#2610)

This commit is contained in:
Vishal Sharma 2023-04-24 20:38:08 +05:30 committed by GitHub
parent 21c6d3ba99
commit e2df2e7c41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 425 additions and 0 deletions

View File

@ -3,11 +3,143 @@ package utils
import ( import (
"fmt" "fmt"
"reflect" "reflect"
"strconv"
"strings" "strings"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.uber.org/zap" "go.uber.org/zap"
) )
func ValidateAndCastValue(v interface{}, dataType v3.AttributeKeyDataType) (interface{}, error) {
switch dataType {
case v3.AttributeKeyDataTypeString:
switch x := v.(type) {
case string, int, int64, float32, float64, bool:
return fmt.Sprintf("%v", x), nil
case []interface{}:
for i, val := range x {
// if val is not string and it is int, int64, float, bool, convert it to string
if _, ok := val.(string); ok {
continue
} else if _, ok := val.(int); ok {
x[i] = fmt.Sprintf("%v", val)
} else if _, ok := val.(int64); ok {
x[i] = fmt.Sprintf("%v", val)
} else if _, ok := val.(float32); ok {
x[i] = fmt.Sprintf("%v", val)
} else if _, ok := val.(float64); ok {
x[i] = fmt.Sprintf("%v", val)
} else if _, ok := val.(bool); ok {
x[i] = fmt.Sprintf("%v", val)
} else {
return nil, fmt.Errorf("invalid data type, expected string, got %v", reflect.TypeOf(val))
}
}
return x, nil
default:
return nil, fmt.Errorf("invalid data type, expected string, got %v", reflect.TypeOf(v))
}
case v3.AttributeKeyDataTypeBool:
switch x := v.(type) {
case []interface{}:
for i, val := range x {
if _, ok := val.(string); ok {
boolean, err := strconv.ParseBool(val.(string))
if err != nil {
return nil, fmt.Errorf("invalid data type, expected bool, got %v", reflect.TypeOf(val))
}
x[i] = boolean
} else if _, ok := val.(bool); !ok {
return nil, fmt.Errorf("invalid data type, expected bool, got %v", reflect.TypeOf(val))
} else {
x[i] = val.(bool)
}
}
return x, nil
case bool:
return x, nil
case string:
boolean, err := strconv.ParseBool(x)
if err != nil {
return nil, fmt.Errorf("invalid data type, expected bool, got %v", reflect.TypeOf(v))
}
return boolean, nil
default:
return nil, fmt.Errorf("invalid data type, expected bool, got %v", reflect.TypeOf(v))
}
case v3.AttributeKeyDataTypeInt64:
switch x := v.(type) {
case []interface{}:
for i, val := range x {
if _, ok := val.(string); ok {
int64val, err := strconv.ParseInt(val.(string), 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid data type, expected int, got %v", reflect.TypeOf(val))
}
x[i] = int64val
} else if _, ok := val.(int); ok {
x[i] = int64(val.(int))
} else if _, ok := val.(int64); !ok {
return nil, fmt.Errorf("invalid data type, expected int, got %v", reflect.TypeOf(val))
} else {
x[i] = val.(int64)
}
}
return x, nil
case int, int64:
return x, nil
case string:
int64val, err := strconv.ParseInt(x, 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid data type, expected int, got %v", reflect.TypeOf(v))
}
return int64val, nil
default:
return nil, fmt.Errorf("invalid data type, expected int, got %v", reflect.TypeOf(v))
}
case v3.AttributeKeyDataTypeFloat64:
switch x := v.(type) {
case []interface{}:
for i, val := range x {
if _, ok := val.(string); ok {
float64val, err := strconv.ParseFloat(val.(string), 64)
if err != nil {
return nil, fmt.Errorf("invalid data type, expected float, got %v", reflect.TypeOf(val))
}
x[i] = float64val
} else if _, ok := val.(float32); ok {
x[i] = float64(val.(float32))
} else if _, ok := val.(int); ok {
x[i] = float64(val.(int))
} else if _, ok := val.(int64); ok {
x[i] = float64(val.(int64))
} else if _, ok := val.(float64); !ok {
return nil, fmt.Errorf("invalid data type, expected float, got %v", reflect.TypeOf(val))
} else {
x[i] = val.(float64)
}
}
return x, nil
case float32, float64:
return x, nil
case string:
float64val, err := strconv.ParseFloat(x, 64)
if err != nil {
return nil, fmt.Errorf("invalid data type, expected float, got %v", reflect.TypeOf(v))
}
return float64val, nil
case int:
return float64(x), nil
case int64:
return float64(x), nil
default:
return nil, fmt.Errorf("invalid data type, expected float, got %v", reflect.TypeOf(v))
}
default:
return nil, fmt.Errorf("invalid data type, expected float, bool, int, string or []interface{} but got %v", dataType)
}
}
// ClickHouseFormattedValue formats the value to be used in clickhouse query // ClickHouseFormattedValue formats the value to be used in clickhouse query
func ClickHouseFormattedValue(v interface{}) string { func ClickHouseFormattedValue(v interface{}) string {
switch x := v.(type) { switch x := v.(type) {

View File

@ -0,0 +1,293 @@
package utils
import (
"reflect"
"testing"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
type args struct {
v interface{}
dataType v3.AttributeKeyDataType
}
var testValidateAndCastValueData = []struct {
name string
args args
want interface{}
wantErr bool
}{
// Test cases for v3.AttributeKeyDataTypeString
{
name: "v3.AttributeKeyDataTypeString: Valid string",
args: args{
v: "test",
dataType: v3.AttributeKeyDataTypeString,
},
want: "test",
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid int",
args: args{
v: 1,
dataType: v3.AttributeKeyDataTypeString,
},
want: "1",
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid float32",
args: args{
v: float32(1.1),
dataType: v3.AttributeKeyDataTypeString,
},
want: "1.1",
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid float64",
args: args{
v: float64(1.1),
dataType: v3.AttributeKeyDataTypeString,
},
want: "1.1",
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid bool",
args: args{
v: true,
dataType: v3.AttributeKeyDataTypeString,
},
want: "true",
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid []interface{}",
args: args{
v: []interface{}{"test", "test2"},
dataType: v3.AttributeKeyDataTypeString,
},
want: []interface{}{"test", "test2"},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Valid []interface{}",
args: args{
v: []interface{}{"test", 1},
dataType: v3.AttributeKeyDataTypeString,
},
want: []interface{}{"test", "1"},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeString: Invalid []interface{}",
args: args{
v: []interface{}{"test", [1]string{"string Array"}},
dataType: v3.AttributeKeyDataTypeString,
},
want: nil,
wantErr: true,
},
{
name: "v3.AttributeKeyDataTypeString: Invalid type",
args: args{
v: map[string]interface{}{"test": "test"},
dataType: v3.AttributeKeyDataTypeString,
},
want: nil,
wantErr: true,
},
// Test cases for v3.AttributeKeyDataTypeBool
{
name: "v3.AttributeKeyDataTypeBool: Valid bool",
args: args{
v: true,
dataType: v3.AttributeKeyDataTypeBool,
},
want: true,
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeBool: Valid string",
args: args{
v: "true",
dataType: v3.AttributeKeyDataTypeBool,
},
want: true,
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeBool: Valid []interface{}",
args: args{
v: []interface{}{"true", false},
dataType: v3.AttributeKeyDataTypeBool,
},
want: []interface{}{true, false},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeBool: Invalid type",
args: args{
v: 1,
dataType: v3.AttributeKeyDataTypeBool,
},
want: nil,
wantErr: true,
},
{
name: "v3.AttributeKeyDataTypeBool: Invalid []interface{}",
args: args{
v: []interface{}{1, false},
dataType: v3.AttributeKeyDataTypeBool,
},
want: nil,
wantErr: true,
},
// Test cases for v3.AttributeKeyDataTypeInt64
{
name: "v3.AttributeKeyDataTypeInt64: Valid int",
args: args{
v: 1,
dataType: v3.AttributeKeyDataTypeInt64,
},
want: 1,
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeInt64: Valid int64",
args: args{
v: int64(1),
dataType: v3.AttributeKeyDataTypeInt64,
},
want: int64(1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeInt64: Valid string",
args: args{
v: "1",
dataType: v3.AttributeKeyDataTypeInt64,
},
want: int64(1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeInt64: Valid []interface{}",
args: args{
v: []interface{}{"1", 2},
dataType: v3.AttributeKeyDataTypeInt64,
},
want: []interface{}{int64(1), int64(2)},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeInt64: Invalid []interface{}",
args: args{
v: []interface{}{"1", false},
dataType: v3.AttributeKeyDataTypeInt64,
},
want: nil,
wantErr: true,
},
{
name: "v3.AttributeKeyDataTypeInt64: Invalid type",
args: args{
v: true,
dataType: v3.AttributeKeyDataTypeInt64,
},
want: nil,
wantErr: true,
},
// Test cases for v3.AttributeKeyDataTypeFloat64
{
name: "v3.AttributeKeyDataTypeFloat64: Valid float32",
args: args{
v: float32(1.1),
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: float32(1.1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat64: Valid float64",
args: args{
v: float64(1.1),
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: float64(1.1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat64: Valid int",
args: args{
v: 1,
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: float64(1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat64: Valid string",
args: args{
v: "1.1",
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: float64(1.1),
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat: Valid []interface{}",
args: args{
v: []interface{}{4, 3},
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: []interface{}{float64(4), float64(3)},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat: Valid []interface{}",
args: args{
v: []interface{}{4, "3"},
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: []interface{}{float64(4), float64(3)},
wantErr: false,
},
{
name: "v3.AttributeKeyDataTypeFloat: Invalid []interface{}",
args: args{
v: []interface{}{4, "true"},
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: nil,
wantErr: true,
},
{
name: "v3.AttributeKeyDataTypeFloat64: Invalid type",
args: args{
v: true,
dataType: v3.AttributeKeyDataTypeFloat64,
},
want: nil,
wantErr: true,
},
}
// Test cases for ValidateAndCastValue function in pkg/query-service/utils/format.go
func TestValidateAndCastValue(t *testing.T) {
for _, tt := range testValidateAndCastValueData {
t.Run(tt.name, func(t *testing.T) {
got, err := ValidateAndCastValue(tt.args.v, tt.args.dataType)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateAndCastValue() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) && !reflect.DeepEqual(err, tt.wantErr) {
t.Errorf("ValidateAndCastValue() = %v, want %v", got, tt.want)
}
})
}
}