Vendor cleanup

Signed-off-by: Madhu Rajanna <mrajanna@redhat.com>
This commit is contained in:
Madhu Rajanna
2019-01-16 18:11:54 +05:30
parent 661818bd79
commit 0f836c62fa
16816 changed files with 20 additions and 4611100 deletions

View File

@ -1 +0,0 @@
language: go

View File

@ -1,12 +0,0 @@
# BTree implementation for Go
![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master)
This package provides an in-memory B-Tree implementation for Go, useful as
an ordered, mutable data structure.
The API is based off of the wonderful
http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to
act as a drop-in replacement for gollrb trees.
See http://godoc.org/github.com/google/btree for documentation.

View File

@ -1,785 +0,0 @@
// Copyright 2014 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package btree
import (
"flag"
"fmt"
"math/rand"
"reflect"
"sort"
"sync"
"testing"
"time"
)
func init() {
seed := time.Now().Unix()
fmt.Println(seed)
rand.Seed(seed)
}
// perm returns a random permutation of n Int items in the range [0, n).
func perm(n int) (out []Item) {
for _, v := range rand.Perm(n) {
out = append(out, Int(v))
}
return
}
// rang returns an ordered list of Int items in the range [0, n).
func rang(n int) (out []Item) {
for i := 0; i < n; i++ {
out = append(out, Int(i))
}
return
}
// all extracts all items from a tree in order as a slice.
func all(t *BTree) (out []Item) {
t.Ascend(func(a Item) bool {
out = append(out, a)
return true
})
return
}
// rangerev returns a reversed ordered list of Int items in the range [0, n).
func rangrev(n int) (out []Item) {
for i := n - 1; i >= 0; i-- {
out = append(out, Int(i))
}
return
}
// allrev extracts all items from a tree in reverse order as a slice.
func allrev(t *BTree) (out []Item) {
t.Descend(func(a Item) bool {
out = append(out, a)
return true
})
return
}
var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
func TestBTree(t *testing.T) {
tr := New(*btreeDegree)
const treeSize = 10000
for i := 0; i < 10; i++ {
if min := tr.Min(); min != nil {
t.Fatalf("empty min, got %+v", min)
}
if max := tr.Max(); max != nil {
t.Fatalf("empty max, got %+v", max)
}
for _, item := range perm(treeSize) {
if x := tr.ReplaceOrInsert(item); x != nil {
t.Fatal("insert found item", item)
}
}
for _, item := range perm(treeSize) {
if x := tr.ReplaceOrInsert(item); x == nil {
t.Fatal("insert didn't find item", item)
}
}
if min, want := tr.Min(), Item(Int(0)); min != want {
t.Fatalf("min: want %+v, got %+v", want, min)
}
if max, want := tr.Max(), Item(Int(treeSize-1)); max != want {
t.Fatalf("max: want %+v, got %+v", want, max)
}
got := all(tr)
want := rang(treeSize)
if !reflect.DeepEqual(got, want) {
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
}
gotrev := allrev(tr)
wantrev := rangrev(treeSize)
if !reflect.DeepEqual(gotrev, wantrev) {
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
}
for _, item := range perm(treeSize) {
if x := tr.Delete(item); x == nil {
t.Fatalf("didn't find %v", item)
}
}
if got = all(tr); len(got) > 0 {
t.Fatalf("some left!: %v", got)
}
}
}
func ExampleBTree() {
tr := New(*btreeDegree)
for i := Int(0); i < 10; i++ {
tr.ReplaceOrInsert(i)
}
fmt.Println("len: ", tr.Len())
fmt.Println("get3: ", tr.Get(Int(3)))
fmt.Println("get100: ", tr.Get(Int(100)))
fmt.Println("del4: ", tr.Delete(Int(4)))
fmt.Println("del100: ", tr.Delete(Int(100)))
fmt.Println("replace5: ", tr.ReplaceOrInsert(Int(5)))
fmt.Println("replace100:", tr.ReplaceOrInsert(Int(100)))
fmt.Println("min: ", tr.Min())
fmt.Println("delmin: ", tr.DeleteMin())
fmt.Println("max: ", tr.Max())
fmt.Println("delmax: ", tr.DeleteMax())
fmt.Println("len: ", tr.Len())
// Output:
// len: 10
// get3: 3
// get100: <nil>
// del4: 4
// del100: <nil>
// replace5: 5
// replace100: <nil>
// min: 0
// delmin: 0
// max: 100
// delmax: 100
// len: 8
}
func TestDeleteMin(t *testing.T) {
tr := New(3)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
for v := tr.DeleteMin(); v != nil; v = tr.DeleteMin() {
got = append(got, v)
}
if want := rang(100); !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestDeleteMax(t *testing.T) {
tr := New(3)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
for v := tr.DeleteMax(); v != nil; v = tr.DeleteMax() {
got = append(got, v)
}
// Reverse our list.
for i := 0; i < len(got)/2; i++ {
got[i], got[len(got)-i-1] = got[len(got)-i-1], got[i]
}
if want := rang(100); !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestAscendRange(t *testing.T) {
tr := New(2)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
got = append(got, a)
return true
})
if want := rang(100)[40:60]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
if a.(Int) > 50 {
return false
}
got = append(got, a)
return true
})
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestDescendRange(t *testing.T) {
tr := New(2)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestAscendLessThan(t *testing.T) {
tr := New(*btreeDegree)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.AscendLessThan(Int(60), func(a Item) bool {
got = append(got, a)
return true
})
if want := rang(100)[:60]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.AscendLessThan(Int(60), func(a Item) bool {
if a.(Int) > 50 {
return false
}
got = append(got, a)
return true
})
if want := rang(100)[:51]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestDescendLessOrEqual(t *testing.T) {
tr := New(*btreeDegree)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendLessOrEqual(Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendLessOrEqual(Int(60), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
}
}
func TestAscendGreaterOrEqual(t *testing.T) {
tr := New(*btreeDegree)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rang(100)[40:]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
if a.(Int) > 50 {
return false
}
got = append(got, a)
return true
})
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestDescendGreaterThan(t *testing.T) {
tr := New(*btreeDegree)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendGreaterThan(Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendGreaterThan(Int(40), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
}
}
const benchmarkTreeSize = 10000
func BenchmarkInsert(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
b.StartTimer()
i := 0
for i < b.N {
tr := New(*btreeDegree)
for _, item := range insertP {
tr.ReplaceOrInsert(item)
i++
if i >= b.N {
return
}
}
}
}
func BenchmarkSeek(b *testing.B) {
b.StopTimer()
size := 100000
insertP := perm(size)
tr := New(*btreeDegree)
for _, item := range insertP {
tr.ReplaceOrInsert(item)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
tr.AscendGreaterOrEqual(Int(i%size), func(i Item) bool { return false })
}
}
func BenchmarkDeleteInsert(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, item := range insertP {
tr.ReplaceOrInsert(item)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
tr.Delete(insertP[i%benchmarkTreeSize])
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
}
}
func BenchmarkDeleteInsertCloneOnce(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, item := range insertP {
tr.ReplaceOrInsert(item)
}
tr = tr.Clone()
b.StartTimer()
for i := 0; i < b.N; i++ {
tr.Delete(insertP[i%benchmarkTreeSize])
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
}
}
func BenchmarkDeleteInsertCloneEachTime(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, item := range insertP {
tr.ReplaceOrInsert(item)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
tr = tr.Clone()
tr.Delete(insertP[i%benchmarkTreeSize])
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
}
}
func BenchmarkDelete(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
removeP := perm(benchmarkTreeSize)
b.StartTimer()
i := 0
for i < b.N {
b.StopTimer()
tr := New(*btreeDegree)
for _, v := range insertP {
tr.ReplaceOrInsert(v)
}
b.StartTimer()
for _, item := range removeP {
tr.Delete(item)
i++
if i >= b.N {
return
}
}
if tr.Len() > 0 {
panic(tr.Len())
}
}
}
func BenchmarkGet(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
removeP := perm(benchmarkTreeSize)
b.StartTimer()
i := 0
for i < b.N {
b.StopTimer()
tr := New(*btreeDegree)
for _, v := range insertP {
tr.ReplaceOrInsert(v)
}
b.StartTimer()
for _, item := range removeP {
tr.Get(item)
i++
if i >= b.N {
return
}
}
}
}
func BenchmarkGetCloneEachTime(b *testing.B) {
b.StopTimer()
insertP := perm(benchmarkTreeSize)
removeP := perm(benchmarkTreeSize)
b.StartTimer()
i := 0
for i < b.N {
b.StopTimer()
tr := New(*btreeDegree)
for _, v := range insertP {
tr.ReplaceOrInsert(v)
}
b.StartTimer()
for _, item := range removeP {
tr = tr.Clone()
tr.Get(item)
i++
if i >= b.N {
return
}
}
}
}
type byInts []Item
func (a byInts) Len() int {
return len(a)
}
func (a byInts) Less(i, j int) bool {
return a[i].(Int) < a[j].(Int)
}
func (a byInts) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func BenchmarkAscend(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := 0
tr.Ascend(func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j++
return true
})
}
}
func BenchmarkDescend(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := len(arr) - 1
tr.Descend(func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j--
return true
})
}
}
func BenchmarkAscendRange(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := 100
tr.AscendRange(Int(100), arr[len(arr)-100], func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j++
return true
})
if j != len(arr)-100 {
b.Fatalf("expected: %v, got %v", len(arr)-100, j)
}
}
}
func BenchmarkDescendRange(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := len(arr) - 100
tr.DescendRange(arr[len(arr)-100], Int(100), func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j--
return true
})
if j != 100 {
b.Fatalf("expected: %v, got %v", len(arr)-100, j)
}
}
}
func BenchmarkAscendGreaterOrEqual(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := 100
k := 0
tr.AscendGreaterOrEqual(Int(100), func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j++
k++
return true
})
if j != len(arr) {
b.Fatalf("expected: %v, got %v", len(arr), j)
}
if k != len(arr)-100 {
b.Fatalf("expected: %v, got %v", len(arr)-100, k)
}
}
}
func BenchmarkDescendLessOrEqual(b *testing.B) {
arr := perm(benchmarkTreeSize)
tr := New(*btreeDegree)
for _, v := range arr {
tr.ReplaceOrInsert(v)
}
sort.Sort(byInts(arr))
b.ResetTimer()
for i := 0; i < b.N; i++ {
j := len(arr) - 100
k := len(arr)
tr.DescendLessOrEqual(arr[len(arr)-100], func(item Item) bool {
if item.(Int) != arr[j].(Int) {
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
}
j--
k--
return true
})
if j != -1 {
b.Fatalf("expected: %v, got %v", -1, j)
}
if k != 99 {
b.Fatalf("expected: %v, got %v", 99, k)
}
}
}
const cloneTestSize = 10000
func cloneTest(t *testing.T, b *BTree, start int, p []Item, wg *sync.WaitGroup, trees *[]*BTree) {
t.Logf("Starting new clone at %v", start)
*trees = append(*trees, b)
for i := start; i < cloneTestSize; i++ {
b.ReplaceOrInsert(p[i])
if i%(cloneTestSize/5) == 0 {
wg.Add(1)
go cloneTest(t, b.Clone(), i+1, p, wg, trees)
}
}
wg.Done()
}
func TestCloneConcurrentOperations(t *testing.T) {
b := New(*btreeDegree)
trees := []*BTree{}
p := perm(cloneTestSize)
var wg sync.WaitGroup
wg.Add(1)
go cloneTest(t, b, 0, p, &wg, &trees)
wg.Wait()
want := rang(cloneTestSize)
t.Logf("Starting equality checks on %d trees", len(trees))
for i, tree := range trees {
if !reflect.DeepEqual(want, all(tree)) {
t.Errorf("tree %v mismatch", i)
}
}
t.Log("Removing half from first half")
toRemove := rang(cloneTestSize)[cloneTestSize/2:]
for i := 0; i < len(trees)/2; i++ {
tree := trees[i]
wg.Add(1)
go func() {
for _, item := range toRemove {
tree.Delete(item)
}
wg.Done()
}()
}
wg.Wait()
t.Log("Checking all values again")
for i, tree := range trees {
var wantpart []Item
if i < len(trees)/2 {
wantpart = want[:cloneTestSize/2]
} else {
wantpart = want
}
if got := all(tree); !reflect.DeepEqual(wantpart, got) {
t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
}
}
}
func BenchmarkDeleteAndRestore(b *testing.B) {
items := perm(16392)
b.ResetTimer()
b.Run(`CopyBigFreeList`, func(b *testing.B) {
fl := NewFreeList(16392)
tr := NewWithFreeList(*btreeDegree, fl)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
dels := make([]Item, 0, tr.Len())
tr.Ascend(ItemIterator(func(b Item) bool {
dels = append(dels, b)
return true
}))
for _, del := range dels {
tr.Delete(del)
}
// tr is now empty, we make a new empty copy of it.
tr = NewWithFreeList(*btreeDegree, fl)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
}
})
b.Run(`Copy`, func(b *testing.B) {
tr := New(*btreeDegree)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
dels := make([]Item, 0, tr.Len())
tr.Ascend(ItemIterator(func(b Item) bool {
dels = append(dels, b)
return true
}))
for _, del := range dels {
tr.Delete(del)
}
// tr is now empty, we make a new empty copy of it.
tr = New(*btreeDegree)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
}
})
b.Run(`ClearBigFreelist`, func(b *testing.B) {
fl := NewFreeList(16392)
tr := NewWithFreeList(*btreeDegree, fl)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
tr.Clear(true)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
}
})
b.Run(`Clear`, func(b *testing.B) {
tr := New(*btreeDegree)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
tr.Clear(true)
for _, v := range items {
tr.ReplaceOrInsert(v)
}
}
})
}

