Repository: kubernetes/kubernetes
File: staging/src/k8s.io/dynamic-resource-allocation/api/conversion_test.go (Go)

Code before:
		func(d *resourceapi.Device, c randfill.Continue) {
			c.FillNoCustom(d)
			if d.BindsToNode == nil {
				d.BindsToNode = new(bool)
			}
		},
	}
}

// TestConversionRoundTrip verifies that the conversion code for the internal
// DRA API correctly round-trips between v1 and the internal api types.
// For v1 -> api -> v1, the conversion should be lossless.
func TestConversionRoundTrip(t *testing.T) {
	scheme := runtime.NewScheme()
	if err := resourceapi.AddToScheme(scheme); err != nil {
		t.Fatal(err)
	}
	if err := AddToScheme(scheme); err != nil {
		t.Fatal(err)
	}

	filler := apitest.NewFiller(t, scheme, fuzzer.FuzzerFuncs(v1FillFuncs))

	// Test v1 -> api -> v1 roundtrip for types that have conversions.
	// Note: api -> v1 -> api is NOT lossless because api types use UniqueString
	// which has different identity semantics than regular strings.
	testCases := []struct {
		name   string
		v1Type func() runtime.Object
		apiNew func() interface{}
	}{
		{
			name:   "ResourceSlice",
			v1Type: func() runtime.Object { return &resourceapi.ResourceSlice{} },
			apiNew: func() interface{} { return &ResourceSlice{} },
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			for i := range apitest.FuzzIterations {
				// Create and fuzz v1 object.
				v1Obj := tc.v1Type()
				filler.Fill(v1Obj)

				// Convert v1 -> api.
				apiObj := tc.apiNew()
				if err := scheme.Convert(v1Obj, apiObj, nil); err != nil {
					t.Fatalf("iteration %d: v1 -> api: %v", i, err)
				}


Review comment (suggestion):
But `MakeUniqueString("foo") -> "foo" -> MakeUniqueString("foo")` should be fine, shouldn't it? The second call must resolve to the same `unique.Handle[string]`.

Or is `apiequality.Semantic.DeepEqual` not handling it?

But that aside, the main reason why `api -> v1 -> api` cannot work are the extra fields in the internal representation. We would have to ensure that they are all unset. This is simply not worth it because we never really create instances using the internal API.

I think we can remove the entire comment block here and explain this in the function doc (see proposal).

Code after:
		func(d *resourceapi.Device, c randfill.Continue) {
			c.FillNoCustom(d)
			if d.BindsToNode == nil {
				d.BindsToNode = new(bool)
			}
		},
	}
}

// TestConversionRoundTrip verifies that the conversion code for the internal
// DRA API correctly round-trips between v1 and the internal api types.
// For v1 -> api -> v1, the conversion should be lossless.
//
// api -> v1 -> api is not lossless because of
// additional fields in the internal representation.
// Those would get lost during conversion.
// But this doesn't matter because in practice,
// the internal representation is never converted back,
// therefore this direction is not tested.
func TestConversionRoundTrip(t *testing.T) {
	scheme := runtime.NewScheme()
	if err := resourceapi.AddToScheme(scheme); err != nil {
		t.Fatal(err)
	}
	if err := AddToScheme(scheme); err != nil {
		t.Fatal(err)
	}

	filler := apitest.NewFiller(t, scheme, fuzzer.FuzzerFuncs(v1FillFuncs))

	testCases := []struct {
		name   string
		v1Type func() runtime.Object
		apiNew func() interface{}
	}{
		{
			name:   "ResourceSlice",
			v1Type: func() runtime.Object { return &resourceapi.ResourceSlice{} },
			apiNew: func() interface{} { return &ResourceSlice{} },
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			for i := range apitest.FuzzIterations {
				// Create and fuzz v1 object.
				v1Obj := tc.v1Type()
				filler.Fill(v1Obj)

				// Convert v1 -> api.
				apiObj := tc.apiNew()