leanovate/gopter

Trying to use a concrete generator to fill an interface variable panics

Closed this issue · 0 comments

The following test panics:

package main_test

import (
	"reflect"
	"testing"

	"github.com/leanovate/gopter"
	"github.com/leanovate/gopter/gen"
	"github.com/leanovate/gopter/prop"
)

type Box struct {
	Content interface{}
}

func BoxOf(inner gopter.Gen) gopter.Gen {
	return gen.Struct(reflect.TypeOf(Box{}), map[string]gopter.Gen{
		"Content": inner,
	})
}

func TestPanics(t *testing.T) {
	properties := gopter.NewProperties(nil)

	properties.Property("Should not panic",
		prop.ForAll(
			func(e Box) bool {
				return reflect.DeepEqual(e, Box{0})
			},
			BoxOf(gen.Int()),
		))

	properties.TestingRun(t)
}

What seems to be happening is that I can't use a generator of int to fill a variable of type interface{} in Box. What I expected to happen is for this to be fine. After all, there's nothing wrong with var i interface{} = 3 so why is there a problem with BoxOf(gen.Int())?

I can work around by using an explicit Map() to change the type of the Int() generator to interface{}:

			func(e Box) bool {
				return reflect.DeepEqual(e, Box{0})
			},
-			BoxOf(gen.Int()),
+			BoxOf(
+				gen.Int().Map(func(in *gopter.GenResult) *gopter.GenResult {
+					in.ResultType = reflect.TypeOf((*interface{})(nil)).Elem()
+					return in
+				}),
+			),
		))

	properties.TestingRun(t)

but this feels pretty heavyweight. Is it possible to get structs to accept concrete generators for interface types?