initial commit
commit
10e811e304
|
@ -0,0 +1,19 @@
|
|||
Copyright (c) 2015 Charles Iliya Krempeaux <charles@reptile.ca> :: http://changelog.ca/
|
||||
|
||||
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.
|
|
@ -0,0 +1,16 @@
|
|||
# go-arbitrary
|
||||
|
||||
**go-arbitrary** is a Go library which provides tools for generating arbitrary data.
|
||||
|
||||
## Example
|
||||
```
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
arb := arbitrary.New(src)
|
||||
|
||||
// Generate an arbitrary bool.
|
||||
// Might be false, might be true.
|
||||
bl := arb.Bool()
|
||||
|
||||
// Generate an arbitrary string.
|
||||
s := arb.String()
|
||||
```
|
|
@ -0,0 +1,19 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
import "math/rand"
|
||||
|
||||
|
||||
// A T is a source of arbitrary data.
|
||||
type T struct {
|
||||
randomness *rand.Rand
|
||||
}
|
||||
|
||||
|
||||
// New returns a new T.
|
||||
func New(src rand.Source) T {
|
||||
|
||||
randomness := rand.New(src)
|
||||
|
||||
return T{randomness: randomness}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
// Bool returns an arbitrary bool.
|
||||
func (arb T) Bool() bool {
|
||||
return 0 == arb.randomness.Intn(2)
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
import "testing"
|
||||
|
||||
import "math/rand"
|
||||
import "time"
|
||||
|
||||
|
||||
func TestBool(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen_false := false
|
||||
seen_true := false
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
bl := arb.Bool()
|
||||
|
||||
switch bl {
|
||||
case false:
|
||||
seen_false = true
|
||||
case true:
|
||||
seen_true = true
|
||||
}
|
||||
}
|
||||
|
||||
if !seen_false {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and did not see the value false.", limit)
|
||||
}
|
||||
if !seen_true {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and did not see the value true.", limit)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Package arbitrary provides tools for generating arbitrary data.
|
||||
|
||||
So that you can do things such as:
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
arb := arbitrary.New(src)
|
||||
|
||||
// Generate an arbitrary bool.
|
||||
// Might be false, might be true.
|
||||
bl := arb.Bool()
|
||||
|
||||
// Generate an arbitrary string.
|
||||
s := arb.String()
|
||||
*/
|
||||
package arbitrary
|
|
@ -0,0 +1,78 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
||||
// Runes returns an arbitrary []rune.
|
||||
//
|
||||
// Runes accepts either zero (0), one (1) or two (2) parameters. (These parameters
|
||||
// must be specific types and have specific and different meanings.)
|
||||
//
|
||||
// So you can call it like:
|
||||
//
|
||||
// rs1 := arb.Runes()
|
||||
//
|
||||
// rs2 := arb.Runes(10) // Returns an arbitrary []rune of length 10
|
||||
//
|
||||
// rs1 := arb.Runes(10, "ABCDEF0123456789") // Returns an arbitrary []rune of length 10,
|
||||
// // with characters drawn from "ABCDEF0123456789".
|
||||
//
|
||||
// rs1 := arb.Runes(10, []rune{'a', 'b', 'c'}) // Returns an arbitrary []rune of length 10,
|
||||
// // with characters drawn from []rune{'a', 'b', 'c'}.
|
||||
//
|
||||
func (arb T) Runes(args ...interface{}) []rune {
|
||||
|
||||
// For the arbitrary []rune, figure out (a) the number of runes to include and (b) which runes
|
||||
// to draw from.
|
||||
//
|
||||
// We store "the number of runes to include" in the variable "num_arbitrary_runes".
|
||||
// And we store "which runes to draw from" in the variable "runes".
|
||||
//
|
||||
// These have default values, but they can be overridden by parameters.
|
||||
var num_arbitrary_runes = 13
|
||||
var runes []rune = []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
switch length := len(args); length {
|
||||
case 2:
|
||||
switch t := args[1].(type) {
|
||||
case string:
|
||||
runes = []rune(t)
|
||||
case []rune:
|
||||
runes = t
|
||||
default:
|
||||
panic( fmt.Sprintf("Runes only accept a 2nd parameter to type string of type []rune. %T was passed.", args[0]) )
|
||||
}
|
||||
fallthrough
|
||||
case 1:
|
||||
switch t := args[0].(type) {
|
||||
case int:
|
||||
num_arbitrary_runes = t
|
||||
default:
|
||||
panic( fmt.Sprintf("Runes only accept a 1st parameter to type string of type int. %T was passed.", args[0]) )
|
||||
}
|
||||
case 0:
|
||||
// Nothing here.
|
||||
default:
|
||||
panic( fmt.Sprintf("Runes only accepts zero (0) or one (1) parameters. %d was passed.", length) )
|
||||
}
|
||||
|
||||
// Short circuit.
|
||||
//
|
||||
// If the "num_arbitrary_runes" is zero (0), then there is
|
||||
// no point executing the rest of the code.
|
||||
if 1 > num_arbitrary_runes {
|
||||
/////////////////////// RETURN
|
||||
return []rune{}
|
||||
}
|
||||
|
||||
// Construct the arbitrary []rune.
|
||||
arbitrary_runes := make([]rune, num_arbitrary_runes)
|
||||
|
||||
for i,_ := range arbitrary_runes {
|
||||
arbitrary_runes[i] = runes[arb.randomness.Intn(num_arbitrary_runes)]
|
||||
}
|
||||
|
||||
// Return.
|
||||
return arbitrary_runes
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
import "testing"
|
||||
|
||||
import "math/rand"
|
||||
import "strings"
|
||||
import "time"
|
||||
|
||||
|
||||
func TestRunes(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
rns := arb.Runes()
|
||||
|
||||
s := string(rns)
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunesWithStringLength(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
rns := arb.Runes(string_length)
|
||||
|
||||
if rns_length := len(rns) ; rns_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, rns_length, rns)
|
||||
}
|
||||
|
||||
s := string(rns)
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunesWithStringLengthAndStringToDrawFrom(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
draw_from := `!@#$%^&*()_+-={}[]|\:;"'<>,.?/`
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
rns := arb.Runes(string_length, draw_from)
|
||||
|
||||
if rns_length := len(rns) ; rns_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, rns_length, rns)
|
||||
}
|
||||
|
||||
for ii,r := range rns {
|
||||
if !strings.ContainsRune(draw_from, r) {
|
||||
t.Errorf("Rune #%d from arbitrary string contained rune %q but was only suppose to contain runes from %q. Arbitrary string was %q.", ii, string(r), draw_from, string(rns))
|
||||
}
|
||||
}
|
||||
|
||||
s := string(rns)
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunesWithStringLengthAndRunesToDrawFrom(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
draw_from := []rune(`!@#$%^&*()_+-={}[]|\:;"'<>,.?/`)
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
rns := arb.Runes(string_length, draw_from)
|
||||
|
||||
if rns_length := len(rns) ; rns_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, rns_length, rns)
|
||||
}
|
||||
|
||||
for ii,r := range rns {
|
||||
if !strings.ContainsRune(string(draw_from), r) {
|
||||
t.Errorf("Rune #%d from arbitrary string contained rune %q but was only suppose to contain runes from %q. Arbitrary string was %q.", ii, string(r), string(draw_from), string(rns))
|
||||
}
|
||||
}
|
||||
|
||||
s := string(rns)
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
// String returns an arbitrary string.
|
||||
//
|
||||
// String accepts either zero (0), one (1) or two (2) parameters.
|
||||
// So you can call it like:
|
||||
//
|
||||
// s1 := arb.String()
|
||||
//
|
||||
// s2 := arb.String(10) // Returns an arbitrary string of length 10
|
||||
//
|
||||
// s1 := arb.String(10, "ABCDEF0123456789") // Returns an arbitrary string of length 10,
|
||||
// // with characters drawn from "ABCDEF0123456789".
|
||||
//
|
||||
// s1 := arb.String(10, []rune{'a', 'b', 'c'}) // Returns an arbitrary string of length 10,
|
||||
// // with characters drawn from []rune{'a', 'b', 'c'}.
|
||||
//
|
||||
func (arb T) String(args ...interface{}) string {
|
||||
return string(arb.Runes(args...))
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package arbitrary
|
||||
|
||||
|
||||
import "testing"
|
||||
|
||||
import "math/rand"
|
||||
import "strings"
|
||||
import "time"
|
||||
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
s := arb.String()
|
||||
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringWithStringLength(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
s := arb.String(string_length)
|
||||
|
||||
if s_length := len(s) ; s_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, s_length, s)
|
||||
}
|
||||
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringWithStringLengthAndStringToDrawFrom(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
draw_from := `!@#$%^&*()_+-={}[]|\:;"'<>,.?/`
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
s := arb.String(string_length, draw_from)
|
||||
|
||||
if s_length := len(s) ; s_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, s_length, s)
|
||||
}
|
||||
|
||||
for ii,r := range []rune(s) {
|
||||
if !strings.ContainsRune(draw_from, r) {
|
||||
t.Errorf("Rune #%d from arbitrary string contained rune %q but was only suppose to contain runes from %q. Arbitrary string was %q.", ii, string(r), draw_from, s)
|
||||
}
|
||||
}
|
||||
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringWithStringLengthAndRunesToDrawFrom(t *testing.T) {
|
||||
|
||||
src := rand.NewSource( time.Now().UTC().UnixNano() )
|
||||
|
||||
string_length := 10 + rand.Intn(10)
|
||||
draw_from := []rune(`!@#$%^&*()_+-={}[]|\:;"'<>,.?/`)
|
||||
|
||||
arb := New(src)
|
||||
|
||||
seen := make(map[string]int)
|
||||
|
||||
const limit = 50
|
||||
for i:=0; i<limit; i++ {
|
||||
s := arb.String(string_length, draw_from)
|
||||
|
||||
if s_length := len(s) ; s_length != string_length {
|
||||
t.Errorf("Expected the length of the arbitrary string to be %d but it was actually %d. Arbitrary string was %q.", string_length, s_length, s)
|
||||
}
|
||||
|
||||
for ii,r := range []rune(s) {
|
||||
if !strings.ContainsRune(string(draw_from), r) {
|
||||
t.Errorf("Rune #%d from arbitrary string contained rune %q but was only suppose to contain runes from %q. Arbitrary string was %q.", ii, string(r), string(draw_from), s)
|
||||
}
|
||||
}
|
||||
|
||||
if _,ok := seen[s] ; !ok {
|
||||
seen[s] = 0
|
||||
} else {
|
||||
seen[s]++
|
||||
}
|
||||
}
|
||||
|
||||
if length := len(seen) ; length != limit {
|
||||
t.Errorf("It is possible that there is nothing wrong with this test, but it just ran %d times and saw repeats such that only saw %d uniques.", limit, length)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue