github.com/leanovate/gopter@v0.2.9/derived_gen_test.go (about)

     1  package gopter_test
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/leanovate/gopter"
     8  	"github.com/leanovate/gopter/gen"
     9  )
    10  
    11  type downStruct struct {
    12  	a int
    13  	b string
    14  	c bool
    15  }
    16  
    17  func TestDeriveGenSingleDown(t *testing.T) {
    18  	gen := gopter.DeriveGen(
    19  		func(a int, b string, c bool) *downStruct {
    20  			return &downStruct{a: a, b: b, c: c}
    21  		},
    22  		func(d *downStruct) (int, string, bool) {
    23  			return d.a, d.b, d.c
    24  		},
    25  		gen.Int(),
    26  		gen.AnyString(),
    27  		gen.Bool(),
    28  	)
    29  
    30  	sample, ok := gen.Sample()
    31  	if !ok {
    32  		t.Error("Sample not ok")
    33  	}
    34  	_, ok = sample.(*downStruct)
    35  	if !ok {
    36  		t.Errorf("%#v is not a downStruct", sample)
    37  	}
    38  
    39  	shrinker := gen(gopter.DefaultGenParameters()).Shrinker
    40  	shrink := shrinker(&downStruct{a: 10, b: "abcd", c: false})
    41  
    42  	shrunkStructs := make([]*downStruct, 0)
    43  	value, next := shrink()
    44  	for next {
    45  		shrunkStruct, ok := value.(*downStruct)
    46  		if !ok {
    47  			t.Errorf("Invalid shrunk value: %#v", value)
    48  		}
    49  		shrunkStructs = append(shrunkStructs, shrunkStruct)
    50  		value, next = shrink()
    51  	}
    52  
    53  	expected := []*downStruct{
    54  		{a: 0, b: "abcd", c: false},
    55  		{a: 5, b: "abcd", c: false},
    56  		{a: -5, b: "abcd", c: false},
    57  		{a: 8, b: "abcd", c: false},
    58  		{a: -8, b: "abcd", c: false},
    59  		{a: 9, b: "abcd", c: false},
    60  		{a: -9, b: "abcd", c: false},
    61  		{a: 10, b: "cd", c: false},
    62  		{a: 10, b: "ab", c: false},
    63  		{a: 10, b: "bcd", c: false},
    64  		{a: 10, b: "acd", c: false},
    65  		{a: 10, b: "abd", c: false},
    66  		{a: 10, b: "abc", c: false},
    67  	}
    68  	if !reflect.DeepEqual(shrunkStructs, expected) {
    69  		t.Errorf("%v does not equal %v", shrunkStructs, expected)
    70  	}
    71  }
    72  
    73  func TestDeriveGenSingleDownWithSieves(t *testing.T) {
    74  	gen := gopter.DeriveGen(
    75  		func(a int, b string, c bool) *downStruct {
    76  			return &downStruct{a: a, b: b, c: c}
    77  		},
    78  		func(d *downStruct) (int, string, bool) {
    79  			return d.a, d.b, d.c
    80  		},
    81  		gen.Int().SuchThat(func(i int) bool {
    82  			return i%2 == 0
    83  		}),
    84  		gen.AnyString(),
    85  		gen.Bool(),
    86  	)
    87  
    88  	parameters := gopter.DefaultGenParameters()
    89  	parameters.Rng.Seed(1234)
    90  
    91  	hasNoValue := false
    92  	sawEven := false
    93  	sawOdd := false
    94  	for i := 0; i < 100; i++ {
    95  		result := gen(parameters)
    96  		val, ok := result.Retrieve()
    97  		if ok {
    98  			ds := val.(*downStruct)
    99  			if ds.a%2 == 0 {
   100  				sawEven = true
   101  			} else {
   102  				sawOdd = true
   103  			}
   104  		} else {
   105  			hasNoValue = true
   106  		}
   107  	}
   108  	if !hasNoValue {
   109  		t.Error("Sieve is not applied")
   110  	}
   111  
   112  	if !sawEven {
   113  		t.Error("Sieve did not pass even")
   114  	}
   115  
   116  	if sawOdd {
   117  		t.Error("Sieve did pass odd")
   118  	}
   119  }
   120  
   121  func TestDeriveGenMultiDown(t *testing.T) {
   122  	gen := gopter.DeriveGen(
   123  		func(a int, b string, c bool, d int32) (*downStruct, int64) {
   124  			return &downStruct{a: a, b: b, c: c}, int64(a) + int64(d)
   125  		},
   126  		func(d *downStruct, diff int64) (int, string, bool, int32) {
   127  			return d.a, d.b, d.c, int32(diff - int64(d.a))
   128  		},
   129  		gen.Int(),
   130  		gen.AnyString(),
   131  		gen.Bool(),
   132  		gen.Int32(),
   133  	)
   134  
   135  	sample, ok := gen.Sample()
   136  	if !ok {
   137  		t.Error("Sample not ok")
   138  	}
   139  	values, ok := sample.([]interface{})
   140  	if !ok || len(values) != 2 {
   141  		t.Errorf("%#v is not a slice of interface", sample)
   142  	}
   143  	_, ok = values[0].(*downStruct)
   144  	if !ok {
   145  		t.Errorf("%#v is not a downStruct", values[0])
   146  	}
   147  	_, ok = values[1].(int64)
   148  	if !ok {
   149  		t.Errorf("%#v is not a int64", values[1])
   150  	}
   151  
   152  	shrinker := gen(gopter.DefaultGenParameters()).Shrinker
   153  	shrink := shrinker([]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(20)})
   154  
   155  	value, next := shrink()
   156  	shrunkValues := make([][]interface{}, 0)
   157  	for next {
   158  		shrunk, ok := value.([]interface{})
   159  		if !ok || len(values) != 2 {
   160  			t.Errorf("%#v is not a slice of interface", sample)
   161  		}
   162  		shrunkValues = append(shrunkValues, shrunk)
   163  		value, next = shrink()
   164  	}
   165  
   166  	expected := [][]interface{}{
   167  		{&downStruct{a: 0, b: "abcd", c: false}, int64(10)},
   168  		{&downStruct{a: 5, b: "abcd", c: false}, int64(15)},
   169  		{&downStruct{a: -5, b: "abcd", c: false}, int64(5)},
   170  		{&downStruct{a: 8, b: "abcd", c: false}, int64(18)},
   171  		{&downStruct{a: -8, b: "abcd", c: false}, int64(2)},
   172  		{&downStruct{a: 9, b: "abcd", c: false}, int64(19)},
   173  		{&downStruct{a: -9, b: "abcd", c: false}, int64(1)},
   174  		{&downStruct{a: 10, b: "cd", c: false}, int64(20)},
   175  		{&downStruct{a: 10, b: "ab", c: false}, int64(20)},
   176  		{&downStruct{a: 10, b: "bcd", c: false}, int64(20)},
   177  		{&downStruct{a: 10, b: "acd", c: false}, int64(20)},
   178  		{&downStruct{a: 10, b: "abd", c: false}, int64(20)},
   179  		{&downStruct{a: 10, b: "abc", c: false}, int64(20)},
   180  		{&downStruct{a: 10, b: "abcd", c: false}, int64(10)},
   181  		{&downStruct{a: 10, b: "abcd", c: false}, int64(15)},
   182  		{&downStruct{a: 10, b: "abcd", c: false}, int64(5)},
   183  		{&downStruct{a: 10, b: "abcd", c: false}, int64(18)},
   184  		{&downStruct{a: 10, b: "abcd", c: false}, int64(2)},
   185  		{&downStruct{a: 10, b: "abcd", c: false}, int64(19)},
   186  		{&downStruct{a: 10, b: "abcd", c: false}, int64(1)},
   187  	}
   188  
   189  	if !reflect.DeepEqual(shrunkValues, expected) {
   190  		t.Errorf("%v does not equal %v", shrunkValues, expected)
   191  	}
   192  }
   193  
   194  func TestDeriveGenVaryingSieveAndShrinker(t *testing.T) {
   195  	gen := gopter.DeriveGen(
   196  		func(a interface{}) interface{} {
   197  			return a
   198  		},
   199  		func(a interface{}) interface{} {
   200  			return a
   201  		},
   202  		gen.OneGenOf(gen.AnyString(), gen.Int()),
   203  	)
   204  
   205  	parameters := gopter.DefaultGenParameters()
   206  	parameters.Rng.Seed(1234)
   207  
   208  	for i := 0; i < 20; i++ {
   209  		result := gen(parameters)
   210  		sample, ok := result.Retrieve()
   211  		if !ok {
   212  			t.Error("Sample not ok")
   213  		}
   214  		if stringval, ok := sample.(string); ok {
   215  			// check that the Shrinker doesn't panic
   216  			result.Shrinker(stringval)
   217  		} else if intval, ok := sample.(int); ok {
   218  			result.Shrinker(intval)
   219  		} else {
   220  			t.Errorf("%#v is not a string or int", sample)
   221  		}
   222  	}
   223  }