View File

@ -1,13 +0,0 @@
language: go
go:
- 1.4
- 1.3
- 1.2
- tip
install:
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
script:
- go test -cover

View File

@ -1,67 +0,0 @@
# How to contribute #
We'd love to accept your patches and contributions to this project. There are
a just a few small guidelines you need to follow.
## Contributor License Agreement ##
Contributions to any Google project must be accompanied by a Contributor
License Agreement. This is not a copyright **assignment**, it simply gives
Google permission to use and redistribute your contributions as part of the
project.
* If you are an individual writing original source code and you're sure you
own the intellectual property, then you'll need to sign an [individual
CLA][].
* If you work for a company that wants to allow you to contribute your work,
then you'll need to sign a [corporate CLA][].
You generally only need to submit a CLA once, so if you've already submitted
one (even if it was for a different project), you probably don't need to do it
again.
[individual CLA]: https://developers.google.com/open-source/cla/individual
[corporate CLA]: https://developers.google.com/open-source/cla/corporate
## Submitting a patch ##
1. It's generally best to start by opening a new issue describing the bug or
feature you're intending to fix. Even if you think it's relatively minor,
it's helpful to know what people are working on. Mention in the initial
issue that you are planning to work on that bug or feature so that it can
be assigned to you.
1. Follow the normal process of [forking][] the project, and setup a new
branch to work in. It's important that each group of changes be done in
separate branches in order to ensure that a pull request only includes the
commits related to that bug or feature.
1. Go makes it very simple to ensure properly formatted code, so always run
`go fmt` on your code before committing it. You should also run
[golint][] over your code. As noted in the [golint readme][], it's not
strictly necessary that your code be completely "lint-free", but this will
help you find common style issues.
1. Any significant changes should almost always be accompanied by tests. The
project already has good test coverage, so look at some of the existing
tests if you're unsure how to go about it. [gocov][] and [gocov-html][]
are invaluable tools for seeing which parts of your code aren't being
exercised by your tests.
1. Do your best to have [well-formed commit messages][] for each change.
This provides consistency throughout the project, and ensures that commit
messages are able to be formatted properly by various git tools.
1. Finally, push the commits to your fork and submit a [pull request][].
[forking]: https://help.github.com/articles/fork-a-repo
[golint]: https://github.com/golang/lint
[golint readme]: https://github.com/golang/lint/blob/master/README
[gocov]: https://github.com/axw/gocov
[gocov-html]: https://github.com/matm/gocov-html
[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
[squash]: http://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
[pull request]: https://help.github.com/articles/creating-a-pull-request

View File

@ -1,71 +0,0 @@
gofuzz
======
gofuzz is a library for populating go objects with random values.
[![GoDoc](https://godoc.org/github.com/google/gofuzz?status.png)](https://godoc.org/github.com/google/gofuzz)
[![Travis](https://travis-ci.org/google/gofuzz.svg?branch=master)](https://travis-ci.org/google/gofuzz)
This is useful for testing:
* Do your project's objects really serialize/unserialize correctly in all cases?
* Is there an incorrectly formatted object that will cause your project to panic?
Import with ```import "github.com/google/gofuzz"```
You can use it on single variables:
```go
f := fuzz.New()
var myInt int
f.Fuzz(&myInt) // myInt gets a random value.
```
You can use it on maps:
```go
f := fuzz.New().NilChance(0).NumElements(1, 1)
var myMap map[ComplexKeyType]string
f.Fuzz(&myMap) // myMap will have exactly one element.
```
Customize the chance of getting a nil pointer:
```go
f := fuzz.New().NilChance(.5)
var fancyStruct struct {
A, B, C, D *string
}
f.Fuzz(&fancyStruct) // About half the pointers should be set.
```
You can even customize the randomization completely if needed:
```go
type MyEnum string
const (
A MyEnum = "A"
B MyEnum = "B"
)
type MyInfo struct {
Type MyEnum
AInfo *string
BInfo *string
}
f := fuzz.New().NilChance(0).Funcs(
func(e *MyInfo, c fuzz.Continue) {
switch c.Intn(2) {
case 0:
e.Type = A
c.Fuzz(&e.AInfo)
case 1:
e.Type = B
c.Fuzz(&e.BInfo)
}
},
)
var myObject MyInfo
f.Fuzz(&myObject) // Type will correspond to whether A or B info is set.
```
See more examples in ```example_test.go```.
Happy testing!

View File

@ -1,225 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzz_test
import (
"encoding/json"
"fmt"
"math/rand"
"github.com/google/gofuzz"
)
func ExampleSimple() {
type MyType struct {
A string
B string
C int
D struct {
E float64
}
}
f := fuzz.New()
object := MyType{}
uniqueObjects := map[MyType]int{}
for i := 0; i < 1000; i++ {
f.Fuzz(&object)
uniqueObjects[object]++
}
fmt.Printf("Got %v unique objects.\n", len(uniqueObjects))
// Output:
// Got 1000 unique objects.
}
func ExampleCustom() {
type MyType struct {
A int
B string
}
counter := 0
f := fuzz.New().Funcs(
func(i *int, c fuzz.Continue) {
*i = counter
counter++
},
)
object := MyType{}
uniqueObjects := map[MyType]int{}
for i := 0; i < 100; i++ {
f.Fuzz(&object)
if object.A != i {
fmt.Printf("Unexpected value: %#v\n", object)
}
uniqueObjects[object]++
}
fmt.Printf("Got %v unique objects.\n", len(uniqueObjects))
// Output:
// Got 100 unique objects.
}
func ExampleComplex() {
type OtherType struct {
A string
B string
}
type MyType struct {
Pointer *OtherType
Map map[string]OtherType
PointerMap *map[string]OtherType
Slice []OtherType
SlicePointer []*OtherType
PointerSlicePointer *[]*OtherType
}
f := fuzz.New().RandSource(rand.NewSource(0)).NilChance(0).NumElements(1, 1).Funcs(
func(o *OtherType, c fuzz.Continue) {
o.A = "Foo"
o.B = "Bar"
},
func(op **OtherType, c fuzz.Continue) {
*op = &OtherType{"A", "B"}
},
func(m map[string]OtherType, c fuzz.Continue) {
m["Works Because"] = OtherType{
"Fuzzer",
"Preallocated",
}
},
)
object := MyType{}
f.Fuzz(&object)
bytes, err := json.MarshalIndent(&object, "", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
fmt.Printf("%s\n", string(bytes))
// Output:
// {
// "Pointer": {
// "A": "A",
// "B": "B"
// },
// "Map": {
// "Works Because": {
// "A": "Fuzzer",
// "B": "Preallocated"
// }
// },
// "PointerMap": {
// "Works Because": {
// "A": "Fuzzer",
// "B": "Preallocated"
// }
// },
// "Slice": [
// {
// "A": "Foo",
// "B": "Bar"
// }
// ],
// "SlicePointer": [
// {
// "A": "A",
// "B": "B"
// }
// ],
// "PointerSlicePointer": [
// {
// "A": "A",
// "B": "B"
// }
// ]
// }
}
func ExampleMap() {
f := fuzz.New().NilChance(0).NumElements(1, 1)
var myMap map[struct{ A, B, C int }]string
f.Fuzz(&myMap)
fmt.Printf("myMap has %v element(s).\n", len(myMap))
// Output:
// myMap has 1 element(s).
}
func ExampleSingle() {
f := fuzz.New()
var i int
f.Fuzz(&i)
// Technically, we'd expect this to fail one out of 2 billion attempts...
fmt.Printf("(i == 0) == %v", i == 0)
// Output:
// (i == 0) == false
}
func ExampleEnum() {
type MyEnum string
const (
A MyEnum = "A"
B MyEnum = "B"
)
type MyInfo struct {
Type MyEnum
AInfo *string
BInfo *string
}
f := fuzz.New().NilChance(0).Funcs(
func(e *MyInfo, c fuzz.Continue) {
// Note c's embedded Rand allows for direct use.
// We could also use c.RandBool() here.
switch c.Intn(2) {
case 0:
e.Type = A
c.Fuzz(&e.AInfo)
case 1:
e.Type = B
c.Fuzz(&e.BInfo)
}
},
)
for i := 0; i < 100; i++ {
var myObject MyInfo
f.Fuzz(&myObject)
switch myObject.Type {
case A:
if myObject.AInfo == nil {
fmt.Println("AInfo should have been set!")
}
if myObject.BInfo != nil {
fmt.Println("BInfo should NOT have been set!")
}
case B:
if myObject.BInfo == nil {
fmt.Println("BInfo should have been set!")
}
if myObject.AInfo != nil {
fmt.Println("AInfo should NOT have been set!")
}
default:
fmt.Println("Invalid enum value!")
}
}
// Output:
}

View File

@ -1,472 +0,0 @@
/*
Copyright 2014 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzz
import (
"reflect"
"testing"
"time"
)
func TestFuzz_basic(t *testing.T) {
obj := &struct {
I int
I8 int8
I16 int16
I32 int32
I64 int64
U uint
U8 uint8
U16 uint16
U32 uint32
U64 uint64
Uptr uintptr
S string
B bool
T time.Time
}{}
failed := map[string]int{}
for i := 0; i < 10; i++ {
New().Fuzz(obj)
if n, v := "i", obj.I; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "i8", obj.I8; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "i16", obj.I16; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "i32", obj.I32; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "i64", obj.I64; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "u", obj.U; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "u8", obj.U8; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "u16", obj.U16; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "u32", obj.U32; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "u64", obj.U64; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "uptr", obj.Uptr; v == 0 {
failed[n] = failed[n] + 1
}
if n, v := "s", obj.S; v == "" {
failed[n] = failed[n] + 1
}
if n, v := "b", obj.B; v == false {
failed[n] = failed[n] + 1
}
if n, v := "t", obj.T; v.IsZero() {
failed[n] = failed[n] + 1
}
}
checkFailed(t, failed)
}
func checkFailed(t *testing.T, failed map[string]int) {
for k, v := range failed {
if v > 8 {
t.Errorf("%v seems to not be getting set, was zero value %v times", k, v)
}
}
}
func TestFuzz_structptr(t *testing.T) {
obj := &struct {
A *struct {
S string
}
}{}
f := New().NilChance(.5)
failed := map[string]int{}
for i := 0; i < 10; i++ {
f.Fuzz(obj)
if n, v := "a not nil", obj.A; v == nil {
failed[n] = failed[n] + 1
}
if n, v := "a nil", obj.A; v != nil {
failed[n] = failed[n] + 1
}
if n, v := "as", obj.A; v == nil || v.S == "" {
failed[n] = failed[n] + 1
}
}
checkFailed(t, failed)
}
// tryFuzz tries fuzzing up to 20 times. Fail if check() never passes, report the highest
// stage it ever got to.
func tryFuzz(t *testing.T, f *Fuzzer, obj interface{}, check func() (stage int, passed bool)) {
maxStage := 0
for i := 0; i < 20; i++ {
f.Fuzz(obj)
stage, passed := check()
if stage > maxStage {
maxStage = stage
}
if passed {
return
}
}
t.Errorf("Only ever got to stage %v", maxStage)
}
func TestFuzz_structmap(t *testing.T) {
obj := &struct {
A map[struct {
S string
}]struct {
S2 string
}
B map[string]string
}{}
tryFuzz(t, New(), obj, func() (int, bool) {
if obj.A == nil {
return 1, false
}
if len(obj.A) == 0 {
return 2, false
}
for k, v := range obj.A {
if k.S == "" {
return 3, false
}
if v.S2 == "" {
return 4, false
}
}
if obj.B == nil {
return 5, false
}
if len(obj.B) == 0 {
return 6, false
}
for k, v := range obj.B {
if k == "" {
return 7, false
}
if v == "" {
return 8, false
}
}
return 9, true
})
}
func TestFuzz_structslice(t *testing.T) {
obj := &struct {
A []struct {
S string
}
B []string
}{}
tryFuzz(t, New(), obj, func() (int, bool) {
if obj.A == nil {
return 1, false
}
if len(obj.A) == 0 {
return 2, false
}
for _, v := range obj.A {
if v.S == "" {
return 3, false
}
}
if obj.B == nil {
return 4, false
}
if len(obj.B) == 0 {
return 5, false
}
for _, v := range obj.B {
if v == "" {
return 6, false
}
}
return 7, true
})
}
func TestFuzz_structarray(t *testing.T) {
obj := &struct {
A [3]struct {
S string
}
B [2]int
}{}
tryFuzz(t, New(), obj, func() (int, bool) {
for _, v := range obj.A {
if v.S == "" {
return 1, false
}
}
for _, v := range obj.B {
if v == 0 {
return 2, false
}
}
return 3, true
})
}
func TestFuzz_custom(t *testing.T) {
obj := &struct {
A string
B *string
C map[string]string
D *map[string]string
}{}
testPhrase := "gotcalled"
testMap := map[string]string{"C": "D"}
f := New().Funcs(
func(s *string, c Continue) {
*s = testPhrase
},
func(m map[string]string, c Continue) {
m["C"] = "D"
},
)
tryFuzz(t, f, obj, func() (int, bool) {
if obj.A != testPhrase {
return 1, false
}
if obj.B == nil {
return 2, false
}
if *obj.B != testPhrase {
return 3, false
}
if e, a := testMap, obj.C; !reflect.DeepEqual(e, a) {
return 4, false
}
if obj.D == nil {
return 5, false
}
if e, a := testMap, *obj.D; !reflect.DeepEqual(e, a) {
return 6, false
}
return 7, true
})
}
type SelfFuzzer string
// Implement fuzz.Interface.
func (sf *SelfFuzzer) Fuzz(c Continue) {
*sf = selfFuzzerTestPhrase
}
const selfFuzzerTestPhrase = "was fuzzed"
func TestFuzz_interface(t *testing.T) {
f := New()
var obj1 SelfFuzzer
tryFuzz(t, f, &obj1, func() (int, bool) {
if obj1 != selfFuzzerTestPhrase {
return 1, false
}
return 1, true
})
var obj2 map[int]SelfFuzzer
tryFuzz(t, f, &obj2, func() (int, bool) {
for _, v := range obj2 {
if v != selfFuzzerTestPhrase {
return 1, false
}
}
return 1, true
})
}
func TestFuzz_interfaceAndFunc(t *testing.T) {
const privateTestPhrase = "private phrase"
f := New().Funcs(
// This should take precedence over SelfFuzzer.Fuzz().
func(s *SelfFuzzer, c Continue) {
*s = privateTestPhrase
},
)
var obj1 SelfFuzzer
tryFuzz(t, f, &obj1, func() (int, bool) {
if obj1 != privateTestPhrase {
return 1, false
}
return 1, true
})
var obj2 map[int]SelfFuzzer
tryFuzz(t, f, &obj2, func() (int, bool) {
for _, v := range obj2 {
if v != privateTestPhrase {
return 1, false
}
}
return 1, true
})
}
func TestFuzz_noCustom(t *testing.T) {
type Inner struct {
Str string
}
type Outer struct {
Str string
In Inner
}
testPhrase := "gotcalled"
f := New().Funcs(
func(outer *Outer, c Continue) {
outer.Str = testPhrase
c.Fuzz(&outer.In)
},
func(inner *Inner, c Continue) {
inner.Str = testPhrase
},
)
c := Continue{fc: &fuzzerContext{fuzzer: f}, Rand: f.r}
// Fuzzer.Fuzz()
obj1 := Outer{}
f.Fuzz(&obj1)
if obj1.Str != testPhrase {
t.Errorf("expected Outer custom function to have been called")
}
if obj1.In.Str != testPhrase {
t.Errorf("expected Inner custom function to have been called")
}
// Continue.Fuzz()
obj2 := Outer{}
c.Fuzz(&obj2)
if obj2.Str != testPhrase {
t.Errorf("expected Outer custom function to have been called")
}
if obj2.In.Str != testPhrase {
t.Errorf("expected Inner custom function to have been called")
}
// Fuzzer.FuzzNoCustom()
obj3 := Outer{}
f.FuzzNoCustom(&obj3)
if obj3.Str == testPhrase {
t.Errorf("expected Outer custom function to not have been called")
}
if obj3.In.Str != testPhrase {
t.Errorf("expected Inner custom function to have been called")
}
// Continue.FuzzNoCustom()
obj4 := Outer{}
c.FuzzNoCustom(&obj4)
if obj4.Str == testPhrase {
t.Errorf("expected Outer custom function to not have been called")
}
if obj4.In.Str != testPhrase {
t.Errorf("expected Inner custom function to have been called")
}
}
func TestFuzz_NumElements(t *testing.T) {
f := New().NilChance(0).NumElements(0, 1)
obj := &struct {
A []int
}{}
tryFuzz(t, f, obj, func() (int, bool) {
if obj.A == nil {
return 1, false
}
return 2, len(obj.A) == 0
})
tryFuzz(t, f, obj, func() (int, bool) {
if obj.A == nil {
return 3, false
}
return 4, len(obj.A) == 1
})
}
func TestFuzz_Maxdepth(t *testing.T) {
type S struct {
S *S
}
f := New().NilChance(0)
f.MaxDepth(1)
for i := 0; i < 100; i++ {
obj := S{}
f.Fuzz(&obj)
if obj.S != nil {
t.Errorf("Expected nil")
}
}
f.MaxDepth(3) // field, ptr
for i := 0; i < 100; i++ {
obj := S{}
f.Fuzz(&obj)
if obj.S == nil {
t.Errorf("Expected obj.S not nil")
} else if obj.S.S != nil {
t.Errorf("Expected obj.S.S nil")
}
}
f.MaxDepth(5) // field, ptr, field, ptr
for i := 0; i < 100; i++ {
obj := S{}
f.Fuzz(&obj)
if obj.S == nil {
t.Errorf("Expected obj.S not nil")
} else if obj.S.S == nil {
t.Errorf("Expected obj.S.S not nil")
} else if obj.S.S.S != nil {
t.Errorf("Expected obj.S.S.S nil")
}
}
}

View File

@ -1,9 +0,0 @@
language: go
go:
- 1.4.3
- 1.5.3
- tip
script:
- go test -v ./...

View File

@ -1,10 +0,0 @@
# How to contribute
We definitely welcome patches and contribution to this project!
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
You may have already signed it for other Google projects.

View File

@ -1,19 +0,0 @@
# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on
[RFC 4122](http://tools.ietf.org/html/rfc4122)
and DCE 1.1: Authentication and Security Services.
This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid). It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice. One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).
###### Install
`go get github.com/google/uuid`
###### Documentation
[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid)
Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
http://godoc.org/github.com/google/uuid

View File

@ -1 +0,0 @@
module github.com/google/uuid

View File

@ -1,62 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/json"
"reflect"
"testing"
)
var testUUID = Must(Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479"))
func TestJSON(t *testing.T) {
type S struct {
ID1 UUID
ID2 UUID
}
s1 := S{ID1: testUUID}
data, err := json.Marshal(&s1)
if err != nil {
t.Fatal(err)
}
var s2 S
if err := json.Unmarshal(data, &s2); err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(&s1, &s2) {
t.Errorf("got %#v, want %#v", s2, s1)
}
}
func BenchmarkUUID_MarshalJSON(b *testing.B) {
x := &struct {
UUID UUID `json:"uuid"`
}{}
var err error
x.UUID, err = Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
js, err := json.Marshal(x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}
func BenchmarkUUID_UnmarshalJSON(b *testing.B) {
js := []byte(`{"uuid":"f47ac10b-58cc-0372-8567-0e02b2c3d479"}`)
var x *struct {
UUID UUID `json:"uuid"`
}
for i := 0; i < b.N; i++ {
err := json.Unmarshal(js, &x)
if err != nil {
b.Fatalf("marshal json: %#v (%v)", js, err)
}
}
}

View File

@ -1,66 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"flag"
"runtime"
"testing"
"time"
)
// This test is only run when --regressions is passed on the go test line.
var regressions = flag.Bool("regressions", false, "run uuid regression tests")
// TestClockSeqRace tests for a particular race condition of returning two
// identical Version1 UUIDs. The duration of 1 minute was chosen as the race
// condition, before being fixed, nearly always occurred in under 30 seconds.
func TestClockSeqRace(t *testing.T) {
if !*regressions {
t.Skip("skipping regression tests")
}
duration := time.Minute
done := make(chan struct{})
defer close(done)
ch := make(chan UUID, 10000)
ncpu := runtime.NumCPU()
switch ncpu {
case 0, 1:
// We can't run the test effectively.
t.Skip("skipping race test, only one CPU detected")
return
default:
runtime.GOMAXPROCS(ncpu)
}
for i := 0; i < ncpu; i++ {
go func() {
for {
select {
case <-done:
return
case ch <- Must(NewUUID()):
}
}
}()
}
uuids := make(map[string]bool)
cnt := 0
start := time.Now()
for u := range ch {
s := u.String()
if uuids[s] {
t.Errorf("duplicate uuid after %d in %v: %s", cnt, time.Since(start), s)
return
}
uuids[s] = true
if time.Since(start) > duration {
return
}
cnt++
}
}

View File

@ -1,113 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"strings"
"testing"
)
func TestScan(t *testing.T) {
stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479"
badTypeTest := 6
invalidTest := "f47ac10b-58cc-0372-8567-0e02b2c3d4"
byteTest := make([]byte, 16)
byteTestUUID := Must(Parse(stringTest))
copy(byteTest, byteTestUUID[:])
// sunny day tests
var uuid UUID
err := (&uuid).Scan(stringTest)
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan([]byte(stringTest))
if err != nil {
t.Fatal(err)
}
err = (&uuid).Scan(byteTest)
if err != nil {
t.Fatal(err)
}
// bad type tests
err = (&uuid).Scan(badTypeTest)
if err == nil {
t.Error("int correctly parsed and shouldn't have")
}
if !strings.Contains(err.Error(), "unable to scan type") {
t.Error("attempting to parse an int returned an incorrect error message")
}
// invalid/incomplete uuids
err = (&uuid).Scan(invalidTest)
if err == nil {
t.Error("invalid uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid UUID returned an incorrect error message")
}
err = (&uuid).Scan(byteTest[:len(byteTest)-2])
if err == nil {
t.Error("invalid byte uuid was parsed without error")
}
if !strings.Contains(err.Error(), "invalid UUID") {
t.Error("attempting to parse an invalid byte UUID returned an incorrect error message")
}
// empty tests
uuid = UUID{}
var emptySlice []byte
err = (&uuid).Scan(emptySlice)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning empty byte slice")
}
}
uuid = UUID{}
var emptyString string
err = (&uuid).Scan(emptyString)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning empty byte slice")
}
}
uuid = UUID{}
err = (&uuid).Scan(nil)
if err != nil {
t.Fatal(err)
}
for _, v := range uuid {
if v != 0 {
t.Error("UUID was not nil after scanning nil")
}
}
}
func TestValue(t *testing.T) {
stringTest := "f47ac10b-58cc-0372-8567-0e02b2c3d479"
uuid := Must(Parse(stringTest))
val, _ := uuid.Value()
if val != stringTest {
t.Error("Value() did not return expected string")
}
}

View File

@ -1,559 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"fmt"
"os"
"runtime"
"strings"
"testing"
"time"
"unsafe"
)
type test struct {
in string
version Version
variant Variant
isuuid bool
}
var tests = []test{
{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
{"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true},
{"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false},
{"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false},
{"f47ac10b58cc037285670e02b2c3d479", 0, RFC4122, true},
{"f47ac10b58cc037285670e02b2c3d4790", 0, Invalid, false},
{"f47ac10b58cc037285670e02b2c3d47", 0, Invalid, false},
}
var constants = []struct {
c interface{}
name string
}{
{Person, "Person"},
{Group, "Group"},
{Org, "Org"},
{Invalid, "Invalid"},
{RFC4122, "RFC4122"},
{Reserved, "Reserved"},
{Microsoft, "Microsoft"},
{Future, "Future"},
{Domain(17), "Domain17"},
{Variant(42), "BadVariant42"},
}
func testTest(t *testing.T, in string, tt test) {
uuid, err := Parse(in)
if ok := (err == nil); ok != tt.isuuid {
t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
}
if err != nil {
return
}
if v := uuid.Variant(); v != tt.variant {
t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
}
if v := uuid.Version(); v != tt.version {
t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
}
}
func testBytes(t *testing.T, in []byte, tt test) {
uuid, err := ParseBytes(in)
if ok := (err == nil); ok != tt.isuuid {
t.Errorf("ParseBytes(%s) got %v expected %v\b", in, ok, tt.isuuid)
}
if err != nil {
return
}
suuid, _ := Parse(string(in))
if uuid != suuid {
t.Errorf("ParseBytes(%s) got %v expected %v\b", in, uuid, suuid)
}
}
func TestUUID(t *testing.T) {
for _, tt := range tests {
testTest(t, tt.in, tt)
testTest(t, strings.ToUpper(tt.in), tt)
testBytes(t, []byte(tt.in), tt)
}
}
func TestFromBytes(t *testing.T) {
b := []byte{
0x7d, 0x44, 0x48, 0x40,
0x9d, 0xc0,
0x11, 0xd1,
0xb2, 0x45,
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
}
uuid, err := FromBytes(b)
if err != nil {
t.Fatalf("%s", err)
}
for i := 0; i < len(uuid); i++ {
if b[i] != uuid[i] {
t.Fatalf("FromBytes() got %v expected %v\b", uuid[:], b)
}
}
}
func TestConstants(t *testing.T) {
for x, tt := range constants {
v, ok := tt.c.(fmt.Stringer)
if !ok {
t.Errorf("%x: %v: not a stringer", x, v)
} else if s := v.String(); s != tt.name {
v, _ := tt.c.(int)
t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name)
}
}
}
func TestRandomUUID(t *testing.T) {
m := make(map[string]bool)
for x := 1; x < 32; x++ {
uuid := New()
s := uuid.String()
if m[s] {
t.Errorf("NewRandom returned duplicated UUID %s", s)
}
m[s] = true
if v := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestNew(t *testing.T) {
m := make(map[UUID]bool)
for x := 1; x < 32; x++ {
s := New()
if m[s] {
t.Errorf("New returned duplicated UUID %s", s)
}
m[s] = true
uuid, err := Parse(s.String())
if err != nil {
t.Errorf("New.String() returned %q which does not decode", s)
continue
}
if v := uuid.Version(); v != 4 {
t.Errorf("Random UUID of version %s", v)
}
if uuid.Variant() != RFC4122 {
t.Errorf("Random UUID is variant %d", uuid.Variant())
}
}
}
func TestClockSeq(t *testing.T) {
// Fake time.Now for this test to return a monotonically advancing time; restore it at end.
defer func(orig func() time.Time) { timeNow = orig }(timeNow)
monTime := time.Now()
timeNow = func() time.Time {
monTime = monTime.Add(1 * time.Second)
return monTime
}
SetClockSequence(-1)
uuid1, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
uuid2, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 != s2 {
t.Errorf("clock sequence %d != %d", s1, s2)
}
SetClockSequence(-1)
uuid2, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
// Just on the very off chance we generated the same sequence
// two times we try again.
if uuid1.ClockSequence() == uuid2.ClockSequence() {
SetClockSequence(-1)
uuid2, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
}
if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 == s2 {
t.Errorf("Duplicate clock sequence %d", s1)
}
SetClockSequence(0x1234)
uuid1, err = NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if seq := uuid1.ClockSequence(); seq != 0x1234 {
t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq)
}
}
func TestCoding(t *testing.T) {
text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
data := UUID{
0x7d, 0x44, 0x48, 0x40,
0x9d, 0xc0,
0x11, 0xd1,
0xb2, 0x45,
0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
}
if v := data.String(); v != text {
t.Errorf("%x: encoded to %s, expected %s", data, v, text)
}
if v := data.URN(); v != urn {
t.Errorf("%x: urn is %s, expected %s", data, v, urn)
}
uuid, err := Parse(text)
if err != nil {
t.Errorf("Parse returned unexpected error %v", err)
}
if data != uuid {
t.Errorf("%s: decoded to %s, expected %s", text, uuid, data)
}
}
func TestVersion1(t *testing.T) {
uuid1, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
uuid2, err := NewUUID()
if err != nil {
t.Fatalf("could not create UUID: %v", err)
}
if uuid1 == uuid2 {
t.Errorf("%s:duplicate uuid", uuid1)
}
if v := uuid1.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid1, v)
}
if v := uuid2.Version(); v != 1 {
t.Errorf("%s: version %s expected 1", uuid2, v)
}
n1 := uuid1.NodeID()
n2 := uuid2.NodeID()
if !bytes.Equal(n1, n2) {
t.Errorf("Different nodes %x != %x", n1, n2)
}
t1 := uuid1.Time()
t2 := uuid2.Time()
q1 := uuid1.ClockSequence()
q2 := uuid2.ClockSequence()
switch {
case t1 == t2 && q1 == q2:
t.Error("time stopped")
case t1 > t2 && q1 == q2:
t.Error("time reversed")
case t1 < t2 && q1 != q2:
t.Error("clock sequence changed unexpectedly")
}
}
func TestNode(t *testing.T) {
// This test is mostly to make sure we don't leave nodeMu locked.
ifname = ""
if ni := NodeInterface(); ni != "" {
t.Errorf("NodeInterface got %q, want %q", ni, "")
}
if SetNodeInterface("xyzzy") {
t.Error("SetNodeInterface succeeded on a bad interface name")
}
if !SetNodeInterface("") {
t.Error("SetNodeInterface failed")
}
if runtime.GOARCH != "js" {
if ni := NodeInterface(); ni == "" {
t.Error("NodeInterface returned an empty string")
}
}
ni := NodeID()
if len(ni) != 6 {
t.Errorf("ni got %d bytes, want 6", len(ni))
}
hasData := false
for _, b := range ni {
if b != 0 {
hasData = true
}
}
if !hasData {
t.Error("nodeid is all zeros")
}
id := []byte{1, 2, 3, 4, 5, 6, 7, 8}
SetNodeID(id)
ni = NodeID()
if !bytes.Equal(ni, id[:6]) {
t.Errorf("got nodeid %v, want %v", ni, id[:6])
}
if ni := NodeInterface(); ni != "user" {
t.Errorf("got interface %q, want %q", ni, "user")
}
}
func TestNodeAndTime(t *testing.T) {
// Time is February 5, 1998 12:30:23.136364800 AM GMT
uuid, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
if err != nil {
t.Fatalf("Parser returned unexpected error %v", err)
}
node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
ts := uuid.Time()
c := time.Unix(ts.UnixTime())
want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
if !c.Equal(want) {
t.Errorf("Got time %v, want %v", c, want)
}
if !bytes.Equal(node, uuid.NodeID()) {
t.Errorf("Expected node %v got %v", node, uuid.NodeID())
}
}
func TestMD5(t *testing.T) {
uuid := NewMD5(NameSpaceDNS, []byte("python.org")).String()
want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
if uuid != want {
t.Errorf("MD5: got %q expected %q", uuid, want)
}
}
func TestSHA1(t *testing.T) {
uuid := NewSHA1(NameSpaceDNS, []byte("python.org")).String()
want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
if uuid != want {
t.Errorf("SHA1: got %q expected %q", uuid, want)
}
}
func TestNodeID(t *testing.T) {
nid := []byte{1, 2, 3, 4, 5, 6}
SetNodeInterface("")
s := NodeInterface()
if runtime.GOARCH != "js" {
if s == "" || s == "user" {
t.Errorf("NodeInterface %q after SetInterface", s)
}
}
node1 := NodeID()
if node1 == nil {
t.Error("NodeID nil after SetNodeInterface", s)
}
SetNodeID(nid)
s = NodeInterface()
if s != "user" {
t.Errorf("Expected NodeInterface %q got %q", "user", s)
}
node2 := NodeID()
if node2 == nil {
t.Error("NodeID nil after SetNodeID", s)
}
if bytes.Equal(node1, node2) {
t.Error("NodeID not changed after SetNodeID", s)
} else if !bytes.Equal(nid, node2) {
t.Errorf("NodeID is %x, expected %x", node2, nid)
}
}
func testDCE(t *testing.T, name string, uuid UUID, err error, domain Domain, id uint32) {
if err != nil {
t.Errorf("%s failed: %v", name, err)
return
}
if v := uuid.Version(); v != 2 {
t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v)
return
}
if v := uuid.Domain(); v != domain {
t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v)
}
if v := uuid.ID(); v != id {
t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v)
}
}
func TestDCE(t *testing.T) {
uuid, err := NewDCESecurity(42, 12345678)
testDCE(t, "NewDCESecurity", uuid, err, 42, 12345678)
uuid, err = NewDCEPerson()
testDCE(t, "NewDCEPerson", uuid, err, Person, uint32(os.Getuid()))
uuid, err = NewDCEGroup()
testDCE(t, "NewDCEGroup", uuid, err, Group, uint32(os.Getgid()))
}
type badRand struct{}
func (r badRand) Read(buf []byte) (int, error) {
for i := range buf {
buf[i] = byte(i)
}
return len(buf), nil
}
func TestBadRand(t *testing.T) {
SetRand(badRand{})
uuid1 := New()
uuid2 := New()
if uuid1 != uuid2 {
t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
}
SetRand(nil)
uuid1 = New()
uuid2 = New()
if uuid1 == uuid2 {
t.Errorf("unexpected duplicates, got %q", uuid1)
}
}
var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
var asBytes = []byte(asString)
func BenchmarkParse(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := Parse(asString)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkParseBytes(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := ParseBytes(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
// parseBytesUnsafe is to benchmark using unsafe.
func parseBytesUnsafe(b []byte) (UUID, error) {
return Parse(*(*string)(unsafe.Pointer(&b)))
}
func BenchmarkParseBytesUnsafe(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := parseBytesUnsafe(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
// parseBytesCopy is to benchmark not using unsafe.
func parseBytesCopy(b []byte) (UUID, error) {
return Parse(string(b))
}
func BenchmarkParseBytesCopy(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := parseBytesCopy(asBytes)
if err != nil {
b.Fatal(err)
}
}
}
func BenchmarkNew(b *testing.B) {
for i := 0; i < b.N; i++ {
New()
}
}
func BenchmarkUUID_String(b *testing.B) {
uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
if uuid.String() == "" {
b.Fatal("invalid uuid")
}
}
}
func BenchmarkUUID_URN(b *testing.B) {
uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
if err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
if uuid.URN() == "" {
b.Fatal("invalid uuid")
}
}
}