package systemlayoutbundleauthorityv1

import (
	"reflect"
	"testing"
)

func TestValueSurfacesAreExact(t *testing.T) {
	assertExactFields(t, reflect.TypeOf(BundleKey{}), []string{
		"BundleKeyVersion",
		"SlotOwnerKind",
		"SlotOwnerNamespace",
		"LocalComponentKey",
	})
	assertExactFields(t, reflect.TypeOf(SystemLayoutBundleSlotV1{}), []string{
		"ValueVersion",
		"BundleKey",
		"State",
	})
	assertExactFields(t, reflect.TypeOf(ExpectedPrior{}), []string{
		"Variant",
		"SlotValueDigest",
	})
	assertExactFields(t, reflect.TypeOf(SystemLayoutBundleSlotCommandRequest{}), []string{
		"Operation",
		"TargetBundleKey",
		"DesiredSlotValue",
		"ExpectedPrior",
	})
	assertExactFields(t, reflect.TypeOf(SystemLayoutBundleAuthorityEvidenceV1{}), []string{
		"EvidenceVersion",
		"SourceCatalogSnapshot",
		"BundleKey",
		"SlotValueVersion",
		"SlotState",
	})
}

func TestValueSurfacesContainNoMutableAggregateFields(t *testing.T) {
	for _, typ := range []reflect.Type{
		reflect.TypeOf(BundleKey{}),
		reflect.TypeOf(SystemLayoutBundleSlotV1{}),
		reflect.TypeOf(ExpectedPrior{}),
		reflect.TypeOf(SystemLayoutBundleSlotCommandRequest{}),
		reflect.TypeOf(SystemLayoutBundleAuthorityEvidenceV1{}),
	} {
		for index := 0; index < typ.NumField(); index++ {
			kind := typ.Field(index).Type.Kind()
			if kind == reflect.Map || kind == reflect.Slice || kind == reflect.Pointer || kind == reflect.Interface {
				t.Fatalf("%s.%s has mutable or open kind %s", typ.Name(), typ.Field(index).Name, kind)
			}
		}
	}
}

func assertExactFields(t *testing.T, typ reflect.Type, expected []string) {
	t.Helper()
	if typ.NumField() != len(expected) {
		t.Fatalf("%s field count = %d, want %d", typ.Name(), typ.NumField(), len(expected))
	}
	for index, fieldName := range expected {
		if got := typ.Field(index).Name; got != fieldName {
			t.Fatalf("%s field %d = %s, want %s", typ.Name(), index, got, fieldName)
		}
	}
}
