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.
219 lines
5.1 KiB
219 lines
5.1 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{}
|
|
|
|
switch cloud {
|
|
case "cloudapi":
|
|
requests = getRequestsMapCloudAPI()
|
|
case "cloudbroker":
|
|
requests = getRequestsMapCloudbroker()
|
|
default:
|
|
t.Fatalf("Wrong cloud provided, expected `cloudapi` or `cloudbroker`, got %s", cloud)
|
|
}
|
|
|
|
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 := param["required"].(bool)
|
|
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 {
|
|
t.Errorf("Path %s has following errors: %v", k, errs)
|
|
}
|
|
}
|
|
|
|
if len(requests) != i {
|
|
t.Errorf("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))
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|