You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
decort-golang-sdk/tests/platform_upgrade/utils_requests.go

237 lines
5.6 KiB

package test
import (
"fmt"
"io"
"os"
"reflect"
"strings"
"testing"
)
func getParameters(input map[string]interface{}) []interface{} {
var emptySlice []interface{}
post, ok := input["post"]
if !ok {
return emptySlice
}
parameters, ok := post.(map[string]interface{})
if !ok {
return emptySlice
}
params, ok := parameters["parameters"]
if !ok {
return emptySlice
}
res, ok := params.([]interface{})
if !ok {
return emptySlice
}
return res
}
func getBytesFromJSON(fileName string, t *testing.T) []byte {
jsonFile, err := os.Open(fileName)
if err != nil {
t.Error(err)
}
defer jsonFile.Close()
bytes, err := io.ReadAll(jsonFile)
if err != nil {
t.Error(err)
}
return bytes
}
func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
var requests map[string]interface{}
var logFileName string
switch cloud {
case "cloudapi":
requests = getRequestsMapCloudAPI()
logFileName = "test_requests_cloudAPI.log"
case "cloudbroker":
requests = getRequestsMapCloudbroker()
logFileName = "test_requests_cloudbroker.log"
default:
t.Fatalf("Wrong cloud provided, expected `cloudapi` or `cloudbroker`, got %s", cloud)
}
var dataLogs []string
paths, err := getMapFromFile(bytes)
if err != nil {
t.Error(err)
}
i := 0
for k, v := range paths {
// exclude deprecated urls from analysis
if !validateUrlFromJson(k) {
continue
}
params := getParameters(v.(map[string]interface{}))
structure, ok := requests[k]
if !ok {
continue
}
i++
typStruct := reflect.TypeOf(structure)
var errs []string
// empty request case
if len(params) == 0 && structure == nil {
continue
}
if len(params) != typStruct.NumField() {
errs = append(errs, fmt.Sprintf("Platform (%d) and golang structure (%d) have different amount of fields.", len(params), typStruct.NumField()))
}
for _, p := range params {
param, ok := p.(map[string]interface{})
if !ok {
continue
}
name := param["name"].(string)
required, ok := param["required"].(bool)
if !ok {
required = false
}
typ := p.(map[string]interface{})["type"].(string)
var items string
if p.(map[string]interface{})["items"] != nil {
itemsTemp := p.(map[string]interface{})["items"]
if itemsTemp != nil {
itemsType := itemsTemp.(map[string]interface{})["type"]
if itemsType != nil {
items = itemsType.(string)
}
}
}
var found bool
for i := 0; i < typStruct.NumField(); i++ {
jsonTag := typStruct.Field(i).Tag.Get("json")
validation, _ := typStruct.Field(i).Tag.Lookup("validate")
if checkName(name, jsonTag) {
if !checkRequired(required, validation, typ) {
errs = append(errs, fmt.Sprintf("Field %s has different required parameters on the platform and in golang structure", name))
}
if !checkKind(typ, items, typStruct.Field(i).Type) {
errs = append(errs, fmt.Sprintf("Field %s has different type parameters on the platform and in golang structure", name))
}
found = true
break
}
}
if !found {
errs = append(errs, fmt.Sprintf("Platform has field %s that golang structure doesn't", name))
}
}
if len(errs) > 0 {
msg := fmt.Sprintf("Path %s has following errors: %v", k, errs)
t.Error(msg)
dataLogs = append(dataLogs, msg)
}
}
if len(requests) != i {
msg := fmt.Sprintf("Amount of structure checked (%d) is not the same as amount of platform requests available (%d), please check getRequestsMapCloudAPI func in code.",
i, len(requests))
t.Error(msg)
dataLogs = append(dataLogs, msg)
}
compareLogs(logFileName, dataLogs, t, "request")
}
// checkName checks if name field from platform has the same value as json tag in golang structure (maybe including omitempty)
func checkName(name, tag string) bool {
return strings.Contains(tag, name)
}
// checkRequired checks if required field from platform has the same value as validate tag in golang structure
func checkRequired(required bool, validation, fieldType string) bool {
if required && strings.Contains(validation, "required") {
return true
}
if required && (!strings.Contains(validation, "omitempty") && validation != "") {
return true
}
if !required && (validation == "" || strings.Contains(validation, "omitempty")) {
return true
}
if fieldType == "boolean" {
return true // otherwise we have issues with setting false/true
}
return false
}
// checkKind checks if type field from platform has the same value as field type in golang structure
func checkKind(platformType, items string, typ reflect.Type) bool {
//nolint
switch typ.Kind() {
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint64, reflect.Uint16, reflect.Uint32, reflect.Uint8:
if platformType == "integer" {
return true
}
return false
case reflect.String:
if platformType == "string" {
return true
}
return false
case reflect.Bool:
if platformType == "boolean" {
return true
}
return false
case reflect.Float32, reflect.Float64:
if platformType == "number" {
return true
}
return false
case reflect.Array, reflect.Slice:
if platformType != "array" {
return false
}
elem := typ.Elem()
switch elem.Kind() {
case reflect.String:
if items == "string" {
return true
}
return false
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint64, reflect.Uint16, reflect.Uint32, reflect.Uint8:
if items == "integer" {
return true
}
return false
default: // for cases like dataDisks etc.
return true
}
default: // for cases like drivers etc
return true
}
}