mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Add App,Trigger,Fn Equality and Clone Testing (#1159)
Creates a test that aims to assert that the Equals and Clone functions for our three entity structs actually work. The bulk of the code is spent creating gopter generators for the entities. See information of generative or property based testing for explainations on that topic, but basically it's an object that is capable of creating a stream of unique instances of the given struct. With the generator we then make three assertions: 1) Entities are always equal to themselves. 2) A .Clone() of an entity is Equal to the original entity. 3) A .Clone() of an entity that has a field modified is not equal to the orignal. The third property is the worse for implementation, as it does not generate the field to modify, it simply loops all fields for each generated entity, and checks Equals always breaks. Break testing shows that this would have caught earlier bugs in Equals due to field addition. It will add to the work to add further fields, generators have to be manually specified for each field, but that seems a worthy cost.
This commit is contained in:
12
Gopkg.lock
generated
12
Gopkg.lock
generated
@@ -221,6 +221,16 @@
|
||||
]
|
||||
revision = "0dae4fefe7c0e190f7b5a78dac28a1c82cc8d849"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/leanovate/gopter"
|
||||
packages = [
|
||||
".",
|
||||
"gen",
|
||||
"prop"
|
||||
]
|
||||
revision = "1f4d0ba27bd5df5390eb622bcb458f8f7ac2573c"
|
||||
version = "v0.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lib/pq"
|
||||
@@ -494,6 +504,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "643d4a3862aeaa6f1115edc26fa3f1f3a6822bb17c01d60fcbdf9ce98bf183ac"
|
||||
inputs-digest = "6c6cfaf48ee2f7f926ed2d063af6a65a505f927e7354fe4613ead8c8a6efb203"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
@@ -115,7 +115,7 @@ func (a *App) Clone() *App {
|
||||
clone.Config[k] = v
|
||||
}
|
||||
}
|
||||
clone.ID = a.ID
|
||||
|
||||
return clone
|
||||
}
|
||||
|
||||
|
||||
143
api/models/app_test.go
Normal file
143
api/models/app_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fnproject/fn/api/common"
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
var stringType = reflect.TypeOf("")
|
||||
var intType = reflect.TypeOf(0)
|
||||
|
||||
func appReflectType() reflect.Type {
|
||||
app := App{}
|
||||
return reflect.TypeOf(app)
|
||||
}
|
||||
|
||||
func configGenerator() gopter.Gen {
|
||||
return gen.MapOf(gen.AlphaString(), gen.AlphaString())
|
||||
}
|
||||
|
||||
func annotationGenerator() gopter.Gen {
|
||||
annotation1, _ := EmptyAnnotations().With("anAnnotation1", "value1")
|
||||
annotation2, _ := EmptyAnnotations().With("anAnnotation2", "value2")
|
||||
|
||||
return gen.OneConstOf(annotation1, annotation2)
|
||||
}
|
||||
|
||||
func datetimeGenerator() gopter.Gen {
|
||||
return gen.Time().Map(func(t time.Time) common.DateTime {
|
||||
return common.DateTime(t)
|
||||
})
|
||||
}
|
||||
|
||||
func appFieldGenerators(t *testing.T) map[string]gopter.Gen {
|
||||
fieldGens := make(map[string]gopter.Gen)
|
||||
fieldGens["ID"] = gen.AlphaString()
|
||||
fieldGens["Name"] = gen.AlphaString()
|
||||
fieldGens["Config"] = configGenerator()
|
||||
fieldGens["Annotations"] = annotationGenerator()
|
||||
fieldGens["SyslogURL"] = gen.AlphaString().Map(func(s string) *string {
|
||||
return &s
|
||||
})
|
||||
fieldGens["CreatedAt"] = datetimeGenerator()
|
||||
fieldGens["UpdatedAt"] = datetimeGenerator()
|
||||
|
||||
appFieldCount := appReflectType().NumField()
|
||||
|
||||
if appFieldCount != len(fieldGens) {
|
||||
t.Fatalf("App struct field count, %d, does not match app generator field count, %d", appFieldCount, len(fieldGens))
|
||||
}
|
||||
|
||||
return fieldGens
|
||||
}
|
||||
|
||||
func appGenerator(t *testing.T) gopter.Gen {
|
||||
return gen.Struct(appReflectType(), appFieldGenerators(t))
|
||||
}
|
||||
|
||||
func novelValue(t *testing.T, originalInstance reflect.Value, fieldName string, fieldGen gopter.Gen) (interface{}, reflect.Value) {
|
||||
newValue, result := fieldGen.Sample()
|
||||
if !result {
|
||||
t.Fatalf("Error sampling field generator, %s, %v", fieldName, result)
|
||||
}
|
||||
|
||||
field := originalInstance.FieldByName(fieldName)
|
||||
currentValue := field.Interface()
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
if fieldName == "Annotations" {
|
||||
if !newValue.(Annotations).Equals(currentValue.(Annotations)) {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if newValue != currentValue {
|
||||
break
|
||||
}
|
||||
}
|
||||
newValue, result = fieldGen.Sample()
|
||||
if !result {
|
||||
t.Fatalf("Error sampling field generator, %s, %v", fieldName, result)
|
||||
}
|
||||
|
||||
if i == 99 {
|
||||
t.Fatalf("Failed to generate a novel value for field, %s", fieldName)
|
||||
}
|
||||
}
|
||||
return currentValue, reflect.ValueOf(newValue)
|
||||
}
|
||||
|
||||
func TestAppEquality(t *testing.T) {
|
||||
properties := gopter.NewProperties(nil)
|
||||
|
||||
properties.Property("An app should always equal itself", prop.ForAll(
|
||||
func(app App) bool {
|
||||
return app.Equals(&app)
|
||||
},
|
||||
appGenerator(t),
|
||||
))
|
||||
|
||||
properties.Property("An app should always equal a clone of itself", prop.ForAll(
|
||||
func(app App) bool {
|
||||
clone := app.Clone()
|
||||
return app.Equals(clone)
|
||||
},
|
||||
appGenerator(t),
|
||||
))
|
||||
|
||||
appFieldGens := appFieldGenerators(t)
|
||||
|
||||
properties.Property("An app should never match a modified version of itself", prop.ForAll(
|
||||
func(app App) bool {
|
||||
for fieldName, fieldGen := range appFieldGens {
|
||||
|
||||
if fieldName == "CreatedAt" ||
|
||||
fieldName == "UpdatedAt" {
|
||||
continue
|
||||
}
|
||||
|
||||
currentValue, newValue := novelValue(t, reflect.ValueOf(app), fieldName, fieldGen)
|
||||
|
||||
clone := app.Clone()
|
||||
s := reflect.ValueOf(clone).Elem()
|
||||
field := s.FieldByName(fieldName)
|
||||
|
||||
field.Set(newValue)
|
||||
|
||||
if app.Equals(clone) {
|
||||
t.Errorf("Changed field, %s, from {%v} to {%v}, but still equal.", fieldName, currentValue, newValue)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
appGenerator(t),
|
||||
))
|
||||
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
109
api/models/fn_test.go
Normal file
109
api/models/fn_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
func fnReflectType() reflect.Type {
|
||||
fn := Fn{}
|
||||
return reflect.TypeOf(fn)
|
||||
}
|
||||
|
||||
func resourceConfigGenerator(t *testing.T) gopter.Gen {
|
||||
fieldGens := make(map[string]gopter.Gen)
|
||||
|
||||
fieldGens["Memory"] = gen.UInt64()
|
||||
fieldGens["Timeout"] = gen.Int32()
|
||||
fieldGens["IdleTimeout"] = gen.Int32()
|
||||
|
||||
resourceConfig := ResourceConfig{}
|
||||
resourceConfigFieldCount := reflect.TypeOf(resourceConfig).NumField()
|
||||
|
||||
if resourceConfigFieldCount != len(fieldGens) {
|
||||
t.Fatalf("Fn struct field count, %d, does not match fn generator field count, %d", resourceConfigFieldCount, len(fieldGens))
|
||||
}
|
||||
|
||||
return gen.Struct(reflect.TypeOf(resourceConfig), fieldGens)
|
||||
}
|
||||
|
||||
func fnFieldGenerators(t *testing.T) map[string]gopter.Gen {
|
||||
fieldGens := make(map[string]gopter.Gen)
|
||||
|
||||
fieldGens["ID"] = gen.AlphaString()
|
||||
fieldGens["Name"] = gen.AlphaString()
|
||||
fieldGens["AppID"] = gen.AlphaString()
|
||||
fieldGens["Image"] = gen.AlphaString()
|
||||
fieldGens["Config"] = configGenerator()
|
||||
fieldGens["ResourceConfig"] = resourceConfigGenerator(t)
|
||||
fieldGens["Annotations"] = annotationGenerator()
|
||||
fieldGens["CreatedAt"] = datetimeGenerator()
|
||||
fieldGens["UpdatedAt"] = datetimeGenerator()
|
||||
fieldGens["Format"] = gen.AlphaString()
|
||||
|
||||
fnFieldCount := fnReflectType().NumField()
|
||||
|
||||
if fnFieldCount != len(fieldGens) {
|
||||
t.Fatalf("Fn struct field count, %d, does not match fn generator field count, %d", fnFieldCount, len(fieldGens))
|
||||
}
|
||||
|
||||
return fieldGens
|
||||
}
|
||||
|
||||
func fnGenerator(t *testing.T) gopter.Gen {
|
||||
return gen.Struct(fnReflectType(), fnFieldGenerators(t))
|
||||
}
|
||||
|
||||
func TestFnEquality(t *testing.T) {
|
||||
properties := gopter.NewProperties(nil)
|
||||
|
||||
properties.Property("A fn should always equal itself", prop.ForAll(
|
||||
func(fn Fn) bool {
|
||||
return fn.Equals(&fn)
|
||||
},
|
||||
fnGenerator(t),
|
||||
))
|
||||
|
||||
properties.Property("A fn should always equal a clone of itself", prop.ForAll(
|
||||
func(fn Fn) bool {
|
||||
clone := fn.Clone()
|
||||
return fn.Equals(clone)
|
||||
},
|
||||
fnGenerator(t),
|
||||
))
|
||||
|
||||
fnFieldGens := fnFieldGenerators(t)
|
||||
|
||||
properties.Property("A fn should never match a modified version of itself", prop.ForAll(
|
||||
func(fn Fn) bool {
|
||||
for fieldName, fieldGen := range fnFieldGens {
|
||||
|
||||
if fieldName == "CreatedAt" ||
|
||||
fieldName == "UpdatedAt" {
|
||||
continue
|
||||
}
|
||||
|
||||
currentValue, newValue := novelValue(t, reflect.ValueOf(fn), fieldName, fieldGen)
|
||||
|
||||
clone := fn.Clone()
|
||||
s := reflect.ValueOf(clone).Elem()
|
||||
field := s.FieldByName(fieldName)
|
||||
|
||||
field.Set(newValue)
|
||||
|
||||
if fn.Equals(clone) {
|
||||
t.Errorf("Changed field, %s, from {%v} to {%v}, but still equal.", fieldName, currentValue, newValue)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
fnGenerator(t),
|
||||
))
|
||||
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
@@ -2,7 +2,12 @@ package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
var openEmptyJSON = `{"id":"","name":"","app_id":"","fn_id":"","created_at":"0001-01-01T00:00:00.000Z","updated_at":"0001-01-01T00:00:00.000Z","type":"","source":""`
|
||||
@@ -62,3 +67,83 @@ func TestTriggerValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func triggerReflectType() reflect.Type {
|
||||
trigger := Trigger{}
|
||||
return reflect.TypeOf(trigger)
|
||||
}
|
||||
|
||||
func triggerFieldGenerators(t *testing.T) map[string]gopter.Gen {
|
||||
fieldGens := make(map[string]gopter.Gen)
|
||||
fieldGens["ID"] = gen.AlphaString()
|
||||
fieldGens["Name"] = gen.AlphaString()
|
||||
fieldGens["AppID"] = gen.AlphaString()
|
||||
fieldGens["FnID"] = gen.AlphaString()
|
||||
fieldGens["CreatedAt"] = datetimeGenerator()
|
||||
fieldGens["UpdatedAt"] = datetimeGenerator()
|
||||
fieldGens["Type"] = gen.AlphaString()
|
||||
fieldGens["Source"] = gen.AlphaString()
|
||||
fieldGens["Annotations"] = annotationGenerator()
|
||||
|
||||
triggerFieldCount := triggerReflectType().NumField()
|
||||
|
||||
if triggerFieldCount != len(fieldGens) {
|
||||
t.Fatalf("Trigger struct field count, %d, does not match trigger generator field count, %d", triggerFieldCount, len(fieldGens))
|
||||
}
|
||||
|
||||
return fieldGens
|
||||
}
|
||||
|
||||
func triggerGenerator(t *testing.T) gopter.Gen {
|
||||
return gen.Struct(triggerReflectType(), triggerFieldGenerators(t))
|
||||
}
|
||||
|
||||
func TestTriggerEquality(t *testing.T) {
|
||||
properties := gopter.NewProperties(nil)
|
||||
|
||||
properties.Property("A trigger should always equal itself", prop.ForAll(
|
||||
func(trigger Trigger) bool {
|
||||
return trigger.Equals(&trigger)
|
||||
},
|
||||
triggerGenerator(t),
|
||||
))
|
||||
|
||||
properties.Property("A trigger should always equal a clone of itself", prop.ForAll(
|
||||
func(trigger Trigger) bool {
|
||||
clone := trigger.Clone()
|
||||
return trigger.Equals(clone)
|
||||
},
|
||||
triggerGenerator(t),
|
||||
))
|
||||
|
||||
triggerFieldGens := triggerFieldGenerators(t)
|
||||
|
||||
properties.Property("A trigger should never match a modified version of itself", prop.ForAll(
|
||||
func(trigger Trigger) bool {
|
||||
for fieldName, fieldGen := range triggerFieldGens {
|
||||
|
||||
if fieldName == "CreatedAt" ||
|
||||
fieldName == "UpdatedAt" {
|
||||
continue
|
||||
}
|
||||
|
||||
currentValue, newValue := novelValue(t, reflect.ValueOf(trigger), fieldName, fieldGen)
|
||||
|
||||
clone := trigger.Clone()
|
||||
s := reflect.ValueOf(clone).Elem()
|
||||
field := s.FieldByName(fieldName)
|
||||
|
||||
field.Set(newValue)
|
||||
|
||||
if trigger.Equals(clone) {
|
||||
t.Errorf("Changed field, %s, from {%v} to {%v}, but still equal.", fieldName, currentValue, newValue)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
triggerGenerator(t),
|
||||
))
|
||||
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
|
||||
30
vendor/github.com/leanovate/gopter/.gitignore
generated
vendored
Normal file
30
vendor/github.com/leanovate/gopter/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
bin/
|
||||
*.iml
|
||||
.idea/
|
||||
coverage.txt
|
||||
.pkg.coverage
|
||||
12
vendor/github.com/leanovate/gopter/.travis.yml
generated
vendored
Normal file
12
vendor/github.com/leanovate/gopter/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
sudo: false
|
||||
language: go
|
||||
go:
|
||||
- 1.x
|
||||
script: make all coverage refreshGodoc
|
||||
before_install:
|
||||
- pip install --user codecov
|
||||
after_success:
|
||||
- codecov
|
||||
notifications:
|
||||
slack:
|
||||
secure: M0PgOUB0Kzn0maWtd6NNtiKYINxMY/7zgbbDpb8mAa6NTPYuypEYkUgmo6HC74BzDWSjkJaLQOeZrumrOuJUKbGdT+eEYR1pXColp2qb/WxnSCAwlL9iM/k7pj6nIRUdlP7l6WX0QB/DNh+BC/9STHrcSKjBpUu38oO9CwT7klSj2hfPMjzcx7EO4f8pjSfwCrIyYbANKxLzP0lr4PcbdY/ZeGbc8R5/m9torzPjS2YXDl0tQQ7pvSS8UVToLfL0m+omp9A/lOu0n6FpdNIkof2Eu9qWJqsI7jy+Pi+8DGbfEyxSLKAhDiTn0nfO/5nwqWIBhUaVACBDxpaH6ewpiuMbs4RO+wNaEEuVEH8QMKZOx9PGgnzNJ3zZ5Hfm+FP8zBrwrKlsjUoy31waGFjgua2ne4X0wa+Ld4iFEsj+XoMKa1oxRKRXYFhyEywalwgBVjXH2+ZCMlFGV3QxaV5gVuYcfEuNQ4pOlJpk+WSgm7yfXEX2qosOk2p91yGyX2Msbe3B7Ov3PXVzs2CshIsYasHr46pLplMvG6Z+712TPsrFS0zhb8FAsm/Vd7xX2xxmNS/uffh3RgFzeZxg8S9/ObVq+JBkZAtK4j0SwLVsOkjI4W3yUVgfxvhnAM1iLzzeSyD64BSo1VyUZu1eSJ9YxJ1+K6ldo0u0hj2VHwO1vUE=
|
||||
65
vendor/github.com/leanovate/gopter/CHANGELOG.md
generated
vendored
Normal file
65
vendor/github.com/leanovate/gopter/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
# Change log
|
||||
|
||||
## [Unreleased]
|
||||
### Additions
|
||||
- `gopter.GenParameters` now has a `CloneWithSeed(seed int64)` function to
|
||||
temparary copies to create rerunable sections of code.
|
||||
- Added `gopter.Gen.MapResult` for power-user mappings
|
||||
- Added `gopter.DeriveGen` to derive a generator and it's shrinker from a
|
||||
bi-directional mapping (`gopter.BiMapper`)
|
||||
|
||||
### Changed
|
||||
- Refactored `commands` package under the hood to allow the use of mutable state.
|
||||
Re-runability of commands is provided by invoking the `commands.GenInitialState`
|
||||
generator with the same `gopter.GenParameters`. Of course `commands.GenInitialState`
|
||||
is supposed to create the same state for the same parameters every time.
|
||||
- Fixed a bug in `commands` that might lead to shrinked command sequences not
|
||||
satisfying the precondtions.
|
||||
- `commands.Command.PostCondition` was called with the state before running the command. It makes
|
||||
much more sense to first do `commands.Command.NextState` and then `commands.Command.PostCondition`
|
||||
- `commands.Commands.NewSystemUnderTest` now takes has an argument `initialState commands.State` to
|
||||
allow implementators to create/bootstrap a system under test based on an arbitrary initial state.
|
||||
So far examples were just using a constant initial state ... which is a bit boring.
|
||||
- Fixed: Actually use `commands.Commands.InitialPreCondition` as sieve for
|
||||
`commands.Commands.GenInitialState`
|
||||
- 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)
|
||||
})
|
||||
```
|
||||
- Correspondingly Gen.SuchThat now also ccept `interface{}` instead of `func (interface{}) bool`
|
||||
|
||||
This allows cleaner sieve functions without type conversion. E.g. instead of
|
||||
|
||||
```Go
|
||||
gen.AnyString().SuchThat(function (v interface{}) bool {
|
||||
return HasPrefix(v.(string), "P")
|
||||
})
|
||||
```
|
||||
you can (and should) now write
|
||||
|
||||
```Go
|
||||
gen.AnyString().SuchThat(function (v string) bool {
|
||||
return HasPrefix(v, "P")
|
||||
})
|
||||
```
|
||||
- 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
|
||||
- Initial implementation.
|
||||
|
||||
[Unreleased]: https://github.com/leanovate/gopter/compare/v0.1...HEAD
|
||||
[0.1]: https://github.com/leanovate/gopter/tree/v0.1
|
||||
21
vendor/github.com/leanovate/gopter/LICENSE
generated
vendored
Normal file
21
vendor/github.com/leanovate/gopter/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 leanovate
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
41
vendor/github.com/leanovate/gopter/Makefile
generated
vendored
Normal file
41
vendor/github.com/leanovate/gopter/Makefile
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
PACKAGES=$(shell go list ./...)
|
||||
|
||||
all: format
|
||||
@go get github.com/smartystreets/goconvey
|
||||
@go build -v ./...
|
||||
|
||||
format:
|
||||
@echo "--> Running go fmt"
|
||||
@go fmt ./...
|
||||
|
||||
test:
|
||||
@echo "--> Running tests"
|
||||
@go test -v ./...
|
||||
@$(MAKE) vet
|
||||
|
||||
coverage:
|
||||
@echo "--> Running tests with coverage"
|
||||
@echo "" > coverage.txt
|
||||
for pkg in $(shell go list ./...); do \
|
||||
(go test -coverprofile=.pkg.coverage -covermode=atomic -v $$pkg && \
|
||||
cat .pkg.coverage >> coverage.txt) || exit 1; \
|
||||
done
|
||||
@rm .pkg.coverage
|
||||
@$(MAKE) vet
|
||||
|
||||
vet:
|
||||
@go tool vet 2>/dev/null ; if [ $$? -eq 3 ]; then \
|
||||
go get golang.org/x/tools/cmd/vet; \
|
||||
fi
|
||||
@echo "--> Running go tool vet $(VETARGS)"
|
||||
@find . -name "*.go" | grep -v "./Godeps/" | xargs go tool vet $(VETARGS); if [ $$? -eq 1 ]; then \
|
||||
echo ""; \
|
||||
echo "Vet found suspicious constructs. Please check the reported constructs"; \
|
||||
echo "and fix them if necessary before submitting the code for reviewal."; \
|
||||
fi
|
||||
|
||||
refreshGodoc:
|
||||
@echo "--> Refreshing godoc.org"
|
||||
for pkg in $(shell go list ./...); do \
|
||||
curl -d "path=$$pkg" https://godoc.org/-/refresh ; \
|
||||
done
|
||||
44
vendor/github.com/leanovate/gopter/README.md
generated
vendored
Normal file
44
vendor/github.com/leanovate/gopter/README.md
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# GOPTER
|
||||
|
||||
... the GOlang Property TestER
|
||||
[](https://travis-ci.org/leanovate/gopter)
|
||||
[](https://codecov.io/gh/leanovate/gopter)
|
||||
[](https://godoc.org/github.com/leanovate/gopter)
|
||||
|
||||
[Change Log](CHANGELOG.md)
|
||||
|
||||
## Synopsis
|
||||
|
||||
Gopter tries to bring the goodness of [ScalaCheck](https://www.scalacheck.org/) (and implicitly, the goodness of [QuickCheck](http://hackage.haskell.org/package/QuickCheck)) to Go.
|
||||
It can also be seen as a more sophisticated version of the testing/quick package.
|
||||
|
||||
Main differences to ScalaCheck:
|
||||
|
||||
* It is Go ... duh
|
||||
* ... nevertheless: Do not expect the same typesafety and elegance as in ScalaCheck.
|
||||
* For simplicity [Shrink](https://www.scalacheck.org/files/scalacheck_2.11-1.14.0-api/index.html#org.scalacheck.Shrink) has become part of the generators. They can still be easily changed if necessary.
|
||||
* There is no [Pretty](https://www.scalacheck.org/files/scalacheck_2.11-1.14.0-api/index.html#org.scalacheck.util.Pretty) ... so far gopter feels quite comfortable being ugly.
|
||||
* A generator for regex matches
|
||||
* No parallel commands ... yet?
|
||||
|
||||
Main differences to the testing/quick package:
|
||||
|
||||
* Much tighter control over generators
|
||||
* Shrinkers, i.e. automatically find the minimum value falsifying a property
|
||||
* A generator for regex matches (already mentioned that ... but it's cool)
|
||||
* Support for stateful tests
|
||||
|
||||
## Documentation
|
||||
|
||||
Current godocs:
|
||||
|
||||
* [gopter](https://godoc.org/github.com/leanovate/gopter): Main interfaces
|
||||
* [gopter/gen](https://godoc.org/github.com/leanovate/gopter/gen): All commonly used generators
|
||||
* [gopter/prop](https://godoc.org/github.com/leanovate/gopter/prop): Common helpers to create properties from a condition function and specific generators
|
||||
* [gopter/arbitrary](https://godoc.org/github.com/leanovate/gopter/arbitrary): Helpers automatically combine generators for arbitrary types
|
||||
* [gopter/commands](https://godoc.org/github.com/leanovate/gopter/commands): Helpers to create stateful tests based on arbitrary commands
|
||||
* [gopter/convey](https://godoc.org/github.com/leanovate/gopter/convey): Helpers used by gopter inside goconvey tests
|
||||
|
||||
## License
|
||||
|
||||
[MIT Licence](http://opensource.org/licenses/MIT)
|
||||
41
vendor/github.com/leanovate/gopter/arbitrary/arbitraries.go
generated
vendored
Normal file
41
vendor/github.com/leanovate/gopter/arbitrary/arbitraries.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package arbitrary
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
// Arbitraries defines a context to generate arbitrary values of any kind.
|
||||
// Values are generated by either providing a generator for a specific type
|
||||
// or by creating a generator on the fly using golang reflection.
|
||||
type Arbitraries struct {
|
||||
generators map[reflect.Type]gopter.Gen
|
||||
}
|
||||
|
||||
// DefaultArbitraries creates a default arbitrary context with the widest
|
||||
// possible ranges for all types.
|
||||
func DefaultArbitraries() *Arbitraries {
|
||||
return &Arbitraries{
|
||||
generators: map[reflect.Type]gopter.Gen{
|
||||
reflect.TypeOf(time.Now()): gen.Time(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GenForType gets a generator for a generator for a type
|
||||
func (a *Arbitraries) GenForType(rt reflect.Type) gopter.Gen {
|
||||
if gen, ok := a.generators[rt]; ok {
|
||||
return gen
|
||||
}
|
||||
return a.genForKind(rt)
|
||||
}
|
||||
|
||||
// RegisterGen registers a generator
|
||||
func (a *Arbitraries) RegisterGen(gen gopter.Gen) {
|
||||
result := gen(gopter.DefaultGenParameters())
|
||||
rt := result.ResultType
|
||||
a.generators[rt] = gen
|
||||
}
|
||||
32
vendor/github.com/leanovate/gopter/arbitrary/doc.go
generated
vendored
Normal file
32
vendor/github.com/leanovate/gopter/arbitrary/doc.go
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Package arbitrary contains helpers to create contexts of arbitrary values, i.e.
|
||||
automatically combine generators as needed using reflection.
|
||||
|
||||
A simple example might look like this:
|
||||
|
||||
func TestIntParse(t *testing.T) {
|
||||
properties := gopter.NewProperties(nil)
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
|
||||
properties.Property("printed integers can be parsed", arbitraries.ForAll(
|
||||
func(a int64) bool {
|
||||
str := fmt.Sprintf("%d", a)
|
||||
parsed, err := strconv.ParseInt(str, 10, 64)
|
||||
return err == nil && parsed == a
|
||||
}))
|
||||
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
|
||||
Be aware that by default always the most generic generators are used. I.e. in
|
||||
the example above the gen.Int64 generator will be used and the condition will
|
||||
be tested for the full range of int64 numbers.
|
||||
|
||||
To adapt this one might register a generator for a specific type in an
|
||||
arbitraries context. I.e. by adding
|
||||
|
||||
arbitraries.RegisterGen(gen.Int64Range(-1000, 1000))
|
||||
|
||||
any generated int64 number will be between -1000 and 1000.
|
||||
*/
|
||||
package arbitrary
|
||||
64
vendor/github.com/leanovate/gopter/arbitrary/example_arbitrary_struct_test.go
generated
vendored
Normal file
64
vendor/github.com/leanovate/gopter/arbitrary/example_arbitrary_struct_test.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
)
|
||||
|
||||
type MyStringType string
|
||||
type MyInt8Type int8
|
||||
type MyInt16Type int16
|
||||
type MyInt32Type int32
|
||||
type MyInt64Type int64
|
||||
type MyUInt8Type uint8
|
||||
type MyUInt16Type uint16
|
||||
type MyUInt32Type uint32
|
||||
type MyUInt64Type uint64
|
||||
|
||||
type Foo struct {
|
||||
Name MyStringType
|
||||
Id1 MyInt8Type
|
||||
Id2 MyInt16Type
|
||||
Id3 MyInt32Type
|
||||
Id4 MyInt64Type
|
||||
Id5 MyUInt8Type
|
||||
Id6 MyUInt16Type
|
||||
Id7 MyUInt32Type
|
||||
Id8 MyUInt64Type
|
||||
}
|
||||
|
||||
func Example_arbitrary_structs() {
|
||||
parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducable results, otherwise DefaultTestParameters() will suffice
|
||||
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("MyInt64", arbitraries.ForAll(
|
||||
func(id MyInt64Type) bool {
|
||||
return id > -1000
|
||||
}))
|
||||
properties.Property("MyUInt32Type", arbitraries.ForAll(
|
||||
func(id MyUInt32Type) bool {
|
||||
return id < 2000
|
||||
}))
|
||||
properties.Property("Foo", arbitraries.ForAll(
|
||||
func(foo *Foo) bool {
|
||||
return true
|
||||
}))
|
||||
properties.Property("Foo2", arbitraries.ForAll(
|
||||
func(foo Foo) bool {
|
||||
return true
|
||||
}))
|
||||
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// ! MyInt64: Falsified after 6 passed tests.
|
||||
// ARG_0: -1000
|
||||
// ARG_0_ORIGINAL (54 shrinks): -1601066829744837253
|
||||
// ! MyUInt32Type: Falsified after 0 passed tests.
|
||||
// ARG_0: 2000
|
||||
// ARG_0_ORIGINAL (23 shrinks): 2161922319
|
||||
// + Foo: OK, passed 100 tests.
|
||||
// + Foo2: OK, passed 100 tests.
|
||||
}
|
||||
28
vendor/github.com/leanovate/gopter/arbitrary/example_parseint_test.go
generated
vendored
Normal file
28
vendor/github.com/leanovate/gopter/arbitrary/example_parseint_test.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
)
|
||||
|
||||
func Example_parseint() {
|
||||
parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducable results, otherwise DefaultTestParameters() will suffice
|
||||
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("printed integers can be parsed", arbitraries.ForAll(
|
||||
func(a int64) bool {
|
||||
str := fmt.Sprintf("%d", a)
|
||||
parsed, err := strconv.ParseInt(str, 10, 64)
|
||||
return err == nil && parsed == a
|
||||
}))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// + printed integers can be parsed: OK, passed 100 tests.
|
||||
}
|
||||
78
vendor/github.com/leanovate/gopter/arbitrary/example_quadratic_test.go
generated
vendored
Normal file
78
vendor/github.com/leanovate/gopter/arbitrary/example_quadratic_test.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/cmplx"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type QudraticEquation struct {
|
||||
A, B, C complex128
|
||||
}
|
||||
|
||||
func (q *QudraticEquation) Eval(x complex128) complex128 {
|
||||
return q.A*x*x + q.B*x + q.C
|
||||
}
|
||||
|
||||
func (q *QudraticEquation) Solve() (complex128, complex128, error) {
|
||||
if q.A == 0 {
|
||||
return 0, 0, errors.New("No solution")
|
||||
}
|
||||
v := q.B*q.B - 4*q.A*q.C
|
||||
v = cmplx.Sqrt(v)
|
||||
return (-q.B + v) / 2 / q.A, (-q.B - v) / 2 / q.A, nil
|
||||
}
|
||||
|
||||
func Example_quadratic() {
|
||||
parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducable results, otherwise DefaultTestParameters() will suffice
|
||||
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
arbitraries.RegisterGen(gen.Complex128Box(-1e8-1e8i, 1e8+1e8i)) // Only use complex values within a range
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("Quadratic equations can be solved (as pointer)", arbitraries.ForAll(
|
||||
func(quadratic *QudraticEquation) bool {
|
||||
x1, x2, err := quadratic.Solve()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5
|
||||
}))
|
||||
|
||||
properties.Property("Quadratic equations can be solved (as struct)", arbitraries.ForAll(
|
||||
func(quadratic QudraticEquation) bool {
|
||||
x1, x2, err := quadratic.Solve()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5
|
||||
}))
|
||||
|
||||
properties.Property("Quadratic equations can be solved alternative", arbitraries.ForAll(
|
||||
func(a, b, c complex128) bool {
|
||||
quadratic := &QudraticEquation{
|
||||
A: a,
|
||||
B: b,
|
||||
C: c,
|
||||
}
|
||||
x1, x2, err := quadratic.Solve()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return cmplx.Abs(quadratic.Eval(x1)) < 1e-5 && cmplx.Abs(quadratic.Eval(x2)) < 1e-5
|
||||
}))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// + Quadratic equations can be solved (as pointer): OK, passed 100 tests.
|
||||
// + Quadratic equations can be solved (as struct): OK, passed 100 tests.
|
||||
// + Quadratic equations can be solved alternative: OK, passed 100 tests.
|
||||
}
|
||||
33
vendor/github.com/leanovate/gopter/arbitrary/forall.go
generated
vendored
Normal file
33
vendor/github.com/leanovate/gopter/arbitrary/forall.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package arbitrary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
/*
|
||||
ForAll creates a property that requires the check condition to be true for all
|
||||
values, if the condition falsiies the generated values will be shrinked.
|
||||
|
||||
"condition" has to be a function with the any number of parameters that can
|
||||
generated in context of the Arbitraries. The function may return a simple bool,
|
||||
a *PropResult, a boolean with error or a *PropResult with error.
|
||||
*/
|
||||
func (a *Arbitraries) ForAll(condition interface{}) gopter.Prop {
|
||||
conditionVal := reflect.ValueOf(condition)
|
||||
conditionType := conditionVal.Type()
|
||||
|
||||
if conditionType.Kind() != reflect.Func {
|
||||
return prop.ErrorProp(fmt.Errorf("Param of ForrAll has to be a func: %v", conditionType.Kind()))
|
||||
}
|
||||
|
||||
gens := make([]gopter.Gen, conditionType.NumIn())
|
||||
for i := 0; i < conditionType.NumIn(); i++ {
|
||||
gens[i] = a.GenForType(conditionType.In(i))
|
||||
}
|
||||
|
||||
return prop.ForAll(condition, gens...)
|
||||
}
|
||||
333
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind.go
generated
vendored
Normal file
333
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind.go
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
package arbitrary
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func mapBoolish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetBool(value.Bool())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func mapIntish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetInt(value.Int())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func mapUintish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetUint(value.Uint())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func mapFloatish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetFloat(value.Float())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func mapComplexish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetComplex(value.Complex())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func mapStringish(to reflect.Type, v interface{}) interface{} {
|
||||
value := reflect.ValueOf(v)
|
||||
result := reflect.New(to).Elem()
|
||||
result.SetString(value.String())
|
||||
return result.Interface()
|
||||
}
|
||||
|
||||
func (a *Arbitraries) genForKind(rt reflect.Type) gopter.Gen {
|
||||
switch rt.Kind() {
|
||||
case reflect.Bool:
|
||||
return gen.Bool().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapBoolish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapBoolish(reflect.TypeOf(bool(false)), v))
|
||||
},
|
||||
Shrinker: gopter.NoShrinker,
|
||||
}
|
||||
})
|
||||
case reflect.Int:
|
||||
return gen.Int().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapIntish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapIntish(reflect.TypeOf(int(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapIntish(reflect.TypeOf(int(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapIntish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Uint:
|
||||
return gen.UInt().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapUintish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapUintish(reflect.TypeOf(uint(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapUintish(reflect.TypeOf(uint(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapUintish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Int8:
|
||||
return gen.Int8().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapIntish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapIntish(reflect.TypeOf(int8(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapIntish(reflect.TypeOf(int8(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapIntish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Uint8:
|
||||
return gen.UInt8().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapUintish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapUintish(reflect.TypeOf(uint8(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapUintish(reflect.TypeOf(uint8(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapUintish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Int16:
|
||||
return gen.Int16().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapIntish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapIntish(reflect.TypeOf(int16(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapIntish(reflect.TypeOf(int16(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapIntish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Uint16:
|
||||
return gen.UInt16().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapUintish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapUintish(reflect.TypeOf(uint16(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapUintish(reflect.TypeOf(uint16(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapUintish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Int32:
|
||||
return gen.Int32().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapIntish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapIntish(reflect.TypeOf(int32(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapIntish(reflect.TypeOf(int32(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapIntish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Uint32:
|
||||
return gen.UInt32().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapUintish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapUintish(reflect.TypeOf(uint32(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapUintish(reflect.TypeOf(uint32(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapUintish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Int64:
|
||||
return gen.Int64().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapIntish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapIntish(reflect.TypeOf(int32(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapIntish(reflect.TypeOf(int64(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapIntish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Uint64:
|
||||
return gen.UInt64().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapUintish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapUintish(reflect.TypeOf(uint64(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapUintish(reflect.TypeOf(uint64(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapUintish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Float32:
|
||||
return gen.Float32().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapFloatish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapFloatish(reflect.TypeOf(float32(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapFloatish(reflect.TypeOf(float32(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapFloatish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Float64:
|
||||
return gen.Float64().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapFloatish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapFloatish(reflect.TypeOf(float64(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapFloatish(reflect.TypeOf(float64(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapFloatish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Complex64:
|
||||
return gen.Complex64().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapComplexish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapComplexish(reflect.TypeOf(complex64(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapComplexish(reflect.TypeOf(complex64(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapComplexish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Complex128:
|
||||
return gen.Complex128().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapComplexish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapComplexish(reflect.TypeOf(complex128(0)), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapComplexish(reflect.TypeOf(complex128(0)), v)).Map(func(s interface{}) interface{} {
|
||||
return mapComplexish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.String:
|
||||
return gen.AnyString().MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
return &gopter.GenResult{
|
||||
Labels: result.Labels,
|
||||
ResultType: rt,
|
||||
Result: mapStringish(rt, result.Result),
|
||||
Sieve: func(v interface{}) bool {
|
||||
return result.Sieve == nil || result.Sieve(mapStringish(reflect.TypeOf(string("")), v))
|
||||
},
|
||||
Shrinker: func(v interface{}) gopter.Shrink {
|
||||
return result.Shrinker(mapStringish(reflect.TypeOf(string("")), v)).Map(func(s interface{}) interface{} {
|
||||
return mapStringish(rt, s)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
case reflect.Slice:
|
||||
if elementGen := a.GenForType(rt.Elem()); elementGen != nil {
|
||||
return gen.SliceOf(elementGen)
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if rt.Elem().Kind() == reflect.Struct {
|
||||
gens := make(map[string]gopter.Gen)
|
||||
for i := 0; i < rt.Elem().NumField(); i++ {
|
||||
field := rt.Elem().Field(i)
|
||||
if gen := a.GenForType(field.Type); gen != nil {
|
||||
gens[field.Name] = gen
|
||||
}
|
||||
}
|
||||
return gen.StructPtr(rt, gens)
|
||||
}
|
||||
return gen.PtrOf(a.GenForType(rt.Elem()))
|
||||
case reflect.Struct:
|
||||
gens := make(map[string]gopter.Gen)
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
field := rt.Field(i)
|
||||
if gen := a.GenForType(field.Type); gen != nil {
|
||||
gens[field.Name] = gen
|
||||
}
|
||||
}
|
||||
return gen.Struct(rt, gens)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
30
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_slice_test.go
generated
vendored
Normal file
30
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_slice_test.go
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
)
|
||||
|
||||
func TestArbitrariesSlices(t *testing.T) {
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
|
||||
gen := arbitraries.GenForType(reflect.TypeOf([]bool{}))
|
||||
value, ok := gen.Sample()
|
||||
if !ok {
|
||||
t.Errorf("Invalid value %#v", value)
|
||||
}
|
||||
if _, ok = value.([]bool); !ok {
|
||||
t.Errorf("Invalid value %#v", value)
|
||||
}
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf([]*int64{}))
|
||||
value, ok = gen.Sample()
|
||||
if !ok {
|
||||
t.Errorf("Invalid value %#v", value)
|
||||
}
|
||||
if _, ok = value.([]*int64); !ok {
|
||||
t.Errorf("Invalid value %#v", value)
|
||||
}
|
||||
}
|
||||
52
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_struct_test.go
generated
vendored
Normal file
52
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_struct_test.go
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type DemoStruct struct {
|
||||
Value1 int64
|
||||
Value2 string
|
||||
Value3 []uint
|
||||
Value4 int32
|
||||
}
|
||||
|
||||
func TestArbitrariesStructs(t *testing.T) {
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
|
||||
arbitraries.RegisterGen(gen.Int64Range(10, 100))
|
||||
arbitraries.RegisterGen(gen.Int32Range(1, 10))
|
||||
arbitraries.RegisterGen(gen.Const([]uint{1, 2, 3}))
|
||||
arbitraries.RegisterGen(gen.AlphaString())
|
||||
|
||||
gen := arbitraries.GenForType(reflect.TypeOf(&DemoStruct{}))
|
||||
for i := 0; i < 100; i++ {
|
||||
raw, ok := gen.Sample()
|
||||
if !ok {
|
||||
t.Errorf("Invalid value: %#v", raw)
|
||||
}
|
||||
value, ok := raw.(*DemoStruct)
|
||||
if !ok {
|
||||
t.Errorf("Invalid value: %#v", raw)
|
||||
}
|
||||
if value.Value1 < 10 || value.Value1 > 100 {
|
||||
t.Errorf("Invalid value.Value1 out of bounds: %#v", raw)
|
||||
}
|
||||
for _, ch := range value.Value2 {
|
||||
if !unicode.IsLetter(ch) {
|
||||
t.Errorf("Invalid value.Value2: %#v", raw)
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(value.Value3, []uint{1, 2, 3}) {
|
||||
t.Errorf("Invalid value.Value3: %#v", raw)
|
||||
}
|
||||
if value.Value4 < 1 || value.Value4 > 10 {
|
||||
t.Errorf("Invalid value.Value4 out of bounds: %#v", raw)
|
||||
}
|
||||
}
|
||||
}
|
||||
135
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_test.go
generated
vendored
Normal file
135
vendor/github.com/leanovate/gopter/arbitrary/gen_for_kind_test.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
package arbitrary_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
)
|
||||
|
||||
func commonGeneratorTest(t *testing.T, name string, gen gopter.Gen, valueCheck func(interface{}) bool) {
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := gen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid generator result (%s): %#v", name, value)
|
||||
} else if !valueCheck(value) {
|
||||
t.Errorf("Invalid value (%s): %#v", name, value)
|
||||
}
|
||||
|
||||
genResult := gen(gopter.DefaultGenParameters())
|
||||
if genResult.Shrinker != nil {
|
||||
value, ok := genResult.Retrieve()
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid generator result (%s): %#v", name, value)
|
||||
} else {
|
||||
shrink := genResult.Shrinker(value).Filter(genResult.Sieve)
|
||||
shrunkValue, ok := shrink()
|
||||
if ok && !valueCheck(shrunkValue) {
|
||||
t.Errorf("Invalid shrunk value (%s): %#v -> %#v", name, value, shrunkValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestArbitrariesSimple(t *testing.T) {
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
|
||||
gen := arbitraries.GenForType(reflect.TypeOf(true))
|
||||
commonGeneratorTest(t, "bool", gen, func(value interface{}) bool {
|
||||
_, ok := value.(bool)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(0))
|
||||
commonGeneratorTest(t, "int", gen, func(value interface{}) bool {
|
||||
_, ok := value.(int)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(uint(0)))
|
||||
commonGeneratorTest(t, "uint", gen, func(value interface{}) bool {
|
||||
_, ok := value.(uint)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(int8(0)))
|
||||
commonGeneratorTest(t, "int8", gen, func(value interface{}) bool {
|
||||
_, ok := value.(int8)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(uint8(0)))
|
||||
commonGeneratorTest(t, "uint8", gen, func(value interface{}) bool {
|
||||
_, ok := value.(uint8)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(int16(0)))
|
||||
commonGeneratorTest(t, "int16", gen, func(value interface{}) bool {
|
||||
_, ok := value.(int16)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(uint16(0)))
|
||||
commonGeneratorTest(t, "uint16", gen, func(value interface{}) bool {
|
||||
_, ok := value.(uint16)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(int32(0)))
|
||||
commonGeneratorTest(t, "int32", gen, func(value interface{}) bool {
|
||||
_, ok := value.(int32)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(uint32(0)))
|
||||
commonGeneratorTest(t, "uint32", gen, func(value interface{}) bool {
|
||||
_, ok := value.(uint32)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(int64(0)))
|
||||
commonGeneratorTest(t, "int64", gen, func(value interface{}) bool {
|
||||
_, ok := value.(int64)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(uint64(0)))
|
||||
commonGeneratorTest(t, "uint64", gen, func(value interface{}) bool {
|
||||
_, ok := value.(uint64)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(float32(0)))
|
||||
commonGeneratorTest(t, "float32", gen, func(value interface{}) bool {
|
||||
_, ok := value.(float32)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(float64(0)))
|
||||
commonGeneratorTest(t, "float64", gen, func(value interface{}) bool {
|
||||
_, ok := value.(float64)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(complex128(0)))
|
||||
commonGeneratorTest(t, "complex128", gen, func(value interface{}) bool {
|
||||
_, ok := value.(complex128)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(complex64(0)))
|
||||
commonGeneratorTest(t, "complex64", gen, func(value interface{}) bool {
|
||||
_, ok := value.(complex64)
|
||||
return ok
|
||||
})
|
||||
|
||||
gen = arbitraries.GenForType(reflect.TypeOf(""))
|
||||
commonGeneratorTest(t, "string", gen, func(value interface{}) bool {
|
||||
_, ok := value.(string)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
111
vendor/github.com/leanovate/gopter/bi_mapper.go
generated
vendored
Normal file
111
vendor/github.com/leanovate/gopter/bi_mapper.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// BiMapper is a bi-directional (or bijective) mapper of a tuple of values (up)
|
||||
// to another tuple of values (down).
|
||||
type BiMapper struct {
|
||||
UpTypes []reflect.Type
|
||||
DownTypes []reflect.Type
|
||||
Downstream reflect.Value
|
||||
Upstream reflect.Value
|
||||
}
|
||||
|
||||
// NewBiMapper creates a BiMapper of two functions `downstream` and its
|
||||
// inverse `upstream`.
|
||||
// That is: The return values of `downstream` must match the parameters of
|
||||
// `upstream` and vice versa.
|
||||
func NewBiMapper(downstream interface{}, upstream interface{}) *BiMapper {
|
||||
downstreamVal := reflect.ValueOf(downstream)
|
||||
if downstreamVal.Kind() != reflect.Func {
|
||||
panic("downstream has to be a function")
|
||||
}
|
||||
upstreamVal := reflect.ValueOf(upstream)
|
||||
if upstreamVal.Kind() != reflect.Func {
|
||||
panic("upstream has to be a function")
|
||||
}
|
||||
|
||||
downstreamType := downstreamVal.Type()
|
||||
upTypes := make([]reflect.Type, downstreamType.NumIn())
|
||||
for i := 0; i < len(upTypes); i++ {
|
||||
upTypes[i] = downstreamType.In(i)
|
||||
}
|
||||
downTypes := make([]reflect.Type, downstreamType.NumOut())
|
||||
for i := 0; i < len(downTypes); i++ {
|
||||
downTypes[i] = downstreamType.Out(i)
|
||||
}
|
||||
|
||||
upstreamType := upstreamVal.Type()
|
||||
if len(upTypes) != upstreamType.NumOut() {
|
||||
panic(fmt.Sprintf("upstream is expected to have %d return values", len(upTypes)))
|
||||
}
|
||||
for i, upType := range upTypes {
|
||||
if upstreamType.Out(i) != upType {
|
||||
panic(fmt.Sprintf("upstream has wrong return type %d: %v != %v", i, upstreamType.Out(i), upType))
|
||||
}
|
||||
}
|
||||
if len(downTypes) != upstreamType.NumIn() {
|
||||
panic(fmt.Sprintf("upstream is expected to have %d parameters", len(downTypes)))
|
||||
}
|
||||
for i, downType := range downTypes {
|
||||
if upstreamType.In(i) != downType {
|
||||
panic(fmt.Sprintf("upstream has wrong parameter type %d: %v != %v", i, upstreamType.In(i), downType))
|
||||
}
|
||||
}
|
||||
|
||||
return &BiMapper{
|
||||
UpTypes: upTypes,
|
||||
DownTypes: downTypes,
|
||||
Downstream: downstreamVal,
|
||||
Upstream: upstreamVal,
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertUp calls the Upstream function on the arguments in the down array
|
||||
// and returns the results.
|
||||
func (b *BiMapper) ConvertUp(down []interface{}) []interface{} {
|
||||
if len(down) != len(b.DownTypes) {
|
||||
panic(fmt.Sprintf("Expected %d values != %d", len(b.DownTypes), len(down)))
|
||||
}
|
||||
downVals := make([]reflect.Value, len(b.DownTypes))
|
||||
for i, val := range down {
|
||||
if val == nil {
|
||||
downVals[i] = reflect.Zero(b.DownTypes[i])
|
||||
} else {
|
||||
downVals[i] = reflect.ValueOf(val)
|
||||
}
|
||||
}
|
||||
upVals := b.Upstream.Call(downVals)
|
||||
up := make([]interface{}, len(upVals))
|
||||
for i, upVal := range upVals {
|
||||
up[i] = upVal.Interface()
|
||||
}
|
||||
|
||||
return up
|
||||
}
|
||||
|
||||
// ConvertDown calls the Downstream function on the elements of the up array
|
||||
// and returns the results.
|
||||
func (b *BiMapper) ConvertDown(up []interface{}) []interface{} {
|
||||
if len(up) != len(b.UpTypes) {
|
||||
panic(fmt.Sprintf("Expected %d values != %d", len(b.UpTypes), len(up)))
|
||||
}
|
||||
upVals := make([]reflect.Value, len(b.UpTypes))
|
||||
for i, val := range up {
|
||||
if val == nil {
|
||||
upVals[i] = reflect.Zero(b.UpTypes[i])
|
||||
} else {
|
||||
upVals[i] = reflect.ValueOf(val)
|
||||
}
|
||||
}
|
||||
downVals := b.Downstream.Call(upVals)
|
||||
down := make([]interface{}, len(downVals))
|
||||
for i, downVal := range downVals {
|
||||
down[i] = downVal.Interface()
|
||||
}
|
||||
|
||||
return down
|
||||
}
|
||||
27
vendor/github.com/leanovate/gopter/bi_mapper_test.go
generated
vendored
Normal file
27
vendor/github.com/leanovate/gopter/bi_mapper_test.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
func TestBiMapperParamNotMatch(t *testing.T) {
|
||||
defer expectPanic(t, "upstream has wrong parameter type 0: string != int")
|
||||
gopter.NewBiMapper(func(int) int { return 0 }, func(string) int { return 0 })
|
||||
}
|
||||
|
||||
func TestBiMapperReturnNotMatch(t *testing.T) {
|
||||
defer expectPanic(t, "upstream has wrong return type 0: string != int")
|
||||
gopter.NewBiMapper(func(int) int { return 0 }, func(int) string { return "" })
|
||||
}
|
||||
|
||||
func TestBiMapperInvalidDownstream(t *testing.T) {
|
||||
defer expectPanic(t, "downstream has to be a function")
|
||||
gopter.NewBiMapper(1, 2)
|
||||
}
|
||||
|
||||
func TestBiMapperInvalidUpstream(t *testing.T) {
|
||||
defer expectPanic(t, "upstream has to be a function")
|
||||
gopter.NewBiMapper(func(int) int { return 0 }, 2)
|
||||
}
|
||||
140
vendor/github.com/leanovate/gopter/commands/actions.go
generated
vendored
Normal file
140
vendor/github.com/leanovate/gopter/commands/actions.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type shrinkableCommand struct {
|
||||
command Command
|
||||
shrinker gopter.Shrinker
|
||||
}
|
||||
|
||||
func (s shrinkableCommand) shrink() gopter.Shrink {
|
||||
return s.shrinker(s.command).Map(func(command Command) shrinkableCommand {
|
||||
return shrinkableCommand{
|
||||
command: command,
|
||||
shrinker: s.shrinker,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s shrinkableCommand) String() string {
|
||||
return fmt.Sprintf("%v", s.command)
|
||||
}
|
||||
|
||||
type actions struct {
|
||||
// initialStateProvider has to reset/recreate the initial state exactly the
|
||||
// same every time.
|
||||
initialStateProvider func() State
|
||||
sequentialCommands []shrinkableCommand
|
||||
// parallel commands will come later
|
||||
}
|
||||
|
||||
func (a *actions) String() string {
|
||||
return fmt.Sprintf("initialState=%v sequential=%s", a.initialStateProvider(), a.sequentialCommands)
|
||||
}
|
||||
|
||||
func (a *actions) run(systemUnderTest SystemUnderTest) (*gopter.PropResult, error) {
|
||||
state := a.initialStateProvider()
|
||||
propResult := &gopter.PropResult{Status: gopter.PropTrue}
|
||||
for _, shrinkableCommand := range a.sequentialCommands {
|
||||
if !shrinkableCommand.command.PreCondition(state) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}, nil
|
||||
}
|
||||
result := shrinkableCommand.command.Run(systemUnderTest)
|
||||
state = shrinkableCommand.command.NextState(state)
|
||||
propResult = propResult.And(shrinkableCommand.command.PostCondition(state, result))
|
||||
}
|
||||
return propResult, nil
|
||||
}
|
||||
|
||||
type sizedCommands struct {
|
||||
state State
|
||||
commands []shrinkableCommand
|
||||
}
|
||||
|
||||
func actionsShrinker(v interface{}) gopter.Shrink {
|
||||
a := v.(*actions)
|
||||
elementShrinker := gopter.Shrinker(func(v interface{}) gopter.Shrink {
|
||||
return v.(shrinkableCommand).shrink()
|
||||
})
|
||||
return gen.SliceShrinker(elementShrinker)(a.sequentialCommands).Map(func(v []shrinkableCommand) *actions {
|
||||
return &actions{
|
||||
initialStateProvider: a.initialStateProvider,
|
||||
sequentialCommands: v,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func genActions(commands Commands) gopter.Gen {
|
||||
genInitialState := commands.GenInitialState()
|
||||
genInitialStateProvider := gopter.Gen(func(params *gopter.GenParameters) *gopter.GenResult {
|
||||
seed := params.NextInt64()
|
||||
return gopter.NewGenResult(func() State {
|
||||
paramsWithSeed := params.CloneWithSeed(seed)
|
||||
if initialState, ok := genInitialState(paramsWithSeed).Retrieve(); ok {
|
||||
return initialState
|
||||
}
|
||||
return nil
|
||||
}, gopter.NoShrinker)
|
||||
}).SuchThat(func(initialStateProvoder func() State) bool {
|
||||
state := initialStateProvoder()
|
||||
return state != nil && commands.InitialPreCondition(state)
|
||||
})
|
||||
return genInitialStateProvider.FlatMap(func(v interface{}) gopter.Gen {
|
||||
initialStateProvider := v.(func() State)
|
||||
return genSizedCommands(commands, initialStateProvider).Map(func(v sizedCommands) *actions {
|
||||
return &actions{
|
||||
initialStateProvider: initialStateProvider,
|
||||
sequentialCommands: v.commands,
|
||||
}
|
||||
}).SuchThat(func(actions *actions) bool {
|
||||
state := actions.initialStateProvider()
|
||||
for _, shrinkableCommand := range actions.sequentialCommands {
|
||||
if !shrinkableCommand.command.PreCondition(state) {
|
||||
return false
|
||||
}
|
||||
state = shrinkableCommand.command.NextState(state)
|
||||
}
|
||||
return true
|
||||
}).WithShrinker(actionsShrinker)
|
||||
}, reflect.TypeOf((*actions)(nil)))
|
||||
}
|
||||
|
||||
func genSizedCommands(commands Commands, initialStateProvider func() State) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
sizedCommandsGen := gen.Const(sizedCommands{
|
||||
state: initialStateProvider(),
|
||||
commands: make([]shrinkableCommand, 0, genParams.MaxSize),
|
||||
})
|
||||
for i := 0; i < genParams.MaxSize; i++ {
|
||||
sizedCommandsGen = sizedCommandsGen.FlatMap(func(v interface{}) gopter.Gen {
|
||||
prev := v.(sizedCommands)
|
||||
return gen.RetryUntil(commands.GenCommand(prev.state), func(command Command) bool {
|
||||
return command.PreCondition(prev.state)
|
||||
}, 100).MapResult(func(result *gopter.GenResult) *gopter.GenResult {
|
||||
value, ok := result.Retrieve()
|
||||
if !ok {
|
||||
return gopter.NewEmptyResult(reflect.TypeOf(sizedCommands{}))
|
||||
}
|
||||
command := value.(Command)
|
||||
return gopter.NewGenResult(
|
||||
sizedCommands{
|
||||
state: command.NextState(prev.state),
|
||||
commands: append(prev.commands, shrinkableCommand{
|
||||
command: command,
|
||||
shrinker: result.Shrinker,
|
||||
}),
|
||||
},
|
||||
gopter.NoShrinker,
|
||||
)
|
||||
})
|
||||
}, reflect.TypeOf(sizedCommands{}))
|
||||
}
|
||||
return sizedCommandsGen(genParams)
|
||||
}
|
||||
}
|
||||
72
vendor/github.com/leanovate/gopter/commands/command.go
generated
vendored
Normal file
72
vendor/github.com/leanovate/gopter/commands/command.go
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
package commands
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// SystemUnderTest resembles the system under test, which may be any kind
|
||||
// of stateful unit of code
|
||||
type SystemUnderTest interface{}
|
||||
|
||||
// State resembles the state the system under test is expected to be in
|
||||
type State interface{}
|
||||
|
||||
// Result resembles the result of a command that may or may not be checked
|
||||
type Result interface{}
|
||||
|
||||
// Command is any kind of command that may be applied to the system under test
|
||||
type Command interface {
|
||||
// Run applies the command to the system under test
|
||||
Run(systemUnderTest SystemUnderTest) Result
|
||||
// NextState calculates the next expected state if the command is applied
|
||||
NextState(state State) State
|
||||
// PreCondition checks if the state is valid before the command is applied
|
||||
PreCondition(state State) bool
|
||||
// PostCondition checks if the state is valid after the command is applied
|
||||
PostCondition(state State, result Result) *gopter.PropResult
|
||||
// String gets a (short) string representation of the command
|
||||
String() string
|
||||
}
|
||||
|
||||
// ProtoCommand is a prototype implementation of the Command interface
|
||||
type ProtoCommand struct {
|
||||
Name string
|
||||
RunFunc func(systemUnderTest SystemUnderTest) Result
|
||||
NextStateFunc func(state State) State
|
||||
PreConditionFunc func(state State) bool
|
||||
PostConditionFunc func(state State, result Result) *gopter.PropResult
|
||||
}
|
||||
|
||||
// Run applies the command to the system under test
|
||||
func (p *ProtoCommand) Run(systemUnderTest SystemUnderTest) Result {
|
||||
if p.RunFunc != nil {
|
||||
return p.RunFunc(systemUnderTest)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextState calculates the next expected state if the command is applied
|
||||
func (p *ProtoCommand) NextState(state State) State {
|
||||
if p.NextStateFunc != nil {
|
||||
return p.NextStateFunc(state)
|
||||
}
|
||||
return state
|
||||
}
|
||||
|
||||
// PreCondition checks if the state is valid before the command is applied
|
||||
func (p *ProtoCommand) PreCondition(state State) bool {
|
||||
if p.PreConditionFunc != nil {
|
||||
return p.PreConditionFunc(state)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// PostCondition checks if the state is valid after the command is applied
|
||||
func (p *ProtoCommand) PostCondition(state State, result Result) *gopter.PropResult {
|
||||
if p.PostConditionFunc != nil {
|
||||
return p.PostConditionFunc(state, result)
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
}
|
||||
|
||||
func (p *ProtoCommand) String() string {
|
||||
return p.Name
|
||||
}
|
||||
84
vendor/github.com/leanovate/gopter/commands/commands.go
generated
vendored
Normal file
84
vendor/github.com/leanovate/gopter/commands/commands.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
// Commands provide an entry point for testing a stateful system
|
||||
type Commands interface {
|
||||
// NewSystemUnderTest should create a new/isolated system under test
|
||||
NewSystemUnderTest(initialState State) SystemUnderTest
|
||||
// DestroySystemUnderTest may perform any cleanup tasks to destroy a system
|
||||
DestroySystemUnderTest(SystemUnderTest)
|
||||
// GenInitialState provides a generator for the initial State.
|
||||
// IMPORTANT: The generated state itself may be mutable, but this generator
|
||||
// is supposed to generate a clean and reproductable state every time.
|
||||
// Do not use an external random generator and be especially vary about
|
||||
// `gen.Const(<pointer to some mutable struct>)`.
|
||||
GenInitialState() gopter.Gen
|
||||
// GenCommand provides a generator for applicable commands to for a state
|
||||
GenCommand(state State) gopter.Gen
|
||||
// InitialPreCondition checks if the initial state is valid
|
||||
InitialPreCondition(state State) bool
|
||||
}
|
||||
|
||||
// ProtoCommands is a prototype implementation of the Commands interface
|
||||
type ProtoCommands struct {
|
||||
NewSystemUnderTestFunc func(initialState State) SystemUnderTest
|
||||
DestroySystemUnderTestFunc func(SystemUnderTest)
|
||||
InitialStateGen gopter.Gen
|
||||
GenCommandFunc func(State) gopter.Gen
|
||||
InitialPreConditionFunc func(State) bool
|
||||
}
|
||||
|
||||
// NewSystemUnderTest should create a new/isolated system under test
|
||||
func (p *ProtoCommands) NewSystemUnderTest(initialState State) SystemUnderTest {
|
||||
if p.NewSystemUnderTestFunc != nil {
|
||||
return p.NewSystemUnderTestFunc(initialState)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DestroySystemUnderTest may perform any cleanup tasks to destroy a system
|
||||
func (p *ProtoCommands) DestroySystemUnderTest(systemUnderTest SystemUnderTest) {
|
||||
if p.DestroySystemUnderTestFunc != nil {
|
||||
p.DestroySystemUnderTestFunc(systemUnderTest)
|
||||
}
|
||||
}
|
||||
|
||||
// GenCommand provides a generator for applicable commands to for a state
|
||||
func (p *ProtoCommands) GenCommand(state State) gopter.Gen {
|
||||
if p.GenCommandFunc != nil {
|
||||
return p.GenCommandFunc(state)
|
||||
}
|
||||
return gen.Fail(reflect.TypeOf((*Command)(nil)).Elem())
|
||||
}
|
||||
|
||||
// GenInitialState provides a generator for the initial State
|
||||
func (p *ProtoCommands) GenInitialState() gopter.Gen {
|
||||
return p.InitialStateGen.SuchThat(func(state State) bool {
|
||||
return p.InitialPreCondition(state)
|
||||
})
|
||||
}
|
||||
|
||||
// InitialPreCondition checks if the initial state is valid
|
||||
func (p *ProtoCommands) InitialPreCondition(state State) bool {
|
||||
if p.InitialPreConditionFunc != nil {
|
||||
return p.InitialPreConditionFunc(state)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Prop creates a gopter.Prop from Commands
|
||||
func Prop(commands Commands) gopter.Prop {
|
||||
return prop.ForAll(func(actions *actions) (*gopter.PropResult, error) {
|
||||
systemUnderTest := commands.NewSystemUnderTest(actions.initialStateProvider())
|
||||
defer commands.DestroySystemUnderTest(systemUnderTest)
|
||||
|
||||
return actions.run(systemUnderTest)
|
||||
}, genActions(commands))
|
||||
}
|
||||
112
vendor/github.com/leanovate/gopter/commands/commands_test.go
generated
vendored
Normal file
112
vendor/github.com/leanovate/gopter/commands/commands_test.go
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
package commands_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/commands"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type counter struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (c *counter) Get() int {
|
||||
return c.value
|
||||
}
|
||||
|
||||
func (c *counter) Inc() int {
|
||||
c.value++
|
||||
return c.value
|
||||
}
|
||||
|
||||
func (c *counter) Dec() int {
|
||||
c.value--
|
||||
return c.value
|
||||
}
|
||||
|
||||
var GetCommand = &commands.ProtoCommand{
|
||||
Name: "GET",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
return systemUnderTest.(*counter).Get()
|
||||
},
|
||||
PreConditionFunc: func(state commands.State) bool {
|
||||
_, ok := state.(int)
|
||||
return ok
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if state.(int) != result.(int) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
}
|
||||
|
||||
var IncCommand = &commands.ProtoCommand{
|
||||
Name: "INC",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
return systemUnderTest.(*counter).Inc()
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
return state.(int) + 1
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if state.(int) != result.(int) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
}
|
||||
|
||||
var DecCommand = &commands.ProtoCommand{
|
||||
Name: "DEC",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
return systemUnderTest.(*counter).Dec()
|
||||
},
|
||||
PreConditionFunc: func(state commands.State) bool {
|
||||
return state.(int) > 0
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
return state.(int) - 1
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if state.(int) != result.(int) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
}
|
||||
|
||||
type counterCommands struct {
|
||||
}
|
||||
|
||||
func (c *counterCommands) NewSystemUnderTest(initialState commands.State) commands.SystemUnderTest {
|
||||
return &counter{value: initialState.(int)}
|
||||
}
|
||||
|
||||
func (c *counterCommands) DestroySystemUnderTest(commands.SystemUnderTest) {
|
||||
}
|
||||
|
||||
func (c *counterCommands) GenInitialState() gopter.Gen {
|
||||
return gen.Int()
|
||||
}
|
||||
|
||||
func (c *counterCommands) InitialPreCondition(state commands.State) bool {
|
||||
return state.(int) >= 0
|
||||
}
|
||||
|
||||
func (c *counterCommands) GenCommand(state commands.State) gopter.Gen {
|
||||
return gen.OneConstOf(GetCommand, IncCommand, DecCommand)
|
||||
}
|
||||
|
||||
func TestCommands(t *testing.T) {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
|
||||
prop := commands.Prop(&counterCommands{})
|
||||
|
||||
result := prop.Check(parameters)
|
||||
if !result.Passed() {
|
||||
t.Errorf("Invalid result: %v", result)
|
||||
}
|
||||
}
|
||||
11
vendor/github.com/leanovate/gopter/commands/doc.go
generated
vendored
Normal file
11
vendor/github.com/leanovate/gopter/commands/doc.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Package commands conains helpers to create stateful tests based on commands.
|
||||
|
||||
Tester have to implement the Commands interface providing generators for the
|
||||
initial state and the commands. For convenience testers may also use the
|
||||
ProtoCommands as prototype.
|
||||
|
||||
The commands themself have to implement the Command interface, whereas
|
||||
testers might choose to use ProtoCommand as prototype.
|
||||
*/
|
||||
package commands
|
||||
256
vendor/github.com/leanovate/gopter/commands/example_circularqueue_test.go
generated
vendored
Normal file
256
vendor/github.com/leanovate/gopter/commands/example_circularqueue_test.go
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
package commands_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/commands"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
// *****************************************
|
||||
// Production code (i.e. the implementation)
|
||||
// *****************************************
|
||||
|
||||
type Queue struct {
|
||||
inp int
|
||||
outp int
|
||||
size int
|
||||
buf []int
|
||||
}
|
||||
|
||||
func New(n int) *Queue {
|
||||
return &Queue{
|
||||
inp: 0,
|
||||
outp: 0,
|
||||
size: n + 1,
|
||||
buf: make([]int, n+1),
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Queue) Put(n int) int {
|
||||
if q.inp == 4 && n > 0 { // Intentional spooky bug
|
||||
q.buf[q.size-1] *= n
|
||||
}
|
||||
q.buf[q.inp] = n
|
||||
q.inp = (q.inp + 1) % q.size
|
||||
return n
|
||||
}
|
||||
|
||||
func (q *Queue) Get() int {
|
||||
ans := q.buf[q.outp]
|
||||
q.outp = (q.outp + 1) % q.size
|
||||
return ans
|
||||
}
|
||||
|
||||
func (q *Queue) Size() int {
|
||||
return (q.inp - q.outp + q.size) % q.size
|
||||
}
|
||||
|
||||
func (q *Queue) Init() {
|
||||
q.inp = 0
|
||||
q.outp = 0
|
||||
}
|
||||
|
||||
// *****************************************
|
||||
// Test code
|
||||
// *****************************************
|
||||
|
||||
// cbState holds the expected state (i.e. its the commands.State)
|
||||
type cbState struct {
|
||||
size int
|
||||
elements []int
|
||||
takenElement int
|
||||
}
|
||||
|
||||
func (st *cbState) TakeFront() {
|
||||
st.takenElement = st.elements[0]
|
||||
st.elements = append(st.elements[:0], st.elements[1:]...)
|
||||
}
|
||||
|
||||
func (st *cbState) PushBack(value int) {
|
||||
st.elements = append(st.elements, value)
|
||||
}
|
||||
|
||||
func (st *cbState) String() string {
|
||||
return fmt.Sprintf("State(size=%d, elements=%v)", st.size, st.elements)
|
||||
}
|
||||
|
||||
// Get command simply invokes the Get function on the queue and compares the
|
||||
// result with the expected state.
|
||||
var genGetCommand = gen.Const(&commands.ProtoCommand{
|
||||
Name: "Get",
|
||||
RunFunc: func(q commands.SystemUnderTest) commands.Result {
|
||||
return q.(*Queue).Get()
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
state.(*cbState).TakeFront()
|
||||
return state
|
||||
},
|
||||
// The implementation implicitly assumes that Get is never called on an
|
||||
// empty Queue, therefore the command requires a corresponding pre-condition
|
||||
PreConditionFunc: func(state commands.State) bool {
|
||||
return len(state.(*cbState).elements) > 0
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if result.(int) != state.(*cbState).takenElement {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
})
|
||||
|
||||
// Put command puts a value into the queue by using the Put function. Since
|
||||
// the Put function has an int argument the Put command should have a
|
||||
// corresponding parameter.
|
||||
type putCommand int
|
||||
|
||||
func (value putCommand) Run(q commands.SystemUnderTest) commands.Result {
|
||||
return q.(*Queue).Put(int(value))
|
||||
}
|
||||
|
||||
func (value putCommand) NextState(state commands.State) commands.State {
|
||||
state.(*cbState).PushBack(int(value))
|
||||
return state
|
||||
}
|
||||
|
||||
// The implementation implicitly assumes that that Put is never called if
|
||||
// the capacity is exhausted, therefore the command requires a corresponding
|
||||
// pre-condition.
|
||||
func (putCommand) PreCondition(state commands.State) bool {
|
||||
s := state.(*cbState)
|
||||
return len(s.elements) < s.size
|
||||
}
|
||||
|
||||
func (putCommand) PostCondition(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
st := state.(*cbState)
|
||||
if result.(int) != st.elements[len(st.elements)-1] {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
}
|
||||
|
||||
func (value putCommand) String() string {
|
||||
return fmt.Sprintf("Put(%d)", value)
|
||||
}
|
||||
|
||||
// We want to have a generator for put commands for arbitrary int values.
|
||||
// In this case the command is actually shrinkable, e.g. if the property fails
|
||||
// by putting a 1000, it might already fail for a 500 as well ...
|
||||
var genPutCommand = gen.Int().Map(func(value int) commands.Command {
|
||||
return putCommand(value)
|
||||
}).WithShrinker(func(v interface{}) gopter.Shrink {
|
||||
return gen.IntShrinker(int(v.(putCommand))).Map(func(value int) putCommand {
|
||||
return putCommand(value)
|
||||
})
|
||||
})
|
||||
|
||||
// Size command is simple again, it just invokes the Size function and
|
||||
// compares compares the result with the expected state.
|
||||
// The Size function can be called any time, therefore this command does not
|
||||
// require a pre-condition.
|
||||
var genSizeCommand = gen.Const(&commands.ProtoCommand{
|
||||
Name: "Size",
|
||||
RunFunc: func(q commands.SystemUnderTest) commands.Result {
|
||||
return q.(*Queue).Size()
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if result.(int) != len(state.(*cbState).elements) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
})
|
||||
|
||||
// cbCommands implements the command.Commands interface, i.e. is
|
||||
// responsible for creating/destroying the system under test and generating
|
||||
// commands and initial states (cbState)
|
||||
var cbCommands = &commands.ProtoCommands{
|
||||
NewSystemUnderTestFunc: func(initialState commands.State) commands.SystemUnderTest {
|
||||
s := initialState.(*cbState)
|
||||
q := New(s.size)
|
||||
for e := range s.elements {
|
||||
q.Put(e)
|
||||
}
|
||||
return q
|
||||
},
|
||||
DestroySystemUnderTestFunc: func(sut commands.SystemUnderTest) {
|
||||
sut.(*Queue).Init()
|
||||
},
|
||||
InitialStateGen: gen.IntRange(1, 30).Map(func(size int) *cbState {
|
||||
return &cbState{
|
||||
size: size,
|
||||
elements: make([]int, 0, size),
|
||||
}
|
||||
}),
|
||||
InitialPreConditionFunc: func(state commands.State) bool {
|
||||
s := state.(*cbState)
|
||||
return len(s.elements) >= 0 && len(s.elements) <= s.size
|
||||
},
|
||||
GenCommandFunc: func(state commands.State) gopter.Gen {
|
||||
return gen.OneGenOf(genGetCommand, genPutCommand, genSizeCommand)
|
||||
},
|
||||
}
|
||||
|
||||
// Kudos to @jamesd for providing this real world example.
|
||||
// ... of course he did not implemented the bug, that was evil me
|
||||
//
|
||||
// The bug only occures on the following conditions:
|
||||
// - the queue size has to be greater than 4
|
||||
// - the queue has to be filled entirely once
|
||||
// - Get operations have to be at least 5 elements behind put
|
||||
// - The Put at the end of the queue and 5 elements later have to be non-zero
|
||||
//
|
||||
// Lets see what gopter has to say:
|
||||
//
|
||||
// The output of this example will be
|
||||
// ! circular buffer: Falsified after 96 passed tests.
|
||||
// ARG_0: initialState=State(size=7, elements=[]) sequential=[Put(0) Put(0)
|
||||
// Get Put(0) Get Put(0) Put(0) Get Put(0) Get Put(0) Get Put(-1) Put(0)
|
||||
// Put(0) Put(0) Put(0) Get Get Put(2) Get]
|
||||
// ARG_0_ORIGINAL (85 shrinks): initialState=State(size=7, elements=[])
|
||||
// sequential=[Put(-1855365712) Put(-1591723498) Get Size Size
|
||||
// Put(-1015561691) Get Put(397128011) Size Get Put(1943174048) Size
|
||||
// Put(1309500770) Size Get Put(-879438231) Size Get Put(-1644094687) Get
|
||||
// Put(-1818606323) Size Put(488620313) Size Put(-1219794505)
|
||||
// Put(1166147059) Get Put(11390361) Get Size Put(-1407993944) Get Get Size
|
||||
// Put(1393923085) Get Put(1222853245) Size Put(2070918543) Put(1741323168)
|
||||
// Size Get Get Size Put(2019939681) Get Put(-170089451) Size Get Get Size
|
||||
// Size Put(-49249034) Put(1229062846) Put(642598551) Get Put(1183453167)
|
||||
// Size Get Get Get Put(1010460728) Put(6828709) Put(-185198587) Size Size
|
||||
// Get Put(586459644) Get Size Put(-1802196502) Get Size Put(2097590857) Get
|
||||
// Get Get Get Size Put(-474576011) Size Get Size Size Put(771190414) Size
|
||||
// Put(-1509199920) Get Put(967212411) Size Get Put(578995532) Size Get Size
|
||||
// Get]
|
||||
//
|
||||
// Though this is not the minimal possible combination of command, its already
|
||||
// pretty close.
|
||||
func Example_circularqueue() {
|
||||
parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducable results, otherwise DefaultTestParameters() will suffice
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("circular buffer", commands.Prop(cbCommands))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// ! circular buffer: Falsified after 96 passed tests.
|
||||
// ARG_0: initialState=State(size=7, elements=[]) sequential=[Put(0) Put(0)
|
||||
// Get Put(0) Get Put(0) Put(0) Get Put(0) Get Put(0) Get Put(-1) Put(0)
|
||||
// Put(0) Put(0) Put(0) Get Get Put(2) Get]
|
||||
// ARG_0_ORIGINAL (85 shrinks): initialState=State(size=7, elements=[])
|
||||
// sequential=[Put(-1855365712) Put(-1591723498) Get Size Size
|
||||
// Put(-1015561691) Get Put(397128011) Size Get Put(1943174048) Size
|
||||
// Put(1309500770) Size Get Put(-879438231) Size Get Put(-1644094687) Get
|
||||
// Put(-1818606323) Size Put(488620313) Size Put(-1219794505)
|
||||
// Put(1166147059) Get Put(11390361) Get Size Put(-1407993944) Get Get Size
|
||||
// Put(1393923085) Get Put(1222853245) Size Put(2070918543) Put(1741323168)
|
||||
// Size Get Get Size Put(2019939681) Get Put(-170089451) Size Get Get Size
|
||||
// Size Put(-49249034) Put(1229062846) Put(642598551) Get Put(1183453167)
|
||||
// Size Get Get Get Put(1010460728) Put(6828709) Put(-185198587) Size Size
|
||||
// Get Put(586459644) Get Size Put(-1802196502) Get Size Put(2097590857) Get
|
||||
// Get Get Get Size Put(-474576011) Size Get Size Size Put(771190414) Size
|
||||
// Put(-1509199920) Get Put(967212411) Size Get Put(578995532) Size Get Size
|
||||
// Get]
|
||||
}
|
||||
125
vendor/github.com/leanovate/gopter/commands/example_commands_test.go
generated
vendored
Normal file
125
vendor/github.com/leanovate/gopter/commands/example_commands_test.go
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package commands_test
|
||||
|
||||
import (
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/commands"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type BuggyCounter struct {
|
||||
n int
|
||||
}
|
||||
|
||||
func (c *BuggyCounter) Inc() {
|
||||
c.n++
|
||||
}
|
||||
|
||||
func (c *BuggyCounter) Dec() {
|
||||
if c.n > 3 {
|
||||
// Intentional error
|
||||
c.n -= 2
|
||||
} else {
|
||||
c.n--
|
||||
}
|
||||
}
|
||||
|
||||
func (c *BuggyCounter) Get() int {
|
||||
return c.n
|
||||
}
|
||||
|
||||
func (c *BuggyCounter) Reset() {
|
||||
c.n = 0
|
||||
}
|
||||
|
||||
var GetBuggyCommand = &commands.ProtoCommand{
|
||||
Name: "GET",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
return systemUnderTest.(*BuggyCounter).Get()
|
||||
},
|
||||
PostConditionFunc: func(state commands.State, result commands.Result) *gopter.PropResult {
|
||||
if state.(int) != result.(int) {
|
||||
return &gopter.PropResult{Status: gopter.PropFalse}
|
||||
}
|
||||
return &gopter.PropResult{Status: gopter.PropTrue}
|
||||
},
|
||||
}
|
||||
|
||||
var IncBuggyCommand = &commands.ProtoCommand{
|
||||
Name: "INC",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
systemUnderTest.(*BuggyCounter).Inc()
|
||||
return nil
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
return state.(int) + 1
|
||||
},
|
||||
}
|
||||
|
||||
var DecBuggyCommand = &commands.ProtoCommand{
|
||||
Name: "DEC",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
systemUnderTest.(*BuggyCounter).Dec()
|
||||
return nil
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
return state.(int) - 1
|
||||
},
|
||||
}
|
||||
|
||||
var ResetBuggyCommand = &commands.ProtoCommand{
|
||||
Name: "RESET",
|
||||
RunFunc: func(systemUnderTest commands.SystemUnderTest) commands.Result {
|
||||
systemUnderTest.(*BuggyCounter).Reset()
|
||||
return nil
|
||||
},
|
||||
NextStateFunc: func(state commands.State) commands.State {
|
||||
return 0
|
||||
},
|
||||
}
|
||||
|
||||
var buggyCounterCommands = &commands.ProtoCommands{
|
||||
NewSystemUnderTestFunc: func(initialState commands.State) commands.SystemUnderTest {
|
||||
return &BuggyCounter{}
|
||||
},
|
||||
InitialStateGen: gen.Const(0),
|
||||
InitialPreConditionFunc: func(state commands.State) bool {
|
||||
return state.(int) == 0
|
||||
},
|
||||
GenCommandFunc: func(state commands.State) gopter.Gen {
|
||||
return gen.OneConstOf(GetBuggyCommand, IncBuggyCommand, DecBuggyCommand, ResetBuggyCommand)
|
||||
},
|
||||
}
|
||||
|
||||
// Demonstrates the usage of the commands package to find a bug in a counter
|
||||
// implementation that only occures if the counter is above 3.
|
||||
//
|
||||
// The output of this example will be
|
||||
// ! buggy counter: Falsified after 45 passed tests.
|
||||
// ARG_0: initial=0 sequential=[INC INC INC INC DEC GET]
|
||||
// ARG_0_ORIGINAL (9 shrinks): initial=0 sequential=[DEC RESET GET GET GET
|
||||
// RESET DEC DEC INC INC RESET RESET DEC INC RESET INC INC GET INC INC DEC
|
||||
// DEC GET RESET INC INC DEC INC INC INC RESET RESET INC INC GET INC DEC GET
|
||||
// DEC GET INC RESET INC INC RESET]
|
||||
// I.e. gopter found an invalid state with a rather long sequence of arbitrary
|
||||
// commonds/function calls, and then shrinkted that sequence down to
|
||||
// INC INC INC INC DEC GET
|
||||
// which is indeed the minimal set of commands one has to perform to find the
|
||||
// bug.
|
||||
func Example_buggyCounter() {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
parameters.Rng.Seed(1234) // Just for this example to generate reproducable results
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("buggy counter", commands.Prop(buggyCounterCommands))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// ! buggy counter: Falsified after 43 passed tests.
|
||||
// ARG_0: initialState=0 sequential=[INC INC INC INC DEC GET]
|
||||
// ARG_0_ORIGINAL (8 shrinks): initialState=0 sequential=[RESET GET GET GET
|
||||
// RESET DEC DEC INC INC RESET RESET DEC INC RESET INC INC GET INC INC DEC
|
||||
// DEC GET RESET INC INC DEC INC INC INC RESET RESET INC INC GET INC DEC GET
|
||||
// DEC GET INC RESET INC INC]
|
||||
}
|
||||
5
vendor/github.com/leanovate/gopter/convey/doc.go
generated
vendored
Normal file
5
vendor/github.com/leanovate/gopter/convey/doc.go
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
Package convey contains special assertion that come handy when using groper
|
||||
properties with goconvey.
|
||||
*/
|
||||
package convey
|
||||
42
vendor/github.com/leanovate/gopter/convey/should_forall.go
generated
vendored
Normal file
42
vendor/github.com/leanovate/gopter/convey/should_forall.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package convey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
func ShouldSucceedForAll(condition interface{}, params ...interface{}) string {
|
||||
var arbitraries *arbitrary.Arbitraries
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
gens := make([]gopter.Gen, 0)
|
||||
for _, param := range params {
|
||||
switch param.(type) {
|
||||
case *arbitrary.Arbitraries:
|
||||
arbitraries = param.(*arbitrary.Arbitraries)
|
||||
case *gopter.TestParameters:
|
||||
parameters = param.(*gopter.TestParameters)
|
||||
case gopter.Gen:
|
||||
gens = append(gens, param.(gopter.Gen))
|
||||
}
|
||||
}
|
||||
|
||||
var property gopter.Prop
|
||||
if arbitraries != nil {
|
||||
property = arbitraries.ForAll(condition)
|
||||
} else {
|
||||
property = prop.ForAll(condition, gens...)
|
||||
}
|
||||
result := property.Check(parameters)
|
||||
|
||||
if !result.Passed() {
|
||||
buffer := bytes.NewBufferString("")
|
||||
reporter := gopter.NewFormatedReporter(true, 75, buffer)
|
||||
reporter.ReportTestResult("", result)
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
80
vendor/github.com/leanovate/gopter/convey/should_forall_test.go
generated
vendored
Normal file
80
vendor/github.com/leanovate/gopter/convey/should_forall_test.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package convey_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/arbitrary"
|
||||
. "github.com/leanovate/gopter/convey"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
type QudraticEquation struct {
|
||||
A, B, C float64
|
||||
}
|
||||
|
||||
func (q *QudraticEquation) Eval(x float64) float64 {
|
||||
return q.A*x*x + q.B*x + q.C
|
||||
}
|
||||
|
||||
func (q *QudraticEquation) Solve() (float64, float64, error) {
|
||||
if q.A == 0 {
|
||||
return 0, 0, errors.New("No solution")
|
||||
}
|
||||
v := q.B*q.B - 4*q.A*q.C
|
||||
if v < 0 {
|
||||
return 0, 0, errors.New("No solution")
|
||||
}
|
||||
v = math.Sqrt(v)
|
||||
return (-q.B + v) / 2 / q.A, (-q.B - v) / 2 / q.A, nil
|
||||
}
|
||||
|
||||
func TestShouldSucceedForAll(t *testing.T) {
|
||||
Convey("Given a check for quadratic equations", t, func() {
|
||||
checkSolve := func(quadratic *QudraticEquation) bool {
|
||||
x1, x2, err := quadratic.Solve()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return math.Abs(quadratic.Eval(x1)) < 1e-5 && math.Abs(quadratic.Eval(x2)) < 1e-5
|
||||
}
|
||||
|
||||
Convey("Then check with arbitraries succeeds", func() {
|
||||
arbitraries := arbitrary.DefaultArbitraries()
|
||||
arbitraries.RegisterGen(gen.Float64Range(-1e5, 1e5))
|
||||
|
||||
So(checkSolve, ShouldSucceedForAll, arbitraries)
|
||||
|
||||
Convey("And test parameters may be modified", func() {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
parameters.MinSuccessfulTests = 200
|
||||
|
||||
So(checkSolve, ShouldSucceedForAll, arbitraries, parameters)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Then check with explicit generator succeeds", func() {
|
||||
anyQudraticEquation := gen.StructPtr(reflect.TypeOf(QudraticEquation{}), map[string]gopter.Gen{
|
||||
"A": gen.Float64Range(-1e5, 1e5),
|
||||
"B": gen.Float64Range(-1e5, 1e5),
|
||||
"C": gen.Float64Range(-1e5, 1e5),
|
||||
})
|
||||
|
||||
So(checkSolve, ShouldSucceedForAll, anyQudraticEquation)
|
||||
})
|
||||
|
||||
Convey("Expect fail", func() {
|
||||
parameters := gopter.DefaultTestParametersWithSeed(1234) // Example should generate reproducable results, otherwise DefaultTestParameters() will suffice
|
||||
result := ShouldSucceedForAll(func(i int) bool {
|
||||
return i > 500
|
||||
}, gen.Int(), parameters)
|
||||
|
||||
So(result, ShouldStartWith, "! : Falsified after 1 passed tests.\nARG_0: 0\nARG_0_ORIGINAL (1 shrinks): -642623569")
|
||||
})
|
||||
})
|
||||
}
|
||||
122
vendor/github.com/leanovate/gopter/derived_gen.go
generated
vendored
Normal file
122
vendor/github.com/leanovate/gopter/derived_gen.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type derivedGen struct {
|
||||
biMapper *BiMapper
|
||||
upGens []Gen
|
||||
upSieves []func(interface{}) bool
|
||||
upShrinker Shrinker
|
||||
resultType reflect.Type
|
||||
}
|
||||
|
||||
func (d *derivedGen) Generate(genParams *GenParameters) *GenResult {
|
||||
labels := []string{}
|
||||
up := make([]interface{}, len(d.upGens))
|
||||
shrinkers := make([]Shrinker, len(d.upGens))
|
||||
sieves := make([]func(v interface{}) bool, len(d.upGens))
|
||||
|
||||
var ok bool
|
||||
for i, gen := range d.upGens {
|
||||
result := gen(genParams)
|
||||
labels = append(labels, result.Labels...)
|
||||
shrinkers[i] = result.Shrinker
|
||||
sieves[i] = result.Sieve
|
||||
up[i], ok = result.Retrieve()
|
||||
if !ok {
|
||||
return &GenResult{
|
||||
Shrinker: d.Shrinker,
|
||||
Result: nil,
|
||||
Labels: result.Labels,
|
||||
ResultType: d.resultType,
|
||||
Sieve: d.Sieve,
|
||||
}
|
||||
}
|
||||
}
|
||||
down := d.biMapper.ConvertDown(up)
|
||||
if len(down) == 1 {
|
||||
return &GenResult{
|
||||
Shrinker: d.Shrinker,
|
||||
Result: down[0],
|
||||
Labels: labels,
|
||||
ResultType: reflect.TypeOf(down[0]),
|
||||
Sieve: d.Sieve,
|
||||
}
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: d.Shrinker,
|
||||
Result: down,
|
||||
Labels: labels,
|
||||
ResultType: reflect.TypeOf(down),
|
||||
Sieve: d.Sieve,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *derivedGen) Sieve(down interface{}) bool {
|
||||
if down == nil {
|
||||
return false
|
||||
}
|
||||
downs, ok := down.([]interface{})
|
||||
if !ok {
|
||||
downs = []interface{}{down}
|
||||
}
|
||||
ups := d.biMapper.ConvertUp(downs)
|
||||
for i, up := range ups {
|
||||
if d.upSieves[i] != nil && !d.upSieves[i](up) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *derivedGen) Shrinker(down interface{}) Shrink {
|
||||
downs, ok := down.([]interface{})
|
||||
if !ok {
|
||||
downs = []interface{}{down}
|
||||
}
|
||||
ups := d.biMapper.ConvertUp(downs)
|
||||
upShrink := d.upShrinker(ups)
|
||||
|
||||
return upShrink.Map(func(shrinkedUps []interface{}) interface{} {
|
||||
downs := d.biMapper.ConvertDown(shrinkedUps)
|
||||
if len(downs) == 1 {
|
||||
return downs[0]
|
||||
}
|
||||
return downs
|
||||
})
|
||||
}
|
||||
|
||||
// DeriveGen derives a generator with shrinkers from a sequence of other
|
||||
// generators mapped by a bijective function (BiMapper)
|
||||
func DeriveGen(downstream interface{}, upstream interface{}, gens ...Gen) Gen {
|
||||
biMapper := NewBiMapper(downstream, upstream)
|
||||
|
||||
if len(gens) != len(biMapper.UpTypes) {
|
||||
panic(fmt.Sprintf("Expected %d generators != %d", len(biMapper.UpTypes), len(gens)))
|
||||
}
|
||||
|
||||
resultType := reflect.TypeOf([]interface{}{})
|
||||
if len(biMapper.DownTypes) == 1 {
|
||||
resultType = biMapper.DownTypes[0]
|
||||
}
|
||||
|
||||
sieves := make([]func(interface{}) bool, len(gens))
|
||||
shrinkers := make([]Shrinker, len(gens))
|
||||
for i, gen := range gens {
|
||||
result := gen(DefaultGenParams)
|
||||
sieves[i] = result.Sieve
|
||||
shrinkers[i] = result.Shrinker
|
||||
}
|
||||
|
||||
derived := &derivedGen{
|
||||
biMapper: biMapper,
|
||||
upGens: gens,
|
||||
upSieves: sieves,
|
||||
upShrinker: CombineShrinker(shrinkers...),
|
||||
resultType: resultType,
|
||||
}
|
||||
return derived.Generate
|
||||
}
|
||||
186
vendor/github.com/leanovate/gopter/derived_gen_test.go
generated
vendored
Normal file
186
vendor/github.com/leanovate/gopter/derived_gen_test.go
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type downStruct struct {
|
||||
a int
|
||||
b string
|
||||
c bool
|
||||
}
|
||||
|
||||
func TestDeriveGenSingleDown(t *testing.T) {
|
||||
gen := gopter.DeriveGen(
|
||||
func(a int, b string, c bool) *downStruct {
|
||||
return &downStruct{a: a, b: b, c: c}
|
||||
},
|
||||
func(d *downStruct) (int, string, bool) {
|
||||
return d.a, d.b, d.c
|
||||
},
|
||||
gen.Int(),
|
||||
gen.AnyString(),
|
||||
gen.Bool(),
|
||||
)
|
||||
|
||||
sample, ok := gen.Sample()
|
||||
if !ok {
|
||||
t.Error("Sample not ok")
|
||||
}
|
||||
_, ok = sample.(*downStruct)
|
||||
if !ok {
|
||||
t.Errorf("%#v is not a downStruct", sample)
|
||||
}
|
||||
|
||||
shrinker := gen(gopter.DefaultGenParameters()).Shrinker
|
||||
shrink := shrinker(&downStruct{a: 10, b: "abcd", c: false})
|
||||
|
||||
shrinkedStructs := make([]*downStruct, 0)
|
||||
value, next := shrink()
|
||||
for next {
|
||||
shrinkedStruct, ok := value.(*downStruct)
|
||||
if !ok {
|
||||
t.Errorf("Invalid shrinked value: %#v", value)
|
||||
}
|
||||
shrinkedStructs = append(shrinkedStructs, shrinkedStruct)
|
||||
value, next = shrink()
|
||||
}
|
||||
|
||||
expected := []*downStruct{
|
||||
&downStruct{a: 0, b: "abcd", c: false},
|
||||
&downStruct{a: 5, b: "abcd", c: false},
|
||||
&downStruct{a: -5, b: "abcd", c: false},
|
||||
&downStruct{a: 8, b: "abcd", c: false},
|
||||
&downStruct{a: -8, b: "abcd", c: false},
|
||||
&downStruct{a: 9, b: "abcd", c: false},
|
||||
&downStruct{a: -9, b: "abcd", c: false},
|
||||
&downStruct{a: 10, b: "cd", c: false},
|
||||
&downStruct{a: 10, b: "ab", c: false},
|
||||
&downStruct{a: 10, b: "bcd", c: false},
|
||||
&downStruct{a: 10, b: "acd", c: false},
|
||||
&downStruct{a: 10, b: "abd", c: false},
|
||||
&downStruct{a: 10, b: "abc", c: false},
|
||||
}
|
||||
if !reflect.DeepEqual(shrinkedStructs, expected) {
|
||||
t.Errorf("%v does not equal %v", shrinkedStructs, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeriveGenSingleDownWithSieves(t *testing.T) {
|
||||
gen := gopter.DeriveGen(
|
||||
func(a int, b string, c bool) *downStruct {
|
||||
return &downStruct{a: a, b: b, c: c}
|
||||
},
|
||||
func(d *downStruct) (int, string, bool) {
|
||||
return d.a, d.b, d.c
|
||||
},
|
||||
gen.Int().SuchThat(func(i int) bool {
|
||||
return i%2 == 0
|
||||
}),
|
||||
gen.AnyString(),
|
||||
gen.Bool(),
|
||||
)
|
||||
|
||||
parameters := gopter.DefaultGenParameters()
|
||||
parameters.Rng.Seed(1234)
|
||||
|
||||
hasNoValue := false
|
||||
for i := 0; i < 100; i++ {
|
||||
result := gen(parameters)
|
||||
_, ok := result.Retrieve()
|
||||
if !ok {
|
||||
hasNoValue = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasNoValue {
|
||||
t.Error("Sieve is not applied")
|
||||
}
|
||||
|
||||
sieve := gen(parameters).Sieve
|
||||
|
||||
if !sieve(&downStruct{a: 2, b: "something", c: false}) {
|
||||
t.Error("Sieve did not pass even")
|
||||
}
|
||||
|
||||
if sieve(&downStruct{a: 3, b: "something", c: false}) {
|
||||
t.Error("Sieve did pass odd")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeriveGenMultiDown(t *testing.T) {
|
||||
gen := gopter.DeriveGen(
|
||||
func(a int, b string, c bool, d int32) (*downStruct, int64) {
|
||||
return &downStruct{a: a, b: b, c: c}, int64(a) + int64(d)
|
||||
},
|
||||
func(d *downStruct, diff int64) (int, string, bool, int32) {
|
||||
return d.a, d.b, d.c, int32(diff - int64(d.a))
|
||||
},
|
||||
gen.Int(),
|
||||
gen.AnyString(),
|
||||
gen.Bool(),
|
||||
gen.Int32(),
|
||||
)
|
||||
|
||||
sample, ok := gen.Sample()
|
||||
if !ok {
|
||||
t.Error("Sample not ok")
|
||||
}
|
||||
values, ok := sample.([]interface{})
|
||||
if !ok || len(values) != 2 {
|
||||
t.Errorf("%#v is not a slice of interface", sample)
|
||||
}
|
||||
_, ok = values[0].(*downStruct)
|
||||
if !ok {
|
||||
t.Errorf("%#v is not a downStruct", values[0])
|
||||
}
|
||||
_, ok = values[1].(int64)
|
||||
if !ok {
|
||||
t.Errorf("%#v is not a int64", values[1])
|
||||
}
|
||||
|
||||
shrinker := gen(gopter.DefaultGenParameters()).Shrinker
|
||||
shrink := shrinker([]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(20)})
|
||||
|
||||
value, next := shrink()
|
||||
shrinkedValues := make([][]interface{}, 0)
|
||||
for next {
|
||||
shrinked, ok := value.([]interface{})
|
||||
if !ok || len(values) != 2 {
|
||||
t.Errorf("%#v is not a slice of interface", sample)
|
||||
}
|
||||
shrinkedValues = append(shrinkedValues, shrinked)
|
||||
value, next = shrink()
|
||||
}
|
||||
|
||||
expected := [][]interface{}{
|
||||
[]interface{}{&downStruct{a: 0, b: "abcd", c: false}, int64(10)},
|
||||
[]interface{}{&downStruct{a: 5, b: "abcd", c: false}, int64(15)},
|
||||
[]interface{}{&downStruct{a: -5, b: "abcd", c: false}, int64(5)},
|
||||
[]interface{}{&downStruct{a: 8, b: "abcd", c: false}, int64(18)},
|
||||
[]interface{}{&downStruct{a: -8, b: "abcd", c: false}, int64(2)},
|
||||
[]interface{}{&downStruct{a: 9, b: "abcd", c: false}, int64(19)},
|
||||
[]interface{}{&downStruct{a: -9, b: "abcd", c: false}, int64(1)},
|
||||
[]interface{}{&downStruct{a: 10, b: "cd", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "ab", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "bcd", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "acd", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abd", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abc", c: false}, int64(20)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(10)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(15)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(5)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(18)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(2)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(19)},
|
||||
[]interface{}{&downStruct{a: 10, b: "abcd", c: false}, int64(1)},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(shrinkedValues, expected) {
|
||||
t.Errorf("%v does not equal %v", shrinkedValues, expected)
|
||||
}
|
||||
}
|
||||
35
vendor/github.com/leanovate/gopter/doc.go
generated
vendored
Normal file
35
vendor/github.com/leanovate/gopter/doc.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Package gopter contain the main interfaces of the GOlang Property TestER.
|
||||
|
||||
A simple property test might look like this:
|
||||
|
||||
func TestSqrt(t *testing.T) {
|
||||
properties := gopter.NewProperties(nil)
|
||||
|
||||
properties.Property("greater one of all greater one", prop.ForAll(
|
||||
func(v float64) bool {
|
||||
return math.Sqrt(v) >= 1
|
||||
},
|
||||
gen.Float64Range(1, math.MaxFloat64),
|
||||
))
|
||||
|
||||
properties.Property("squared is equal to value", prop.ForAll(
|
||||
func(v float64) bool {
|
||||
r := math.Sqrt(v)
|
||||
return math.Abs(r*r-v) < 1e-10*v
|
||||
},
|
||||
gen.Float64Range(0, math.MaxFloat64),
|
||||
))
|
||||
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
|
||||
Generally a property is just a function that takes GenParameters and produces
|
||||
a PropResult:
|
||||
|
||||
type Prop func(*GenParameters) *PropResult
|
||||
|
||||
but usually you will use prop.ForAll, prop.ForAllNoShrink or arbitrary.ForAll.
|
||||
There is also the commands package, which can be helpful for stateful testing.
|
||||
*/
|
||||
package gopter
|
||||
78
vendor/github.com/leanovate/gopter/example_fizzbuzz_test.go
generated
vendored
Normal file
78
vendor/github.com/leanovate/gopter/example_fizzbuzz_test.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
// Fizzbuzz: See https://wikipedia.org/wiki/Fizz_buzz
|
||||
func fizzbuzz(number int) (string, error) {
|
||||
if number <= 0 {
|
||||
return "", errors.New("Undefined")
|
||||
}
|
||||
switch {
|
||||
case number%15 == 0:
|
||||
return "FizzBuzz", nil
|
||||
case number%3 == 0:
|
||||
return "Fizz", nil
|
||||
case number%5 == 0:
|
||||
return "Buzz", nil
|
||||
}
|
||||
return strconv.Itoa(number), nil
|
||||
}
|
||||
|
||||
func Example_fizzbuzz() {
|
||||
properties := gopter.NewProperties(nil)
|
||||
|
||||
properties.Property("Undefined for all <= 0", prop.ForAll(
|
||||
func(number int) bool {
|
||||
result, err := fizzbuzz(number)
|
||||
return err != nil && result == ""
|
||||
},
|
||||
gen.IntRange(math.MinInt32, 0),
|
||||
))
|
||||
|
||||
properties.Property("Start with Fizz for all multiples of 3", prop.ForAll(
|
||||
func(i int) bool {
|
||||
result, err := fizzbuzz(i * 3)
|
||||
return err == nil && strings.HasPrefix(result, "Fizz")
|
||||
},
|
||||
gen.IntRange(1, math.MaxInt32/3),
|
||||
))
|
||||
|
||||
properties.Property("End with Buzz for all multiples of 5", prop.ForAll(
|
||||
func(i int) bool {
|
||||
result, err := fizzbuzz(i * 5)
|
||||
return err == nil && strings.HasSuffix(result, "Buzz")
|
||||
},
|
||||
gen.IntRange(1, math.MaxInt32/5),
|
||||
))
|
||||
|
||||
properties.Property("Int as string for all non-divisible by 3 or 5", prop.ForAll(
|
||||
func(number int) bool {
|
||||
result, err := fizzbuzz(number)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
parsed, err := strconv.ParseInt(result, 10, 64)
|
||||
return err == nil && parsed == int64(number)
|
||||
},
|
||||
gen.IntRange(1, math.MaxInt32).SuchThat(func(v interface{}) bool {
|
||||
return v.(int)%3 != 0 && v.(int)%5 != 0
|
||||
}),
|
||||
))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// + Undefined for all <= 0: OK, passed 100 tests.
|
||||
// + Start with Fizz for all multiples of 3: OK, passed 100 tests.
|
||||
// + End with Buzz for all multiples of 5: OK, passed 100 tests.
|
||||
// + Int as string for all non-divisible by 3 or 5: OK, passed 100 tests.
|
||||
}
|
||||
59
vendor/github.com/leanovate/gopter/example_labels_test.go
generated
vendored
Normal file
59
vendor/github.com/leanovate/gopter/example_labels_test.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
func spookyCalculation(a, b int) int {
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
if b < 0 {
|
||||
b = -b
|
||||
}
|
||||
return 2*b + 3*(2+(a+1)+b*(b+1))
|
||||
}
|
||||
|
||||
// Example_labels demonstrates how labels may help, in case of more complex
|
||||
// conditions.
|
||||
// The output will be:
|
||||
// ! Check spooky: Falsified after 0 passed tests.
|
||||
// > Labels of failing property: even result
|
||||
// a: 3
|
||||
// a_ORIGINAL (44 shrinks): 861384713
|
||||
// b: 0
|
||||
// b_ORIGINAL (1 shrinks): -642623569
|
||||
func Example_labels() {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
parameters.Rng.Seed(1234) // Just for this example to generate reproducable results
|
||||
parameters.MinSuccessfulTests = 10000
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("Check spooky", prop.ForAll(
|
||||
func(a, b int) string {
|
||||
result := spookyCalculation(a, b)
|
||||
if result < 0 {
|
||||
return "negative result"
|
||||
}
|
||||
if result%2 == 0 {
|
||||
return "even result"
|
||||
}
|
||||
return ""
|
||||
},
|
||||
gen.Int().WithLabel("a"),
|
||||
gen.Int().WithLabel("b"),
|
||||
))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// ! Check spooky: Falsified after 0 passed tests.
|
||||
// > Labels of failing property: even result
|
||||
// a: 3
|
||||
// a_ORIGINAL (44 shrinks): 861384713
|
||||
// b: 0
|
||||
// b_ORIGINAL (1 shrinks): -642623569
|
||||
}
|
||||
37
vendor/github.com/leanovate/gopter/example_sqrt_test.go
generated
vendored
Normal file
37
vendor/github.com/leanovate/gopter/example_sqrt_test.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
func Example_sqrt() {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
parameters.Rng.Seed(1234) // Just for this example to generate reproducable results
|
||||
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("greater one of all greater one", prop.ForAll(
|
||||
func(v float64) bool {
|
||||
return math.Sqrt(v) >= 1
|
||||
},
|
||||
gen.Float64().SuchThat(func(x float64) bool { return x >= 1.0 }),
|
||||
))
|
||||
|
||||
properties.Property("squared is equal to value", prop.ForAll(
|
||||
func(v float64) bool {
|
||||
r := math.Sqrt(v)
|
||||
return math.Abs(r*r-v) < 1e-10*v
|
||||
},
|
||||
gen.Float64().SuchThat(func(x float64) bool { return x >= 0.0 }),
|
||||
))
|
||||
|
||||
// When using testing.T you might just use: properties.TestingRun(t)
|
||||
properties.Run(gopter.ConsoleReporter(false))
|
||||
// Output:
|
||||
// + greater one of all greater one: OK, passed 100 tests.
|
||||
// + squared is equal to value: OK, passed 100 tests.
|
||||
}
|
||||
23
vendor/github.com/leanovate/gopter/flag.go
generated
vendored
Normal file
23
vendor/github.com/leanovate/gopter/flag.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package gopter
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
// Flag is a convenient helper for an atomic boolean
|
||||
type Flag struct {
|
||||
flag int32
|
||||
}
|
||||
|
||||
// Get the value of the flag
|
||||
func (f *Flag) Get() bool {
|
||||
return atomic.LoadInt32(&f.flag) > 0
|
||||
}
|
||||
|
||||
// Set the the flag
|
||||
func (f *Flag) Set() {
|
||||
atomic.StoreInt32(&f.flag, 1)
|
||||
}
|
||||
|
||||
// Unset the flag
|
||||
func (f *Flag) Unset() {
|
||||
atomic.StoreInt32(&f.flag, 0)
|
||||
}
|
||||
22
vendor/github.com/leanovate/gopter/flag_test.go
generated
vendored
Normal file
22
vendor/github.com/leanovate/gopter/flag_test.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
func TestFlag(t *testing.T) {
|
||||
flag := &gopter.Flag{}
|
||||
if flag.Get() {
|
||||
t.Errorf("Flag should be initially unset: %#v", flag)
|
||||
}
|
||||
flag.Set()
|
||||
if !flag.Get() {
|
||||
t.Errorf("Flag should be set: %#v", flag)
|
||||
}
|
||||
flag.Unset()
|
||||
if flag.Get() {
|
||||
t.Errorf("Flag should be unset: %#v", flag)
|
||||
}
|
||||
}
|
||||
140
vendor/github.com/leanovate/gopter/formated_reporter.go
generated
vendored
Normal file
140
vendor/github.com/leanovate/gopter/formated_reporter.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const newLine = "\n"
|
||||
|
||||
// FormatedReporter reports test results in a human readable manager.
|
||||
type FormatedReporter struct {
|
||||
verbose bool
|
||||
width int
|
||||
output io.Writer
|
||||
}
|
||||
|
||||
// NewFormatedReporter create a new formated reporter
|
||||
// verbose toggles verbose output of the property results
|
||||
// width is the maximal width per line
|
||||
// output is the writer were the report will be written to
|
||||
func NewFormatedReporter(verbose bool, width int, output io.Writer) Reporter {
|
||||
return &FormatedReporter{
|
||||
verbose: verbose,
|
||||
width: width,
|
||||
output: output,
|
||||
}
|
||||
}
|
||||
|
||||
// ConsoleReporter creates a FormatedReporter writing to the console (i.e. stdout)
|
||||
func ConsoleReporter(verbose bool) Reporter {
|
||||
return NewFormatedReporter(verbose, 75, os.Stdout)
|
||||
}
|
||||
|
||||
// ReportTestResult reports a single property result
|
||||
func (r *FormatedReporter) ReportTestResult(propName string, result *TestResult) {
|
||||
if result.Passed() {
|
||||
fmt.Fprintln(r.output, r.formatLines(fmt.Sprintf("+ %s: %s", propName, r.reportResult(result)), "", ""))
|
||||
} else {
|
||||
fmt.Fprintln(r.output, r.formatLines(fmt.Sprintf("! %s: %s", propName, r.reportResult(result)), "", ""))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) reportResult(result *TestResult) string {
|
||||
status := ""
|
||||
switch result.Status {
|
||||
case TestProved:
|
||||
status = "OK, proved property.\n" + r.reportPropArgs(result.Args)
|
||||
case TestPassed:
|
||||
status = fmt.Sprintf("OK, passed %d tests.", result.Succeeded)
|
||||
case TestFailed:
|
||||
status = fmt.Sprintf("Falsified after %d passed tests.\n%s%s", result.Succeeded, r.reportLabels(result.Labels), r.reportPropArgs(result.Args))
|
||||
case TestExhausted:
|
||||
status = fmt.Sprintf("Gave up after only %d passed tests. %d tests were discarded.", result.Succeeded, result.Discarded)
|
||||
case TestError:
|
||||
status = fmt.Sprintf("Error on property evaluation after %d passed tests: %s\n%s", result.Succeeded, result.Error.Error(), r.reportPropArgs(result.Args))
|
||||
}
|
||||
|
||||
if r.verbose {
|
||||
return concatLines(status, fmt.Sprintf("Elapsed time: %s", result.Time.String()))
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) reportLabels(labels []string) string {
|
||||
if labels != nil && len(labels) > 0 {
|
||||
return fmt.Sprintf("> Labels of failing property: %s\n", strings.Join(labels, newLine))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) reportPropArgs(p PropArgs) string {
|
||||
result := ""
|
||||
for i, arg := range p {
|
||||
if result != "" {
|
||||
result += newLine
|
||||
}
|
||||
result += r.reportPropArg(i, arg)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) reportPropArg(idx int, propArg *PropArg) string {
|
||||
label := propArg.Label
|
||||
if label == "" {
|
||||
label = fmt.Sprintf("ARG_%d", idx)
|
||||
}
|
||||
result := fmt.Sprintf("%s: %v", label, propArg.Arg)
|
||||
if propArg.Shrinks > 0 {
|
||||
result += fmt.Sprintf("\n%s_ORIGINAL (%d shrinks): %v", label, propArg.Shrinks, propArg.OrigArg)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) formatLines(str, lead, trail string) string {
|
||||
result := ""
|
||||
for _, line := range strings.Split(str, "\n") {
|
||||
if result != "" {
|
||||
result += newLine
|
||||
}
|
||||
result += r.breakLine(lead+line+trail, " ")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *FormatedReporter) breakLine(str, lead string) string {
|
||||
if len(str) <= r.width {
|
||||
return str
|
||||
}
|
||||
|
||||
result := ""
|
||||
for len(str) > r.width {
|
||||
idx := strings.LastIndexFunc(str[0:r.width], func(ch rune) bool {
|
||||
return unicode.IsSpace(ch)
|
||||
})
|
||||
if idx <= 0 {
|
||||
idx = r.width
|
||||
}
|
||||
result += str[0:idx] + "\n" + lead
|
||||
str = str[idx:]
|
||||
}
|
||||
result += str
|
||||
return result
|
||||
}
|
||||
|
||||
func concatLines(strs ...string) string {
|
||||
result := ""
|
||||
for _, str := range strs {
|
||||
if str != "" {
|
||||
if result != "" {
|
||||
result += "\n"
|
||||
}
|
||||
result += str
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
80
vendor/github.com/leanovate/gopter/formated_reporter_test.go
generated
vendored
Normal file
80
vendor/github.com/leanovate/gopter/formated_reporter_test.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestConsoleReporter(t *testing.T) {
|
||||
var buffer bytes.Buffer
|
||||
reporter := &FormatedReporter{
|
||||
verbose: false,
|
||||
width: 75,
|
||||
output: &buffer,
|
||||
}
|
||||
|
||||
reporter.ReportTestResult("test property", &TestResult{Status: TestPassed, Succeeded: 50})
|
||||
if buffer.String() != "+ test property: OK, passed 50 tests.\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
|
||||
reporter.ReportTestResult("test property", &TestResult{
|
||||
Status: TestFailed,
|
||||
Succeeded: 50,
|
||||
Args: PropArgs([]*PropArg{&PropArg{
|
||||
Arg: "0",
|
||||
}}),
|
||||
})
|
||||
if buffer.String() != "! test property: Falsified after 50 passed tests.\nARG_0: 0\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
|
||||
reporter.ReportTestResult("test property", &TestResult{
|
||||
Status: TestProved,
|
||||
Succeeded: 50,
|
||||
Args: PropArgs([]*PropArg{&PropArg{
|
||||
Arg: "0",
|
||||
Label: "somehing",
|
||||
OrigArg: "10",
|
||||
Shrinks: 6,
|
||||
}}),
|
||||
})
|
||||
if buffer.String() != "+ test property: OK, proved property.\nsomehing: 0\nsomehing_ORIGINAL (6 shrinks): 10\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
|
||||
reporter.ReportTestResult("test property", &TestResult{
|
||||
Status: TestExhausted,
|
||||
Succeeded: 50,
|
||||
Discarded: 40,
|
||||
})
|
||||
if buffer.String() != "! test property: Gave up after only 50 passed tests. 40 tests were\n discarded.\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
|
||||
reporter.ReportTestResult("test property", &TestResult{
|
||||
Status: TestError,
|
||||
Error: errors.New("Poop"),
|
||||
Succeeded: 50,
|
||||
Args: PropArgs([]*PropArg{&PropArg{
|
||||
Arg: "0",
|
||||
}}),
|
||||
})
|
||||
if buffer.String() != "! test property: Error on property evaluation after 50 passed tests: Poop\nARG_0: 0\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
|
||||
reporter.verbose = true
|
||||
reporter.ReportTestResult("test property", &TestResult{Status: TestPassed, Succeeded: 50, Time: time.Minute})
|
||||
if buffer.String() != "+ test property: OK, passed 50 tests.\nElapsed time: 1m0s\n" {
|
||||
t.Errorf("Invalid output: %#v", buffer.String())
|
||||
}
|
||||
buffer.Reset()
|
||||
}
|
||||
251
vendor/github.com/leanovate/gopter/gen.go
generated
vendored
Normal file
251
vendor/github.com/leanovate/gopter/gen.go
generated
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Gen generator of arbitrary values.
|
||||
// Usually properties are checked by verifing a condition holds true for
|
||||
// arbitrary input parameters generated by a Gen.
|
||||
//
|
||||
// IMPORTANT: Even though a generator is supposed to generate random values, it
|
||||
// should do this in a reproducable way. Therefore a generator has to create the
|
||||
// same result for the same GenParameters, i.e. ensure that you just use the
|
||||
// RNG provided by GenParameters and no external one.
|
||||
// If you just plug generators together you do not have to worry about this.
|
||||
type Gen func(*GenParameters) *GenResult
|
||||
|
||||
var (
|
||||
// DefaultGenParams can be used as default für *GenParameters
|
||||
DefaultGenParams = DefaultGenParameters()
|
||||
)
|
||||
|
||||
// Sample generate a sample value.
|
||||
// Depending on the state of the RNG the generate might fail to provide a sample
|
||||
func (g Gen) Sample() (interface{}, bool) {
|
||||
return g(DefaultGenParameters()).Retrieve()
|
||||
}
|
||||
|
||||
// WithLabel adds a label to a generated value.
|
||||
// Labels are usually used for reporting for the arguments of a property check.
|
||||
func (g Gen) WithLabel(label string) Gen {
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
result := g(genParams)
|
||||
result.Labels = append(result.Labels, label)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// SuchThat creates a derived generator by adding a sieve.
|
||||
// f: has to be a function with one parameter (matching the generated value) returning a bool.
|
||||
// All generated values are expected to satisfy
|
||||
// f(value) == true.
|
||||
// Use this care, if the sieve to to fine the generator will have many misses which results
|
||||
// in an undecided property.
|
||||
func (g Gen) SuchThat(f interface{}) Gen {
|
||||
checkVal := reflect.ValueOf(f)
|
||||
checkType := checkVal.Type()
|
||||
|
||||
if checkVal.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("Param of SuchThat has to be a func, but is %v", checkType.Kind()))
|
||||
}
|
||||
if checkType.NumIn() != 1 {
|
||||
panic(fmt.Sprintf("Param of SuchThat has to be a func with one param, but is %v", checkType.NumIn()))
|
||||
} else {
|
||||
genResultType := g(DefaultGenParams).ResultType
|
||||
if !genResultType.AssignableTo(checkType.In(0)) {
|
||||
panic(fmt.Sprintf("Param of SuchThat has to be a func with one param assignable to %v, but is %v", genResultType, checkType.In(0)))
|
||||
}
|
||||
}
|
||||
if checkType.NumOut() != 1 {
|
||||
panic(fmt.Sprintf("Param of SuchThat has to be a func with one return value, but is %v", checkType.NumOut()))
|
||||
} else if checkType.Out(0).Kind() != reflect.Bool {
|
||||
panic(fmt.Sprintf("Param of SuchThat has to be a func with one return value of bool, but is %v", checkType.Out(0).Kind()))
|
||||
}
|
||||
sieve := func(v interface{}) bool {
|
||||
return checkVal.Call([]reflect.Value{reflect.ValueOf(v)})[0].Bool()
|
||||
}
|
||||
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
result := g(genParams)
|
||||
prevSieve := result.Sieve
|
||||
if prevSieve == nil {
|
||||
result.Sieve = sieve
|
||||
} else {
|
||||
result.Sieve = func(value interface{}) bool {
|
||||
return prevSieve(value) && sieve(value)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// WithShrinker creates a derived generator with a specific shrinker
|
||||
func (g Gen) WithShrinker(shrinker Shrinker) Gen {
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
result := g(genParams)
|
||||
if shrinker == nil {
|
||||
result.Shrinker = NoShrinker
|
||||
} else {
|
||||
result.Shrinker = shrinker
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
// Map creates a derived generators by mapping all generatored values with a given function.
|
||||
// f: has to be a function with one parameter (matching the generated value) and a single return.
|
||||
// Note: The derived generator will not have a sieve or shrinker.
|
||||
// Note: The mapping function may have a second parameter "*GenParameters"
|
||||
// Note: The first parameter of the mapping function and its return may be a *GenResult (this makes MapResult obsolete)
|
||||
func (g Gen) Map(f interface{}) Gen {
|
||||
mapperVal := reflect.ValueOf(f)
|
||||
mapperType := mapperVal.Type()
|
||||
needsGenParameters := false
|
||||
genResultInput := false
|
||||
genResultOutput := false
|
||||
|
||||
if mapperVal.Kind() != reflect.Func {
|
||||
panic(fmt.Sprintf("Param of Map has to be a func, but is %v", mapperType.Kind()))
|
||||
}
|
||||
if mapperType.NumIn() != 1 && mapperType.NumIn() != 2 {
|
||||
panic(fmt.Sprintf("Param of Map has to be a func with one or two params, but is %v", mapperType.NumIn()))
|
||||
} else {
|
||||
if mapperType.NumIn() == 2 {
|
||||
if !reflect.TypeOf(&GenParameters{}).AssignableTo(mapperType.In(1)) {
|
||||
panic("Second parameter of mapper function has to be a *GenParameters")
|
||||
}
|
||||
needsGenParameters = true
|
||||
}
|
||||
genResultType := g(DefaultGenParams).ResultType
|
||||
if reflect.TypeOf(&GenResult{}).AssignableTo(mapperType.In(0)) {
|
||||
genResultInput = true
|
||||
} else if !genResultType.AssignableTo(mapperType.In(0)) {
|
||||
panic(fmt.Sprintf("Param of Map 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, but is %v", mapperType.NumOut()))
|
||||
} else if reflect.TypeOf(&GenResult{}).AssignableTo(mapperType.Out(0)) {
|
||||
genResultOutput = true
|
||||
}
|
||||
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
result := g(genParams)
|
||||
if genResultInput {
|
||||
var mapped reflect.Value
|
||||
if needsGenParameters {
|
||||
mapped = mapperVal.Call([]reflect.Value{reflect.ValueOf(result), reflect.ValueOf(genParams)})[0]
|
||||
} else {
|
||||
mapped = mapperVal.Call([]reflect.Value{reflect.ValueOf(result)})[0]
|
||||
}
|
||||
if genResultOutput {
|
||||
return mapped.Interface().(*GenResult)
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: NoShrinker,
|
||||
Result: mapped.Interface(),
|
||||
Labels: result.Labels,
|
||||
ResultType: mapperType.Out(0),
|
||||
}
|
||||
}
|
||||
value, ok := result.RetrieveAsValue()
|
||||
if ok {
|
||||
var mapped reflect.Value
|
||||
if needsGenParameters {
|
||||
mapped = mapperVal.Call([]reflect.Value{value, reflect.ValueOf(genParams)})[0]
|
||||
} else {
|
||||
mapped = mapperVal.Call([]reflect.Value{value})[0]
|
||||
}
|
||||
if genResultOutput {
|
||||
return mapped.Interface().(*GenResult)
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: NoShrinker,
|
||||
Result: mapped.Interface(),
|
||||
Labels: result.Labels,
|
||||
ResultType: mapperType.Out(0),
|
||||
}
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: NoShrinker,
|
||||
Result: nil,
|
||||
Labels: result.Labels,
|
||||
ResultType: mapperType.Out(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FlatMap creates a derived generator by passing a generated value to a function which itself
|
||||
// creates a generator.
|
||||
func (g Gen) FlatMap(f func(interface{}) Gen, resultType reflect.Type) Gen {
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
result := g(genParams)
|
||||
value, ok := result.Retrieve()
|
||||
if ok {
|
||||
return f(value)(genParams)
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: NoShrinker,
|
||||
Result: nil,
|
||||
Labels: result.Labels,
|
||||
ResultType: resultType,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MapResult creates a derived generator by mapping the GenResult directly.
|
||||
// Contrary to `Map` and `FlatMap` this also allow the conversion of
|
||||
// shrinkers and sieves, but implementation is more cumbersome.
|
||||
// Deprecation note: Map now has the same functionality
|
||||
func (g Gen) MapResult(f func(*GenResult) *GenResult) Gen {
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
return f(g(genParams))
|
||||
}
|
||||
}
|
||||
|
||||
// CombineGens creates a generators from a list of generators.
|
||||
// The result type will be a []interface{} containing the generated values of each generators in
|
||||
// the list.
|
||||
// Note: The combined generator will not have a sieve or shrinker.
|
||||
func CombineGens(gens ...Gen) Gen {
|
||||
return func(genParams *GenParameters) *GenResult {
|
||||
labels := []string{}
|
||||
values := make([]interface{}, len(gens))
|
||||
shrinkers := make([]Shrinker, len(gens))
|
||||
sieves := make([]func(v interface{}) bool, len(gens))
|
||||
|
||||
var ok bool
|
||||
for i, gen := range gens {
|
||||
result := gen(genParams)
|
||||
labels = append(labels, result.Labels...)
|
||||
shrinkers[i] = result.Shrinker
|
||||
sieves[i] = result.Sieve
|
||||
values[i], ok = result.Retrieve()
|
||||
if !ok {
|
||||
return &GenResult{
|
||||
Shrinker: NoShrinker,
|
||||
Result: nil,
|
||||
Labels: result.Labels,
|
||||
ResultType: reflect.TypeOf(values),
|
||||
}
|
||||
}
|
||||
}
|
||||
return &GenResult{
|
||||
Shrinker: CombineShrinker(shrinkers...),
|
||||
Result: values,
|
||||
Labels: labels,
|
||||
ResultType: reflect.TypeOf(values),
|
||||
Sieve: func(v interface{}) bool {
|
||||
values := v.([]interface{})
|
||||
for i, value := range values {
|
||||
if sieves[i] != nil && !sieves[i](value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
10
vendor/github.com/leanovate/gopter/gen/bool.go
generated
vendored
Normal file
10
vendor/github.com/leanovate/gopter/gen/bool.go
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// Bool generates an arbitrary bool value
|
||||
func Bool() gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(genParams.NextBool(), gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
14
vendor/github.com/leanovate/gopter/gen/bool_test.go
generated
vendored
Normal file
14
vendor/github.com/leanovate/gopter/gen/bool_test.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
commonGeneratorTest(t, "bool", gen.Bool(), func(value interface{}) bool {
|
||||
_, ok := value.(bool)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
49
vendor/github.com/leanovate/gopter/gen/complex.go
generated
vendored
Normal file
49
vendor/github.com/leanovate/gopter/gen/complex.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// Complex128Box generate complex128 numbers within a rectangle/box in the complex plane
|
||||
func Complex128Box(min, max complex128) gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Float64Range(real(min), real(max)),
|
||||
Float64Range(imag(min), imag(max)),
|
||||
).Map(func(values []interface{}) complex128 {
|
||||
return complex(values[0].(float64), values[1].(float64))
|
||||
}).SuchThat(func(v complex128) bool {
|
||||
return real(v) >= real(min) && real(v) <= real(max) &&
|
||||
imag(v) >= imag(min) && imag(v) <= imag(max)
|
||||
}).WithShrinker(Complex128Shrinker)
|
||||
}
|
||||
|
||||
// Complex128 generate arbitrary complex128 numbers
|
||||
func Complex128() gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Float64(),
|
||||
Float64(),
|
||||
).Map(func(values []interface{}) complex128 {
|
||||
return complex(values[0].(float64), values[1].(float64))
|
||||
}).WithShrinker(Complex128Shrinker)
|
||||
}
|
||||
|
||||
// Complex64Box generate complex64 numbers within a rectangle/box in the complex plane
|
||||
func Complex64Box(min, max complex64) gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Float32Range(real(min), real(max)),
|
||||
Float32Range(imag(min), imag(max)),
|
||||
).Map(func(values []interface{}) complex64 {
|
||||
return complex(values[0].(float32), values[1].(float32))
|
||||
}).SuchThat(func(v complex64) bool {
|
||||
return real(v) >= real(min) && real(v) <= real(max) &&
|
||||
imag(v) >= imag(min) && imag(v) <= imag(max)
|
||||
}).WithShrinker(Complex64Shrinker)
|
||||
}
|
||||
|
||||
// Complex64 generate arbitrary complex64 numbers
|
||||
func Complex64() gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Float32(),
|
||||
Float32(),
|
||||
).Map(func(values []interface{}) complex64 {
|
||||
return complex(values[0].(float32), values[1].(float32))
|
||||
}).WithShrinker(Complex64Shrinker)
|
||||
}
|
||||
27
vendor/github.com/leanovate/gopter/gen/complex_shrink.go
generated
vendored
Normal file
27
vendor/github.com/leanovate/gopter/gen/complex_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// Complex128Shrinker is a shrinker for complex128 numbers
|
||||
func Complex128Shrinker(v interface{}) gopter.Shrink {
|
||||
c := v.(complex128)
|
||||
realShrink := Float64Shrinker(real(c)).Map(func(r float64) complex128 {
|
||||
return complex(r, imag(c))
|
||||
})
|
||||
imagShrink := Float64Shrinker(imag(c)).Map(func(i float64) complex128 {
|
||||
return complex(real(c), i)
|
||||
})
|
||||
return realShrink.Interleave(imagShrink)
|
||||
}
|
||||
|
||||
// Complex64Shrinker is a shrinker for complex64 numbers
|
||||
func Complex64Shrinker(v interface{}) gopter.Shrink {
|
||||
c := v.(complex64)
|
||||
realShrink := Float64Shrinker(float64(real(c))).Map(func(r float64) complex64 {
|
||||
return complex(float32(r), imag(c))
|
||||
})
|
||||
imagShrink := Float64Shrinker(float64(imag(c))).Map(func(i float64) complex64 {
|
||||
return complex(real(c), float32(i))
|
||||
})
|
||||
return realShrink.Interleave(imagShrink)
|
||||
}
|
||||
91
vendor/github.com/leanovate/gopter/gen/complex_shrink_test.go
generated
vendored
Normal file
91
vendor/github.com/leanovate/gopter/gen/complex_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestComplex128Shrinker(t *testing.T) {
|
||||
zeroShrinks := gen.Complex128Shrinker(0 + 0i).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
oneShrink := gen.Complex128Shrinker(1 + 0i).All()
|
||||
if !reflect.DeepEqual(oneShrink, []interface{}{
|
||||
(0 + 0i), (0.5 + 0i), (-0.5 + 0i), (0.75 + 0i), (-0.75 + 0i), (0.875 + 0i), (-0.875 + 0i),
|
||||
(0.9375 + 0i), (-0.9375 + 0i), (0.96875 + 0i), (-0.96875 + 0i), (0.984375 + 0i),
|
||||
(-0.984375 + 0i), (0.9921875 + 0i), (-0.9921875 + 0i), (0.99609375 + 0i),
|
||||
(-0.99609375 + 0i), (0.998046875 + 0i), (-0.998046875 + 0i), (0.9990234375 + 0i),
|
||||
(-0.9990234375 + 0i), (0.99951171875 + 0i), (-0.99951171875 + 0i), (0.999755859375 + 0i),
|
||||
(-0.999755859375 + 0i), (0.9998779296875 + 0i), (-0.9998779296875 + 0i),
|
||||
(0.99993896484375 + 0i), (-0.99993896484375 + 0i), (0.999969482421875 + 0i),
|
||||
(-0.999969482421875 + 0i), (0.9999847412109375 + 0i), (-0.9999847412109375 + 0i),
|
||||
}) {
|
||||
t.Errorf("Invalid oneShrink: %#v", oneShrink)
|
||||
}
|
||||
|
||||
iShrink := gen.Complex128Shrinker(1i).All()
|
||||
if !reflect.DeepEqual(iShrink, []interface{}{
|
||||
(0 + 0i), (0 + 0.5i), (0 - 0.5i), (0 + 0.75i), (0 - 0.75i), (0 + 0.875i), (0 - 0.875i),
|
||||
(0 + 0.9375i), (0 - 0.9375i), (0 + 0.96875i), (0 - 0.96875i), (0 + 0.984375i),
|
||||
(0 - 0.984375i), (0 + 0.9921875i), (0 - 0.9921875i), (0 + 0.99609375i), (0 - 0.99609375i),
|
||||
(0 + 0.998046875i), (0 - 0.998046875i), (0 + 0.9990234375i), (0 - 0.9990234375i),
|
||||
(0 + 0.99951171875i), (0 - 0.99951171875i), (0 + 0.999755859375i), (0 - 0.999755859375i),
|
||||
(0 + 0.9998779296875i), (0 - 0.9998779296875i), (0 + 0.99993896484375i),
|
||||
(0 - 0.99993896484375i), (0 + 0.999969482421875i), (0 - 0.999969482421875i),
|
||||
(0 + 0.9999847412109375i), (0 - 0.9999847412109375i),
|
||||
}) {
|
||||
t.Errorf("Invalid iShrink: %#v", iShrink)
|
||||
}
|
||||
|
||||
teniShrink := gen.Complex128Shrinker(10 + 1i).All()
|
||||
if !reflect.DeepEqual(teniShrink, []interface{}{(0 + 1i), (10 + 0i), (5 + 1i), (10 + 0.5i),
|
||||
(-5 + 1i), (10 - 0.5i), (7.5 + 1i), (10 + 0.75i), (-7.5 + 1i), (10 - 0.75i), (8.75 + 1i),
|
||||
(10 + 0.875i), (-8.75 + 1i), (10 - 0.875i), (9.375 + 1i), (10 + 0.9375i), (-9.375 + 1i),
|
||||
(10 - 0.9375i), (9.6875 + 1i), (10 + 0.96875i), (-9.6875 + 1i), (10 - 0.96875i),
|
||||
(9.84375 + 1i), (10 + 0.984375i), (-9.84375 + 1i), (10 - 0.984375i), (9.921875 + 1i),
|
||||
(10 + 0.9921875i), (-9.921875 + 1i), (10 - 0.9921875i), (9.9609375 + 1i),
|
||||
(10 + 0.99609375i), (-9.9609375 + 1i), (10 - 0.99609375i), (9.98046875 + 1i),
|
||||
(10 + 0.998046875i), (-9.98046875 + 1i), (10 - 0.998046875i), (9.990234375 + 1i),
|
||||
(10 + 0.9990234375i), (-9.990234375 + 1i), (10 - 0.9990234375i), (9.9951171875 + 1i),
|
||||
(10 + 0.99951171875i), (-9.9951171875 + 1i), (10 - 0.99951171875i), (9.99755859375 + 1i),
|
||||
(10 + 0.999755859375i), (-9.99755859375 + 1i), (10 - 0.999755859375i),
|
||||
(9.998779296875 + 1i), (10 + 0.9998779296875i), (-9.998779296875 + 1i),
|
||||
(10 - 0.9998779296875i), (9.9993896484375 + 1i), (10 + 0.99993896484375i),
|
||||
(-9.9993896484375 + 1i), (10 - 0.99993896484375i), (9.99969482421875 + 1i),
|
||||
(10 + 0.999969482421875i), (-9.99969482421875 + 1i), (10 - 0.999969482421875i),
|
||||
(9.999847412109375 + 1i), (10 + 0.9999847412109375i), (-9.999847412109375 + 1i),
|
||||
(10 - 0.9999847412109375i), (9.999923706054688 + 1i), (-9.999923706054688 + 1i),
|
||||
(9.999961853027344 + 1i), (-9.999961853027344 + 1i), (9.999980926513672 + 1i),
|
||||
(-9.999980926513672 + 1i),
|
||||
}) {
|
||||
t.Errorf("Invalid teniShrink: %#v", teniShrink)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComplex64Shrinker(t *testing.T) {
|
||||
zeroShrinks := gen.Complex64Shrinker(complex64(0 + 0i)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
oneShrink := gen.Complex64Shrinker(complex64(1 + 0i)).All()
|
||||
if !reflect.DeepEqual(oneShrink, []interface{}{
|
||||
complex64(0 + 0i), complex64(0.5 + 0i), complex64(-0.5 + 0i), complex64(0.75 + 0i),
|
||||
complex64(-0.75 + 0i), complex64(0.875 + 0i), complex64(-0.875 + 0i),
|
||||
complex64(0.9375 + 0i), complex64(-0.9375 + 0i), complex64(0.96875 + 0i),
|
||||
complex64(-0.96875 + 0i), complex64(0.984375 + 0i), complex64(-0.984375 + 0i),
|
||||
complex64(0.9921875 + 0i), complex64(-0.9921875 + 0i), complex64(0.99609375 + 0i),
|
||||
complex64(-0.99609375 + 0i), complex64(0.9980469 + 0i), complex64(-0.9980469 + 0i),
|
||||
complex64(0.99902344 + 0i), complex64(-0.99902344 + 0i), complex64(0.9995117 + 0i),
|
||||
complex64(-0.9995117 + 0i), complex64(0.99975586 + 0i), complex64(-0.99975586 + 0i),
|
||||
complex64(0.9998779 + 0i), complex64(-0.9998779 + 0i), complex64(0.99993896 + 0i),
|
||||
complex64(-0.99993896 + 0i), complex64(0.9999695 + 0i), complex64(-0.9999695 + 0i),
|
||||
complex64(0.99998474 + 0i), complex64(-0.99998474 + 0i),
|
||||
}) {
|
||||
t.Errorf("Invalid oneShrink: %#v", oneShrink)
|
||||
}
|
||||
}
|
||||
46
vendor/github.com/leanovate/gopter/gen/complex_test.go
generated
vendored
Normal file
46
vendor/github.com/leanovate/gopter/gen/complex_test.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestComplex128Box(t *testing.T) {
|
||||
minReal := -12345.67
|
||||
maxReal := 2345.78
|
||||
minImag := -5432.8
|
||||
maxImag := 8764.6
|
||||
complexs := gen.Complex128Box(complex(minReal, minImag), complex(maxReal, maxImag))
|
||||
commonGeneratorTest(t, "complex 128 box", complexs, func(value interface{}) bool {
|
||||
v, ok := value.(complex128)
|
||||
return ok && real(v) >= minReal && real(v) < maxReal && imag(v) >= minImag && imag(v) < maxImag
|
||||
})
|
||||
}
|
||||
|
||||
func TestComplex128(t *testing.T) {
|
||||
commonGeneratorTest(t, "complex 128", gen.Complex128(), func(value interface{}) bool {
|
||||
v, ok := value.(complex128)
|
||||
return ok && !math.IsNaN(real(v)) && !math.IsNaN(imag(v)) && !math.IsInf(real(v), 0) && !math.IsInf(imag(v), 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestComplex64Box(t *testing.T) {
|
||||
minReal := float32(-12345.67)
|
||||
maxReal := float32(2345.78)
|
||||
minImag := float32(-5432.8)
|
||||
maxImag := float32(8764.6)
|
||||
complexs := gen.Complex64Box(complex(minReal, minImag), complex(maxReal, maxImag))
|
||||
commonGeneratorTest(t, "complex 64 box", complexs, func(value interface{}) bool {
|
||||
v, ok := value.(complex64)
|
||||
return ok && real(v) >= minReal && real(v) < maxReal && imag(v) >= minImag && imag(v) < maxImag
|
||||
})
|
||||
}
|
||||
|
||||
func TestComplex64(t *testing.T) {
|
||||
commonGeneratorTest(t, "complex 64", gen.Complex64(), func(value interface{}) bool {
|
||||
_, ok := value.(complex64)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
11
vendor/github.com/leanovate/gopter/gen/const.go
generated
vendored
Normal file
11
vendor/github.com/leanovate/gopter/gen/const.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// Const creates a generator for a constant value
|
||||
// Not the most exciting generator, but can be helpful from time to time
|
||||
func Const(value interface{}) gopter.Gen {
|
||||
return func(*gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(value, gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
14
vendor/github.com/leanovate/gopter/gen/const_test.go
generated
vendored
Normal file
14
vendor/github.com/leanovate/gopter/gen/const_test.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestConstGen(t *testing.T) {
|
||||
commonGeneratorTest(t, "const", gen.Const("some constant"), func(value interface{}) bool {
|
||||
v, ok := value.(string)
|
||||
return ok && v == "some constant"
|
||||
})
|
||||
}
|
||||
4
vendor/github.com/leanovate/gopter/gen/doc.go
generated
vendored
Normal file
4
vendor/github.com/leanovate/gopter/gen/doc.go
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
Package gen contains all commonly used generators and shrinkers.
|
||||
*/
|
||||
package gen
|
||||
15
vendor/github.com/leanovate/gopter/gen/fail.go
generated
vendored
Normal file
15
vendor/github.com/leanovate/gopter/gen/fail.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Fail is a generator that always fails to generate a value
|
||||
// Useful as fallback
|
||||
func Fail(resultType reflect.Type) gopter.Gen {
|
||||
return func(*gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewEmptyResult(resultType)
|
||||
}
|
||||
}
|
||||
18
vendor/github.com/leanovate/gopter/gen/fail_test.go
generated
vendored
Normal file
18
vendor/github.com/leanovate/gopter/gen/fail_test.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestFail(t *testing.T) {
|
||||
fail := gen.Fail(reflect.TypeOf(""))
|
||||
|
||||
value, ok := fail.Sample()
|
||||
|
||||
if value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
69
vendor/github.com/leanovate/gopter/gen/floats.go
generated
vendored
Normal file
69
vendor/github.com/leanovate/gopter/gen/floats.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Float64Range generates float64 numbers within a given range
|
||||
func Float64Range(min, max float64) gopter.Gen {
|
||||
d := max - min
|
||||
if d < 0 || d > math.MaxFloat64 {
|
||||
return Fail(reflect.TypeOf(float64(0)))
|
||||
}
|
||||
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
genResult := gopter.NewGenResult(min+genParams.Rng.Float64()*d, Float64Shrinker)
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return v.(float64) >= min && v.(float64) <= max
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 generates arbitrary float64 numbers that do not contain NaN or Inf
|
||||
func Float64() gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Int64Range(0, 1),
|
||||
Int64Range(0, 0x7fe),
|
||||
Int64Range(0, 0xfffffffffffff),
|
||||
).Map(func(values []interface{}) float64 {
|
||||
sign := uint64(values[0].(int64))
|
||||
exponent := uint64(values[1].(int64))
|
||||
mantissa := uint64(values[2].(int64))
|
||||
|
||||
return math.Float64frombits((sign << 63) | (exponent << 52) | mantissa)
|
||||
}).WithShrinker(Float64Shrinker)
|
||||
}
|
||||
|
||||
// Float32Range generates float32 numbers within a given range
|
||||
func Float32Range(min, max float32) gopter.Gen {
|
||||
d := max - min
|
||||
if d < 0 || d > math.MaxFloat32 {
|
||||
return Fail(reflect.TypeOf(float32(0)))
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
genResult := gopter.NewGenResult(min+genParams.Rng.Float32()*d, Float32Shrinker)
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return v.(float32) >= min && v.(float32) <= max
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// Float32 generates arbitrary float32 numbers that do not contain NaN or Inf
|
||||
func Float32() gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
Int32Range(0, 1),
|
||||
Int32Range(0, 0xfe),
|
||||
Int32Range(0, 0x7fffff),
|
||||
).Map(func(values []interface{}) float32 {
|
||||
sign := uint32(values[0].(int32))
|
||||
exponent := uint32(values[1].(int32))
|
||||
mantissa := uint32(values[2].(int32))
|
||||
|
||||
return math.Float32frombits((sign << 31) | (exponent << 23) | mantissa)
|
||||
}).WithShrinker(Float32Shrinker)
|
||||
}
|
||||
49
vendor/github.com/leanovate/gopter/gen/floats_shrink.go
generated
vendored
Normal file
49
vendor/github.com/leanovate/gopter/gen/floats_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type float64Shrink struct {
|
||||
original float64
|
||||
half float64
|
||||
}
|
||||
|
||||
func (s *float64Shrink) isZeroOrVeryClose() bool {
|
||||
if s.half == 0 {
|
||||
return true
|
||||
}
|
||||
muliple := s.half * 100000
|
||||
return math.Abs(muliple) < 1 && muliple != 0
|
||||
}
|
||||
|
||||
func (s *float64Shrink) Next() (interface{}, bool) {
|
||||
if s.isZeroOrVeryClose() {
|
||||
return nil, false
|
||||
}
|
||||
value := s.original - s.half
|
||||
s.half /= 2
|
||||
return value, true
|
||||
}
|
||||
|
||||
// Float64Shrinker is a shrinker for float64 numbers
|
||||
func Float64Shrinker(v interface{}) gopter.Shrink {
|
||||
negShrink := float64Shrink{
|
||||
original: -v.(float64),
|
||||
half: -v.(float64),
|
||||
}
|
||||
posShrink := float64Shrink{
|
||||
original: v.(float64),
|
||||
half: v.(float64) / 2,
|
||||
}
|
||||
return gopter.Shrink(negShrink.Next).Interleave(gopter.Shrink(posShrink.Next))
|
||||
}
|
||||
|
||||
// Float32Shrinker is a shrinker for float32 numbers
|
||||
func Float32Shrinker(v interface{}) gopter.Shrink {
|
||||
return Float64Shrinker(float64(v.(float32))).Map(func(e float64) float32 {
|
||||
return float32(e)
|
||||
})
|
||||
}
|
||||
154
vendor/github.com/leanovate/gopter/gen/floats_shrink_test.go
generated
vendored
Normal file
154
vendor/github.com/leanovate/gopter/gen/floats_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestFloat64Shrinker(t *testing.T) {
|
||||
zeroShrinks := gen.Float64Shrinker(float64(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
oneShrinks := gen.Float64Shrinker(float64(1)).All()
|
||||
if !reflect.DeepEqual(oneShrinks, []interface{}{
|
||||
0.0,
|
||||
0.5,
|
||||
-0.5,
|
||||
0.75,
|
||||
-0.75,
|
||||
0.875,
|
||||
-0.875,
|
||||
0.9375,
|
||||
-0.9375,
|
||||
0.96875,
|
||||
-0.96875,
|
||||
0.984375,
|
||||
-0.984375,
|
||||
0.9921875,
|
||||
-0.9921875,
|
||||
0.99609375,
|
||||
-0.99609375,
|
||||
0.998046875,
|
||||
-0.998046875,
|
||||
0.9990234375,
|
||||
-0.9990234375,
|
||||
0.99951171875,
|
||||
-0.99951171875,
|
||||
0.999755859375,
|
||||
-0.999755859375,
|
||||
0.9998779296875,
|
||||
-0.9998779296875,
|
||||
0.99993896484375,
|
||||
-0.99993896484375,
|
||||
0.999969482421875,
|
||||
-0.999969482421875,
|
||||
0.9999847412109375,
|
||||
-0.9999847412109375,
|
||||
}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", oneShrinks)
|
||||
}
|
||||
|
||||
hundretShrinks := gen.Float64Shrinker(float64(100)).All()
|
||||
if !reflect.DeepEqual(hundretShrinks, []interface{}{
|
||||
0.0,
|
||||
50.0,
|
||||
-50.0,
|
||||
75.0,
|
||||
-75.0,
|
||||
87.5,
|
||||
-87.5,
|
||||
93.75,
|
||||
-93.75,
|
||||
96.875,
|
||||
-96.875,
|
||||
98.4375,
|
||||
-98.4375,
|
||||
99.21875,
|
||||
-99.21875,
|
||||
99.609375,
|
||||
-99.609375,
|
||||
99.8046875,
|
||||
-99.8046875,
|
||||
99.90234375,
|
||||
-99.90234375,
|
||||
99.951171875,
|
||||
-99.951171875,
|
||||
99.9755859375,
|
||||
-99.9755859375,
|
||||
99.98779296875,
|
||||
-99.98779296875,
|
||||
99.993896484375,
|
||||
-99.993896484375,
|
||||
99.9969482421875,
|
||||
-99.9969482421875,
|
||||
99.99847412109375,
|
||||
-99.99847412109375,
|
||||
99.99923706054688,
|
||||
-99.99923706054688,
|
||||
99.99961853027344,
|
||||
-99.99961853027344,
|
||||
99.99980926513672,
|
||||
-99.99980926513672,
|
||||
99.99990463256836,
|
||||
-99.99990463256836,
|
||||
99.99995231628418,
|
||||
-99.99995231628418,
|
||||
99.99997615814209,
|
||||
-99.99997615814209,
|
||||
99.99998807907104,
|
||||
-99.99998807907104,
|
||||
}) {
|
||||
t.Errorf("Invalid hundretShrinks: %#v", hundretShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFloat32Shrinker(t *testing.T) {
|
||||
zeroShrinks := gen.Float32Shrinker(float32(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
oneShrinks := gen.Float32Shrinker(float32(1)).All()
|
||||
if !reflect.DeepEqual(oneShrinks, []interface{}{
|
||||
float32(0),
|
||||
float32(0.5),
|
||||
float32(-0.5),
|
||||
float32(0.75),
|
||||
float32(-0.75),
|
||||
float32(0.875),
|
||||
float32(-0.875),
|
||||
float32(0.9375),
|
||||
float32(-0.9375),
|
||||
float32(0.96875),
|
||||
float32(-0.96875),
|
||||
float32(0.984375),
|
||||
float32(-0.984375),
|
||||
float32(0.9921875),
|
||||
float32(-0.9921875),
|
||||
float32(0.99609375),
|
||||
float32(-0.99609375),
|
||||
float32(0.9980469),
|
||||
float32(-0.9980469),
|
||||
float32(0.99902344),
|
||||
float32(-0.99902344),
|
||||
float32(0.9995117),
|
||||
float32(-0.9995117),
|
||||
float32(0.99975586),
|
||||
float32(-0.99975586),
|
||||
float32(0.9998779),
|
||||
float32(-0.9998779),
|
||||
float32(0.99993896),
|
||||
float32(-0.99993896),
|
||||
float32(0.9999695),
|
||||
float32(-0.9999695),
|
||||
float32(0.99998474),
|
||||
float32(-0.99998474),
|
||||
}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", oneShrinks)
|
||||
}
|
||||
|
||||
}
|
||||
48
vendor/github.com/leanovate/gopter/gen/floats_test.go
generated
vendored
Normal file
48
vendor/github.com/leanovate/gopter/gen/floats_test.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestFloat64(t *testing.T) {
|
||||
commonGeneratorTest(t, "float 64", gen.Float64(), func(value interface{}) bool {
|
||||
v, ok := value.(float64)
|
||||
return ok && !math.IsNaN(v) && !math.IsInf(v, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFloat64Range(t *testing.T) {
|
||||
fail := gen.Float64Range(200, 100)
|
||||
|
||||
if value, ok := fail.Sample(); value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
commonGeneratorTest(t, "float 64 range", gen.Float64Range(-1234.5, 56789.123), func(value interface{}) bool {
|
||||
v, ok := value.(float64)
|
||||
return ok && !math.IsNaN(v) && !math.IsInf(v, 0) && v >= -1234.5 && v <= 56789.123
|
||||
})
|
||||
}
|
||||
|
||||
func TestFloat32(t *testing.T) {
|
||||
commonGeneratorTest(t, "float 32", gen.Float32(), func(value interface{}) bool {
|
||||
_, ok := value.(float32)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestFloat32Range(t *testing.T) {
|
||||
fail := gen.Float32Range(200, 100)
|
||||
|
||||
if value, ok := fail.Sample(); value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
commonGeneratorTest(t, "float 32 range", gen.Float32Range(-1234.5, 56789.123), func(value interface{}) bool {
|
||||
v, ok := value.(float32)
|
||||
return ok && v >= -1234.5 && v <= 56789.123
|
||||
})
|
||||
}
|
||||
33
vendor/github.com/leanovate/gopter/gen/frequency.go
generated
vendored
Normal file
33
vendor/github.com/leanovate/gopter/gen/frequency.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Frequency combines multiple weighted generators of the the same result type
|
||||
// The generators from weightedGens will be used accrding to the weight, i.e. generators
|
||||
// with a hight weight will be used more often than generators with a low weight.
|
||||
func Frequency(weightedGens map[int]gopter.Gen) gopter.Gen {
|
||||
if len(weightedGens) == 0 {
|
||||
return Fail(nil)
|
||||
}
|
||||
weights := make(sort.IntSlice, 0, len(weightedGens))
|
||||
max := 0
|
||||
for weight := range weightedGens {
|
||||
if weight > max {
|
||||
max = weight
|
||||
}
|
||||
weights = append(weights, weight)
|
||||
}
|
||||
weights.Sort()
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
idx := weights.Search(genParams.Rng.Intn(max + 1))
|
||||
gen := weightedGens[weights[idx]]
|
||||
|
||||
result := gen(genParams)
|
||||
result.Sieve = nil
|
||||
return result
|
||||
}
|
||||
}
|
||||
48
vendor/github.com/leanovate/gopter/gen/frequency_test.go
generated
vendored
Normal file
48
vendor/github.com/leanovate/gopter/gen/frequency_test.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type fixedSeed struct {
|
||||
fixed int64
|
||||
}
|
||||
|
||||
func (f fixedSeed) Int63() int64 { return f.fixed }
|
||||
func (f fixedSeed) Seed(seed int64) {}
|
||||
|
||||
func fixedParameters(size int, fixed int64) *gopter.GenParameters {
|
||||
return &gopter.GenParameters{
|
||||
MaxSize: size,
|
||||
Rng: rand.New(fixedSeed{
|
||||
fixed: fixed,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrequency(t *testing.T) {
|
||||
zeroNine := gen.Frequency(map[int]gopter.Gen{
|
||||
0: gen.Const("zero"),
|
||||
9: gen.Const("nine"),
|
||||
})
|
||||
value, ok := zeroNine(fixedParameters(10, 0)).Retrieve()
|
||||
if !ok {
|
||||
t.FailNow()
|
||||
}
|
||||
if value.(string) != "zero" {
|
||||
t.Errorf("Invalid value for 0: %#v", value)
|
||||
}
|
||||
for i := int64(1); i < int64(10); i++ {
|
||||
value, ok = zeroNine(fixedParameters(10, i<<32)).Retrieve()
|
||||
if !ok {
|
||||
t.FailNow()
|
||||
}
|
||||
if value.(string) != "nine" {
|
||||
t.Errorf("Invalid value for %d: %#v", i, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/leanovate/gopter/gen/helper_test.go
generated
vendored
Normal file
33
vendor/github.com/leanovate/gopter/gen/helper_test.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
func commonGeneratorTest(t *testing.T, name string, gen gopter.Gen, valueCheck func(interface{}) bool) {
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := gen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid generator result (%s): %#v", name, value)
|
||||
} else if !valueCheck(value) {
|
||||
t.Errorf("Invalid value (%s): %#v", name, value)
|
||||
}
|
||||
|
||||
genResult := gen(gopter.DefaultGenParameters())
|
||||
if genResult.Shrinker != nil {
|
||||
value, ok := genResult.Retrieve()
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid generator result (%s): %#v", name, value)
|
||||
} else {
|
||||
shrink := genResult.Shrinker(value).Filter(genResult.Sieve)
|
||||
shrunkValue, ok := shrink()
|
||||
if ok && !valueCheck(shrunkValue) {
|
||||
t.Errorf("Invalid shrunk value (%s): %#v -> %#v", name, value, shrunkValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
225
vendor/github.com/leanovate/gopter/gen/integers.go
generated
vendored
Normal file
225
vendor/github.com/leanovate/gopter/gen/integers.go
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Int64Range generates int64 numbers within a given range
|
||||
func Int64Range(min, max int64) gopter.Gen {
|
||||
if max < min {
|
||||
return Fail(reflect.TypeOf(int64(0)))
|
||||
}
|
||||
if max == math.MaxInt64 && min == math.MinInt64 { // Check for range overflow
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(genParams.NextInt64(), Int64Shrinker)
|
||||
}
|
||||
}
|
||||
|
||||
rangeSize := uint64(max - min + 1)
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
var nextResult = uint64(min) + (genParams.NextUint64() % rangeSize)
|
||||
genResult := gopter.NewGenResult(int64(nextResult), Int64Shrinker)
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return v.(int64) >= min && v.(int64) <= max
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// UInt64Range generates uint64 numbers within a given range
|
||||
func UInt64Range(min, max uint64) gopter.Gen {
|
||||
if max < min {
|
||||
return Fail(reflect.TypeOf(uint64(0)))
|
||||
}
|
||||
d := max - min + 1
|
||||
if d == 0 { // Check overflow (i.e. max = MaxInt64, min = MinInt64)
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(genParams.NextUint64(), UInt64Shrinker)
|
||||
}
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
genResult := gopter.NewGenResult(min+genParams.NextUint64()%d, UInt64Shrinker)
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return v.(uint64) >= min && v.(uint64) <= max
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// Int64 generates an arbitrary int64 number
|
||||
func Int64() gopter.Gen {
|
||||
return Int64Range(math.MinInt64, math.MaxInt64)
|
||||
}
|
||||
|
||||
// UInt64 generates an arbitrary Uint64 number
|
||||
func UInt64() gopter.Gen {
|
||||
return UInt64Range(0, math.MaxUint64)
|
||||
}
|
||||
|
||||
// Int32Range generates int32 numbers within a given range
|
||||
func Int32Range(min, max int32) gopter.Gen {
|
||||
return Int64Range(int64(min), int64(max)).
|
||||
Map(int64To32).
|
||||
WithShrinker(Int32Shrinker).
|
||||
SuchThat(func(v int32) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// UInt32Range generates uint32 numbers within a given range
|
||||
func UInt32Range(min, max uint32) gopter.Gen {
|
||||
return UInt64Range(uint64(min), uint64(max)).
|
||||
Map(uint64To32).
|
||||
WithShrinker(UInt32Shrinker).
|
||||
SuchThat(func(v uint32) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// Int32 generate arbitrary int32 numbers
|
||||
func Int32() gopter.Gen {
|
||||
return Int32Range(math.MinInt32, math.MaxInt32)
|
||||
}
|
||||
|
||||
// UInt32 generate arbitrary int32 numbers
|
||||
func UInt32() gopter.Gen {
|
||||
return UInt32Range(0, math.MaxUint32)
|
||||
}
|
||||
|
||||
// Int16Range generates int16 numbers within a given range
|
||||
func Int16Range(min, max int16) gopter.Gen {
|
||||
return Int64Range(int64(min), int64(max)).
|
||||
Map(int64To16).
|
||||
WithShrinker(Int16Shrinker).
|
||||
SuchThat(func(v int16) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// UInt16Range generates uint16 numbers within a given range
|
||||
func UInt16Range(min, max uint16) gopter.Gen {
|
||||
return UInt64Range(uint64(min), uint64(max)).
|
||||
Map(uint64To16).
|
||||
WithShrinker(UInt16Shrinker).
|
||||
SuchThat(func(v uint16) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// Int16 generate arbitrary int16 numbers
|
||||
func Int16() gopter.Gen {
|
||||
return Int16Range(math.MinInt16, math.MaxInt16)
|
||||
}
|
||||
|
||||
// UInt16 generate arbitrary uint16 numbers
|
||||
func UInt16() gopter.Gen {
|
||||
return UInt16Range(0, math.MaxUint16)
|
||||
}
|
||||
|
||||
// Int8Range generates int8 numbers within a given range
|
||||
func Int8Range(min, max int8) gopter.Gen {
|
||||
return Int64Range(int64(min), int64(max)).
|
||||
Map(int64To8).
|
||||
WithShrinker(Int8Shrinker).
|
||||
SuchThat(func(v int8) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// UInt8Range generates uint8 numbers within a given range
|
||||
func UInt8Range(min, max uint8) gopter.Gen {
|
||||
return UInt64Range(uint64(min), uint64(max)).
|
||||
Map(uint64To8).
|
||||
WithShrinker(UInt8Shrinker).
|
||||
SuchThat(func(v uint8) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// Int8 generate arbitrary int8 numbers
|
||||
func Int8() gopter.Gen {
|
||||
return Int8Range(math.MinInt8, math.MaxInt8)
|
||||
}
|
||||
|
||||
// UInt8 generate arbitrary uint8 numbers
|
||||
func UInt8() gopter.Gen {
|
||||
return UInt8Range(0, math.MaxUint8)
|
||||
}
|
||||
|
||||
// IntRange generates int numbers within a given range
|
||||
func IntRange(min, max int) gopter.Gen {
|
||||
return Int64Range(int64(min), int64(max)).
|
||||
Map(int64ToInt).
|
||||
WithShrinker(IntShrinker).
|
||||
SuchThat(func(v int) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// Int generate arbitrary int numbers
|
||||
func Int() gopter.Gen {
|
||||
return Int64Range(math.MinInt32, math.MaxInt32).
|
||||
Map(int64ToInt).
|
||||
WithShrinker(IntShrinker)
|
||||
}
|
||||
|
||||
// UIntRange generates uint numbers within a given range
|
||||
func UIntRange(min, max uint) gopter.Gen {
|
||||
return UInt64Range(uint64(min), uint64(max)).
|
||||
Map(uint64ToUint).
|
||||
WithShrinker(UIntShrinker).
|
||||
SuchThat(func(v uint) bool {
|
||||
return v >= min && v <= max
|
||||
})
|
||||
}
|
||||
|
||||
// UInt generate arbitrary uint numbers
|
||||
func UInt() gopter.Gen {
|
||||
return UInt64Range(0, math.MaxUint32).
|
||||
Map(uint64ToUint).
|
||||
WithShrinker(UIntShrinker)
|
||||
}
|
||||
|
||||
// Size just extracts the MaxSize field of the GenParameters.
|
||||
// This can be helpful to generate limited integer value in a more structued
|
||||
// manner.
|
||||
func Size() gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(genParams.MaxSize, IntShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
func int64To32(value int64) int32 {
|
||||
return int32(value)
|
||||
}
|
||||
|
||||
func uint64To32(value uint64) uint32 {
|
||||
return uint32(value)
|
||||
}
|
||||
|
||||
func int64To16(value int64) int16 {
|
||||
return int16(value)
|
||||
}
|
||||
|
||||
func uint64To16(value uint64) uint16 {
|
||||
return uint16(value)
|
||||
}
|
||||
|
||||
func int64To8(value int64) int8 {
|
||||
return int8(value)
|
||||
}
|
||||
|
||||
func uint64To8(value uint64) uint8 {
|
||||
return uint8(value)
|
||||
}
|
||||
|
||||
func int64ToInt(value int64) int {
|
||||
return int(value)
|
||||
}
|
||||
|
||||
func uint64ToUint(value uint64) uint {
|
||||
return uint(value)
|
||||
}
|
||||
95
vendor/github.com/leanovate/gopter/gen/integers_shrink.go
generated
vendored
Normal file
95
vendor/github.com/leanovate/gopter/gen/integers_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type int64Shrink struct {
|
||||
original int64
|
||||
half int64
|
||||
}
|
||||
|
||||
func (s *int64Shrink) Next() (interface{}, bool) {
|
||||
if s.half == 0 {
|
||||
return nil, false
|
||||
}
|
||||
value := s.original - s.half
|
||||
s.half /= 2
|
||||
return value, true
|
||||
}
|
||||
|
||||
type uint64Shrink struct {
|
||||
original uint64
|
||||
half uint64
|
||||
}
|
||||
|
||||
func (s *uint64Shrink) Next() (interface{}, bool) {
|
||||
if s.half == 0 {
|
||||
return nil, false
|
||||
}
|
||||
value := s.original - s.half
|
||||
s.half >>= 1
|
||||
return value, true
|
||||
}
|
||||
|
||||
// Int64Shrinker is a shrinker for int64 numbers
|
||||
func Int64Shrinker(v interface{}) gopter.Shrink {
|
||||
negShrink := int64Shrink{
|
||||
original: -v.(int64),
|
||||
half: -v.(int64),
|
||||
}
|
||||
posShrink := int64Shrink{
|
||||
original: v.(int64),
|
||||
half: v.(int64) / 2,
|
||||
}
|
||||
return gopter.Shrink(negShrink.Next).Interleave(gopter.Shrink(posShrink.Next))
|
||||
}
|
||||
|
||||
// UInt64Shrinker is a shrinker for uint64 numbers
|
||||
func UInt64Shrinker(v interface{}) gopter.Shrink {
|
||||
shrink := uint64Shrink{
|
||||
original: v.(uint64),
|
||||
half: v.(uint64),
|
||||
}
|
||||
return shrink.Next
|
||||
}
|
||||
|
||||
// Int32Shrinker is a shrinker for int32 numbers
|
||||
func Int32Shrinker(v interface{}) gopter.Shrink {
|
||||
return Int64Shrinker(int64(v.(int32))).Map(int64To32)
|
||||
}
|
||||
|
||||
// UInt32Shrinker is a shrinker for uint32 numbers
|
||||
func UInt32Shrinker(v interface{}) gopter.Shrink {
|
||||
return UInt64Shrinker(uint64(v.(uint32))).Map(uint64To32)
|
||||
}
|
||||
|
||||
// Int16Shrinker is a shrinker for int16 numbers
|
||||
func Int16Shrinker(v interface{}) gopter.Shrink {
|
||||
return Int64Shrinker(int64(v.(int16))).Map(int64To16)
|
||||
}
|
||||
|
||||
// UInt16Shrinker is a shrinker for uint16 numbers
|
||||
func UInt16Shrinker(v interface{}) gopter.Shrink {
|
||||
return UInt64Shrinker(uint64(v.(uint16))).Map(uint64To16)
|
||||
}
|
||||
|
||||
// Int8Shrinker is a shrinker for int8 numbers
|
||||
func Int8Shrinker(v interface{}) gopter.Shrink {
|
||||
return Int64Shrinker(int64(v.(int8))).Map(int64To8)
|
||||
}
|
||||
|
||||
// UInt8Shrinker is a shrinker for uint8 numbers
|
||||
func UInt8Shrinker(v interface{}) gopter.Shrink {
|
||||
return UInt64Shrinker(uint64(v.(uint8))).Map(uint64To8)
|
||||
}
|
||||
|
||||
// IntShrinker is a shrinker for int numbers
|
||||
func IntShrinker(v interface{}) gopter.Shrink {
|
||||
return Int64Shrinker(int64(v.(int))).Map(int64ToInt)
|
||||
}
|
||||
|
||||
// UIntShrinker is a shrinker for uint numbers
|
||||
func UIntShrinker(v interface{}) gopter.Shrink {
|
||||
return UInt64Shrinker(uint64(v.(uint))).Map(uint64ToUint)
|
||||
}
|
||||
127
vendor/github.com/leanovate/gopter/gen/integers_shrink_test.go
generated
vendored
Normal file
127
vendor/github.com/leanovate/gopter/gen/integers_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestInt64Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.Int64Shrinker(int64(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.Int64Shrinker(int64(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{int64(0), int64(5), int64(-5), int64(8), int64(-8), int64(9), int64(-9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
|
||||
negTenShrinks := gen.Int64Shrinker(int64(-10)).All()
|
||||
if !reflect.DeepEqual(negTenShrinks, []interface{}{int64(0), int64(-5), int64(5), int64(-8), int64(8), int64(-9), int64(9)}) {
|
||||
t.Errorf("Invalid negTenShrinks: %#v", negTenShrinks)
|
||||
}
|
||||
|
||||
leetShrink := gen.Int64Shrinker(int64(1337)).All()
|
||||
if !reflect.DeepEqual(leetShrink, []interface{}{
|
||||
int64(0), int64(669), int64(-669), int64(1003), int64(-1003), int64(1170), int64(-1170),
|
||||
int64(1254), int64(-1254), int64(1296), int64(-1296), int64(1317), int64(-1317),
|
||||
int64(1327), int64(-1327), int64(1332), int64(-1332), int64(1335), int64(-1335),
|
||||
int64(1336), int64(-1336)}) {
|
||||
t.Errorf("Invalid leetShrink: %#v", leetShrink)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUInt64Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.UInt64Shrinker(uint64(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.UInt64Shrinker(uint64(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{uint64(0), uint64(5), uint64(8), uint64(9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
|
||||
leetShrink := gen.UInt64Shrinker(uint64(1337)).All()
|
||||
if !reflect.DeepEqual(leetShrink, []interface{}{
|
||||
uint64(0), uint64(669), uint64(1003), uint64(1170),
|
||||
uint64(1254), uint64(1296), uint64(1317),
|
||||
uint64(1327), uint64(1332), uint64(1335),
|
||||
uint64(1336)}) {
|
||||
t.Errorf("Invalid leetShrink: %#v", leetShrink)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt32Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.Int32Shrinker(int32(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.Int32Shrinker(int32(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{int32(0), int32(5), int32(-5), int32(8), int32(-8), int32(9), int32(-9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUInt32Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.UInt32Shrinker(uint32(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.UInt32Shrinker(uint32(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{uint32(0), uint32(5), uint32(8), uint32(9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt16Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.Int16Shrinker(int16(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.Int16Shrinker(int16(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{int16(0), int16(5), int16(-5), int16(8), int16(-8), int16(9), int16(-9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUInt16Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.UInt16Shrinker(uint16(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.UInt16Shrinker(uint16(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{uint16(0), uint16(5), uint16(8), uint16(9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInt8Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.Int8Shrinker(int8(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.Int8Shrinker(int8(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{int8(0), int8(5), int8(-5), int8(8), int8(-8), int8(9), int8(-9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUInt8Shrink(t *testing.T) {
|
||||
zeroShrinks := gen.UInt8Shrinker(uint8(0)).All()
|
||||
if !reflect.DeepEqual(zeroShrinks, []interface{}{}) {
|
||||
t.Errorf("Invalid zeroShrinks: %#v", zeroShrinks)
|
||||
}
|
||||
|
||||
tenShrinks := gen.UInt8Shrinker(uint8(10)).All()
|
||||
if !reflect.DeepEqual(tenShrinks, []interface{}{uint8(0), uint8(5), uint8(8), uint8(9)}) {
|
||||
t.Errorf("Invalid tenShrinks: %#v", tenShrinks)
|
||||
}
|
||||
}
|
||||
130
vendor/github.com/leanovate/gopter/gen/integers_test.go
generated
vendored
Normal file
130
vendor/github.com/leanovate/gopter/gen/integers_test.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestInt64Range(t *testing.T) {
|
||||
fail := gen.Int64Range(200, 100)
|
||||
|
||||
if value, ok := fail.Sample(); value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
commonGeneratorTest(t, "int 64 range", gen.Int64Range(-123456, 234567), func(value interface{}) bool {
|
||||
v, ok := value.(int64)
|
||||
return ok && v >= -123456 || v <= 234567
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "int 64 positive", gen.Int64Range(1, math.MaxInt64), func(value interface{}) bool {
|
||||
v, ok := value.(int64)
|
||||
return ok && v > 0
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "int 64 negative", gen.Int64Range(math.MinInt64, -1), func(value interface{}) bool {
|
||||
v, ok := value.(int64)
|
||||
return ok && v < 0
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "full int 64 range", gen.Int64Range(math.MinInt64, math.MaxInt64), func(value interface{}) bool {
|
||||
_, ok := value.(int64)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestUInt64Range(t *testing.T) {
|
||||
fail := gen.UInt64Range(200, 100)
|
||||
|
||||
if value, ok := fail.Sample(); value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
commonGeneratorTest(t, "uint 64 range", gen.UInt64Range(0, 234567), func(value interface{}) bool {
|
||||
v, ok := value.(uint64)
|
||||
return ok && v <= 234567
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt64(t *testing.T) {
|
||||
commonGeneratorTest(t, "int 64", gen.Int64(), func(value interface{}) bool {
|
||||
_, ok := value.(int64)
|
||||
return ok
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "uint 64", gen.UInt64(), func(value interface{}) bool {
|
||||
_, ok := value.(uint64)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt32(t *testing.T) {
|
||||
commonGeneratorTest(t, "int 32", gen.Int32(), func(value interface{}) bool {
|
||||
_, ok := value.(int32)
|
||||
return ok
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "uint 32", gen.UInt32(), func(value interface{}) bool {
|
||||
_, ok := value.(uint32)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt16(t *testing.T) {
|
||||
commonGeneratorTest(t, "int 16", gen.Int16(), func(value interface{}) bool {
|
||||
_, ok := value.(int16)
|
||||
return ok
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "uint 16", gen.UInt16(), func(value interface{}) bool {
|
||||
_, ok := value.(uint16)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt8(t *testing.T) {
|
||||
commonGeneratorTest(t, "int 8", gen.Int8(), func(value interface{}) bool {
|
||||
_, ok := value.(int8)
|
||||
return ok
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "uint 8", gen.UInt8(), func(value interface{}) bool {
|
||||
_, ok := value.(uint8)
|
||||
return ok
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt(t *testing.T) {
|
||||
commonGeneratorTest(t, "int", gen.Int(), func(value interface{}) bool {
|
||||
_, ok := value.(int)
|
||||
return ok
|
||||
})
|
||||
commonGeneratorTest(t, "intrange", gen.IntRange(-1234, 5678), func(value interface{}) bool {
|
||||
v, ok := value.(int)
|
||||
return ok && v >= -1234 && v <= 5678
|
||||
})
|
||||
|
||||
commonGeneratorTest(t, "uint", gen.UInt(), func(value interface{}) bool {
|
||||
_, ok := value.(uint)
|
||||
return ok
|
||||
})
|
||||
commonGeneratorTest(t, "uintrange", gen.UIntRange(1234, 5678), func(value interface{}) bool {
|
||||
v, ok := value.(uint)
|
||||
return ok && v >= 1234 && v <= 5678
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenSize(t *testing.T) {
|
||||
params := gopter.DefaultGenParameters()
|
||||
genSize := gen.Size()
|
||||
for i := 0; i < 100; i++ {
|
||||
result := genSize(params.WithSize(i))
|
||||
value, ok := result.Retrieve()
|
||||
if !ok || value.(int) != i {
|
||||
t.Errorf("Invalid gen size: %v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
87
vendor/github.com/leanovate/gopter/gen/map_of.go
generated
vendored
Normal file
87
vendor/github.com/leanovate/gopter/gen/map_of.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// MapOf generates an arbitrary map of generated kay values.
|
||||
// genParams.MaxSize sets an (exclusive) upper limit on the size of the map
|
||||
// genParams.MinSize sets an (inclusive) lower limit on the size of the map
|
||||
func MapOf(keyGen, elementGen gopter.Gen) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
len := 0
|
||||
if genParams.MaxSize > 0 || genParams.MinSize > 0 {
|
||||
if genParams.MinSize > genParams.MaxSize {
|
||||
panic("GenParameters.MinSize must be <= GenParameters.MaxSize")
|
||||
}
|
||||
|
||||
if genParams.MaxSize == genParams.MinSize {
|
||||
len = genParams.MaxSize
|
||||
} else {
|
||||
len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize
|
||||
}
|
||||
}
|
||||
|
||||
result, keySieve, keyShrinker, elementSieve, elementShrinker := genMap(keyGen, elementGen, genParams, len)
|
||||
|
||||
genResult := gopter.NewGenResult(result.Interface(), MapShrinker(keyShrinker, elementShrinker))
|
||||
if keySieve != nil || elementSieve != nil {
|
||||
genResult.Sieve = forAllKeyValueSieve(keySieve, elementSieve)
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
func genMap(keyGen, elementGen gopter.Gen, genParams *gopter.GenParameters, len int) (reflect.Value, func(interface{}) bool, gopter.Shrinker, func(interface{}) bool, gopter.Shrinker) {
|
||||
element := elementGen(genParams)
|
||||
elementSieve := element.Sieve
|
||||
elementShrinker := element.Shrinker
|
||||
|
||||
key := keyGen(genParams)
|
||||
keySieve := key.Sieve
|
||||
keyShrinker := key.Shrinker
|
||||
|
||||
result := reflect.MakeMapWithSize(reflect.MapOf(key.ResultType, element.ResultType), len)
|
||||
|
||||
for i := 0; i < len; i++ {
|
||||
keyValue, keyOk := key.Retrieve()
|
||||
elementValue, elementOk := element.Retrieve()
|
||||
|
||||
if keyOk && elementOk {
|
||||
if key == nil {
|
||||
if elementValue == nil {
|
||||
result.SetMapIndex(reflect.Zero(key.ResultType), reflect.Zero(element.ResultType))
|
||||
} else {
|
||||
result.SetMapIndex(reflect.Zero(key.ResultType), reflect.ValueOf(elementValue))
|
||||
}
|
||||
} else {
|
||||
if elementValue == nil {
|
||||
result.SetMapIndex(reflect.ValueOf(keyValue), reflect.Zero(element.ResultType))
|
||||
} else {
|
||||
result.SetMapIndex(reflect.ValueOf(keyValue), reflect.ValueOf(elementValue))
|
||||
}
|
||||
}
|
||||
}
|
||||
key = keyGen(genParams)
|
||||
element = elementGen(genParams)
|
||||
}
|
||||
|
||||
return result, keySieve, keyShrinker, elementSieve, elementShrinker
|
||||
}
|
||||
|
||||
func forAllKeyValueSieve(keySieve, elementSieve func(interface{}) bool) func(interface{}) bool {
|
||||
return func(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
for _, key := range rv.MapKeys() {
|
||||
if keySieve != nil && !keySieve(key.Interface()) {
|
||||
return false
|
||||
}
|
||||
if elementSieve != nil && !elementSieve(rv.MapIndex(key).Interface()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
96
vendor/github.com/leanovate/gopter/gen/map_of_test.go
generated
vendored
Normal file
96
vendor/github.com/leanovate/gopter/gen/map_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestMapOf(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
genParams.MaxSize = 50
|
||||
keyGen := gen.Identifier()
|
||||
elementGen := gen.Const("element")
|
||||
mapGen := gen.MapOf(keyGen, elementGen)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := mapGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.(map[string]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) > 50 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, value := range strings {
|
||||
if value != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genParams.MaxSize = 10
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := mapGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.(map[string]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) > 10 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, value := range strings {
|
||||
if value != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genParams.MaxSize = 0
|
||||
genParams.MinSize = 0
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := mapGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.(map[string]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) != 0 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapOfPanic(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
genParams.MaxSize = 0
|
||||
genParams.MinSize = 1
|
||||
keyGen := gen.Identifier()
|
||||
elementGen := gen.Const("element")
|
||||
mapGen := gen.MapOf(keyGen, elementGen)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("SliceOf did not panic when MinSize was > MaxSize")
|
||||
}
|
||||
}()
|
||||
|
||||
mapGen(genParams).Retrieve()
|
||||
}
|
||||
149
vendor/github.com/leanovate/gopter/gen/map_shrink.go
generated
vendored
Normal file
149
vendor/github.com/leanovate/gopter/gen/map_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type mapShrinkOne struct {
|
||||
original reflect.Value
|
||||
key reflect.Value
|
||||
keyShrink gopter.Shrink
|
||||
elementShrink gopter.Shrink
|
||||
state bool
|
||||
keyExhausted bool
|
||||
lastKey interface{}
|
||||
elementExhausted bool
|
||||
lastElement interface{}
|
||||
}
|
||||
|
||||
func (s *mapShrinkOne) nextKeyValue() (interface{}, interface{}, bool) {
|
||||
for !s.keyExhausted && !s.elementExhausted {
|
||||
s.state = !s.state
|
||||
if s.state && !s.keyExhausted {
|
||||
value, ok := s.keyShrink()
|
||||
if ok {
|
||||
s.lastKey = value
|
||||
return s.lastKey, s.lastElement, true
|
||||
}
|
||||
s.keyExhausted = true
|
||||
} else if !s.state && !s.elementExhausted {
|
||||
value, ok := s.elementShrink()
|
||||
if ok {
|
||||
s.lastElement = value
|
||||
return s.lastKey, s.lastElement, true
|
||||
}
|
||||
s.elementExhausted = true
|
||||
}
|
||||
}
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
func (s *mapShrinkOne) Next() (interface{}, bool) {
|
||||
nextKey, nextValue, ok := s.nextKeyValue()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
result := reflect.MakeMapWithSize(s.original.Type(), s.original.Len())
|
||||
for _, key := range s.original.MapKeys() {
|
||||
if !reflect.DeepEqual(key.Interface(), s.key.Interface()) {
|
||||
result.SetMapIndex(key, s.original.MapIndex(key))
|
||||
}
|
||||
}
|
||||
result.SetMapIndex(reflect.ValueOf(nextKey), reflect.ValueOf(nextValue))
|
||||
|
||||
return result.Interface(), true
|
||||
}
|
||||
|
||||
// MapShrinkerOne creates a map shrinker from a shrinker for the key values of a map.
|
||||
// The length of the map will remain (mostly) unchanged, instead each key value pair is
|
||||
// shrinked after the other.
|
||||
func MapShrinkerOne(keyShrinker, elementShrinker gopter.Shrinker) gopter.Shrinker {
|
||||
return func(v interface{}) gopter.Shrink {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Map {
|
||||
panic(fmt.Sprintf("%#v is not a map", v))
|
||||
}
|
||||
|
||||
keys := rv.MapKeys()
|
||||
shrinks := make([]gopter.Shrink, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
mapShrinkOne := &mapShrinkOne{
|
||||
original: rv,
|
||||
key: key,
|
||||
keyShrink: keyShrinker(key.Interface()),
|
||||
lastKey: key.Interface(),
|
||||
elementShrink: elementShrinker(rv.MapIndex(key).Interface()),
|
||||
lastElement: rv.MapIndex(key).Interface(),
|
||||
}
|
||||
shrinks = append(shrinks, mapShrinkOne.Next)
|
||||
}
|
||||
return gopter.ConcatShrinks(shrinks...)
|
||||
}
|
||||
}
|
||||
|
||||
type mapShrink struct {
|
||||
original reflect.Value
|
||||
originalKeys []reflect.Value
|
||||
length int
|
||||
offset int
|
||||
chunkLength int
|
||||
}
|
||||
|
||||
func (s *mapShrink) Next() (interface{}, bool) {
|
||||
if s.chunkLength == 0 {
|
||||
return nil, false
|
||||
}
|
||||
keys := make([]reflect.Value, 0, s.length-s.chunkLength)
|
||||
keys = append(keys, s.originalKeys[0:s.offset]...)
|
||||
s.offset += s.chunkLength
|
||||
if s.offset < s.length {
|
||||
keys = append(keys, s.originalKeys[s.offset:s.length]...)
|
||||
} else {
|
||||
s.offset = 0
|
||||
s.chunkLength >>= 1
|
||||
}
|
||||
|
||||
result := reflect.MakeMapWithSize(s.original.Type(), len(keys))
|
||||
for _, key := range keys {
|
||||
result.SetMapIndex(key, s.original.MapIndex(key))
|
||||
}
|
||||
|
||||
return result.Interface(), true
|
||||
}
|
||||
|
||||
// MapShrinker creates a map shrinker from shrinker for the key values.
|
||||
// The length of the map will be shrinked as well
|
||||
func MapShrinker(keyShrinker, elementShrinker gopter.Shrinker) gopter.Shrinker {
|
||||
return func(v interface{}) gopter.Shrink {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Map {
|
||||
panic(fmt.Sprintf("%#v is not a Map", v))
|
||||
}
|
||||
keys := rv.MapKeys()
|
||||
mapShrink := &mapShrink{
|
||||
original: rv,
|
||||
originalKeys: keys,
|
||||
offset: 0,
|
||||
length: rv.Len(),
|
||||
chunkLength: rv.Len() >> 1,
|
||||
}
|
||||
|
||||
shrinks := make([]gopter.Shrink, 0, rv.Len()+1)
|
||||
shrinks = append(shrinks, mapShrink.Next)
|
||||
for _, key := range keys {
|
||||
mapShrinkOne := &mapShrinkOne{
|
||||
original: rv,
|
||||
key: key,
|
||||
keyShrink: keyShrinker(key.Interface()),
|
||||
lastKey: key.Interface(),
|
||||
elementShrink: elementShrinker(rv.MapIndex(key).Interface()),
|
||||
lastElement: rv.MapIndex(key).Interface(),
|
||||
}
|
||||
shrinks = append(shrinks, mapShrinkOne.Next)
|
||||
}
|
||||
return gopter.ConcatShrinks(shrinks...)
|
||||
}
|
||||
}
|
||||
57
vendor/github.com/leanovate/gopter/gen/map_shrink_test.go
generated
vendored
Normal file
57
vendor/github.com/leanovate/gopter/gen/map_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestMapShrinkerOne(t *testing.T) {
|
||||
mapShrink := gen.MapShrinkerOne(gen.StringShrinker, gen.Int64Shrinker)(map[string]int64{
|
||||
"two": 2,
|
||||
}).All()
|
||||
if !reflect.DeepEqual(mapShrink, []interface{}{
|
||||
map[string]int64{"wo": 2},
|
||||
map[string]int64{"wo": 0},
|
||||
map[string]int64{"to": 0},
|
||||
map[string]int64{"to": 1},
|
||||
map[string]int64{"tw": 1},
|
||||
map[string]int64{"tw": -1},
|
||||
}) {
|
||||
t.Errorf("Invalid mapShrink: %#v", mapShrink)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapShrinker(t *testing.T) {
|
||||
mapShrink := gen.MapShrinker(gen.StringShrinker, gen.Int64Shrinker)(map[string]int64{
|
||||
"two": 2,
|
||||
}).All()
|
||||
if !reflect.DeepEqual(mapShrink, []interface{}{
|
||||
map[string]int64{"wo": 2},
|
||||
map[string]int64{"wo": 0},
|
||||
map[string]int64{"to": 0},
|
||||
map[string]int64{"to": 1},
|
||||
map[string]int64{"tw": 1},
|
||||
map[string]int64{"tw": -1},
|
||||
}) {
|
||||
t.Errorf("Invalid mapShrink: %#v", mapShrink)
|
||||
}
|
||||
|
||||
mapShrink2 := gen.MapShrinker(gen.StringShrinker, gen.Int64Shrinker)(map[string]int64{
|
||||
"one": 1,
|
||||
"two": 2,
|
||||
"three": 3,
|
||||
"four": 3,
|
||||
}).All()
|
||||
|
||||
if len(mapShrink2) < 10 {
|
||||
t.Errorf("mapShrink2 too short: %#v", mapShrink2)
|
||||
}
|
||||
for _, shrink := range mapShrink2 {
|
||||
_, ok := shrink.(map[string]int64)
|
||||
if !ok {
|
||||
t.Errorf("mapShrink2 invalid type: %#v", mapShrink2)
|
||||
}
|
||||
}
|
||||
}
|
||||
29
vendor/github.com/leanovate/gopter/gen/one_of.go
generated
vendored
Normal file
29
vendor/github.com/leanovate/gopter/gen/one_of.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// OneConstOf generate one of a list of constant values
|
||||
func OneConstOf(consts ...interface{}) gopter.Gen {
|
||||
if len(consts) == 0 {
|
||||
return Fail(reflect.TypeOf(nil))
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
idx := genParams.Rng.Intn(len(consts))
|
||||
return gopter.NewGenResult(consts[idx], gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
// OneGenOf generate one value from a a list of generators
|
||||
func OneGenOf(gens ...gopter.Gen) gopter.Gen {
|
||||
if len(gens) == 0 {
|
||||
return Fail(reflect.TypeOf(nil))
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
idx := genParams.Rng.Intn(len(gens))
|
||||
return gens[idx](genParams)
|
||||
}
|
||||
}
|
||||
53
vendor/github.com/leanovate/gopter/gen/one_of_test.go
generated
vendored
Normal file
53
vendor/github.com/leanovate/gopter/gen/one_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestOneConstOf(t *testing.T) {
|
||||
consts := gen.OneConstOf("one", "two", "three", "four")
|
||||
commonOneOfTest(t, consts)
|
||||
|
||||
fail := gen.OneConstOf()
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Empty OneConstOf generated a value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOneGenOf(t *testing.T) {
|
||||
consts := gen.OneGenOf(gen.Const("one"), gen.Const("two"), gen.Const("three"), gen.Const("four"))
|
||||
commonOneOfTest(t, consts)
|
||||
|
||||
fail := gen.OneGenOf()
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Empty OneGenOf generated a value")
|
||||
}
|
||||
}
|
||||
|
||||
func commonOneOfTest(t *testing.T, gen gopter.Gen) {
|
||||
generated := make(map[string]bool, 0)
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := gen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid consts: %#v", value)
|
||||
}
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
t.Errorf("Invalid consts: %#v", value)
|
||||
}
|
||||
generated[v] = true
|
||||
}
|
||||
if !reflect.DeepEqual(generated, map[string]bool{
|
||||
"one": true,
|
||||
"two": true,
|
||||
"three": true,
|
||||
"four": true,
|
||||
}) {
|
||||
t.Errorf("Not all consts where generated: %#v", generated)
|
||||
}
|
||||
}
|
||||
41
vendor/github.com/leanovate/gopter/gen/ptr_of.go
generated
vendored
Normal file
41
vendor/github.com/leanovate/gopter/gen/ptr_of.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// PtrOf generates a pointer to a generated element
|
||||
func PtrOf(elementGen gopter.Gen) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
element := elementGen(genParams)
|
||||
elementShrinker := element.Shrinker
|
||||
elementSieve := element.Sieve
|
||||
value, ok := element.Retrieve()
|
||||
if !ok || genParams.NextBool() {
|
||||
result := gopter.NewEmptyResult(reflect.PtrTo(element.ResultType))
|
||||
result.Sieve = func(v interface{}) bool {
|
||||
if elementSieve == nil {
|
||||
return true
|
||||
}
|
||||
r := reflect.ValueOf(v)
|
||||
return !r.IsValid() || r.IsNil() || elementSieve(r.Elem().Interface())
|
||||
}
|
||||
return result
|
||||
}
|
||||
// To get the right pointer type we have to create a slice with one element
|
||||
slice := reflect.MakeSlice(reflect.SliceOf(element.ResultType), 0, 1)
|
||||
slice = reflect.Append(slice, reflect.ValueOf(value))
|
||||
|
||||
result := gopter.NewGenResult(slice.Index(0).Addr().Interface(), PtrShrinker(elementShrinker))
|
||||
result.Sieve = func(v interface{}) bool {
|
||||
if elementSieve == nil {
|
||||
return true
|
||||
}
|
||||
r := reflect.ValueOf(v)
|
||||
return !r.IsValid() || r.IsNil() || elementSieve(r.Elem().Interface())
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
54
vendor/github.com/leanovate/gopter/gen/ptr_of_test.go
generated
vendored
Normal file
54
vendor/github.com/leanovate/gopter/gen/ptr_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
"github.com/leanovate/gopter/prop"
|
||||
)
|
||||
|
||||
func TestPtrOf(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
elementGen := gen.Const("element")
|
||||
ptrGen := gen.PtrOf(elementGen)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := ptrGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
if sample == nil {
|
||||
continue
|
||||
}
|
||||
stringPtr, ok := sample.(*string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not pointer to string: %#v", sample)
|
||||
} else if *stringPtr != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v %#v", sample, *stringPtr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Foo string
|
||||
|
||||
func TestPtrOfFoo(t *testing.T) {
|
||||
parameters := gopter.DefaultTestParameters()
|
||||
properties := gopter.NewProperties(parameters)
|
||||
|
||||
properties.Property("PtrOf", prop.ForAll(
|
||||
func(foo *Foo,
|
||||
) bool {
|
||||
return true
|
||||
},
|
||||
gen.PtrOf(GenFoo()),
|
||||
))
|
||||
properties.TestingRun(t)
|
||||
}
|
||||
|
||||
func GenFoo() gopter.Gen {
|
||||
return gen.SliceOfN(16, gen.Rune()).Map(func(v []rune) Foo {
|
||||
return Foo(v)
|
||||
})
|
||||
}
|
||||
41
vendor/github.com/leanovate/gopter/gen/ptr_shrink.go
generated
vendored
Normal file
41
vendor/github.com/leanovate/gopter/gen/ptr_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type nilShrink struct {
|
||||
done bool
|
||||
}
|
||||
|
||||
func (s *nilShrink) Next() (interface{}, bool) {
|
||||
if !s.done {
|
||||
s.done = true
|
||||
return nil, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// PtrShrinker convert a value shrinker to a pointer to value shrinker
|
||||
func PtrShrinker(elementShrinker gopter.Shrinker) gopter.Shrinker {
|
||||
return func(v interface{}) gopter.Shrink {
|
||||
if v == nil {
|
||||
return gopter.NoShrink
|
||||
}
|
||||
rt := reflect.TypeOf(v)
|
||||
elementShink := elementShrinker(reflect.ValueOf(v).Elem().Interface())
|
||||
|
||||
nilShrink := &nilShrink{}
|
||||
return gopter.ConcatShrinks(
|
||||
nilShrink.Next,
|
||||
elementShink.Map(func(elem interface{}) interface{} {
|
||||
slice := reflect.MakeSlice(reflect.SliceOf(rt.Elem()), 0, 1)
|
||||
slice = reflect.Append(slice, reflect.ValueOf(elem))
|
||||
|
||||
return slice.Index(0).Addr().Interface()
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
17
vendor/github.com/leanovate/gopter/gen/ptr_shrink_test.go
generated
vendored
Normal file
17
vendor/github.com/leanovate/gopter/gen/ptr_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestPtrShrinker(t *testing.T) {
|
||||
v := 10
|
||||
shinks := []int{0, 5, -5, 8, -8, 9, -9}
|
||||
intPtrShrink := gen.PtrShrinker(gen.IntShrinker)(&v).All()
|
||||
if !reflect.DeepEqual(intPtrShrink, []interface{}{nil, &shinks[0], &shinks[1], &shinks[2], &shinks[3], &shinks[4], &shinks[5], &shinks[6]}) {
|
||||
t.Errorf("Invalid intPtrShrink: %#v", intPtrShrink)
|
||||
}
|
||||
}
|
||||
78
vendor/github.com/leanovate/gopter/gen/regex.go
generated
vendored
Normal file
78
vendor/github.com/leanovate/gopter/gen/regex.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"regexp/syntax"
|
||||
"strings"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// RegexMatch generates matches for a given regular expression
|
||||
// regexStr is supposed to conform to the perl regular expression syntax
|
||||
func RegexMatch(regexStr string) gopter.Gen {
|
||||
regexSyntax, err1 := syntax.Parse(regexStr, syntax.Perl)
|
||||
regex, err2 := regexp.Compile(regexStr)
|
||||
if err1 != nil || err2 != nil {
|
||||
return Fail(reflect.TypeOf(""))
|
||||
}
|
||||
return regexMatchGen(regexSyntax.Simplify()).SuchThat(func(v string) bool {
|
||||
return regex.MatchString(v)
|
||||
}).WithShrinker(StringShrinker)
|
||||
}
|
||||
|
||||
func regexMatchGen(regex *syntax.Regexp) gopter.Gen {
|
||||
switch regex.Op {
|
||||
case syntax.OpLiteral:
|
||||
return Const(string(regex.Rune))
|
||||
case syntax.OpCharClass:
|
||||
gens := make([]gopter.Gen, 0, len(regex.Rune)/2)
|
||||
for i := 0; i+1 < len(regex.Rune); i += 2 {
|
||||
gens = append(gens, RuneRange(regex.Rune[i], regex.Rune[i+1]).Map(runeToString))
|
||||
}
|
||||
return OneGenOf(gens...)
|
||||
case syntax.OpAnyChar:
|
||||
return Rune().Map(runeToString)
|
||||
case syntax.OpAnyCharNotNL:
|
||||
return RuneNoControl().Map(runeToString)
|
||||
case syntax.OpCapture:
|
||||
return regexMatchGen(regex.Sub[0])
|
||||
case syntax.OpStar:
|
||||
elementGen := regexMatchGen(regex.Sub[0])
|
||||
return SliceOf(elementGen).Map(func(v []string) string {
|
||||
return strings.Join(v, "")
|
||||
})
|
||||
case syntax.OpPlus:
|
||||
elementGen := regexMatchGen(regex.Sub[0])
|
||||
return gopter.CombineGens(elementGen, SliceOf(elementGen)).Map(func(vs []interface{}) string {
|
||||
return vs[0].(string) + strings.Join(vs[1].([]string), "")
|
||||
})
|
||||
case syntax.OpQuest:
|
||||
elementGen := regexMatchGen(regex.Sub[0])
|
||||
return OneGenOf(Const(""), elementGen)
|
||||
case syntax.OpConcat:
|
||||
gens := make([]gopter.Gen, len(regex.Sub))
|
||||
for i, sub := range regex.Sub {
|
||||
gens[i] = regexMatchGen(sub)
|
||||
}
|
||||
return gopter.CombineGens(gens...).Map(func(v []interface{}) string {
|
||||
result := ""
|
||||
for _, str := range v {
|
||||
result += str.(string)
|
||||
}
|
||||
return result
|
||||
})
|
||||
case syntax.OpAlternate:
|
||||
gens := make([]gopter.Gen, len(regex.Sub))
|
||||
for i, sub := range regex.Sub {
|
||||
gens[i] = regexMatchGen(sub)
|
||||
}
|
||||
return OneGenOf(gens...)
|
||||
}
|
||||
return Const("")
|
||||
}
|
||||
|
||||
func runeToString(v rune) string {
|
||||
return string(v)
|
||||
}
|
||||
36
vendor/github.com/leanovate/gopter/gen/regex_test.go
generated
vendored
Normal file
36
vendor/github.com/leanovate/gopter/gen/regex_test.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestRegexMatch(t *testing.T) {
|
||||
regexs := []string{
|
||||
"[a-z][0-9a-zA-Z]*",
|
||||
"AB[0-9]+",
|
||||
"1?(zero|one)0",
|
||||
"ABCD.+1234",
|
||||
"^[0-9]{3}[A-Z]{5,}[a-z]{10,20}$",
|
||||
"(?s)[^0-9]*ABCD.*1234",
|
||||
}
|
||||
for _, regex := range regexs {
|
||||
pattern, err := regexp.Compile(regex)
|
||||
if err != nil {
|
||||
t.Error("Invalid regex", err)
|
||||
}
|
||||
commonGeneratorTest(t, fmt.Sprintf("matches for %s", regex), gen.RegexMatch(regex), func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
return ok && pattern.MatchString(str)
|
||||
})
|
||||
}
|
||||
|
||||
gen := gen.RegexMatch("]]}})Invalid{]]]")
|
||||
value, ok := gen.Sample()
|
||||
if ok || value != nil {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
}
|
||||
21
vendor/github.com/leanovate/gopter/gen/retry_until.go
generated
vendored
Normal file
21
vendor/github.com/leanovate/gopter/gen/retry_until.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
// RetryUntil creates a generator that retries a given generator until a condition in met.
|
||||
// condition: has to be a function with one parameter (matching the generated value of gen) returning a bool.
|
||||
// Note: The new generator will only create an empty result once maxRetries is reached.
|
||||
// Depending on the hit-ratio of the condition is may result in long running tests, use with care.
|
||||
func RetryUntil(gen gopter.Gen, condition interface{}, maxRetries int) gopter.Gen {
|
||||
genWithSieve := gen.SuchThat(condition)
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
result := genWithSieve(genParams)
|
||||
if _, ok := result.Retrieve(); ok {
|
||||
return result
|
||||
}
|
||||
}
|
||||
resultType := gen(genParams).ResultType
|
||||
return gopter.NewEmptyResult(resultType)
|
||||
}
|
||||
}
|
||||
33
vendor/github.com/leanovate/gopter/gen/retry_until_test.go
generated
vendored
Normal file
33
vendor/github.com/leanovate/gopter/gen/retry_until_test.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestRetryUntil(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
origGen := gen.IntRange(0, 100)
|
||||
retryGen := gen.RetryUntil(origGen, func(v int) bool {
|
||||
return v > 50
|
||||
}, 1000)
|
||||
result := retryGen(genParams)
|
||||
value, ok := result.Retrieve()
|
||||
if value == nil || !ok {
|
||||
t.Errorf("RetryGen generated empty result")
|
||||
}
|
||||
if value.(int) <= 50 {
|
||||
t.Errorf("RetryGen generyte invalid value: %#v", value)
|
||||
}
|
||||
|
||||
noMatchGen := gen.RetryUntil(origGen, func(v int) bool {
|
||||
return v > 500
|
||||
}, 100)
|
||||
result = noMatchGen(genParams)
|
||||
_, ok = result.Retrieve()
|
||||
if ok {
|
||||
t.Errorf("RetryGen nomatch generated a value")
|
||||
}
|
||||
}
|
||||
89
vendor/github.com/leanovate/gopter/gen/slice_of.go
generated
vendored
Normal file
89
vendor/github.com/leanovate/gopter/gen/slice_of.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// SliceOf generates an arbitrary slice of generated elements
|
||||
// genParams.MaxSize sets an (exclusive) upper limit on the size of the slice
|
||||
// genParams.MinSize sets an (inclusive) lower limit on the size of the slice
|
||||
func SliceOf(elementGen gopter.Gen) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
len := 0
|
||||
if genParams.MaxSize > 0 || genParams.MinSize > 0 {
|
||||
if genParams.MinSize > genParams.MaxSize {
|
||||
panic("GenParameters.MinSize must be <= GenParameters.MaxSize")
|
||||
}
|
||||
|
||||
if genParams.MaxSize == genParams.MinSize {
|
||||
len = genParams.MaxSize
|
||||
} else {
|
||||
len = genParams.Rng.Intn(genParams.MaxSize-genParams.MinSize) + genParams.MinSize
|
||||
}
|
||||
}
|
||||
result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)
|
||||
|
||||
genResult := gopter.NewGenResult(result.Interface(), SliceShrinker(elementShrinker))
|
||||
if elementSieve != nil {
|
||||
genResult.Sieve = forAllSieve(elementSieve)
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// SliceOfN generates a slice of generated elements with definied length
|
||||
func SliceOfN(len int, elementGen gopter.Gen) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
result, elementSieve, elementShrinker := genSlice(elementGen, genParams, len)
|
||||
|
||||
genResult := gopter.NewGenResult(result.Interface(), SliceShrinkerOne(elementShrinker))
|
||||
if elementSieve != nil {
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
return rv.Len() == len && forAllSieve(elementSieve)(v)
|
||||
}
|
||||
} else {
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return reflect.ValueOf(v).Len() == len
|
||||
}
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
func genSlice(elementGen gopter.Gen, genParams *gopter.GenParameters, len int) (reflect.Value, func(interface{}) bool, gopter.Shrinker) {
|
||||
element := elementGen(genParams)
|
||||
elementSieve := element.Sieve
|
||||
elementShrinker := element.Shrinker
|
||||
|
||||
result := reflect.MakeSlice(reflect.SliceOf(element.ResultType), 0, len)
|
||||
|
||||
for i := 0; i < len; i++ {
|
||||
value, ok := element.Retrieve()
|
||||
|
||||
if ok {
|
||||
if value == nil {
|
||||
result = reflect.Append(result, reflect.Zero(element.ResultType))
|
||||
} else {
|
||||
result = reflect.Append(result, reflect.ValueOf(value))
|
||||
}
|
||||
}
|
||||
element = elementGen(genParams)
|
||||
}
|
||||
|
||||
return result, elementSieve, elementShrinker
|
||||
}
|
||||
|
||||
func forAllSieve(elementSieve func(interface{}) bool) func(interface{}) bool {
|
||||
return func(v interface{}) bool {
|
||||
rv := reflect.ValueOf(v)
|
||||
for i := rv.Len() - 1; i >= 0; i-- {
|
||||
if !elementSieve(rv.Index(i).Interface()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
172
vendor/github.com/leanovate/gopter/gen/slice_of_test.go
generated
vendored
Normal file
172
vendor/github.com/leanovate/gopter/gen/slice_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestSliceOf(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
genParams.MaxSize = 50
|
||||
elementGen := gen.Const("element")
|
||||
sliceGen := gen.SliceOf(elementGen)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := sliceGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.([]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) > 50 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, str := range strings {
|
||||
if str != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genParams.MinSize = 10
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := sliceGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.([]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) > 50 || len(strings) < 10 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, str := range strings {
|
||||
if str != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genParams.MaxSize = 10
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := sliceGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.([]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) != 10 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, str := range strings {
|
||||
if str != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genParams.MaxSize = 0
|
||||
genParams.MinSize = 0
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := sliceGen(genParams).Retrieve()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.([]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) != 0 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceOfPanic(t *testing.T) {
|
||||
genParams := gopter.DefaultGenParameters()
|
||||
genParams.MaxSize = 0
|
||||
genParams.MinSize = 1
|
||||
elementGen := gen.Const("element")
|
||||
sliceGen := gen.SliceOf(elementGen)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Error("SliceOf did not panic when MinSize was > MaxSize")
|
||||
}
|
||||
}()
|
||||
|
||||
sliceGen(genParams).Retrieve()
|
||||
}
|
||||
|
||||
func TestSliceOfN(t *testing.T) {
|
||||
elementGen := gen.Const("element")
|
||||
sliceGen := gen.SliceOfN(10, elementGen)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
sample, ok := sliceGen.Sample()
|
||||
|
||||
if !ok {
|
||||
t.Error("Sample was not ok")
|
||||
}
|
||||
strings, ok := sample.([]string)
|
||||
if !ok {
|
||||
t.Errorf("Sample not slice of string: %#v", sample)
|
||||
} else {
|
||||
if len(strings) != 10 {
|
||||
t.Errorf("Sample has invalid length: %#v", len(strings))
|
||||
}
|
||||
for _, str := range strings {
|
||||
if str != "element" {
|
||||
t.Errorf("Sample contains invalid value: %#v", sample)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceOfNSieve(t *testing.T) {
|
||||
var called int
|
||||
elementSieve := func(v interface{}) bool {
|
||||
called++
|
||||
return v == "element"
|
||||
}
|
||||
elementGen := gen.Const("element").SuchThat(elementSieve)
|
||||
sliceGen := gen.SliceOfN(10, elementGen)
|
||||
result := sliceGen(gopter.DefaultGenParameters())
|
||||
value, ok := result.Retrieve()
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
strs, ok := value.([]string)
|
||||
if !ok || len(strs) != 10 {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
if called != 20 {
|
||||
t.Errorf("Invalid called: %d", called)
|
||||
}
|
||||
if result.Sieve(strs[0:9]) {
|
||||
t.Error("Sieve must not allow array len < 10")
|
||||
}
|
||||
strs[0] = "bla"
|
||||
if result.Sieve(strs) {
|
||||
t.Error("Sieve must not allow array with invalid element")
|
||||
}
|
||||
}
|
||||
101
vendor/github.com/leanovate/gopter/gen/slice_shrink.go
generated
vendored
Normal file
101
vendor/github.com/leanovate/gopter/gen/slice_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type sliceShrinkOne struct {
|
||||
original reflect.Value
|
||||
index int
|
||||
elementShrink gopter.Shrink
|
||||
}
|
||||
|
||||
func (s *sliceShrinkOne) Next() (interface{}, bool) {
|
||||
value, ok := s.elementShrink()
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
result := reflect.MakeSlice(s.original.Type(), s.original.Len(), s.original.Len())
|
||||
reflect.Copy(result, s.original)
|
||||
result.Index(s.index).Set(reflect.ValueOf(value))
|
||||
|
||||
return result.Interface(), true
|
||||
}
|
||||
|
||||
// SliceShrinkerOne creates a slice shrinker from a shrinker for the elements of the slice.
|
||||
// The length of the slice will remains unchanged, instead each element is shrinked after the
|
||||
// other.
|
||||
func SliceShrinkerOne(elementShrinker gopter.Shrinker) gopter.Shrinker {
|
||||
return func(v interface{}) gopter.Shrink {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("%#v is not a slice", v))
|
||||
}
|
||||
|
||||
shrinks := make([]gopter.Shrink, 0, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
sliceShrinkOne := &sliceShrinkOne{
|
||||
original: rv,
|
||||
index: i,
|
||||
elementShrink: elementShrinker(rv.Index(i).Interface()),
|
||||
}
|
||||
shrinks = append(shrinks, sliceShrinkOne.Next)
|
||||
}
|
||||
return gopter.ConcatShrinks(shrinks...)
|
||||
}
|
||||
}
|
||||
|
||||
type sliceShrink struct {
|
||||
original reflect.Value
|
||||
length int
|
||||
offset int
|
||||
chunkLength int
|
||||
}
|
||||
|
||||
func (s *sliceShrink) Next() (interface{}, bool) {
|
||||
if s.chunkLength == 0 {
|
||||
return nil, false
|
||||
}
|
||||
value := reflect.AppendSlice(reflect.MakeSlice(s.original.Type(), 0, s.length-s.chunkLength), s.original.Slice(0, s.offset))
|
||||
s.offset += s.chunkLength
|
||||
if s.offset < s.length {
|
||||
value = reflect.AppendSlice(value, s.original.Slice(s.offset, s.length))
|
||||
} else {
|
||||
s.offset = 0
|
||||
s.chunkLength >>= 1
|
||||
}
|
||||
|
||||
return value.Interface(), true
|
||||
}
|
||||
|
||||
// SliceShrinker creates a slice shrinker from a shrinker for the elements of the slice.
|
||||
// The length of the slice will be shrinked as well
|
||||
func SliceShrinker(elementShrinker gopter.Shrinker) gopter.Shrinker {
|
||||
return func(v interface{}) gopter.Shrink {
|
||||
rv := reflect.ValueOf(v)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("%#v is not a slice", v))
|
||||
}
|
||||
sliceShrink := &sliceShrink{
|
||||
original: rv,
|
||||
offset: 0,
|
||||
length: rv.Len(),
|
||||
chunkLength: rv.Len() >> 1,
|
||||
}
|
||||
|
||||
shrinks := make([]gopter.Shrink, 0, rv.Len()+1)
|
||||
shrinks = append(shrinks, sliceShrink.Next)
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
sliceShrinkOne := &sliceShrinkOne{
|
||||
original: rv,
|
||||
index: i,
|
||||
elementShrink: elementShrinker(rv.Index(i).Interface()),
|
||||
}
|
||||
shrinks = append(shrinks, sliceShrinkOne.Next)
|
||||
}
|
||||
return gopter.ConcatShrinks(shrinks...)
|
||||
}
|
||||
}
|
||||
86
vendor/github.com/leanovate/gopter/gen/slice_shrink_test.go
generated
vendored
Normal file
86
vendor/github.com/leanovate/gopter/gen/slice_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestSliceShrink(t *testing.T) {
|
||||
oneShrink := gen.SliceShrinker(gen.Int64Shrinker)([]int64{0}).All()
|
||||
if !reflect.DeepEqual(oneShrink, []interface{}{}) {
|
||||
t.Errorf("Invalid oneShrink: %#v", oneShrink)
|
||||
}
|
||||
|
||||
twoShrink := gen.SliceShrinker(gen.Int64Shrinker)([]int64{0, 1}).All()
|
||||
if !reflect.DeepEqual(twoShrink, []interface{}{
|
||||
[]int64{1},
|
||||
[]int64{0},
|
||||
[]int64{0, 0},
|
||||
}) {
|
||||
t.Errorf("Invalid twoShrink: %#v", twoShrink)
|
||||
}
|
||||
|
||||
threeShrink := gen.SliceShrinker(gen.Int64Shrinker)([]int64{0, 1, 2}).All()
|
||||
if !reflect.DeepEqual(threeShrink, []interface{}{
|
||||
[]int64{1, 2},
|
||||
[]int64{0, 2},
|
||||
[]int64{0, 1},
|
||||
[]int64{0, 0, 2},
|
||||
[]int64{0, 1, 0},
|
||||
[]int64{0, 1, 1},
|
||||
[]int64{0, 1, -1},
|
||||
}) {
|
||||
t.Errorf("Invalid threeShrink: %#v", threeShrink)
|
||||
}
|
||||
|
||||
fourShrink := gen.SliceShrinker(gen.Int64Shrinker)([]int64{0, 1, 2, 3}).All()
|
||||
if !reflect.DeepEqual(fourShrink, []interface{}{
|
||||
[]int64{2, 3},
|
||||
[]int64{0, 1},
|
||||
[]int64{1, 2, 3},
|
||||
[]int64{0, 2, 3},
|
||||
[]int64{0, 1, 3},
|
||||
[]int64{0, 1, 2},
|
||||
[]int64{0, 0, 2, 3},
|
||||
[]int64{0, 1, 0, 3},
|
||||
[]int64{0, 1, 1, 3},
|
||||
[]int64{0, 1, -1, 3},
|
||||
[]int64{0, 1, 2, 0},
|
||||
[]int64{0, 1, 2, 2},
|
||||
[]int64{0, 1, 2, -2},
|
||||
}) {
|
||||
t.Errorf("Invalid fourShrink: %#v", fourShrink)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSliceShrinkOne(t *testing.T) {
|
||||
oneShrink := gen.SliceShrinkerOne(gen.Int64Shrinker)([]int64{0}).All()
|
||||
if !reflect.DeepEqual(oneShrink, []interface{}{}) {
|
||||
t.Errorf("Invalid oneShrink: %#v", oneShrink)
|
||||
}
|
||||
|
||||
threeShrink := gen.SliceShrinkerOne(gen.Int64Shrinker)([]int64{0, 1, 2}).All()
|
||||
if !reflect.DeepEqual(threeShrink, []interface{}{
|
||||
[]int64{0, 0, 2},
|
||||
[]int64{0, 1, 0},
|
||||
[]int64{0, 1, 1},
|
||||
[]int64{0, 1, -1},
|
||||
}) {
|
||||
t.Errorf("Invalid threeShrink: %#v", threeShrink)
|
||||
}
|
||||
|
||||
fourShrink := gen.SliceShrinkerOne(gen.Int64Shrinker)([]int64{0, 1, 2, 3}).All()
|
||||
if !reflect.DeepEqual(fourShrink, []interface{}{
|
||||
[]int64{0, 0, 2, 3},
|
||||
[]int64{0, 1, 0, 3},
|
||||
[]int64{0, 1, 1, 3},
|
||||
[]int64{0, 1, -1, 3},
|
||||
[]int64{0, 1, 2, 0},
|
||||
[]int64{0, 1, 2, 2},
|
||||
[]int64{0, 1, 2, -2},
|
||||
}) {
|
||||
t.Errorf("Invalid fourShrink: %#v", fourShrink)
|
||||
}
|
||||
}
|
||||
11
vendor/github.com/leanovate/gopter/gen/string_shrink.go
generated
vendored
Normal file
11
vendor/github.com/leanovate/gopter/gen/string_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package gen
|
||||
|
||||
import "github.com/leanovate/gopter"
|
||||
|
||||
var runeSliceShrinker = SliceShrinker(gopter.NoShrinker)
|
||||
|
||||
// StringShrinker is a shrinker for strings.
|
||||
// It is very similiar to a sliace shrinker just that the elements themselves will not be shrinkeed.
|
||||
func StringShrinker(v interface{}) gopter.Shrink {
|
||||
return runeSliceShrinker([]rune(v.(string))).Map(runesToString)
|
||||
}
|
||||
158
vendor/github.com/leanovate/gopter/gen/strings.go
generated
vendored
Normal file
158
vendor/github.com/leanovate/gopter/gen/strings.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// RuneRange generates runes within a given range
|
||||
func RuneRange(min, max rune) gopter.Gen {
|
||||
return genRune(Int64Range(int64(min), int64(max)))
|
||||
}
|
||||
|
||||
// Rune generates an arbitrary character rune
|
||||
func Rune() gopter.Gen {
|
||||
return genRune(Frequency(map[int]gopter.Gen{
|
||||
0xD800: Int64Range(0, 0xD800),
|
||||
utf8.MaxRune - 0xDFFF: Int64Range(0xDFFF, int64(utf8.MaxRune)),
|
||||
}))
|
||||
}
|
||||
|
||||
// RuneNoControl generates an arbitrary character rune that is not a control character
|
||||
func RuneNoControl() gopter.Gen {
|
||||
return genRune(Frequency(map[int]gopter.Gen{
|
||||
0xD800: Int64Range(32, 0xD800),
|
||||
utf8.MaxRune - 0xDFFF: Int64Range(0xDFFF, int64(utf8.MaxRune)),
|
||||
}))
|
||||
}
|
||||
|
||||
func genRune(int64Gen gopter.Gen) gopter.Gen {
|
||||
return int64Gen.Map(func(value int64) rune {
|
||||
return rune(value)
|
||||
}).SuchThat(func(v rune) bool {
|
||||
return utf8.ValidRune(v)
|
||||
})
|
||||
}
|
||||
|
||||
// NumChar generates arbitrary numberic character runes
|
||||
func NumChar() gopter.Gen {
|
||||
return RuneRange('0', '9')
|
||||
}
|
||||
|
||||
// AlphaUpperChar generates arbitrary uppercase alpha character runes
|
||||
func AlphaUpperChar() gopter.Gen {
|
||||
return RuneRange('A', 'Z')
|
||||
}
|
||||
|
||||
// AlphaLowerChar generates arbitrary lowercase alpha character runes
|
||||
func AlphaLowerChar() gopter.Gen {
|
||||
return RuneRange('a', 'z')
|
||||
}
|
||||
|
||||
// AlphaChar generates arbitrary character runes (upper- and lowercase)
|
||||
func AlphaChar() gopter.Gen {
|
||||
return Frequency(map[int]gopter.Gen{
|
||||
0: AlphaUpperChar(),
|
||||
9: AlphaLowerChar(),
|
||||
})
|
||||
}
|
||||
|
||||
// AlphaNumChar generates arbitrary alpha-numeric character runes
|
||||
func AlphaNumChar() gopter.Gen {
|
||||
return Frequency(map[int]gopter.Gen{
|
||||
0: NumChar(),
|
||||
9: AlphaChar(),
|
||||
})
|
||||
}
|
||||
|
||||
// UnicodeChar generates arbitrary character runes with a given unicode table
|
||||
func UnicodeChar(table *unicode.RangeTable) gopter.Gen {
|
||||
if table == nil || len(table.R16)+len(table.R32) == 0 {
|
||||
return Fail(reflect.TypeOf(rune('a')))
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
tableIdx := genParams.Rng.Intn(len(table.R16) + len(table.R32))
|
||||
|
||||
var selectedRune rune
|
||||
if tableIdx < len(table.R16) {
|
||||
r := table.R16[tableIdx]
|
||||
runeOffset := uint16(genParams.Rng.Int63n(int64((r.Hi-r.Lo+1)/r.Stride))) * r.Stride
|
||||
selectedRune = rune(runeOffset + r.Lo)
|
||||
} else {
|
||||
r := table.R32[tableIdx-len(table.R16)]
|
||||
runeOffset := uint32(genParams.Rng.Int63n(int64((r.Hi-r.Lo+1)/r.Stride))) * r.Stride
|
||||
selectedRune = rune(runeOffset + r.Lo)
|
||||
}
|
||||
genResult := gopter.NewGenResult(selectedRune, gopter.NoShrinker)
|
||||
genResult.Sieve = func(v interface{}) bool {
|
||||
return unicode.Is(table, v.(rune))
|
||||
}
|
||||
return genResult
|
||||
}
|
||||
}
|
||||
|
||||
// AnyString generates an arbitrary string
|
||||
func AnyString() gopter.Gen {
|
||||
return genString(Rune(), utf8.ValidRune)
|
||||
}
|
||||
|
||||
// AlphaString generates an arbitrary string with letters
|
||||
func AlphaString() gopter.Gen {
|
||||
return genString(AlphaChar(), unicode.IsLetter)
|
||||
}
|
||||
|
||||
// NumString generates an arbitrary string with digits
|
||||
func NumString() gopter.Gen {
|
||||
return genString(NumChar(), unicode.IsDigit)
|
||||
}
|
||||
|
||||
// Identifier generates an arbitrary identifier string
|
||||
// Identitiers are supporsed to start with a lowercase letter and contain only
|
||||
// letters and digits
|
||||
func Identifier() gopter.Gen {
|
||||
return gopter.CombineGens(
|
||||
AlphaLowerChar(),
|
||||
SliceOf(AlphaNumChar()),
|
||||
).Map(func(values []interface{}) string {
|
||||
first := values[0].(rune)
|
||||
tail := values[1].([]rune)
|
||||
result := make([]rune, 0, len(tail)+1)
|
||||
return string(append(append(result, first), tail...))
|
||||
}).SuchThat(func(str string) bool {
|
||||
if len(str) < 1 || !unicode.IsLower(([]rune(str))[0]) {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !unicode.IsLetter(ch) && !unicode.IsDigit(ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}).WithShrinker(StringShrinker)
|
||||
}
|
||||
|
||||
// UnicodeString generates an arbitrary string from a given
|
||||
// unicode table.
|
||||
func UnicodeString(table *unicode.RangeTable) gopter.Gen {
|
||||
return genString(UnicodeChar(table), func(ch rune) bool {
|
||||
return unicode.Is(table, ch)
|
||||
})
|
||||
}
|
||||
|
||||
func genString(runeGen gopter.Gen, runeSieve func(ch rune) bool) gopter.Gen {
|
||||
return SliceOf(runeGen).Map(runesToString).SuchThat(func(v string) bool {
|
||||
for _, ch := range v {
|
||||
if !runeSieve(ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}).WithShrinker(StringShrinker)
|
||||
}
|
||||
|
||||
func runesToString(v []rune) string {
|
||||
return string(v)
|
||||
}
|
||||
161
vendor/github.com/leanovate/gopter/gen/strings_test.go
generated
vendored
Normal file
161
vendor/github.com/leanovate/gopter/gen/strings_test.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestRune(t *testing.T) {
|
||||
commonGeneratorTest(t, "rune", gen.Rune(), func(value interface{}) bool {
|
||||
v, ok := value.(rune)
|
||||
return ok && utf8.ValidRune(v)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNumChar(t *testing.T) {
|
||||
commonGeneratorTest(t, "num char", gen.NumChar(), func(value interface{}) bool {
|
||||
v, ok := value.(rune)
|
||||
return ok && unicode.IsNumber(v)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAlphaUpper(t *testing.T) {
|
||||
commonGeneratorTest(t, "alpha upper char", gen.AlphaUpperChar(), func(value interface{}) bool {
|
||||
v, ok := value.(rune)
|
||||
return ok && unicode.IsUpper(v) && unicode.IsLetter(v)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAlphaLower(t *testing.T) {
|
||||
commonGeneratorTest(t, "alpha lower char", gen.AlphaLowerChar(), func(value interface{}) bool {
|
||||
v, ok := value.(rune)
|
||||
return ok && unicode.IsLower(v) && unicode.IsLetter(v)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAlphaChar(t *testing.T) {
|
||||
commonGeneratorTest(t, "alpha char", gen.AlphaChar(), func(value interface{}) bool {
|
||||
v, ok := value.(rune)
|
||||
return ok && unicode.IsLetter(v)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAnyString(t *testing.T) {
|
||||
commonGeneratorTest(t, "any string", gen.AnyString(), func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !utf8.ValidRune(ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestAlphaString(t *testing.T) {
|
||||
alphaString := gen.AlphaString()
|
||||
commonGeneratorTest(t, "alpha string", alphaString, func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !utf8.ValidRune(ch) || !unicode.IsLetter(ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
sieve := alphaString(gopter.DefaultGenParameters()).Sieve
|
||||
if sieve == nil {
|
||||
t.Error("No sieve")
|
||||
}
|
||||
if !sieve("abcdABCD") || sieve("abc12") {
|
||||
t.Error("Invalid sieve")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumString(t *testing.T) {
|
||||
numString := gen.NumString()
|
||||
commonGeneratorTest(t, "num string", numString, func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !utf8.ValidRune(ch) || !unicode.IsDigit(ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
sieve := numString(gopter.DefaultGenParameters()).Sieve
|
||||
if sieve == nil {
|
||||
t.Error("No sieve")
|
||||
}
|
||||
if !sieve("123456789") || sieve("123abcd") {
|
||||
t.Error("Invalid sieve")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIdentifier(t *testing.T) {
|
||||
identifiers := gen.Identifier()
|
||||
commonGeneratorTest(t, "identifiers", identifiers, func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if len(str) == 0 || !unicode.IsLetter([]rune(str)[0]) {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !utf8.ValidRune(ch) || (!unicode.IsDigit(ch) && !unicode.IsLetter(ch)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
sieve := identifiers(gopter.DefaultGenParameters()).Sieve
|
||||
if sieve == nil {
|
||||
t.Error("No sieve")
|
||||
}
|
||||
if !sieve("abc123") || sieve("123abc") || sieve("abcd123-") {
|
||||
t.Error("Invalid sieve")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnicodeString(t *testing.T) {
|
||||
fail := gen.UnicodeChar(nil)
|
||||
value, ok := fail.Sample()
|
||||
if value != nil || ok {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
for _, table := range unicode.Scripts {
|
||||
unicodeString := gen.UnicodeString(table)
|
||||
commonGeneratorTest(t, "unicodeString", unicodeString, func(value interface{}) bool {
|
||||
str, ok := value.(string)
|
||||
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
for _, ch := range str {
|
||||
if !utf8.ValidRune(ch) || !unicode.Is(table, ch) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
69
vendor/github.com/leanovate/gopter/gen/struct.go
generated
vendored
Normal file
69
vendor/github.com/leanovate/gopter/gen/struct.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Struct generates a given struct type.
|
||||
// rt has to be the reflect type of the struct, gens contains a map of field generators.
|
||||
// Note that the result types of the generators in gen have to match the type of the correspoinding
|
||||
// field in the struct. Also note that only public fields of a struct can be generated
|
||||
func Struct(rt reflect.Type, gens map[string]gopter.Gen) gopter.Gen {
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
if rt.Kind() != reflect.Struct {
|
||||
return Fail(rt)
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
result := reflect.New(rt)
|
||||
|
||||
for name, gen := range gens {
|
||||
field, ok := rt.FieldByName(name)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
value, ok := gen(genParams).Retrieve()
|
||||
if !ok {
|
||||
return gopter.NewEmptyResult(rt)
|
||||
}
|
||||
result.Elem().FieldByIndex(field.Index).Set(reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
return gopter.NewGenResult(reflect.Indirect(result).Interface(), gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
// StructPtr generates pointers to a given struct type.
|
||||
// Not that SturctPtr does not generate nil, if you want to include nil in your
|
||||
// testing you should combine gen.PtrOf with gen.Struct.
|
||||
// rt has to be the reflect type of the struct, gens contains a map of field generators.
|
||||
// Note that the result types of the generators in gen have to match the type of the correspoinding
|
||||
// field in the struct. Also note that only public fields of a struct can be generated
|
||||
func StructPtr(rt reflect.Type, gens map[string]gopter.Gen) gopter.Gen {
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rt = rt.Elem()
|
||||
}
|
||||
if rt.Kind() != reflect.Struct {
|
||||
return Fail(rt)
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
result := reflect.New(rt)
|
||||
|
||||
for name, gen := range gens {
|
||||
field, ok := rt.FieldByName(name)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
value, ok := gen(genParams).Retrieve()
|
||||
if !ok {
|
||||
return gopter.NewEmptyResult(rt)
|
||||
}
|
||||
result.Elem().FieldByIndex(field.Index).Set(reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
return gopter.NewGenResult(result.Interface(), gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
96
vendor/github.com/leanovate/gopter/gen/struct_test.go
generated
vendored
Normal file
96
vendor/github.com/leanovate/gopter/gen/struct_test.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
type testStruct struct {
|
||||
Value1 string
|
||||
Value2 int64
|
||||
Value3 []int8
|
||||
Value4 string
|
||||
}
|
||||
|
||||
func TestStruct(t *testing.T) {
|
||||
structGen := gen.Struct(reflect.TypeOf(&testStruct{}), map[string]gopter.Gen{
|
||||
"Value1": gen.Identifier(),
|
||||
"Value2": gen.Int64(),
|
||||
"Value3": gen.SliceOf(gen.Int8()),
|
||||
"NotThere": gen.AnyString(),
|
||||
})
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := structGen.Sample()
|
||||
|
||||
if !ok {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
v, ok := value.(testStruct)
|
||||
if !ok || v.Value1 == "" || v.Value3 == nil || v.Value4 != "" {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructPropageEmpty(t *testing.T) {
|
||||
fail := gen.Struct(reflect.TypeOf(&testStruct{}), map[string]gopter.Gen{
|
||||
"Value1": gen.Identifier().SuchThat(func(str string) bool {
|
||||
return false
|
||||
}),
|
||||
})
|
||||
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Failing field generator in Struct generated a value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructNoStruct(t *testing.T) {
|
||||
fail := gen.Struct(reflect.TypeOf(""), map[string]gopter.Gen{})
|
||||
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Invalid Struct generated a value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructPtr(t *testing.T) {
|
||||
structGen := gen.StructPtr(reflect.TypeOf(&testStruct{}), map[string]gopter.Gen{
|
||||
"Value1": gen.Identifier(),
|
||||
"Value2": gen.Int64(),
|
||||
"Value3": gen.SliceOf(gen.Int8()),
|
||||
"NotThere": gen.AnyString(),
|
||||
})
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := structGen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
v, ok := value.(*testStruct)
|
||||
if !ok || v.Value1 == "" || v.Value3 == nil || v.Value4 != "" {
|
||||
t.Errorf("Invalid value: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructPtrPropageEmpty(t *testing.T) {
|
||||
fail := gen.StructPtr(reflect.TypeOf(&testStruct{}), map[string]gopter.Gen{
|
||||
"Value1": gen.Identifier().SuchThat(func(str string) bool {
|
||||
return false
|
||||
}),
|
||||
})
|
||||
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Failing field generator in StructPtr generated a value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructPtrNoStruct(t *testing.T) {
|
||||
fail := gen.StructPtr(reflect.TypeOf(""), map[string]gopter.Gen{})
|
||||
|
||||
if _, ok := fail.Sample(); ok {
|
||||
t.Errorf("Invalid StructPtr generated a value")
|
||||
}
|
||||
}
|
||||
37
vendor/github.com/leanovate/gopter/gen/time.go
generated
vendored
Normal file
37
vendor/github.com/leanovate/gopter/gen/time.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// Time generates an arbitrary time.Time within year [0, 9999]
|
||||
func Time() gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
sec := genParams.Rng.Int63n(253402214400) // Ensure year in [0, 9999]
|
||||
usec := genParams.Rng.Int63n(1000000000)
|
||||
|
||||
return gopter.NewGenResult(time.Unix(sec, usec), TimeShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
// AnyTime generates an arbitrary time.Time struct (might be way out of bounds of any reason)
|
||||
func AnyTime() gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
sec := genParams.NextInt64()
|
||||
usec := genParams.NextInt64()
|
||||
|
||||
return gopter.NewGenResult(time.Unix(sec, usec), TimeShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
// TimeRange generates an arbitrary time.Time with a range
|
||||
// from defines the start of the time range
|
||||
// duration defines the overall duration of the time range
|
||||
func TimeRange(from time.Time, duration time.Duration) gopter.Gen {
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
v := from.Add(time.Duration(genParams.Rng.Int63n(int64(duration))))
|
||||
return gopter.NewGenResult(v, TimeShrinker)
|
||||
}
|
||||
}
|
||||
27
vendor/github.com/leanovate/gopter/gen/time_shrink.go
generated
vendored
Normal file
27
vendor/github.com/leanovate/gopter/gen/time_shrink.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// TimeShrinker is a shrinker for time.Time structs
|
||||
func TimeShrinker(v interface{}) gopter.Shrink {
|
||||
t := v.(time.Time)
|
||||
sec := t.Unix()
|
||||
nsec := int64(t.Nanosecond())
|
||||
secShrink := uint64Shrink{
|
||||
original: uint64(sec),
|
||||
half: uint64(sec),
|
||||
}
|
||||
nsecShrink := uint64Shrink{
|
||||
original: uint64(nsec),
|
||||
half: uint64(nsec),
|
||||
}
|
||||
return gopter.Shrink(secShrink.Next).Map(func(v uint64) time.Time {
|
||||
return time.Unix(int64(v), nsec)
|
||||
}).Interleave(gopter.Shrink(nsecShrink.Next).Map(func(v uint64) time.Time {
|
||||
return time.Unix(sec, int64(v))
|
||||
}))
|
||||
}
|
||||
27
vendor/github.com/leanovate/gopter/gen/time_shrink_test.go
generated
vendored
Normal file
27
vendor/github.com/leanovate/gopter/gen/time_shrink_test.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestTimeShrink(t *testing.T) {
|
||||
timeShrink := gen.TimeShrinker(time.Unix(20, 10)).All()
|
||||
if !reflect.DeepEqual(timeShrink, []interface{}{
|
||||
time.Unix(0, 10),
|
||||
time.Unix(20, 0),
|
||||
time.Unix(10, 10),
|
||||
time.Unix(20, 5),
|
||||
time.Unix(15, 10),
|
||||
time.Unix(20, 8),
|
||||
time.Unix(18, 10),
|
||||
time.Unix(20, 9),
|
||||
time.Unix(19, 10),
|
||||
}) {
|
||||
t.Errorf("Invalid timeShrink: %#v", timeShrink)
|
||||
}
|
||||
|
||||
}
|
||||
60
vendor/github.com/leanovate/gopter/gen/time_test.go
generated
vendored
Normal file
60
vendor/github.com/leanovate/gopter/gen/time_test.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
timeGen := gen.Time()
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := timeGen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
v, ok := value.(time.Time)
|
||||
if !ok || v.String() == "" {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
if v.Year() < 0 || v.Year() > 9999 {
|
||||
t.Errorf("Year out of range: %#v", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnyTime(t *testing.T) {
|
||||
timeGen := gen.AnyTime()
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := timeGen.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
v, ok := value.(time.Time)
|
||||
if !ok || v.String() == "" {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeRegion(t *testing.T) {
|
||||
duration := time.Duration(10*24*365) * time.Hour
|
||||
from := time.Unix(1000, 0)
|
||||
until := from.Add(duration)
|
||||
timeRange := gen.TimeRange(from, duration)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
value, ok := timeRange.Sample()
|
||||
|
||||
if !ok || value == nil {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
v, ok := value.(time.Time)
|
||||
if !ok || v.Before(from) || v.After(until) {
|
||||
t.Errorf("Invalid time: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
44
vendor/github.com/leanovate/gopter/gen/weighted.go
generated
vendored
Normal file
44
vendor/github.com/leanovate/gopter/gen/weighted.go
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
// WeightedGen adds a weight number to a generator.
|
||||
// To be used as parameter to gen.Weighted
|
||||
type WeightedGen struct {
|
||||
Weight int
|
||||
Gen gopter.Gen
|
||||
}
|
||||
|
||||
// Weighted combines multiple generators, where each generator has a weight.
|
||||
// The weight of a generator is proportional to the probability that the
|
||||
// generator gets selected.
|
||||
func Weighted(weightedGens []WeightedGen) gopter.Gen {
|
||||
if len(weightedGens) == 0 {
|
||||
panic("weightedGens must be non-empty")
|
||||
}
|
||||
weights := make(sort.IntSlice, 0, len(weightedGens))
|
||||
|
||||
totalWeight := 0
|
||||
for _, weightedGen := range weightedGens {
|
||||
w := weightedGen.Weight
|
||||
if w <= 0 {
|
||||
panic(fmt.Sprintf(
|
||||
"weightedGens must have positive weights; got %d",
|
||||
w))
|
||||
}
|
||||
totalWeight += weightedGen.Weight
|
||||
weights = append(weights, totalWeight)
|
||||
}
|
||||
return func(genParams *gopter.GenParameters) *gopter.GenResult {
|
||||
idx := weights.Search(1 + genParams.Rng.Intn(totalWeight))
|
||||
gen := weightedGens[idx].Gen
|
||||
result := gen(genParams)
|
||||
result.Sieve = nil
|
||||
return result
|
||||
}
|
||||
}
|
||||
41
vendor/github.com/leanovate/gopter/gen/weighted_test.go
generated
vendored
Normal file
41
vendor/github.com/leanovate/gopter/gen/weighted_test.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package gen_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter/gen"
|
||||
)
|
||||
|
||||
func TestWeighted(t *testing.T) {
|
||||
weighted := gen.Weighted([]gen.WeightedGen{
|
||||
{Weight: 1, Gen: gen.Const("A")},
|
||||
{Weight: 2, Gen: gen.Const("B")},
|
||||
{Weight: 7, Gen: gen.Const("C")},
|
||||
})
|
||||
results := make(map[string]int)
|
||||
for i := int64(0); i < int64(1000); i++ {
|
||||
result, ok := weighted.Sample()
|
||||
if !ok {
|
||||
t.FailNow()
|
||||
}
|
||||
results[result.(string)]++
|
||||
}
|
||||
expectedResults := map[string]int{
|
||||
"A": 100,
|
||||
"B": 200,
|
||||
"C": 700,
|
||||
}
|
||||
delta := 50
|
||||
for _, value := range []string{"A", "B", "C"} {
|
||||
result := results[value]
|
||||
expected := expectedResults[value]
|
||||
if result < expected-delta || result > expected+delta {
|
||||
t.Errorf(
|
||||
"Result %d for %v falls outside acceptable range %d, %d",
|
||||
result,
|
||||
value,
|
||||
expected-delta,
|
||||
expected+delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
63
vendor/github.com/leanovate/gopter/gen_parameter_test.go
generated
vendored
Normal file
63
vendor/github.com/leanovate/gopter/gen_parameter_test.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
type fixedSeed struct {
|
||||
fixed int64
|
||||
}
|
||||
|
||||
func (f *fixedSeed) Int63() int64 { return f.fixed }
|
||||
func (f *fixedSeed) Seed(seed int64) { f.fixed = seed }
|
||||
|
||||
func TestGenParameters(t *testing.T) {
|
||||
parameters := &gopter.GenParameters{
|
||||
MaxSize: 100,
|
||||
Rng: rand.New(&fixedSeed{}),
|
||||
}
|
||||
|
||||
if !parameters.NextBool() {
|
||||
t.Error("Bool should be true")
|
||||
}
|
||||
if parameters.NextInt64() != 0 {
|
||||
t.Error("int64 should be 0")
|
||||
}
|
||||
if parameters.NextUint64() != 0 {
|
||||
t.Error("uint64 should be 0")
|
||||
}
|
||||
|
||||
parameters.Rng.Seed(1)
|
||||
if parameters.NextBool() {
|
||||
t.Error("Bool should be false")
|
||||
}
|
||||
if parameters.NextInt64() != 1 {
|
||||
t.Error("int64 should be 1")
|
||||
}
|
||||
if parameters.NextUint64() != 3 {
|
||||
t.Error("uint64 should be 3")
|
||||
}
|
||||
|
||||
parameters.Rng.Seed(2)
|
||||
if !parameters.NextBool() {
|
||||
t.Error("Bool should be true")
|
||||
}
|
||||
if parameters.NextInt64() != -2 {
|
||||
t.Error("int64 should be -2")
|
||||
}
|
||||
if parameters.NextUint64() != 6 {
|
||||
t.Error("uint64 should be 6")
|
||||
}
|
||||
|
||||
param1 := parameters.CloneWithSeed(1024)
|
||||
param2 := parameters.CloneWithSeed(1024)
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
if param1.NextInt64() != param2.NextInt64() {
|
||||
t.Error("cloned parameters create different random numbers")
|
||||
}
|
||||
}
|
||||
}
|
||||
68
vendor/github.com/leanovate/gopter/gen_parameters.go
generated
vendored
Normal file
68
vendor/github.com/leanovate/gopter/gen_parameters.go
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
package gopter
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GenParameters encapsulates the parameters for all generators.
|
||||
type GenParameters struct {
|
||||
MinSize int
|
||||
MaxSize int
|
||||
MaxShrinkCount int
|
||||
Rng *rand.Rand
|
||||
}
|
||||
|
||||
// WithSize modifies the size parameter. The size parameter defines an upper bound for the size of
|
||||
// generated slices or strings.
|
||||
func (p *GenParameters) WithSize(size int) *GenParameters {
|
||||
newParameters := *p
|
||||
newParameters.MaxSize = size
|
||||
return &newParameters
|
||||
}
|
||||
|
||||
// NextBool create a random boolean using the underlying Rng.
|
||||
func (p *GenParameters) NextBool() bool {
|
||||
return p.Rng.Int63()&1 == 0
|
||||
}
|
||||
|
||||
// NextInt64 create a random int64 using the underlying Rng.
|
||||
func (p *GenParameters) NextInt64() int64 {
|
||||
v := p.Rng.Int63()
|
||||
if p.NextBool() {
|
||||
return -v
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// NextUint64 create a random uint64 using the underlying Rng.
|
||||
func (p *GenParameters) NextUint64() uint64 {
|
||||
first := uint64(p.Rng.Int63())
|
||||
second := uint64(p.Rng.Int63())
|
||||
|
||||
return (first << 1) ^ second
|
||||
}
|
||||
|
||||
// CloneWithSeed clone the current parameters with a new seed.
|
||||
// This is useful to create subsections that can rerun (provided you keep the
|
||||
// seed)
|
||||
func (p *GenParameters) CloneWithSeed(seed int64) *GenParameters {
|
||||
return &GenParameters{
|
||||
MinSize: p.MinSize,
|
||||
MaxSize: p.MaxSize,
|
||||
MaxShrinkCount: p.MaxShrinkCount,
|
||||
Rng: rand.New(NewLockedSource(seed)),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultGenParameters creates default GenParameters.
|
||||
func DefaultGenParameters() *GenParameters {
|
||||
seed := time.Now().UnixNano()
|
||||
|
||||
return &GenParameters{
|
||||
MinSize: 0,
|
||||
MaxSize: 100,
|
||||
MaxShrinkCount: 1000,
|
||||
Rng: rand.New(NewLockedSource(seed)),
|
||||
}
|
||||
}
|
||||
55
vendor/github.com/leanovate/gopter/gen_result.go
generated
vendored
Normal file
55
vendor/github.com/leanovate/gopter/gen_result.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package gopter
|
||||
|
||||
import "reflect"
|
||||
|
||||
// GenResult contains the result of a generator.
|
||||
type GenResult struct {
|
||||
Labels []string
|
||||
Shrinker Shrinker
|
||||
ResultType reflect.Type
|
||||
Result interface{}
|
||||
Sieve func(interface{}) bool
|
||||
}
|
||||
|
||||
// NewGenResult creates a new generator result from for a concrete value and
|
||||
// shrinker.
|
||||
// Note: The concrete value "result" not be nil
|
||||
func NewGenResult(result interface{}, shrinker Shrinker) *GenResult {
|
||||
return &GenResult{
|
||||
Shrinker: shrinker,
|
||||
ResultType: reflect.TypeOf(result),
|
||||
Result: result,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEmptyResult creates an empty generator result.
|
||||
// Unless the sieve does not explicitly allow it, empty (i.e. nil-valued)
|
||||
// results are considered invalid.
|
||||
func NewEmptyResult(resultType reflect.Type) *GenResult {
|
||||
return &GenResult{
|
||||
ResultType: resultType,
|
||||
Shrinker: NoShrinker,
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve gets the concrete generator result.
|
||||
// If the result is invalid or does not pass the sieve there is no concrete
|
||||
// value and the property using the generator should be undecided.
|
||||
func (r *GenResult) Retrieve() (interface{}, bool) {
|
||||
if (r.Sieve == nil && r.Result != nil) || (r.Sieve != nil && r.Sieve(r.Result)) {
|
||||
return r.Result, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// RetrieveAsValue get the concrete generator result as reflect value.
|
||||
// If the result is invalid or does not pass the sieve there is no concrete
|
||||
// value and the property using the generator should be undecided.
|
||||
func (r *GenResult) RetrieveAsValue() (reflect.Value, bool) {
|
||||
if r.Result != nil && (r.Sieve == nil || r.Sieve(r.Result)) {
|
||||
return reflect.ValueOf(r.Result), true
|
||||
} else if r.Result == nil && r.Sieve != nil && r.Sieve(r.Result) {
|
||||
return reflect.Zero(r.ResultType), true
|
||||
}
|
||||
return reflect.Zero(r.ResultType), false
|
||||
}
|
||||
26
vendor/github.com/leanovate/gopter/gen_result_test.go
generated
vendored
Normal file
26
vendor/github.com/leanovate/gopter/gen_result_test.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
func TestNewGenResult(t *testing.T) {
|
||||
result := gopter.NewGenResult(123, gopter.NoShrinker)
|
||||
value, ok := result.Retrieve()
|
||||
|
||||
if !ok || value != 123 || result.ResultType.Kind() != reflect.Int {
|
||||
t.Errorf("Invalid result: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewEmptyResult(t *testing.T) {
|
||||
result := gopter.NewEmptyResult(reflect.TypeOf(0))
|
||||
value, ok := result.Retrieve()
|
||||
|
||||
if ok || value != nil || result.ResultType.Kind() != reflect.Int {
|
||||
t.Errorf("Invalid result: %#v", value)
|
||||
}
|
||||
}
|
||||
387
vendor/github.com/leanovate/gopter/gen_test.go
generated
vendored
Normal file
387
vendor/github.com/leanovate/gopter/gen_test.go
generated
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
package gopter_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/leanovate/gopter"
|
||||
)
|
||||
|
||||
func constGen(value interface{}) gopter.Gen {
|
||||
return func(*gopter.GenParameters) *gopter.GenResult {
|
||||
return gopter.NewGenResult(value, gopter.NoShrinker)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenSample(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
|
||||
value, ok := gen.Sample()
|
||||
if !ok || value != "sample" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkMap(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
gen := constGen("sample")
|
||||
var mappedWith string
|
||||
mapper := func(v string) string {
|
||||
mappedWith = v
|
||||
return "other"
|
||||
}
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
b.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith != "sample" {
|
||||
b.Errorf("Invalid mapped with: %#v", mappedWith)
|
||||
}
|
||||
|
||||
gen = gen.SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
value, ok = gen.Map(mapper).Sample()
|
||||
if ok {
|
||||
b.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMap(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith string
|
||||
mapper := func(v string) string {
|
||||
mappedWith = v
|
||||
return "other"
|
||||
}
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith != "sample" {
|
||||
t.Errorf("Invalid mapped with: %#v", mappedWith)
|
||||
}
|
||||
|
||||
gen = gen.SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
value, ok = gen.Map(mapper).Sample()
|
||||
if ok {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMapWithParams(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith string
|
||||
var mappedWithParams *gopter.GenParameters
|
||||
mapper := func(v string, params *gopter.GenParameters) string {
|
||||
mappedWith = v
|
||||
mappedWithParams = params
|
||||
return "other"
|
||||
}
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith != "sample" {
|
||||
t.Errorf("Invalid mapped with: %#v", mappedWith)
|
||||
}
|
||||
if mappedWithParams == nil || mappedWithParams.MaxSize != 100 {
|
||||
t.Error("Mapper not called with currect parameters")
|
||||
}
|
||||
|
||||
gen = gen.SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
value, ok = gen.Map(mapper).Sample()
|
||||
if ok {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
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 or two params, but is 3")
|
||||
constGen("sample").Map(func(a, b, C string) string {
|
||||
return ""
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenMapInvalidSecondParam(t *testing.T) {
|
||||
defer expectPanic(t, "Second parameter of mapper function has to be a *GenParameters")
|
||||
constGen("sample").Map(func(a, b string) string {
|
||||
return ""
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenMapToInvalidParamtype(t *testing.T) {
|
||||
defer expectPanic(t, "Param of Map 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 TestGenMapResultIn(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith *gopter.GenResult
|
||||
mapper := func(result *gopter.GenResult) string {
|
||||
mappedWith = result
|
||||
return "other"
|
||||
}
|
||||
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith == nil {
|
||||
t.Error("Mapper not called")
|
||||
}
|
||||
if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" {
|
||||
t.Errorf("Mapper was called with invalid value: %#v", mapperValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMapResultInWithParams(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith *gopter.GenResult
|
||||
var mappedWithParams *gopter.GenParameters
|
||||
mapper := func(result *gopter.GenResult, params *gopter.GenParameters) string {
|
||||
mappedWith = result
|
||||
mappedWithParams = params
|
||||
return "other"
|
||||
}
|
||||
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith == nil {
|
||||
t.Error("Mapper not called")
|
||||
}
|
||||
if mappedWithParams == nil || mappedWithParams.MaxSize != 100 {
|
||||
t.Error("Mapper not called with currect parameters")
|
||||
}
|
||||
if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" {
|
||||
t.Errorf("Mapper was called with invalid value: %#v", mapperValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMapResultOut(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith string
|
||||
mapper := func(v string) *gopter.GenResult {
|
||||
mappedWith = v
|
||||
return gopter.NewGenResult("other", gopter.NoShrinker)
|
||||
}
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith != "sample" {
|
||||
t.Errorf("Invalid mapped with: %#v", mappedWith)
|
||||
}
|
||||
|
||||
gen = gen.SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
value, ok = gen.Map(mapper).Sample()
|
||||
if ok {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMapResultInOut(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith *gopter.GenResult
|
||||
mapper := func(result *gopter.GenResult) *gopter.GenResult {
|
||||
mappedWith = result
|
||||
return gopter.NewGenResult("other", gopter.NoShrinker)
|
||||
}
|
||||
|
||||
value, ok := gen.Map(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith == nil {
|
||||
t.Error("Mapper not called")
|
||||
}
|
||||
if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" {
|
||||
t.Errorf("Mapper was called with invalid value: %#v", mapperValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenFlatMap(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith interface{}
|
||||
mapper := func(v interface{}) gopter.Gen {
|
||||
mappedWith = v
|
||||
return constGen("other")
|
||||
}
|
||||
value, ok := gen.FlatMap(mapper, reflect.TypeOf("")).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith.(string) != "sample" {
|
||||
t.Errorf("Invalid mapped with: %#v", mappedWith)
|
||||
}
|
||||
|
||||
gen = gen.SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
value, ok = gen.FlatMap(mapper, reflect.TypeOf("")).Sample()
|
||||
if ok {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenMapResult(t *testing.T) {
|
||||
gen := constGen("sample")
|
||||
var mappedWith *gopter.GenResult
|
||||
mapper := func(result *gopter.GenResult) *gopter.GenResult {
|
||||
mappedWith = result
|
||||
return gopter.NewGenResult("other", gopter.NoShrinker)
|
||||
}
|
||||
|
||||
value, ok := gen.MapResult(mapper).Sample()
|
||||
if !ok || value != "other" {
|
||||
t.Errorf("Invalid gen sample: %#v", value)
|
||||
}
|
||||
if mappedWith == nil {
|
||||
t.Error("Mapper not called")
|
||||
}
|
||||
if mapperValue, ok := mappedWith.Retrieve(); !ok || mapperValue != "sample" {
|
||||
t.Errorf("Mapper was called with invalid value: %#v", mapperValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombineGens(t *testing.T) {
|
||||
gens := make([]gopter.Gen, 0, 20)
|
||||
for i := 0; i < 20; i++ {
|
||||
gens = append(gens, constGen(i))
|
||||
}
|
||||
gen := gopter.CombineGens(gens...)
|
||||
raw, ok := gen.Sample()
|
||||
if !ok {
|
||||
t.Errorf("Invalid combined gen: %#v", raw)
|
||||
}
|
||||
values, ok := raw.([]interface{})
|
||||
if !ok || !reflect.DeepEqual(values, []interface{}{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}) {
|
||||
t.Errorf("Invalid combined gen: %#v", raw)
|
||||
}
|
||||
|
||||
gens[0] = gens[0].SuchThat(func(interface{}) bool {
|
||||
return false
|
||||
})
|
||||
gen = gopter.CombineGens(gens...)
|
||||
raw, ok = gen.Sample()
|
||||
if ok {
|
||||
t.Errorf("Invalid combined gen: %#v", raw)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuchThat(t *testing.T) {
|
||||
var sieveArg string
|
||||
sieve := func(v string) bool {
|
||||
sieveArg = v
|
||||
return true
|
||||
}
|
||||
gen := constGen("sample").SuchThat(sieve)
|
||||
value, ok := gen.Sample()
|
||||
if !ok || value != "sample" {
|
||||
t.Errorf("Invalid result: %#v", value)
|
||||
}
|
||||
if sieveArg != "sample" {
|
||||
t.Errorf("Invalid sieveArg: %#v", sieveArg)
|
||||
}
|
||||
|
||||
sieveArg = ""
|
||||
var sieve2Arg string
|
||||
sieve2 := func(v string) bool {
|
||||
sieve2Arg = v
|
||||
return false
|
||||
}
|
||||
gen = gen.SuchThat(sieve2)
|
||||
_, ok = gen.Sample()
|
||||
if ok {
|
||||
t.Error("Did not expect a result")
|
||||
}
|
||||
if sieveArg != "sample" {
|
||||
t.Errorf("Invalid sieveArg: %#v", sieveArg)
|
||||
}
|
||||
if sieve2Arg != "sample" {
|
||||
t.Errorf("Invalid sieve2Arg: %#v", sieve2Arg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenSuchThatNoFunc(t *testing.T) {
|
||||
defer expectPanic(t, "Param of SuchThat has to be a func, but is string")
|
||||
constGen("sample").SuchThat("not a function")
|
||||
}
|
||||
|
||||
func TestGenSuchTooManyParams(t *testing.T) {
|
||||
defer expectPanic(t, "Param of SuchThat has to be a func with one param, but is 2")
|
||||
constGen("sample").SuchThat(func(a, b string) bool {
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenSuchThatToInvalidParamtype(t *testing.T) {
|
||||
defer expectPanic(t, "Param of SuchThat has to be a func with one param assignable to string, but is int")
|
||||
constGen("sample").SuchThat(func(a int) bool {
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenSuchToManyReturns(t *testing.T) {
|
||||
defer expectPanic(t, "Param of SuchThat has to be a func with one return value, but is 2")
|
||||
constGen("sample").SuchThat(func(a string) (string, bool) {
|
||||
return "", false
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenSuchToInvalidReturns(t *testing.T) {
|
||||
defer expectPanic(t, "Param of SuchThat has to be a func with one return value of bool, but is string")
|
||||
constGen("sample").SuchThat(func(a string) string {
|
||||
return ""
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithShrinker(t *testing.T) {
|
||||
var shrinkerArg interface{}
|
||||
shrinker := func(v interface{}) gopter.Shrink {
|
||||
shrinkerArg = v
|
||||
return gopter.NoShrink
|
||||
}
|
||||
gen := constGen("sample").WithShrinker(shrinker)
|
||||
result := gen(gopter.DefaultGenParameters())
|
||||
value, ok := result.Retrieve()
|
||||
if !ok {
|
||||
t.Errorf("Invalid combined value: %#v", value)
|
||||
}
|
||||
result.Shrinker(value)
|
||||
if shrinkerArg != "sample" {
|
||||
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)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user