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