Skip to content

Commit

Permalink
Additional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
untoldwind committed Apr 30, 2016
1 parent f2e9ee9 commit 87bf135
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 6 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# Change log

## [Unreleased]
### Changed
- Gen.Map and Shrink.Map now accept `interface{}` instead of `func (interface{}) interface{}`

This allows cleaner mapping functions without type conversion. E.g. instead of

```Go
gen.AnyString().Map(function (v interface{}) interface{} {
return strings.ToUpper(v.(string))
})
```
you can (and should) now write

```Go
gen.AnyString().Map(function (v string) string {
return strings.ToUpper(v)
})
```
- Gen.FlatMap now has a second parameter `resultType reflect.Type` defining the result type of the mapped generator
- Reason for these changes: The original `Map` and `FlatMap` had a recurring issue with empty results. If the original generator created an empty result there was no clean way to determine the result type of the mapped generator. The new version fixes this by extracting the return type of the mapping functions.

## [0.1] - 2016-04-30
### Added
Expand Down
11 changes: 8 additions & 3 deletions gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,18 @@ func (g Gen) Map(f interface{}) Gen {
mapperType := mapperVal.Type()

if mapperVal.Kind() != reflect.Func {
panic(fmt.Sprintf("Param of Map has to be a func: %v", mapperType.Kind()))
panic(fmt.Sprintf("Param of Map has to be a func, but is %v", mapperType.Kind()))
}
if mapperType.NumIn() != 1 {
panic(fmt.Sprintf("Param of Map has to be a func with one param: %v", mapperType.NumIn()))
panic(fmt.Sprintf("Param of Map has to be a func with one param, but is %v", mapperType.NumIn()))
} else {
genResultType := g(DefaultGenParameters()).ResultType
if !genResultType.AssignableTo(mapperType.In(0)) {
panic(fmt.Sprintf("Param of has to be a func with one param assignable to %v, but is %v", genResultType, mapperType.In(0)))
}
}
if mapperType.NumOut() != 1 {
panic(fmt.Sprintf("Param of Map has to be a func with one return value: %v", mapperType.NumOut()))
panic(fmt.Sprintf("Param of Map has to be a func with one return value, but is %v", mapperType.NumOut()))
}

return func(genParams *GenParameters) *GenResult {
Expand Down
35 changes: 35 additions & 0 deletions gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,32 @@ func TestGenMap(t *testing.T) {
}
}

func TestGenMapNoFunc(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func, but is string")
constGen("sample").Map("not a function")
}

func TestGenMapTooManyParams(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func with one param, but is 2")
constGen("sample").Map(func(a, b string) string {
return ""
})
}

func TestGenMapToInvalidParamtype(t *testing.T) {
defer expectPanic(t, "Param of has to be a func with one param assignable to string, but is int")
constGen("sample").Map(func(a int) string {
return ""
})
}

func TestGenMapToManyReturns(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func with one return value, but is 2")
constGen("sample").Map(func(a string) (string, bool) {
return "", false
})
}

func TestGenFlatMap(t *testing.T) {
gen := constGen("sample")
var mappedWith interface{}
Expand Down Expand Up @@ -146,3 +172,12 @@ func TestWithShrinker(t *testing.T) {
t.Errorf("Invalid shrinkerArg: %#v", shrinkerArg)
}
}

func expectPanic(t *testing.T, expected string) {
r := recover()
if r == nil {
t.Errorf("The code did not panic")
} else if r.(string) != expected {
t.Errorf("Panic does not match: '%#v' != '%#v'", r, expected)
}
}
6 changes: 3 additions & 3 deletions shrink.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ func (s Shrink) Map(f interface{}) Shrink {
mapperType := mapperVal.Type()

if mapperVal.Kind() != reflect.Func {
panic(fmt.Sprintf("Param of Map has to be a func: %v", mapperType.Kind()))
panic(fmt.Sprintf("Param of Map has to be a func, but is %v", mapperType.Kind()))
}
if mapperType.NumIn() != 1 {
panic(fmt.Sprintf("Param of Map has to be a func with one param: %v", mapperType.NumIn()))
panic(fmt.Sprintf("Param of Map has to be a func with one param, but is %v", mapperType.NumIn()))
}
if mapperType.NumOut() != 1 {
panic(fmt.Sprintf("Param of Map has to be a func with one return value: %v", mapperType.NumOut()))
panic(fmt.Sprintf("Param of Map has to be a func with one return value, but is %v", mapperType.NumOut()))
}

return func() (interface{}, bool) {
Expand Down
22 changes: 22 additions & 0 deletions shrink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,28 @@ func TestShrinkMap(t *testing.T) {
}
}

func TestShrinkMapNoFunc(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func, but is string")
counter := &counterShrink{n: 10}
gopter.Shrink(counter.Next).Map("not a function")
}

func TestShrinkMapTooManyParams(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func with one param, but is 2")
counter := &counterShrink{n: 10}
gopter.Shrink(counter.Next).Map(func(a, b string) string {
return ""
})
}

func TestShrinkMapToManyReturns(t *testing.T) {
defer expectPanic(t, "Param of Map has to be a func with one return value, but is 2")
counter := &counterShrink{n: 10}
gopter.Shrink(counter.Next).Map(func(a string) (string, bool) {
return "", false
})
}

func TestNoShrinker(t *testing.T) {
shrink := gopter.NoShrinker(123)
if shrink == nil {
Expand Down

0 comments on commit 87bf135

Please sign in to comment.