From 6d2a3bdd60316b8713e3c8449cecd1777a07e3a6 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Fri, 17 Mar 2017 00:28:05 -0400 Subject: [PATCH] Add a test that verifies all structs have protobuf tags --- pkg/api/serialization_proto_test.go | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/pkg/api/serialization_proto_test.go b/pkg/api/serialization_proto_test.go index 523653d16ab..ac3bbeae74f 100644 --- a/pkg/api/serialization_proto_test.go +++ b/pkg/api/serialization_proto_test.go @@ -19,7 +19,9 @@ package api_test import ( "bytes" "encoding/hex" + "fmt" "math/rand" + "reflect" "testing" "github.com/gogo/protobuf/proto" @@ -59,6 +61,41 @@ func TestUniversalDeserializer(t *testing.T) { } } +func TestAllFieldsHaveTags(t *testing.T) { + for gvk, obj := range api.Scheme.AllKnownTypes() { + if gvk.Version == runtime.APIVersionInternal { + // internal versions are not serialized to protobuf + continue + } + if gvk.Group == "componentconfig" { + // component config is not serialized to protobuf + continue + } + if err := fieldsHaveProtobufTags(obj); err != nil { + t.Errorf("type %s as gvk %v is missing tags: %v", obj, gvk, err) + } + } +} + +func fieldsHaveProtobufTags(obj reflect.Type) error { + switch obj.Kind() { + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Array: + return fieldsHaveProtobufTags(obj.Elem()) + case reflect.Struct: + for i := 0; i < obj.NumField(); i++ { + f := obj.Field(i) + if f.Name == "TypeMeta" && f.Type.Name() == "TypeMeta" { + // TypeMeta is not included in external protobuf because we use an envelope type with TypeMeta + continue + } + if len(f.Tag.Get("json")) > 0 && len(f.Tag.Get("protobuf")) == 0 { + return fmt.Errorf("field %s in %s has a 'json' tag but no protobuf tag", f.Name, obj) + } + } + } + return nil +} + func TestProtobufRoundTrip(t *testing.T) { obj := &v1.Pod{} apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(benchmarkSeed)).Fuzz(obj)