1
16
17 package testing
18
19 import (
20 "fmt"
21 "os"
22 "path/filepath"
23 "testing"
24
25 "github.com/google/go-cmp/cmp"
26 apiequality "k8s.io/apimachinery/pkg/api/equality"
27 "k8s.io/apimachinery/pkg/runtime"
28 "k8s.io/apimachinery/pkg/runtime/schema"
29 "k8s.io/apimachinery/pkg/runtime/serializer"
30 )
31
32
33 func RoundTripTest(t *testing.T, scheme *runtime.Scheme, codecs serializer.CodecFactory) {
34 tc := GetRoundtripTestCases(t, scheme, codecs)
35 RunTestsOnYAMLData(t, tc)
36 }
37
38
39 func GetRoundtripTestCases(t *testing.T, scheme *runtime.Scheme, codecs serializer.CodecFactory) []TestCase {
40 cases := []TestCase{}
41 versionsForKind := map[schema.GroupKind][]string{}
42 for gvk := range scheme.AllKnownTypes() {
43 if gvk.Version != runtime.APIVersionInternal {
44 versionsForKind[gvk.GroupKind()] = append(versionsForKind[gvk.GroupKind()], gvk.Version)
45 }
46 }
47
48 for gk, versions := range versionsForKind {
49 testdir := filepath.Join("testdata", gk.Kind, "roundtrip")
50 dirs, err := os.ReadDir(testdir)
51 if err != nil {
52 t.Fatalf("failed to read testdir %s: %v", testdir, err)
53 }
54
55 for _, dir := range dirs {
56 for _, vin := range versions {
57 for _, vout := range versions {
58 marshalGVK := gk.WithVersion(vout)
59 codec, err := getCodecForGV(codecs, marshalGVK.GroupVersion())
60 if err != nil {
61 t.Fatalf("failed to get codec for %v: %v", marshalGVK.GroupVersion().String(), err)
62 }
63
64 testname := dir.Name()
65 cases = append(cases, TestCase{
66 name: fmt.Sprintf("%s_%sTo%s_%s", gk.Kind, vin, vout, testname),
67 in: filepath.Join(testdir, testname, vin+".yaml"),
68 out: filepath.Join(testdir, testname, vout+".yaml"),
69 codec: codec,
70 })
71 }
72 }
73 }
74 }
75 return cases
76 }
77
78 func roundTrip(t *testing.T, tc TestCase) {
79 object := decodeYAML(t, tc.in, tc.codec)
80
81
82 original := object
83
84
85 data, err := runtime.Encode(tc.codec, object)
86 if err != nil {
87 t.Fatalf("failed to encode object: %v", err)
88 }
89
90
91 if !apiequality.Semantic.DeepEqual(original, object) {
92 t.Fatalf("encode altered the object, diff (- want, + got): \n%v", cmp.Diff(original, object))
93 }
94
95
96 obj2, err := runtime.Decode(tc.codec, data)
97 if err != nil {
98 t.Fatalf("failed to decode: %v", err)
99 }
100
101
102
103 if !apiequality.Semantic.DeepEqual(original, obj2) {
104 t.Fatalf("object was not the same after roundtrip, diff (- want, + got):\n%v", cmp.Diff(object, obj2))
105 }
106
107
108 matchOutputFile(t, data, tc.out)
109 }
110
View as plain text