Browse Source

vendor: update to fix tests with Go 1.12.x

- github.com/smartystreets/goconvey
- github.com/jtolds/gls
unknwon 6 years ago
parent
commit
00a3e368b4

+ 62 - 53
vendor/github.com/jtolds/gls/context.go

@@ -5,12 +5,7 @@ import (
 	"sync"
 )
 
-const (
-	maxCallers = 64
-)
-
 var (
-	stackTagPool   = &idPool{}
 	mgrRegistry    = make(map[*ContextManager]bool)
 	mgrRegistryMtx sync.RWMutex
 )
@@ -25,7 +20,7 @@ type Values map[interface{}]interface{}
 // class of context variables. You should use NewContextManager for
 // construction.
 type ContextManager struct {
-	mtx    sync.RWMutex
+	mtx    sync.Mutex
 	values map[uint]Values
 }
 
@@ -62,63 +57,77 @@ func (m *ContextManager) SetValues(new_values Values, context_call func()) {
 		return
 	}
 
-	tags := readStackTags(1)
+	mutated_keys := make([]interface{}, 0, len(new_values))
+	mutated_vals := make(Values, len(new_values))
 
-	m.mtx.Lock()
-	values := new_values
-	for _, tag := range tags {
-		if existing_values, ok := m.values[tag]; ok {
-			// oh, we found existing values, let's make a copy
-			values = make(Values, len(existing_values)+len(new_values))
-			for key, val := range existing_values {
-				values[key] = val
-			}
-			for key, val := range new_values {
-				values[key] = val
-			}
-			break
-		}
-	}
-	new_tag := stackTagPool.Acquire()
-	m.values[new_tag] = values
-	m.mtx.Unlock()
-	defer func() {
+	EnsureGoroutineId(func(gid uint) {
 		m.mtx.Lock()
-		delete(m.values, new_tag)
+		state, found := m.values[gid]
+		if !found {
+			state = make(Values, len(new_values))
+			m.values[gid] = state
+		}
 		m.mtx.Unlock()
-		stackTagPool.Release(new_tag)
-	}()
 
-	addStackTag(new_tag, context_call)
+		for key, new_val := range new_values {
+			mutated_keys = append(mutated_keys, key)
+			if old_val, ok := state[key]; ok {
+				mutated_vals[key] = old_val
+			}
+			state[key] = new_val
+		}
+
+		defer func() {
+			if !found {
+				m.mtx.Lock()
+				delete(m.values, gid)
+				m.mtx.Unlock()
+				return
+			}
+
+			for _, key := range mutated_keys {
+				if val, ok := mutated_vals[key]; ok {
+					state[key] = val
+				} else {
+					delete(state, key)
+				}
+			}
+		}()
+
+		context_call()
+	})
 }
 
 // GetValue will return a previously set value, provided that the value was set
 // by SetValues somewhere higher up the stack. If the value is not found, ok
 // will be false.
