...

Source file src/github.com/datawire/ambassador/v2/pkg/api/getambassador.io/conversion_test.go

Documentation: github.com/datawire/ambassador/v2/pkg/api/getambassador.io

     1  package getambassadorio_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"path"
     7  	"path/filepath"
     8  	"reflect"
     9  	"testing"
    10  
    11  	"github.com/pmezard/go-difflib/difflib"
    12  	"github.com/stretchr/testify/require"
    13  	"k8s.io/apimachinery/pkg/runtime"
    14  	"sigs.k8s.io/yaml"
    15  
    16  	getambassadorio "github.com/datawire/ambassador/v2/pkg/api/getambassador.io"
    17  	"github.com/datawire/ambassador/v2/pkg/api/getambassador.io/v1"
    18  	"github.com/datawire/ambassador/v2/pkg/api/getambassador.io/v2"
    19  	"github.com/datawire/ambassador/v2/pkg/api/getambassador.io/v3alpha1"
    20  	"github.com/datawire/ambassador/v2/pkg/kates"
    21  )
    22  
    23  func marshalNormalized(t *testing.T, typed interface{}) string {
    24  	t.Helper()
    25  
    26  	// First we discard any type information by seralizing-then-deserializing.  This is
    27  	// important so that the order of struct fields doesn't impact the normalized serialization.
    28  
    29  	bs, err := json.Marshal(typed)
    30  	require.NoError(t, err)
    31  
    32  	var untyped interface{}
    33  	err = json.Unmarshal(bs, &untyped)
    34  	require.NoError(t, err)
    35  
    36  	// Now serialize for real.
    37  
    38  	out, err := json.MarshalIndent(untyped, "", "\t")
    39  	require.NoError(t, err)
    40  
    41  	return string(out)
    42  }
    43  
    44  func requireEqualNormalized(t *testing.T, exp, act interface{}) {
    45  	t.Helper()
    46  	expStr := marshalNormalized(t, exp)
    47  	actStr := marshalNormalized(t, act)
    48  	// Do this directly instead of using require.Equal so that the "%q" version doesn't spam
    49  	// stdout.
    50  	if expStr != actStr {
    51  		diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
    52  			A:        difflib.SplitLines(expStr),
    53  			B:        difflib.SplitLines(actStr),
    54  			FromFile: "Expected",
    55  			FromDate: "",
    56  			ToFile:   "Actual",
    57  			ToDate:   "",
    58  			Context:  3,
    59  		})
    60  		t.Errorf("Not equal\n%s", diff)
    61  	}
    62  }
    63  
    64  func TestConvert(t *testing.T) {
    65  	testcases := map[string]map[string]interface{}{
    66  		"authsvc": {
    67  			"getambassador.io/v1":       v1.AuthService{},
    68  			"getambassador.io/v2":       v2.AuthService{},
    69  			"getambassador.io/v3alpha1": v3alpha1.AuthService{},
    70  		},
    71  		"devportals": {
    72  			"getambassador.io/v1":       v1.DevPortal{},
    73  			"getambassador.io/v2":       v2.DevPortal{},
    74  			"getambassador.io/v3alpha1": v3alpha1.DevPortal{},
    75  		},
    76  		"hosts": {
    77  			"getambassador.io/v2":       v2.Host{},
    78  			"getambassador.io/v3alpha1": v3alpha1.Host{},
    79  		},
    80  		"logsvc": {
    81  			"getambassador.io/v1":       v1.LogService{},
    82  			"getambassador.io/v2":       v2.LogService{},
    83  			"getambassador.io/v3alpha1": v3alpha1.LogService{},
    84  		},
    85  		"mappings": {
    86  			"getambassador.io/v1":       v1.Mapping{},
    87  			"getambassador.io/v2":       v2.Mapping{},
    88  			"getambassador.io/v3alpha1": v3alpha1.Mapping{},
    89  		},
    90  		"modules": {
    91  			"getambassador.io/v1":       v1.Module{},
    92  			"getambassador.io/v2":       v2.Module{},
    93  			"getambassador.io/v3alpha1": v3alpha1.Module{},
    94  		},
    95  		"ratelimitsvc": {
    96  			"getambassador.io/v1":       v1.RateLimitService{},
    97  			"getambassador.io/v2":       v2.RateLimitService{},
    98  			"getambassador.io/v3alpha1": v3alpha1.RateLimitService{},
    99  		},
   100  		"tcpmappings": {
   101  			"getambassador.io/v1":       v1.TCPMapping{},
   102  			"getambassador.io/v2":       v2.TCPMapping{},
   103  			"getambassador.io/v3alpha1": v3alpha1.TCPMapping{},
   104  		},
   105  		"tlscontexts": {
   106  			"getambassador.io/v1":       v1.TLSContext{},
   107  			"getambassador.io/v2":       v2.TLSContext{},
   108  			"getambassador.io/v3alpha1": v3alpha1.TLSContext{},
   109  		},
   110  		"tracingsvc": {
   111  			"getambassador.io/v1":       v1.TracingService{},
   112  			"getambassador.io/v2":       v2.TracingService{},
   113  			"getambassador.io/v3alpha1": v3alpha1.TracingService{},
   114  		},
   115  	}
   116  
   117  	scheme := getambassadorio.BuildScheme()
   118  
   119  	v2.MangleAmbassadorID = false
   120  	t.Cleanup(func() {
   121  		v2.MangleAmbassadorID = true
   122  	})
   123  
   124  	t.Run("RoundTrip", func(t *testing.T) {
   125  		t.Parallel()
   126  		for typename := range testcases {
   127  			typename := typename
   128  			t.Run(typename, func(t *testing.T) {
   129  				t.Parallel()
   130  				for mainAPIVersion := range testcases[typename] {
   131  					for throughAPIVersion := range testcases[typename] {
   132  						if mainAPIVersion == throughAPIVersion {
   133  							continue
   134  						}
   135  						mainAPIVersion := mainAPIVersion
   136  						throughAPIVersion := throughAPIVersion
   137  						testname := path.Base(mainAPIVersion) + "_through_" + path.Base(throughAPIVersion)
   138  						t.Run(testname, func(t *testing.T) {
   139  							t.Parallel()
   140  							inBytes, err := os.ReadFile(filepath.Join(path.Base(mainAPIVersion), "testdata", typename+".yaml"))
   141  							require.NoError(t, err)
   142  							inListPtr := reflect.New(reflect.SliceOf(reflect.TypeOf(testcases[typename][mainAPIVersion])))
   143  							require.NoError(t, yaml.Unmarshal(inBytes, inListPtr.Interface()))
   144  							inList := inListPtr.Elem()
   145  							listLen := inList.Len()
   146  
   147  							midList := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(testcases[typename][throughAPIVersion])), listLen, listLen)
   148  							for i := 0; i < listLen; i++ {
   149  								midList.Index(i).FieldByName("TypeMeta").FieldByName("APIVersion").Set(reflect.ValueOf(throughAPIVersion))
   150  								midList.Index(i).FieldByName("TypeMeta").FieldByName("Kind").Set(inList.Index(i).FieldByName("TypeMeta").FieldByName("Kind"))
   151  								require.NoError(t, kates.ConvertObject(scheme, inList.Index(i).Addr().Interface().(runtime.Object), midList.Index(i).Addr().Interface().(runtime.Object)))
   152  							}
   153  
   154  							outList := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(testcases[typename][mainAPIVersion])), listLen, listLen)
   155  							for i := 0; i < listLen; i++ {
   156  								outList.Index(i).FieldByName("TypeMeta").Set(inList.Index(i).FieldByName("TypeMeta"))
   157  								require.NoError(t, kates.ConvertObject(scheme, midList.Index(i).Addr().Interface().(runtime.Object), outList.Index(i).Addr().Interface().(runtime.Object)))
   158  							}
   159  
   160  							requireEqualNormalized(t, inList.Interface(), outList.Interface())
   161  						})
   162  					}
   163  				}
   164  			})
   165  		}
   166  	})
   167  }
   168  

View as plain text