-func (m *ContextManager) GetValue(key interface{}) (value interface{}, ok bool) {
-
-	tags := readStackTags(1)
-	m.mtx.RLock()
-	defer m.mtx.RUnlock()
-	for _, tag := range tags {
-		if values, ok := m.values[tag]; ok {
-			value, ok := values[key]
-			return value, ok
-		}
+func (m *ContextManager) GetValue(key interface{}) (
+	value interface{}, ok bool) {
+	gid, ok := GetGoroutineId()
+	if !ok {
+		return nil, false
 	}
-	return "", false
+
+	m.mtx.Lock()
+	state, found := m.values[gid]
+	m.mtx.Unlock()
+
+	if !found {
+		return nil, false
+	}
+	value, ok = state[key]
+	return value, ok
 }
 
 func (m *ContextManager) getValues() Values {
-	tags := readStackTags(2)
-	m.mtx.RLock()
-	defer m.mtx.RUnlock()
-	for _, tag := range tags {
-		if values, ok := m.values[tag]; ok {
-			return values
-		}
+	gid, ok := GetGoroutineId()
+	if !ok {
+		return nil
 	}
-	return nil
+	m.mtx.Lock()
+	state, _ := m.values[gid]
+	m.mtx.Unlock()
+	return state
 }
 
 // Go preserves ContextManager values and Goroutine-local-storage across new
@@ -131,12 +140,12 @@ func Go(cb func()) {
 	mgrRegistryMtx.RLock()
 	defer mgrRegistryMtx.RUnlock()
 
-	for mgr, _ := range mgrRegistry {
+	for mgr := range mgrRegistry {
 		values := mgr.getValues()
 		if len(values) > 0 {
-			mgr_copy := mgr
-			cb_copy := cb
-			cb = func() { mgr_copy.SetValues(values, cb_copy) }
+			cb = func(mgr *ContextManager, cb func()) func() {
+				return func() { mgr.SetValues(values, cb) }
+			}(mgr, cb)
 		}
 	}
 

+ 11 - 3
vendor/github.com/jtolds/gls/gen_sym.go

@@ -1,13 +1,21 @@
 package gls
 
+import (
+	"sync"
+)
+
 var (
-	symPool = &idPool{}
+	keyMtx     sync.Mutex
+	keyCounter uint64
 )
 
 // ContextKey is a throwaway value you can use as a key to a ContextManager
-type ContextKey struct{ id uint }
+type ContextKey struct{ id uint64 }
 
 // GenSym will return a brand new, never-before-used ContextKey
 func GenSym() ContextKey {
-	return ContextKey{id: symPool.Acquire()}
+	keyMtx.Lock()
+	defer keyMtx.Unlock()
+	keyCounter += 1
+	return ContextKey{id: keyCounter}
 }

+ 25 - 0
vendor/github.com/jtolds/gls/gid.go

@@ -0,0 +1,25 @@
+package gls
+
+var (
+	stackTagPool = &idPool{}
+)
+
+// Will return this goroutine's identifier if set. If you always need a
+// goroutine identifier, you should use EnsureGoroutineId which will make one
+// if there isn't one already.
+func GetGoroutineId() (gid uint, ok bool) {
+	return readStackTag()
+}
+
+// Will call cb with the current goroutine identifier. If one hasn't already
+// been generated, one will be created and set first. The goroutine identifier
+// might be invalid after cb returns.
+func EnsureGoroutineId(cb func(gid uint)) {
+	if gid, ok := readStackTag(); ok {
+		cb(gid)
+		return
+	}
+	gid := stackTagPool.Acquire()
+	defer stackTagPool.Release(gid)
+	addStackTag(gid, func() { cb(gid) })
+}

+ 126 - 22
vendor/github.com/jtolds/gls/stack_tags.go

@@ -3,36 +3,105 @@ package gls
 // so, basically, we're going to encode integer tags in base-16 on the stack
 
 const (
-	bitWidth = 4
+	bitWidth       = 4
+	stackBatchSize = 16
 )
 
+var (
+	pc_lookup   = make(map[uintptr]int8, 17)
+	mark_lookup [16]func(uint, func())
+)
+
+func init() {
+	setEntries := func(f func(uint, func()), v int8) {
+		var ptr uintptr
+		f(0, func() {
+			ptr = findPtr()
+		})
+		pc_lookup[ptr] = v
+		if v >= 0 {
+			mark_lookup[v] = f
+		}
+	}
+	setEntries(github_com_jtolds_gls_markS, -0x1)
+	setEntries(github_com_jtolds_gls_mark0, 0x0)
+	setEntries(github_com_jtolds_gls_mark1, 0x1)
+	setEntries(github_com_jtolds_gls_mark2, 0x2)
+	setEntries(github_com_jtolds_gls_mark3, 0x3)
+	setEntries(github_com_jtolds_gls_mark4, 0x4)
+	setEntries(github_com_jtolds_gls_mark5, 0x5)
+	setEntries(github_com_jtolds_gls_mark6, 0x6)
+	setEntries(github_com_jtolds_gls_mark7, 0x7)
+	setEntries(github_com_jtolds_gls_mark8, 0x8)
+	setEntries(github_com_jtolds_gls_mark9, 0x9)
+	setEntries(github_com_jtolds_gls_markA, 0xa)
+	setEntries(github_com_jtolds_gls_markB, 0xb)
+	setEntries(github_com_jtolds_gls_markC, 0xc)
+	setEntries(github_com_jtolds_gls_markD, 0xd)
+	setEntries(github_com_jtolds_gls_markE, 0xe)
+	setEntries(github_com_jtolds_gls_markF, 0xf)
+}
+
 func addStackTag(tag uint, context_call func()) {
 	if context_call == nil {
 		return
 	}
-	markS(tag, context_call)
+	github_com_jtolds_gls_markS(tag, context_call)
 }
 
-func markS(tag uint, cb func()) { _m(tag, cb) }
-func mark0(tag uint, cb func()) { _m(tag, cb) }
-func mark1(tag uint, cb func()) { _m(tag, cb) }
-func mark2(tag uint, cb func()) { _m(tag, cb) }
-func mark3(tag uint, cb func()) { _m(tag, cb) }
-func mark4(tag uint, cb func()) { _m(tag, cb) }
-func mark5(tag uint, cb func()) { _m(tag, cb) }
-func mark6(tag uint, cb func()) { _m(tag, cb) }
-func mark7(tag uint, cb func()) { _m(tag, cb) }
-func mark8(tag uint, cb func()) { _m(tag, cb) }
-func mark9(tag uint, cb func()) { _m(tag, cb) }
-func markA(tag uint, cb func()) { _m(tag, cb) }
-func markB(tag uint, cb func()) { _m(tag, cb) }
-func markC(tag uint, cb func()) { _m(tag, cb) }
-func markD(tag uint, cb func()) { _m(tag, cb) }
-func markE(tag uint, cb func()) { _m(tag, cb) }
-func markF(tag uint, cb func()) { _m(tag, cb) }
-
-var pc_lookup = make(map[uintptr]int8, 17)
-var mark_lookup [16]func(uint, func())
+// these private methods are named this horrendous name so gopherjs support
+// is easier. it shouldn't add any runtime cost in non-js builds.
+
+//go:noinline
+func github_com_jtolds_gls_markS(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark0(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark1(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark2(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark3(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark4(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark5(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark6(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark7(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark8(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_mark9(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markA(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markB(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markC(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markD(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markE(tag uint, cb func()) { _m(tag, cb) }
+
+//go:noinline
+func github_com_jtolds_gls_markF(tag uint, cb func()) { _m(tag, cb) }
 
 func _m(tag_remainder uint, cb func()) {
 	if tag_remainder == 0 {
@@ -41,3 +110,38 @@ func _m(tag_remainder uint, cb func()) {
 		mark_lookup[tag_remainder&0xf](tag_remainder>>bitWidth, cb)
 	}
 }
+
+func readStackTag() (tag uint, ok bool) {
+	var current_tag uint
+	offset := 0
+	for {
+		batch, next_offset := getStack(offset, stackBatchSize)
+		for _, pc := range batch {
+			val, ok := pc_lookup[pc]
+			if !ok {
+				continue
+			}
+			if val < 0 {
+				return current_tag, true
+			}
+			current_tag <<= bitWidth
+			current_tag += uint(val)
+		}
+		if next_offset == 0 {
+			break
+		}
+		offset = next_offset
+	}
+	return 0, false
+}
+
+func (m *ContextManager) preventInlining() {
+	// dunno if findPtr or getStack are likely to get inlined in a future release
+	// of go, but if they are inlined and their callers are inlined, that could
+	// hork some things. let's do our best to explain to the compiler that we
+	// really don't want those two functions inlined by saying they could change
+	// at any time. assumes preventInlining doesn't get compiled out.
+	// this whole thing is probably overkill.
+	findPtr = m.values[0][0].(func() uintptr)
+	getStack = m.values[0][1].(func(int, int) ([]uintptr, int))
+}

+ 51 - 77
vendor/github.com/jtolds/gls/stack_tags_js.go

@@ -2,100 +2,74 @@
 
 package gls
 
-// This file is used for GopherJS builds, which don't have normal runtime support
+// This file is used for GopherJS builds, which don't have normal runtime
+// stack trace support
 
 import (
-	"regexp"
 	"strconv"
 	"strings"
 
 	"github.com/gopherjs/gopherjs/js"
 )
 
-var stackRE = regexp.MustCompile("\\s+at (\\S*) \\([^:]+:(\\d+):(\\d+)")
+const (
+	jsFuncNamePrefix = "github_com_jtolds_gls_mark"
+)
 
-func findPtr() uintptr {
-	jsStack := js.Global.Get("Error").New().Get("stack").Call("split", "\n")
-	for i := 1; i < jsStack.Get("length").Int(); i++ {
-		item := jsStack.Index(i).String()
-		matches := stackRE.FindAllStringSubmatch(item, -1)
-		if matches == nil {
-			return 0
+func jsMarkStack() (f []uintptr) {
+	lines := strings.Split(
+		js.Global.Get("Error").New().Get("stack").String(), "\n")
+	f = make([]uintptr, 0, len(lines))
+	for i, line := range lines {
+		line = strings.TrimSpace(line)
+		if line == "" {
+			continue
 		}
-		pkgPath := matches[0][1]
-		if strings.HasPrefix(pkgPath, "$packages.github.com/jtolds/gls.mark") {
-			line, _ := strconv.Atoi(matches[0][2])
-			char, _ := strconv.Atoi(matches[0][3])
-			x := (uintptr(line) << 16) | uintptr(char)
-			return x
+		if i == 0 {
+			if line != "Error" {
+				panic("didn't understand js stack trace")
+			}
+			continue
+		}
+		fields := strings.Fields(line)
+		if len(fields) < 2 || fields[0] != "at" {
+			panic("didn't understand js stack trace")
 		}
-	}
-
-	return 0
-}
 
-func init() {
-	setEntries := func(f func(uint, func()), v int8) {
-		var ptr uintptr
-		f(0, func() {
-			ptr = findPtr()
-		})
-		pc_lookup[ptr] = v
-		if v >= 0 {
-			mark_lookup[v] = f
+		pos := strings.Index(fields[1], jsFuncNamePrefix)
+		if pos < 0 {
+			continue
+		}
+		pos += len(jsFuncNamePrefix)
+		if pos >= len(fields[1]) {
+			panic("didn't understand js stack trace")
+		}
+		char := string(fields[1][pos])
+		switch char {
+		case "S":
+			f = append(f, uintptr(0))
+		default:
+			val, err := strconv.ParseUint(char, 16, 8)
+			if err != nil {
+				panic("didn't understand js stack trace")
+			}
+			f = append(f, uintptr(val)+1)
 		}
 	}
-	setEntries(markS, -0x1)
-	setEntries(mark0, 0x0)
-	setEntries(mark1, 0x1)
-	setEntries(mark2, 0x2)
-	setEntries(mark3, 0x3)
-	setEntries(mark4, 0x4)
-	setEntries(mark5, 0x5)
-	setEntries(mark6, 0x6)
-	setEntries(mark7, 0x7)
-	setEntries(mark8, 0x8)
-	setEntries(mark9, 0x9)
-	setEntries(markA, 0xa)
-	setEntries(markB, 0xb)
-	setEntries(markC, 0xc)
-	setEntries(markD, 0xd)
-	setEntries(markE, 0xe)
-	setEntries(markF, 0xf)
+	return f
 }
 
-func currentStack(skip int) (stack []uintptr) {
-	jsStack := js.Global.Get("Error").New().Get("stack").Call("split", "\n")
-	for i := skip + 2; i < jsStack.Get("length").Int(); i++ {
-		item := jsStack.Index(i).String()
-		matches := stackRE.FindAllStringSubmatch(item, -1)
-		if matches == nil {
-			return stack
+// variables to prevent inlining
+var (
+	findPtr = func() uintptr {
+		funcs := jsMarkStack()
+		if len(funcs) == 0 {
+			panic("failed to find function pointer")
 		}
-		line, _ := strconv.Atoi(matches[0][2])
-		char, _ := strconv.Atoi(matches[0][3])
-		x := (uintptr(line) << 16) | uintptr(char)&0xffff
-		stack = append(stack, x)
+		return funcs[0]
 	}
 
-	return stack
-}
-
-func readStackTags(skip int) (tags []uint) {
-	stack := currentStack(skip)
-	var current_tag uint
-	for _, pc := range stack {
-		val, ok := pc_lookup[pc]
-		if !ok {
-			continue
-		}
-		if val < 0 {
-			tags = append(tags, current_tag)
-			current_tag = 0
-			continue
-		}
-		current_tag <<= bitWidth
-		current_tag += uint(val)
+	getStack = func(offset, amount int) (stack []uintptr, next_offset int) {
+		return jsMarkStack(), 0
 	}
-	return
-}
+)

+ 16 - 47
vendor/github.com/jtolds/gls/stack_tags_main.go

@@ -2,60 +2,29 @@
 
 package gls
 
-// This file is used for standard Go builds, which have the expected runtime support
+// This file is used for standard Go builds, which have the expected runtime
+// support
 
 import (
-	"reflect"
 	"runtime"
 )
 
-func init() {
-	setEntries := func(f func(uint, func()), v int8) {
-		pc_lookup[reflect.ValueOf(f).Pointer()] = v
-		if v >= 0 {
-			mark_lookup[v] = f
+var (
+	findPtr = func() uintptr {
+		var pc [1]uintptr
+		n := runtime.Callers(4, pc[:])
+		if n != 1 {
+			panic("failed to find function pointer")
 		}
+		return pc[0]
 	}
-	setEntries(markS, -0x1)
-	setEntries(mark0, 0x0)
-	setEntries(mark1, 0x1)
-	setEntries(mark2, 0x2)
-	setEntries(mark3, 0x3)
-	setEntries(mark4, 0x4)
-	setEntries(mark5, 0x5)
-	setEntries(mark6, 0x6)
-	setEntries(mark7, 0x7)
-	setEntries(mark8, 0x8)
-	setEntries(mark9, 0x9)
-	setEntries(markA, 0xa)
-	setEntries(markB, 0xb)
-	setEntries(markC, 0xc)
-	setEntries(markD, 0xd)
-	setEntries(markE, 0xe)
-	setEntries(markF, 0xf)
-}
 
-func currentStack(skip int) []uintptr {
-	stack := make([]uintptr, maxCallers)
-	return stack[:runtime.Callers(3+skip, stack)]
-}
-
-func readStackTags(skip int) (tags []uint) {
-	stack := currentStack(skip)
-	var current_tag uint
-	for _, pc := range stack {
-		pc = runtime.FuncForPC(pc).Entry()
-		val, ok := pc_lookup[pc]
-		if !ok {
-			continue
-		}
-		if val < 0 {
-			tags = append(tags, current_tag)
-			current_tag = 0
-			continue
+	getStack = func(offset, amount int) (stack []uintptr, next_offset int) {
+		stack = make([]uintptr, amount)
+		stack = stack[:runtime.Callers(offset, stack)]
+		if len(stack) < amount {
+			return stack, 0
 		}
-		current_tag <<= bitWidth
-		current_tag += uint(val)
+		return stack, offset + len(stack)
 	}
-	return
-}
+)

File diff suppressed because it is too large
+ 35 - 0
vendor/github.com/smartystreets/goconvey/CONTRIBUTING.md


+ 1 - 1
vendor/github.com/smartystreets/goconvey/LICENSE.md

@@ -1,4 +1,4 @@
-Copyright (c) 2014 SmartyStreets, LLC
+Copyright (c) 2016 SmartyStreets, LLC
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 124 - 0
vendor/github.com/smartystreets/goconvey/README.md

@@ -0,0 +1,124 @@
+GoConvey is awesome Go testing
+==============================
+
+[![Build Status](https://travis-ci.org/smartystreets/goconvey.png)](https://travis-ci.org/smartystreets/goconvey)
+[![GoDoc](https://godoc.org/github.com/smartystreets/goconvey?status.svg)](http://godoc.org/github.com/smartystreets/goconvey)
+
+
+Welcome to GoConvey, a yummy Go testing tool for gophers. Works with `go test`. Use it in the terminal or browser according to your viewing pleasure. **[View full feature tour.](http://goconvey.co)**
+
+**Features:**
+
+- Directly integrates with `go test`
+- Fully-automatic web UI (works with native Go tests, too)
+- Huge suite of regression tests
+- Shows test coverage (Go 1.2+)
+- Readable, colorized console output (understandable by any manager, IT or not)
+- Test code generator
+- Desktop notifications (optional)
+- Immediately open problem lines in [Sublime Text](http://www.sublimetext.com) ([some assembly required](https://github.com/asuth/subl-handler))
+
+
+You can ask questions about how to use GoConvey on [StackOverflow](http://stackoverflow.com/questions/ask?tags=goconvey,go&title=GoConvey%3A%20). Use the tags `go` and `goconvey`.
+
+**Menu:**
+
+- [Installation](#installation)
+- [Quick start](#quick-start)
+- [Documentation](#documentation)
+- [Screenshots](#screenshots)
+- [Contributors](#contributors)
+
+
+
+
+Installation
+------------
+
+	$ go get github.com/smartystreets/goconvey
+
+[Quick start](https://github.com/smartystreets/goconvey/wiki#get-going-in-25-seconds)
+-----------
+
+Make a test, for example:
+
+```go
+package package_name
+
+import (
+    "testing"
+    . "github.com/smartystreets/goconvey/convey"
+)
+
+func TestSpec(t *testing.T) {
+
+	// Only pass t into top-level Convey calls
+	Convey("Given some integer with a starting value", t, func() {
+		x := 1
+
+		Convey("When the integer is incremented", func() {
+			x++
+
+			Convey("The value should be greater by one", func() {
+				So(x, ShouldEqual, 2)
+			})
+		})
+	})
+}
+```
+
+
+#### [In the browser](https://github.com/smartystreets/goconvey/wiki/Web-UI)
+
+Start up the GoConvey web server at your project's path:
+
+	$ $GOPATH/bin/goconvey
+
+Then watch the test results display in your browser at:
+
+	http://localhost:8080
+
+
+If the browser doesn't open automatically, please click [http://localhost:8080](http://localhost:8080) to open manually.
+
+There you have it.
+![](http://d79i1fxsrar4t.cloudfront.net/goconvey.co/gc-1-dark.png)
+As long as GoConvey is running, test results will automatically update in your browser window.
+
+![](http://d79i1fxsrar4t.cloudfront.net/goconvey.co/gc-5-dark.png)
+The design is responsive, so you can squish the browser real tight if you need to put it beside your code.
+
+
+The [web UI](https://github.com/smartystreets/goconvey/wiki/Web-UI) supports traditional Go tests, so use it even if you're not using GoConvey tests.
+
+
+
+#### [In the terminal](https://github.com/smartystreets/goconvey/wiki/Execution)
+
+Just do what you do best:
+
+    $ go test
+
+Or if you want the output to include the story:
+
+    $ go test -v
+
+
+[Documentation](https://github.com/smartystreets/goconvey/wiki)
+-----------
+
+Check out the
+
+- [GoConvey wiki](https://github.com/smartystreets/goconvey/wiki),
+- [![GoDoc](https://godoc.org/github.com/smartystreets/goconvey?status.png)](http://godoc.org/github.com/smartystreets/goconvey)
+- and the *_test.go files scattered throughout this project.
+
+[Screenshots](http://goconvey.co)
+-----------
+
+For web UI and terminal screenshots, check out [the full feature tour](http://goconvey.co).
+
+Contributors
+----------------------
+
+GoConvey is brought to you by [SmartyStreets](https://github.com/smartystreets) and [several contributors](https://github.com/smartystreets/goconvey/graphs/contributors) (Thanks!).

+ 4 - 0
vendor/github.com/smartystreets/goconvey/dependencies.go

@@ -0,0 +1,4 @@
+package main
+
+import _ "github.com/jtolds/gls"
+import _ "github.com/smartystreets/assertions"

+ 8 - 0
vendor/github.com/smartystreets/goconvey/go.mod

@@ -0,0 +1,8 @@
+module github.com/smartystreets/goconvey
+
+require (
+	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
+	github.com/jtolds/gls v4.20.0+incompatible
+	github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d
+	golang.org/x/tools v0.0.0-20190328211700-ab21143f2384
+)

+ 12 - 0
vendor/github.com/smartystreets/goconvey/go.sum

@@ -0,0 +1,12 @@
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=

+ 293 - 0
vendor/github.com/smartystreets/goconvey/goconvey.go

@@ -0,0 +1,293 @@
+// This executable provides an HTTP server that watches for file system changes
+// to .go files within the working directory (and all nested go packages).
+// Navigating to the configured host and port in a web browser will display the
+// latest results of running `go test` in each go package.
+package main
+
+import (
+	"flag"
+	"fmt"
+	"log"
+	"net"
+	"net/http"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+
+	"github.com/smartystreets/goconvey/web/server/api"
+	"github.com/smartystreets/goconvey/web/server/contract"
+	"github.com/smartystreets/goconvey/web/server/executor"
+	"github.com/smartystreets/goconvey/web/server/messaging"
+	"github.com/smartystreets/goconvey/web/server/parser"
+	"github.com/smartystreets/goconvey/web/server/system"
+	"github.com/smartystreets/goconvey/web/server/watch"
+)
+
+func init() {
+	flags()
+	folders()
+}
+func flags() {
+	flag.IntVar(&port, "port", 8080, "The port at which to serve http.")
+	flag.StringVar(&host, "host", "127.0.0.1", "The host at which to serve http.")
+	flag.DurationVar(&nap, "poll", quarterSecond, "The interval to wait between polling the file system for changes.")
+	flag.IntVar(&parallelPackages, "packages", 10, "The number of packages to test in parallel. Higher == faster but more costly in terms of computing.")
+	flag.StringVar(&gobin, "gobin", "go", "The path to the 'go' binary (default: search on the PATH).")
+	flag.BoolVar(&cover, "cover", true, "Enable package-level coverage statistics. Requires Go 1.2+ and the go cover tool.")
+	flag.IntVar(&depth, "depth", -1, "The directory scanning depth. If -1, scan infinitely deep directory structures. 0: scan working directory. 1+: Scan into nested directories, limited to value.")
+	flag.StringVar(&timeout, "timeout", "0", "The test execution timeout if none is specified in the *.goconvey file (default is '0', which is the same as not providing this option).")
+	flag.StringVar(&watchedSuffixes, "watchedSuffixes", ".go", "A comma separated list of file suffixes to watch for modifications.")
+	flag.StringVar(&excludedDirs, "excludedDirs", "vendor,node_modules", "A comma separated list of directories that will be excluded from being watched")
+	flag.StringVar(&workDir, "workDir", "", "set goconvey working directory (default current directory)")
+	flag.BoolVar(&autoLaunchBrowser, "launchBrowser", true, "toggle auto launching of browser (default: true)")
+
+	log.SetOutput(os.Stdout)
+	log.SetFlags(log.LstdFlags | log.Lshortfile)
+}
+func folders() {
+	_, file, _, _ := runtime.Caller(0)
+	here := filepath.Dir(file)
+	static = filepath.Join(here, "/web/client")
+	reports = filepath.Join(static, "reports")
+}
+
+func main() {
+	flag.Parse()
+	log.Printf(initialConfiguration, host, port, nap, cover)
+
+	working := getWorkDir()
+	cover = coverageEnabled(cover, reports)
+	shell := system.NewShell(gobin, reports, cover, timeout)
+
+	watcherInput := make(chan messaging.WatcherCommand)
+	watcherOutput := make(chan messaging.Folders)
+	excludedDirItems := strings.Split(excludedDirs, `,`)
+	watcher := watch.NewWatcher(working, depth, nap, watcherInput, watcherOutput, watchedSuffixes, excludedDirItems)
+
+	parser := parser.NewParser(parser.ParsePackageResults)
+	tester := executor.NewConcurrentTester(shell)
+	tester.SetBatchSize(parallelPackages)
+
+	longpollChan := make(chan chan string)
+	executor := executor.NewExecutor(tester, parser, longpollChan)
+	server := api.NewHTTPServer(working, watcherInput, executor, longpollChan)
+	listener := createListener()
+	go runTestOnUpdates(watcherOutput, executor, server)
+	go watcher.Listen()
+	if autoLaunchBrowser {
+		go launchBrowser(listener.Addr().String())
+	}
+	serveHTTP(server, listener)
+}
+
+func browserCmd() (string, bool) {
+	browser := map[string]string{
+		"darwin":  "open",
+		"linux":   "xdg-open",
+		"windows": "start",
+	}
+	cmd, ok := browser[runtime.GOOS]
+	return cmd, ok
+}
+
+func launchBrowser(addr string) {
+	browser, ok := browserCmd()
+	if !ok {
+		log.Printf("Skipped launching browser for this OS: %s", runtime.GOOS)
+		return
+	}
+
+	log.Printf("Launching browser on %s", addr)
+	url := fmt.Sprintf("http://%s", addr)
+	cmd := exec.Command(browser, url)
+
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		log.Println(err)
+	}
+	log.Println(string(output))
+}
+
+func runTestOnUpdates(queue chan messaging.Folders, executor contract.Executor, server contract.Server) {
+	for update := range queue {
+		log.Println("Received request from watcher to execute tests...")
+		packages := extractPackages(update)
+		output := executor.ExecuteTests(packages)
+		root := extractRoot(update, packages)
+		server.ReceiveUpdate(root, output)
+	}
+}
+
+func extractPackages(folderList messaging.Folders) []*contract.Package {
+	packageList := []*contract.Package{}
+	for _, folder := range folderList {
+		hasImportCycle := testFilesImportTheirOwnPackage(folder.Path)
+		packageName := resolvePackageName(folder.Path)
+		packageList = append(
+			packageList,
+			contract.NewPackage(folder, packageName, hasImportCycle),
+		)
+	}
+	return packageList
+}
+
+func extractRoot(folderList messaging.Folders, packageList []*contract.Package) string {
+	path := packageList[0].Path
+	folder := folderList[path]
+	return folder.Root
+}
+
+func createListener() net.Listener {
+	l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
+	if err != nil {
+		log.Println(err)
+	}
+	if l == nil {
+		os.Exit(1)
+	}
+	return l
+}
+
+func serveHTTP(server contract.Server, listener net.Listener) {
+	serveStaticResources()
+	serveAjaxMethods(server)
+	activateServer(listener)
+}
+
+func serveStaticResources() {
+	http.Handle("/", http.FileServer(http.Dir(static)))
+}
+
+func serveAjaxMethods(server contract.Server) {
+	http.HandleFunc("/watch", server.Watch)
+	http.HandleFunc("/ignore", server.Ignore)
+	http.HandleFunc("/reinstate", server.Reinstate)
+	http.HandleFunc("/latest", server.Results)
+	http.HandleFunc("/execute", server.Execute)
+	http.HandleFunc("/status", server.Status)
+	http.HandleFunc("/status/poll", server.LongPollStatus)
+	http.HandleFunc("/pause", server.TogglePause)
+}
+
+func activateServer(listener net.Listener) {
+	log.Printf("Serving HTTP at: http://%s\n", listener.Addr())
+	err := http.Serve(listener, nil)
+	if err != nil {
+		log.Println(err)
+	}
+}
+
+func coverageEnabled(cover bool, reports string) bool {
+	return (cover &&
+		goMinVersion(1, 2) &&
+		coverToolInstalled() &&
+		ensureReportDirectoryExists(reports))
+}
+func goMinVersion(wanted ...int) bool {
+	version := runtime.Version() // 'go1.2....'
+	s := regexp.MustCompile(`go([\d]+)\.([\d]+)\.?([\d]+)?`).FindAllStringSubmatch(version, 1)
+	if len(s) == 0 {
+		log.Printf("Cannot determine if newer than go1.2, disabling coverage.")
+		return false
+	}
+	for idx, str := range s[0][1:] {
+		if len(wanted) == idx {
+			break
+		}
+		if v, _ := strconv.Atoi(str); v < wanted[idx] {
+			log.Printf(pleaseUpgradeGoVersion, version)
+			return false
+		}
+	}
+	return true
+}
+func coverToolInstalled() bool {
+	working := getWorkDir()
+	command := system.NewCommand(working, "go", "tool", "cover").Execute()
+	installed := strings.Contains(command.Output, "Usage of 'go tool cover':")
+	if !installed {
+		log.Print(coverToolMissing)
+		return false
+	}
+	return true
+}
+func ensureReportDirectoryExists(reports string) bool {
+	result, err := exists(reports)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if result {
+		return true
+	}
+
+	if err := os.Mkdir(reports, 0755); err == nil {
+		return true
+	}
+
+	log.Printf(reportDirectoryUnavailable, reports)
+	return false
+}
+func exists(path string) (bool, error) {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true, nil
+	}
+	if os.IsNotExist(err) {
+		return false, nil
+	}
+	return false, err
+}
+func getWorkDir() string {
+	working := ""
+	var err error
+	if workDir != "" {
+		working = workDir
+	} else {
+		working, err = os.Getwd()
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+	result, err := exists(working)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if !result {
+		log.Fatalf("Path:%s does not exists", working)
+	}
+	return working
+}
+
+var (
+	port              int
+	host              string
+	gobin             string
+	nap               time.Duration
+	parallelPackages  int
+	cover             bool
+	depth             int
+	timeout           string
+	watchedSuffixes   string
+	excludedDirs      string
+	autoLaunchBrowser bool
+
+	static  string
+	reports string
+
+	quarterSecond = time.Millisecond * 250
+	workDir       string
+)
+
+const (
+	initialConfiguration       = "Initial configuration: [host: %s] [port: %d] [poll: %v] [cover: %v]\n"
+	pleaseUpgradeGoVersion     = "Go version is less that 1.2 (%s), please upgrade to the latest stable version to enable coverage reporting.\n"
+	coverToolMissing           = "Go cover tool is not installed or not accessible: for Go < 1.5 run`go get golang.org/x/tools/cmd/cover`\n For >= Go 1.5 run `go install $GOROOT/src/cmd/cover`\n"
+	reportDirectoryUnavailable = "Could not find or create the coverage report directory (at: '%s'). You probably won't see any coverage statistics...\n"
+	separator                  = string(filepath.Separator)
+	endGoPath                  = separator + "src" + separator
+)

+ 42 - 0
vendor/github.com/smartystreets/goconvey/goconvey_1_8.go

@@ -0,0 +1,42 @@
+// +build !go1.9
+
+// To work correctly with out of GOPATH modules, some functions needed to
+// switch from using go/build to golang.org/x/tools/go/packages. But that
+// package depends on changes to go/types that were introduced in Go 1.9. Since
+// modules weren't introduced until Go 1.11, users of Go 1.8 or below can't be
+// using modules, so they can continue to use go/build.
+
+package main
+
+import (
+	"go/build"
+	"strings"
+)
+
+// This method exists because of a bug in the go cover tool that
+// causes an infinite loop when you try to run `go test -cover`
+// on a package that has an import cycle defined in one of it's
+// test files. Yuck.
+func testFilesImportTheirOwnPackage(packagePath string) bool {
+	meta, err := build.ImportDir(packagePath, build.AllowBinary)
+	if err != nil {
+		return false
+	}
+
+	for _, dependency := range meta.TestImports {
+		if dependency == meta.ImportPath {
+			return true
+		}
+	}
+	return false
+}
+
+func resolvePackageName(path string) string {
+	pkg, err := build.ImportDir(path, build.FindOnly)
+	if err == nil {
+		return pkg.ImportPath
+	}
+
+	nameArr := strings.Split(path, endGoPath)
+	return nameArr[len(nameArr)-1]
+}

+ 64 - 0
vendor/github.com/smartystreets/goconvey/goconvey_1_9.go

@@ -0,0 +1,64 @@
+// +build go1.9
+
+// To work correctly with out of GOPATH modules, some functions needed to
+// switch from using go/build to golang.org/x/tools/go/packages. But that
+// package depends on changes to go/types that were introduced in Go 1.9. Since
+// modules weren't introduced until Go 1.11, using
+// golang.org/x/tools/go/packages can safely be restricted to users of Go 1.9
+// or above.
+package main
+
+import (
+	"fmt"
+	"strings"
+
+	"golang.org/x/tools/go/packages"
+)
+
+// This method exists because of a bug in the go cover tool that
+// causes an infinite loop when you try to run `go test -cover`
+// on a package that has an import cycle defined in one of it's
+// test files. Yuck.
+func testFilesImportTheirOwnPackage(packagePath string) bool {
+	meta, err := packages.Load(
+		&packages.Config{
+			Mode:  packages.NeedName | packages.NeedImports,
+			Tests: true,
+		},
+		packagePath,
+	)
+	if err != nil {
+		return false
+	}
+
+	testPackageID := fmt.Sprintf("%s [%s.test]", meta[0], meta[0])
+
+	for _, testPackage := range meta[1:] {
+		if testPackage.ID != testPackageID {
+			continue
+		}
+
+		for dependency := range testPackage.Imports {
+			if dependency == meta[0].PkgPath {
+				return true
+			}
+		}
+		break
+	}
+	return false
+}
+
+func resolvePackageName(path string) string {
+	pkg, err := packages.Load(
+		&packages.Config{
+			Mode: packages.NeedName,
+		},
+		path,
+	)
+	if err == nil {
+		return pkg[0].PkgPath
+	}
+
+	nameArr := strings.Split(path, endGoPath)
+	return nameArr[len(nameArr)-1]
+}

+ 9 - 3
vendor/vendor.json

@@ -261,10 +261,10 @@
 			"revisionTime": "2018-05-26T01:43:29Z"
 		},
 		{
-			"checksumSHA1": "tewA7jXVGCw1zb5mA0BDecWi4iQ=",
+			"checksumSHA1": "cIiyvAduLLFvu+tg1Qr5Jw3jeWo=",
 			"path": "github.com/jtolds/gls",
-			"revision": "8ddce2a84170772b95dd5d576c48d517b22cac63",
-			"revisionTime": "2016-01-05T22:08:40Z"
+			"revision": "b4936e06046bbecbb94cae9c18127ebe510a2cb9",
+			"revisionTime": "2018-11-10T20:28:10Z"
 		},
 		{
 			"checksumSHA1": "vfzz7zTL9TZLpFO7NC1H6/Du3+s=",
@@ -489,6 +489,12 @@
 			"revisionTime": "2016-02-05T03:39:31Z"
 		},
 		{
+			"checksumSHA1": "7E7jpXiYAxa4vxc+2ftP4aBrDy8=",
+			"path": "github.com/smartystreets/goconvey",
+			"revision": "9d28bd7c0945047857c9740bd2eb3d62f98d3d35",
+			"revisionTime": "2019-07-10T18:59:42Z"
+		},
+		{
 			"checksumSHA1": "fQeXVv5U9dlo3ufH2vjk1GNf4Lo=",
 			"path": "github.com/smartystreets/goconvey/convey",
 			"revision": "bf58a9a1291224109919756b4dcc469c670cc7e4",