From 936cba087caa281af1d2d52313e4d2b786a549eb Mon Sep 17 00:00:00 2001
From: Androlo <andreas@erisindustries.com>
Date: Sat, 20 Jun 2015 12:49:17 +0200
Subject: [PATCH] godep save no path changes

---
 Godeps/Godeps.json                            |  194 ++
 Godeps/Readme                                 |    5 +
 Godeps/_workspace/.gitignore                  |    2 +
 .../src/golang.org/x/net/context/context.go   |  447 +++
 .../golang.org/x/net/context/context_test.go  |  575 ++++
 .../x/net/context/withtimeout_test.go         |   26 +
 .../src/golang.org/x/net/netutil/listen.go    |   48 +
 .../golang.org/x/net/netutil/listen_test.go   |  103 +
 .../bluesuncorp/validator.v5/.gitignore       |   26 +
 .../bluesuncorp/validator.v5/.travis.yml      |   13 +
 .../gopkg.in/bluesuncorp/validator.v5/LICENSE |   22 +
 .../bluesuncorp/validator.v5/README.md        |   44 +
 .../bluesuncorp/validator.v5/baked_in.go      |  864 ++++++
 .../gopkg.in/bluesuncorp/validator.v5/doc.go  |  395 +++
 .../bluesuncorp/validator.v5/regexes.go       |   38 +
 .../bluesuncorp/validator.v5/validator.go     |  571 ++++
 .../validator.v5/validator_test.go            | 2497 +++++++++++++++++
 .../src/gopkg.in/fatih/set.v0/.travis.yml     |    3 +
 .../src/gopkg.in/fatih/set.v0/LICENSE.md      |   20 +
 .../src/gopkg.in/fatih/set.v0/README.md       |  245 ++
 .../src/gopkg.in/fatih/set.v0/set.go          |  121 +
 .../src/gopkg.in/fatih/set.v0/set_nots.go     |  195 ++
 .../gopkg.in/fatih/set.v0/set_nots_test.go    |  282 ++
 .../src/gopkg.in/fatih/set.v0/set_test.go     |  188 ++
 .../src/gopkg.in/fatih/set.v0/set_ts.go       |  200 ++
 .../src/gopkg.in/fatih/set.v0/set_ts_test.go  |  321 +++
 .../gopkg.in/tylerb/graceful.v1/.gitignore    |   23 +
 .../src/gopkg.in/tylerb/graceful.v1/LICENSE   |   21 +
 .../src/gopkg.in/tylerb/graceful.v1/README.md |  137 +
 .../gopkg.in/tylerb/graceful.v1/graceful.go   |  319 +++
 .../tylerb/graceful.v1/graceful_test.go       |  379 +++
 .../gopkg.in/tylerb/graceful.v1/tests/main.go |   40 +
 32 files changed, 8364 insertions(+)
 create mode 100644 Godeps/Godeps.json
 create mode 100644 Godeps/Readme
 create mode 100644 Godeps/_workspace/.gitignore
 create mode 100644 Godeps/_workspace/src/golang.org/x/net/context/context.go
 create mode 100644 Godeps/_workspace/src/golang.org/x/net/context/context_test.go
 create mode 100644 Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go
 create mode 100644 Godeps/_workspace/src/golang.org/x/net/netutil/listen.go
 create mode 100644 Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/LICENSE
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/regexes.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/.travis.yml
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/LICENSE.md
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/README.md
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/.gitignore
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/LICENSE
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/README.md
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful_test.go
 create mode 100644 Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/tests/main.go

diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
new file mode 100644
index 00000000..d3c54ebe
--- /dev/null
+++ b/Godeps/Godeps.json
@@ -0,0 +1,194 @@
+{
+	"ImportPath": "github.com/eris-ltd/eris-db",
+	"GoVersion": "go1.4.2",
+	"Packages": [
+		"./..."
+	],
+	"Deps": [
+		{
+			"ImportPath": "code.google.com/p/go.crypto/ripemd160",
+			"Comment": "null-236",
+			"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
+		},
+		{
+			"ImportPath": "code.google.com/p/mxk/go1/flowcontrol",
+			"Comment": "null-12",
+			"Rev": "5ff2502e25566863e8a0136c7aae8838e4c7de39"
+		},
+		{
+			"ImportPath": "github.com/agl/ed25519/edwards25519",
+			"Rev": "d2b94fd789ea21d12fac1a4443dd3a3f79cda72c"
+		},
+		{
+			"ImportPath": "github.com/gin-gonic/gin",
+			"Comment": "v1.0rc1-99-gd6425f1",
+			"Rev": "d6425f1692d4aa170ece887b62bb75c9c4da5829"
+		},
+		{
+			"ImportPath": "github.com/gorilla/websocket",
+			"Rev": "6fd0f867fef40c540fa05c59f86396de10a632a6"
+		},
+		{
+			"ImportPath": "github.com/inconshreveable/log15/stack",
+			"Comment": "v2.3-38-g352fceb",
+			"Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f"
+		},
+		{
+			"ImportPath": "github.com/inconshreveable/log15/term",
+			"Comment": "v2.3-38-g352fceb",
+			"Rev": "352fceb48e895bd1dd0b9f5d3ae8f8516c49af0f"
+		},
+		{
+			"ImportPath": "github.com/manucorporat/sse",
+			"Rev": "c142f0f1baea5cef7f98a8a6c222f6134368c1f5"
+		},
+		{
+			"ImportPath": "github.com/mattn/go-colorable",
+			"Rev": "d67e0b7d1797975196499f79bcc322c08b9f218b"
+		},
+		{
+			"ImportPath": "github.com/naoina/go-stringutil",
+			"Rev": "360db0db4b01d34e12a2ec042c09e7d37fece761"
+		},
+		{
+			"ImportPath": "github.com/naoina/toml",
+			"Rev": "7b2dffbeaee47506726f29e36d19cf4ee90d361b"
+		},
+		{
+			"ImportPath": "github.com/sfreiberg/gotwilio",
+			"Rev": "b7230c284bd0c1614c94d00b9998c49f9a2737d8"
+		},
+		{
+			"ImportPath": "github.com/stretchr/testify/assert",
+			"Rev": "de7fcff264cd05cc0c90c509ea789a436a0dd206"
+		},
+		{
+			"ImportPath": "github.com/stretchr/testify/suite",
+			"Rev": "de7fcff264cd05cc0c90c509ea789a436a0dd206"
+		},
+		{
+			"ImportPath": "github.com/syndtr/goleveldb/leveldb",
+			"Rev": "315fcfb05d4d46d4354b313d146ef688dda272a9"
+		},
+		{
+			"ImportPath": "github.com/syndtr/gosnappy/snappy",
+			"Rev": "156a073208e131d7d2e212cb749feae7c339e846"
+		},
+		{
+			"ImportPath": "github.com/tendermint/ed25519",
+			"Rev": "533fb6548e2071076888eda3c38749d707ba49bc"
+		},
+		{
+			"ImportPath": "github.com/tendermint/log15",
+			"Comment": "v2.3-33-g105a1be",
+			"Rev": "105a1beefe3379227a0d61733a29fd2c34f7080c"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/account",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/alert",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/binary",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/blockchain",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/common",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/config",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/consensus",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/db",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/events",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/logger",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/mempool",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/merkle",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/node",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/p2p",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/rpc/core",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/rpc/server",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/rpc/types",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/state",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/types",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tendermint/tendermint/vm",
+			"Rev": "46bd0e5d51692347647bb2e250fd0e637fc63a11"
+		},
+		{
+			"ImportPath": "github.com/tommy351/gin-cors",
+			"Rev": "f7219a698f21b23d73ae9330d3c5842951ce0b6a"
+		},
+		{
+			"ImportPath": "golang.org/x/net/context",
+			"Rev": "3cffabab72adf04f8e3b01c5baf775361837b5fe"
+		},
+		{
+			"ImportPath": "golang.org/x/net/netutil",
+			"Rev": "3cffabab72adf04f8e3b01c5baf775361837b5fe"
+		},
+		{
+			"ImportPath": "gopkg.in/bluesuncorp/validator.v5",
+			"Comment": "v5.7.1",
+			"Rev": "df95f9de27b8022e57f8ce09448cee6b1170bb3d"
+		},
+		{
+			"ImportPath": "gopkg.in/fatih/set.v0",
+			"Comment": "v0.1.0-3-g27c4092",
+			"Rev": "27c40922c40b43fe04554d8223a402af3ea333f3"
+		},
+		{
+			"ImportPath": "gopkg.in/tylerb/graceful.v1",
+			"Comment": "v1.1",
+			"Rev": "ff79a7f00848198d26054b472aafb1043c4b3507"
+		}
+	]
+}
diff --git a/Godeps/Readme b/Godeps/Readme
new file mode 100644
index 00000000..4cdaa53d
--- /dev/null
+++ b/Godeps/Readme
@@ -0,0 +1,5 @@
+This directory tree is generated automatically by godep.
+
+Please do not edit.
+
+See https://github.com/tools/godep for more information.
diff --git a/Godeps/_workspace/.gitignore b/Godeps/_workspace/.gitignore
new file mode 100644
index 00000000..f037d684
--- /dev/null
+++ b/Godeps/_workspace/.gitignore
@@ -0,0 +1,2 @@
+/pkg
+/bin
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context.go b/Godeps/_workspace/src/golang.org/x/net/context/context.go
new file mode 100644
index 00000000..ef2f3e86
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/context/context.go
@@ -0,0 +1,447 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package context defines the Context type, which carries deadlines,
+// cancelation signals, and other request-scoped values across API boundaries
+// and between processes.
+//
+// Incoming requests to a server should create a Context, and outgoing calls to
+// servers should accept a Context.  The chain of function calls between must
+// propagate the Context, optionally replacing it with a modified copy created
+// using WithDeadline, WithTimeout, WithCancel, or WithValue.
+//
+// Programs that use Contexts should follow these rules to keep interfaces
+// consistent across packages and enable static analysis tools to check context
+// propagation:
+//
+// Do not store Contexts inside a struct type; instead, pass a Context
+// explicitly to each function that needs it.  The Context should be the first
+// parameter, typically named ctx:
+//
+// 	func DoSomething(ctx context.Context, arg Arg) error {
+// 		// ... use ctx ...
+// 	}
+//
+// Do not pass a nil Context, even if a function permits it.  Pass context.TODO
+// if you are unsure about which Context to use.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+//
+// The same Context may be passed to functions running in different goroutines;
+// Contexts are safe for simultaneous use by multiple goroutines.
+//
+// See http://blog.golang.org/context for example code for a server that uses
+// Contexts.
+package context
+
+import (
+	"errors"
+	"fmt"
+	"sync"
+	"time"
+)
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+	// Deadline returns the time when work done on behalf of this context
+	// should be canceled.  Deadline returns ok==false when no deadline is
+	// set.  Successive calls to Deadline return the same results.
+	Deadline() (deadline time.Time, ok bool)
+
+	// Done returns a channel that's closed when work done on behalf of this
+	// context should be canceled.  Done may return nil if this context can
+	// never be canceled.  Successive calls to Done return the same value.
+	//
+	// WithCancel arranges for Done to be closed when cancel is called;
+	// WithDeadline arranges for Done to be closed when the deadline
+	// expires; WithTimeout arranges for Done to be closed when the timeout
+	// elapses.
+	//
+	// Done is provided for use in select statements:
+	//
+	//  // Stream generates values with DoSomething and sends them to out
+	//  // until DoSomething returns an error or ctx.Done is closed.
+	//  func Stream(ctx context.Context, out <-chan Value) error {
+	//  	for {
+	//  		v, err := DoSomething(ctx)
+	//  		if err != nil {
+	//  			return err
+	//  		}
+	//  		select {
+	//  		case <-ctx.Done():
+	//  			return ctx.Err()
+	//  		case out <- v:
+	//  		}
+	//  	}
+	//  }
+	//
+	// See http://blog.golang.org/pipelines for more examples of how to use
+	// a Done channel for cancelation.
+	Done() <-chan struct{}
+
+	// Err returns a non-nil error value after Done is closed.  Err returns
+	// Canceled if the context was canceled or DeadlineExceeded if the
+	// context's deadline passed.  No other values for Err are defined.
+	// After Done is closed, successive calls to Err return the same value.
+	Err() error
+
+	// Value returns the value associated with this context for key, or nil
+	// if no value is associated with key.  Successive calls to Value with
+	// the same key returns the same result.
+	//
+	// Use context values only for request-scoped data that transits
+	// processes and API boundaries, not for passing optional parameters to
+	// functions.
+	//
+	// A key identifies a specific value in a Context.  Functions that wish
+	// to store values in Context typically allocate a key in a global
+	// variable then use that key as the argument to context.WithValue and
+	// Context.Value.  A key can be any type that supports equality;
+	// packages should define keys as an unexported type to avoid
+	// collisions.
+	//
+	// Packages that define a Context key should provide type-safe accessors
+	// for the values stores using that key:
+	//
+	// 	// Package user defines a User type that's stored in Contexts.
+	// 	package user
+	//
+	// 	import "golang.org/x/net/context"
+	//
+	// 	// User is the type of value stored in the Contexts.
+	// 	type User struct {...}
+	//
+	// 	// key is an unexported type for keys defined in this package.
+	// 	// This prevents collisions with keys defined in other packages.
+	// 	type key int
+	//
+	// 	// userKey is the key for user.User values in Contexts.  It is
+	// 	// unexported; clients use user.NewContext and user.FromContext
+	// 	// instead of using this key directly.
+	// 	var userKey key = 0
+	//
+	// 	// NewContext returns a new Context that carries value u.
+	// 	func NewContext(ctx context.Context, u *User) context.Context {
+	// 		return context.WithValue(ctx, userKey, u)
+	// 	}
+	//
+	// 	// FromContext returns the User value stored in ctx, if any.
+	// 	func FromContext(ctx context.Context) (*User, bool) {
+	// 		u, ok := ctx.Value(userKey).(*User)
+	// 		return u, ok
+	// 	}
+	Value(key interface{}) interface{}
+}
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
+
+// An emptyCtx is never canceled, has no values, and has no deadline.  It is not
+// struct{}, since vars of this type must have distinct addresses.
+type emptyCtx int
+
+func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
+	return
+}
+
+func (*emptyCtx) Done() <-chan struct{} {
+	return nil
+}
+
+func (*emptyCtx) Err() error {
+	return nil
+}
+
+func (*emptyCtx) Value(key interface{}) interface{} {
+	return nil
+}
+
+func (e *emptyCtx) String() string {
+	switch e {
+	case background:
+		return "context.Background"
+	case todo:
+		return "context.TODO"
+	}
+	return "unknown empty Context"
+}
+
+var (
+	background = new(emptyCtx)
+	todo       = new(emptyCtx)
+)
+
+// Background returns a non-nil, empty Context. It is never canceled, has no
+// values, and has no deadline.  It is typically used by the main function,
+// initialization, and tests, and as the top-level Context for incoming
+// requests.
+func Background() Context {
+	return background
+}
+
+// TODO returns a non-nil, empty Context.  Code should use context.TODO when
+// it's unclear which Context to use or it's is not yet available (because the
+// surrounding function has not yet been extended to accept a Context
+// parameter).  TODO is recognized by static analysis tools that determine
+// whether Contexts are propagated correctly in a program.
+func TODO() Context {
+	return todo
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+	c := newCancelCtx(parent)
+	propagateCancel(parent, &c)
+	return &c, func() { c.cancel(true, Canceled) }
+}
+
+// newCancelCtx returns an initialized cancelCtx.
+func newCancelCtx(parent Context) cancelCtx {
+	return cancelCtx{
+		Context: parent,
+		done:    make(chan struct{}),
+	}
+}
+
+// propagateCancel arranges for child to be canceled when parent is.
+func propagateCancel(parent Context, child canceler) {
+	if parent.Done() == nil {
+		return // parent is never canceled
+	}
+	if p, ok := parentCancelCtx(parent); ok {
+		p.mu.Lock()
+		if p.err != nil {
+			// parent has already been canceled
+			child.cancel(false, p.err)
+		} else {
+			if p.children == nil {
+				p.children = make(map[canceler]bool)
+			}
+			p.children[child] = true
+		}
+		p.mu.Unlock()
+	} else {
+		go func() {
+			select {
+			case <-parent.Done():
+				child.cancel(false, parent.Err())
+			case <-child.Done():
+			}
+		}()
+	}
+}
+
+// parentCancelCtx follows a chain of parent references until it finds a
+// *cancelCtx.  This function understands how each of the concrete types in this
+// package represents its parent.
+func parentCancelCtx(parent Context) (*cancelCtx, bool) {
+	for {
+		switch c := parent.(type) {
+		case *cancelCtx:
+			return c, true
+		case *timerCtx:
+			return &c.cancelCtx, true
+		case *valueCtx:
+			parent = c.Context
+		default:
+			return nil, false
+		}
+	}
+}
+
+// removeChild removes a context from its parent.
+func removeChild(parent Context, child canceler) {
+	p, ok := parentCancelCtx(parent)
+	if !ok {
+		return
+	}
+	p.mu.Lock()
+	if p.children != nil {
+		delete(p.children, child)
+	}
+	p.mu.Unlock()
+}
+
+// A canceler is a context type that can be canceled directly.  The
+// implementations are *cancelCtx and *timerCtx.
+type canceler interface {
+	cancel(removeFromParent bool, err error)
+	Done() <-chan struct{}
+}
+
+// A cancelCtx can be canceled.  When canceled, it also cancels any children
+// that implement canceler.
+type cancelCtx struct {
+	Context
+
+	done chan struct{} // closed by the first cancel call.
+
+	mu       sync.Mutex
+	children map[canceler]bool // set to nil by the first cancel call
+	err      error             // set to non-nil by the first cancel call
+}
+
+func (c *cancelCtx) Done() <-chan struct{} {
+	return c.done
+}
+
+func (c *cancelCtx) Err() error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	return c.err
+}
+
+func (c *cancelCtx) String() string {
+	return fmt.Sprintf("%v.WithCancel", c.Context)
+}
+
+// cancel closes c.done, cancels each of c's children, and, if
+// removeFromParent is true, removes c from its parent's children.
+func (c *cancelCtx) cancel(removeFromParent bool, err error) {
+	if err == nil {
+		panic("context: internal error: missing cancel error")
+	}
+	c.mu.Lock()
+	if c.err != nil {
+		c.mu.Unlock()
+		return // already canceled
+	}
+	c.err = err
+	close(c.done)
+	for child := range c.children {
+		// NOTE: acquiring the child's lock while holding parent's lock.
+		child.cancel(false, err)
+	}
+	c.children = nil
+	c.mu.Unlock()
+
+	if removeFromParent {
+		removeChild(c.Context, c)
+	}
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d.  If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent.  The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+	if cur, ok := parent.Deadline(); ok && cur.Before(deadline) {
+		// The current deadline is already sooner than the new one.
+		return WithCancel(parent)
+	}
+	c := &timerCtx{
+		cancelCtx: newCancelCtx(parent),
+		deadline:  deadline,
+	}
+	propagateCancel(parent, c)
+	d := deadline.Sub(time.Now())
+	if d <= 0 {
+		c.cancel(true, DeadlineExceeded) // deadline has already passed
+		return c, func() { c.cancel(true, Canceled) }
+	}
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.err == nil {
+		c.timer = time.AfterFunc(d, func() {
+			c.cancel(true, DeadlineExceeded)
+		})
+	}
+	return c, func() { c.cancel(true, Canceled) }
+}
+
+// A timerCtx carries a timer and a deadline.  It embeds a cancelCtx to
+// implement Done and Err.  It implements cancel by stopping its timer then
+// delegating to cancelCtx.cancel.
+type timerCtx struct {
+	cancelCtx
+	timer *time.Timer // Under cancelCtx.mu.
+
+	deadline time.Time
+}
+
+func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
+	return c.deadline, true
+}
+
+func (c *timerCtx) String() string {
+	return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+}
+
+func (c *timerCtx) cancel(removeFromParent bool, err error) {
+	c.cancelCtx.cancel(false, err)
+	if removeFromParent {
+		// Remove this timerCtx from its parent cancelCtx's children.
+		removeChild(c.cancelCtx.Context, c)
+	}
+	c.mu.Lock()
+	if c.timer != nil {
+		c.timer.Stop()
+		c.timer = nil
+	}
+	c.mu.Unlock()
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// 	func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// 		ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// 		defer cancel()  // releases resources if slowOperation completes before timeout elapses
+// 		return slowOperation(ctx)
+// 	}
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+	return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+	return &valueCtx{parent, key, val}
+}
+
+// A valueCtx carries a key-value pair.  It implements Value for that key and
+// delegates all other calls to the embedded Context.
+type valueCtx struct {
+	Context
+	key, val interface{}
+}
+
+func (c *valueCtx) String() string {
+	return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val)
+}
+
+func (c *valueCtx) Value(key interface{}) interface{} {
+	if c.key == key {
+		return c.val
+	}
+	return c.Context.Value(key)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/context_test.go b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go
new file mode 100644
index 00000000..faf67722
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/context/context_test.go
@@ -0,0 +1,575 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context
+
+import (
+	"fmt"
+	"math/rand"
+	"runtime"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+)
+
+// otherContext is a Context that's not one of the types defined in context.go.
+// This lets us test code paths that differ based on the underlying type of the
+// Context.
+type otherContext struct {
+	Context
+}
+
+func TestBackground(t *testing.T) {
+	c := Background()
+	if c == nil {
+		t.Fatalf("Background returned nil")
+	}
+	select {
+	case x := <-c.Done():
+		t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+	default:
+	}
+	if got, want := fmt.Sprint(c), "context.Background"; got != want {
+		t.Errorf("Background().String() = %q want %q", got, want)
+	}
+}
+
+func TestTODO(t *testing.T) {
+	c := TODO()
+	if c == nil {
+		t.Fatalf("TODO returned nil")
+	}
+	select {
+	case x := <-c.Done():
+		t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+	default:
+	}
+	if got, want := fmt.Sprint(c), "context.TODO"; got != want {
+		t.Errorf("TODO().String() = %q want %q", got, want)
+	}
+}
+
+func TestWithCancel(t *testing.T) {
+	c1, cancel := WithCancel(Background())
+
+	if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
+		t.Errorf("c1.String() = %q want %q", got, want)
+	}
+
+	o := otherContext{c1}
+	c2, _ := WithCancel(o)
+	contexts := []Context{c1, o, c2}
+
+	for i, c := range contexts {
+		if d := c.Done(); d == nil {
+			t.Errorf("c[%d].Done() == %v want non-nil", i, d)
+		}
+		if e := c.Err(); e != nil {
+			t.Errorf("c[%d].Err() == %v want nil", i, e)
+		}
+
+		select {
+		case x := <-c.Done():
+			t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
+		default:
+		}
+	}
+
+	cancel()
+	time.Sleep(100 * time.Millisecond) // let cancelation propagate
+
+	for i, c := range contexts {
+		select {
+		case <-c.Done():
+		default:
+			t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
+		}
+		if e := c.Err(); e != Canceled {
+			t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
+		}
+	}
+}
+
+func TestParentFinishesChild(t *testing.T) {
+	// Context tree:
+	// parent -> cancelChild
+	// parent -> valueChild -> timerChild
+	parent, cancel := WithCancel(Background())
+	cancelChild, stop := WithCancel(parent)
+	defer stop()
+	valueChild := WithValue(parent, "key", "value")
+	timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
+	defer stop()
+
+	select {
+	case x := <-parent.Done():
+		t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+	case x := <-cancelChild.Done():
+		t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
+	case x := <-timerChild.Done():
+		t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
+	case x := <-valueChild.Done():
+		t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
+	default:
+	}
+
+	// The parent's children should contain the two cancelable children.
+	pc := parent.(*cancelCtx)
+	cc := cancelChild.(*cancelCtx)
+	tc := timerChild.(*timerCtx)
+	pc.mu.Lock()
+	if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
+		t.Errorf("bad linkage: pc.children = %v, want %v and %v",
+			pc.children, cc, tc)
+	}
+	pc.mu.Unlock()
+
+	if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
+		t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
+	}
+	if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
+		t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
+	}
+
+	cancel()
+
+	pc.mu.Lock()
+	if len(pc.children) != 0 {
+		t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
+	}
+	pc.mu.Unlock()
+
+	// parent and children should all be finished.
+	check := func(ctx Context, name string) {
+		select {
+		case <-ctx.Done():
+		default:
+			t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
+		}
+		if e := ctx.Err(); e != Canceled {
+			t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
+		}
+	}
+	check(parent, "parent")
+	check(cancelChild, "cancelChild")
+	check(valueChild, "valueChild")
+	check(timerChild, "timerChild")
+
+	// WithCancel should return a canceled context on a canceled parent.
+	precanceledChild := WithValue(parent, "key", "value")
+	select {
+	case <-precanceledChild.Done():
+	default:
+		t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
+	}
+	if e := precanceledChild.Err(); e != Canceled {
+		t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
+	}
+}
+
+func TestChildFinishesFirst(t *testing.T) {
+	cancelable, stop := WithCancel(Background())
+	defer stop()
+	for _, parent := range []Context{Background(), cancelable} {
+		child, cancel := WithCancel(parent)
+
+		select {
+		case x := <-parent.Done():
+			t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+		case x := <-child.Done():
+			t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
+		default:
+		}
+
+		cc := child.(*cancelCtx)
+		pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
+		if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
+			t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
+		}
+
+		if pcok {
+			pc.mu.Lock()
+			if len(pc.children) != 1 || !pc.children[cc] {
+				t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
+			}
+			pc.mu.Unlock()
+		}
+
+		cancel()
+
+		if pcok {
+			pc.mu.Lock()
+			if len(pc.children) != 0 {
+				t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
+			}
+			pc.mu.Unlock()
+		}
+
+		// child should be finished.
+		select {
+		case <-child.Done():
+		default:
+			t.Errorf("<-child.Done() blocked, but shouldn't have")
+		}
+		if e := child.Err(); e != Canceled {
+			t.Errorf("child.Err() == %v want %v", e, Canceled)
+		}
+
+		// parent should not be finished.
+		select {
+		case x := <-parent.Done():
+			t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
+		default:
+		}
+		if e := parent.Err(); e != nil {
+			t.Errorf("parent.Err() == %v want nil", e)
+		}
+	}
+}
+
+func testDeadline(c Context, wait time.Duration, t *testing.T) {
+	select {
+	case <-time.After(wait):
+		t.Fatalf("context should have timed out")
+	case <-c.Done():
+	}
+	if e := c.Err(); e != DeadlineExceeded {
+		t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
+	}
+}
+
+func TestDeadline(t *testing.T) {
+	c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
+	if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
+		t.Errorf("c.String() = %q want prefix %q", got, prefix)
+	}
+	testDeadline(c, 200*time.Millisecond, t)
+
+	c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
+	o := otherContext{c}
+	testDeadline(o, 200*time.Millisecond, t)
+
+	c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
+	o = otherContext{c}
+	c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
+	testDeadline(c, 200*time.Millisecond, t)
+}
+
+func TestTimeout(t *testing.T) {
+	c, _ := WithTimeout(Background(), 100*time.Millisecond)
+	if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
+		t.Errorf("c.String() = %q want prefix %q", got, prefix)
+	}
+	testDeadline(c, 200*time.Millisecond, t)
+
+	c, _ = WithTimeout(Background(), 100*time.Millisecond)
+	o := otherContext{c}
+	testDeadline(o, 200*time.Millisecond, t)
+
+	c, _ = WithTimeout(Background(), 100*time.Millisecond)
+	o = otherContext{c}
+	c, _ = WithTimeout(o, 300*time.Millisecond)
+	testDeadline(c, 200*time.Millisecond, t)
+}
+
+func TestCanceledTimeout(t *testing.T) {
+	c, _ := WithTimeout(Background(), 200*time.Millisecond)
+	o := otherContext{c}
+	c, cancel := WithTimeout(o, 400*time.Millisecond)
+	cancel()
+	time.Sleep(100 * time.Millisecond) // let cancelation propagate
+	select {
+	case <-c.Done():
+	default:
+		t.Errorf("<-c.Done() blocked, but shouldn't have")
+	}
+	if e := c.Err(); e != Canceled {
+		t.Errorf("c.Err() == %v want %v", e, Canceled)
+	}
+}
+
+type key1 int
+type key2 int
+
+var k1 = key1(1)
+var k2 = key2(1) // same int as k1, different type
+var k3 = key2(3) // same type as k2, different int
+
+func TestValues(t *testing.T) {
+	check := func(c Context, nm, v1, v2, v3 string) {
+		if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
+			t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
+		}
+		if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
+			t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
+		}
+		if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
+			t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
+		}
+	}
+
+	c0 := Background()
+	check(c0, "c0", "", "", "")
+
+	c1 := WithValue(Background(), k1, "c1k1")
+	check(c1, "c1", "c1k1", "", "")
+
+	if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
+		t.Errorf("c.String() = %q want %q", got, want)
+	}
+
+	c2 := WithValue(c1, k2, "c2k2")
+	check(c2, "c2", "c1k1", "c2k2", "")
+
+	c3 := WithValue(c2, k3, "c3k3")
+	check(c3, "c2", "c1k1", "c2k2", "c3k3")
+
+	c4 := WithValue(c3, k1, nil)
+	check(c4, "c4", "", "c2k2", "c3k3")
+
+	o0 := otherContext{Background()}
+	check(o0, "o0", "", "", "")
+
+	o1 := otherContext{WithValue(Background(), k1, "c1k1")}
+	check(o1, "o1", "c1k1", "", "")
+
+	o2 := WithValue(o1, k2, "o2k2")
+	check(o2, "o2", "c1k1", "o2k2", "")
+
+	o3 := otherContext{c4}
+	check(o3, "o3", "", "c2k2", "c3k3")
+
+	o4 := WithValue(o3, k3, nil)
+	check(o4, "o4", "", "c2k2", "")
+}
+
+func TestAllocs(t *testing.T) {
+	bg := Background()
+	for _, test := range []struct {
+		desc       string
+		f          func()
+		limit      float64
+		gccgoLimit float64
+	}{
+		{
+			desc:       "Background()",
+			f:          func() { Background() },
+			limit:      0,
+			gccgoLimit: 0,
+		},
+		{
+			desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
+			f: func() {
+				c := WithValue(bg, k1, nil)
+				c.Value(k1)
+			},
+			limit:      3,
+			gccgoLimit: 3,
+		},
+		{
+			desc: "WithTimeout(bg, 15*time.Millisecond)",
+			f: func() {
+				c, _ := WithTimeout(bg, 15*time.Millisecond)
+				<-c.Done()
+			},
+			limit:      8,
+			gccgoLimit: 13,
+		},
+		{
+			desc: "WithCancel(bg)",
+			f: func() {
+				c, cancel := WithCancel(bg)
+				cancel()
+				<-c.Done()
+			},
+			limit:      5,
+			gccgoLimit: 8,
+		},
+		{
+			desc: "WithTimeout(bg, 100*time.Millisecond)",
+			f: func() {
+				c, cancel := WithTimeout(bg, 100*time.Millisecond)
+				cancel()
+				<-c.Done()
+			},
+			limit:      8,
+			gccgoLimit: 25,
+		},
+	} {
+		limit := test.limit
+		if runtime.Compiler == "gccgo" {
+			// gccgo does not yet do escape analysis.
+			// TOOD(iant): Remove this when gccgo does do escape analysis.
+			limit = test.gccgoLimit
+		}
+		if n := testing.AllocsPerRun(100, test.f); n > limit {
+			t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
+		}
+	}
+}
+
+func TestSimultaneousCancels(t *testing.T) {
+	root, cancel := WithCancel(Background())
+	m := map[Context]CancelFunc{root: cancel}
+	q := []Context{root}
+	// Create a tree of contexts.
+	for len(q) != 0 && len(m) < 100 {
+		parent := q[0]
+		q = q[1:]
+		for i := 0; i < 4; i++ {
+			ctx, cancel := WithCancel(parent)
+			m[ctx] = cancel
+			q = append(q, ctx)
+		}
+	}
+	// Start all the cancels in a random order.
+	var wg sync.WaitGroup
+	wg.Add(len(m))
+	for _, cancel := range m {
+		go func(cancel CancelFunc) {
+			cancel()
+			wg.Done()
+		}(cancel)
+	}
+	// Wait on all the contexts in a random order.
+	for ctx := range m {
+		select {
+		case <-ctx.Done():
+		case <-time.After(1 * time.Second):
+			buf := make([]byte, 10<<10)
+			n := runtime.Stack(buf, true)
+			t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
+		}
+	}
+	// Wait for all the cancel functions to return.
+	done := make(chan struct{})
+	go func() {
+		wg.Wait()
+		close(done)
+	}()
+	select {
+	case <-done:
+	case <-time.After(1 * time.Second):
+		buf := make([]byte, 10<<10)
+		n := runtime.Stack(buf, true)
+		t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
+	}
+}
+
+func TestInterlockedCancels(t *testing.T) {
+	parent, cancelParent := WithCancel(Background())
+	child, cancelChild := WithCancel(parent)
+	go func() {
+		parent.Done()
+		cancelChild()
+	}()
+	cancelParent()
+	select {
+	case <-child.Done():
+	case <-time.After(1 * time.Second):
+		buf := make([]byte, 10<<10)
+		n := runtime.Stack(buf, true)
+		t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
+	}
+}
+
+func TestLayersCancel(t *testing.T) {
+	testLayers(t, time.Now().UnixNano(), false)
+}
+
+func TestLayersTimeout(t *testing.T) {
+	testLayers(t, time.Now().UnixNano(), true)
+}
+
+func testLayers(t *testing.T, seed int64, testTimeout bool) {
+	rand.Seed(seed)
+	errorf := func(format string, a ...interface{}) {
+		t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
+	}
+	const (
+		timeout   = 200 * time.Millisecond
+		minLayers = 30
+	)
+	type value int
+	var (
+		vals      []*value
+		cancels   []CancelFunc
+		numTimers int
+		ctx       = Background()
+	)
+	for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
+		switch rand.Intn(3) {
+		case 0:
+			v := new(value)
+			ctx = WithValue(ctx, v, v)
+			vals = append(vals, v)
+		case 1:
+			var cancel CancelFunc
+			ctx, cancel = WithCancel(ctx)
+			cancels = append(cancels, cancel)
+		case 2:
+			var cancel CancelFunc
+			ctx, cancel = WithTimeout(ctx, timeout)
+			cancels = append(cancels, cancel)
+			numTimers++
+		}
+	}
+	checkValues := func(when string) {
+		for _, key := range vals {
+			if val := ctx.Value(key).(*value); key != val {
+				errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
+			}
+		}
+	}
+	select {
+	case <-ctx.Done():
+		errorf("ctx should not be canceled yet")
+	default:
+	}
+	if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
+		t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
+	}
+	t.Log(ctx)
+	checkValues("before cancel")
+	if testTimeout {
+		select {
+		case <-ctx.Done():
+		case <-time.After(timeout + timeout/10):
+			errorf("ctx should have timed out")
+		}
+		checkValues("after timeout")
+	} else {
+		cancel := cancels[rand.Intn(len(cancels))]
+		cancel()
+		select {
+		case <-ctx.Done():
+		default:
+			errorf("ctx should be canceled")
+		}
+		checkValues("after cancel")
+	}
+}
+
+func TestCancelRemoves(t *testing.T) {
+	checkChildren := func(when string, ctx Context, want int) {
+		if got := len(ctx.(*cancelCtx).children); got != want {
+			t.Errorf("%s: context has %d children, want %d", when, got, want)
+		}
+	}
+
+	ctx, _ := WithCancel(Background())
+	checkChildren("after creation", ctx, 0)
+	_, cancel := WithCancel(ctx)
+	checkChildren("with WithCancel child ", ctx, 1)
+	cancel()
+	checkChildren("after cancelling WithCancel child", ctx, 0)
+
+	ctx, _ = WithCancel(Background())
+	checkChildren("after creation", ctx, 0)
+	_, cancel = WithTimeout(ctx, 60*time.Minute)
+	checkChildren("with WithTimeout child ", ctx, 1)
+	cancel()
+	checkChildren("after cancelling WithTimeout child", ctx, 0)
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go b/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go
new file mode 100644
index 00000000..a6754dc3
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/context/withtimeout_test.go
@@ -0,0 +1,26 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context_test
+
+import (
+	"fmt"
+	"time"
+
+	"golang.org/x/net/context"
+)
+
+func ExampleWithTimeout() {
+	// Pass a context with a timeout to tell a blocking function that it
+	// should abandon its work after the timeout elapses.
+	ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
+	select {
+	case <-time.After(200 * time.Millisecond):
+		fmt.Println("overslept")
+	case <-ctx.Done():
+		fmt.Println(ctx.Err()) // prints "context deadline exceeded"
+	}
+	// Output:
+	// context deadline exceeded
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/netutil/listen.go b/Godeps/_workspace/src/golang.org/x/net/netutil/listen.go
new file mode 100644
index 00000000..a2591f83
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/netutil/listen.go
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package netutil provides network utility functions, complementing the more
+// common ones in the net package.
+package netutil
+
+import (
+	"net"
+	"sync"
+)
+
+// LimitListener returns a Listener that accepts at most n simultaneous
+// connections from the provided Listener.
+func LimitListener(l net.Listener, n int) net.Listener {
+	return &limitListener{l, make(chan struct{}, n)}
+}
+
+type limitListener struct {
+	net.Listener
+	sem chan struct{}
+}
+
+func (l *limitListener) acquire() { l.sem <- struct{}{} }
+func (l *limitListener) release() { <-l.sem }
+
+func (l *limitListener) Accept() (net.Conn, error) {
+	l.acquire()
+	c, err := l.Listener.Accept()
+	if err != nil {
+		l.release()
+		return nil, err
+	}
+	return &limitListenerConn{Conn: c, release: l.release}, nil
+}
+
+type limitListenerConn struct {
+	net.Conn
+	releaseOnce sync.Once
+	release     func()
+}
+
+func (l *limitListenerConn) Close() error {
+	err := l.Conn.Close()
+	l.releaseOnce.Do(l.release)
+	return err
+}
diff --git a/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
new file mode 100644
index 00000000..ac87e0ee
--- /dev/null
+++ b/Godeps/_workspace/src/golang.org/x/net/netutil/listen_test.go
@@ -0,0 +1,103 @@
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.3
+
+// (We only run this test on Go 1.3 because the HTTP client timeout behavior
+// was bad in previous releases, causing occasional deadlocks.)
+
+package netutil
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net"
+	"net/http"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+func TestLimitListener(t *testing.T) {
+	const (
+		max = 5
+		num = 200
+	)
+
+	l, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen: %v", err)
+	}
+	defer l.Close()
+	l = LimitListener(l, max)
+
+	var open int32
+	go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		if n := atomic.AddInt32(&open, 1); n > max {
+			t.Errorf("%d open connections, want <= %d", n, max)
+		}
+		defer atomic.AddInt32(&open, -1)
+		time.Sleep(10 * time.Millisecond)
+		fmt.Fprint(w, "some body")
+	}))
+
+	var wg sync.WaitGroup
+	var failed int32
+	for i := 0; i < num; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			c := http.Client{Timeout: 3 * time.Second}
+			r, err := c.Get("http://" + l.Addr().String())
+			if err != nil {
+				t.Logf("Get: %v", err)
+				atomic.AddInt32(&failed, 1)
+				return
+			}
+			defer r.Body.Close()
+			io.Copy(ioutil.Discard, r.Body)
+		}()
+	}
+	wg.Wait()
+
+	// We expect some Gets to fail as the kernel's accept queue is filled,
+	// but most should succeed.
+	if failed >= num/2 {
+		t.Errorf("too many Gets failed: %v", failed)
+	}
+}
+
+type errorListener struct {
+	net.Listener
+}
+
+func (errorListener) Accept() (net.Conn, error) {
+	return nil, errFake
+}
+
+var errFake = errors.New("fake error from errorListener")
+
+// This used to hang.
+func TestLimitListenerError(t *testing.T) {
+	donec := make(chan bool, 1)
+	go func() {
+		const n = 2
+		ll := LimitListener(errorListener{}, n)
+		for i := 0; i < n+1; i++ {
+			_, err := ll.Accept()
+			if err != errFake {
+				t.Fatalf("Accept error = %v; want errFake", err)
+			}
+		}
+		donec <- true
+	}()
+	select {
+	case <-donec:
+	case <-time.After(5 * time.Second):
+		t.Fatal("timeout. deadlock?")
+	}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
new file mode 100644
index 00000000..41590204
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.gitignore
@@ -0,0 +1,26 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
+*.test
+*.out
\ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml
new file mode 100644
index 00000000..68398d9f
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/.travis.yml
@@ -0,0 +1,13 @@
+language: go
+
+notificaitons:
+  email:
+    recipients: bluesuncorp01@gmail.com
+    on_success: change
+    on_failure: always
+
+go:
+  - 1.2
+  - 1.3
+  - 1.4
+  - tip
\ No newline at end of file
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/LICENSE b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/LICENSE
new file mode 100644
index 00000000..6a2ae9aa
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Dean Karn
+
+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.
+
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
new file mode 100644
index 00000000..c1e9d00c
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/README.md
@@ -0,0 +1,44 @@
+Package validator
+================
+[![Build Status](https://travis-ci.org/bluesuncorp/validator.svg?branch=v5.1)](https://travis-ci.org/bluesuncorp/validator)
+[![GoDoc](https://godoc.org/gopkg.in/bluesuncorp/validator.v5?status.svg)](https://godoc.org/gopkg.in/bluesuncorp/validator.v5)
+
+Package validator implements value validations for structs and individual fields based on tags.
+It is also capable of Cross Field and Cross Struct validations.
+
+Installation
+============
+
+Use go get.
+
+	go get gopkg.in/bluesuncorp/validator.v5
+
+or to update
+
+	go get -u gopkg.in/bluesuncorp/validator.v5
+
+Then import the validator package into your own code.
+
+	import "gopkg.in/bluesuncorp/validator.v5"
+
+Usage and documentation
+=======================
+
+Please see http://godoc.org/gopkg.in/bluesuncorp/validator.v5 for detailed usage docs.
+
+How to Contribute
+=================
+
+There will always be a development branch for each version i.e. `v1-development`. In order to contribute, 
+please make your pull requests against those branches.
+
+If the changes being proposed or requested are breaking changes, please create an issue, for discussion 
+or create a pull request against the highest development branch for example this package has a 
+v1 and v1-development branch however, there will also be a v2-development brach even though v2 doesn't exist yet.
+
+I strongly encourage everyone whom creates a custom validation function to contribute them and
+help make this package even better.
+
+License
+=======
+Distributed under MIT License, please see license file in code for more details.
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
new file mode 100644
index 00000000..ed69eb30
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/baked_in.go
@@ -0,0 +1,864 @@
+package validator
+
+import (
+	"fmt"
+	"net/url"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+	"unicode/utf8"
+)
+
+// BakedInValidators is the default map of ValidationFunc
+// you can add, remove or even replace items to suite your needs,
+// or even disregard and use your own map if so desired.
+var BakedInValidators = map[string]Func{
+	"required":     hasValue,
+	"len":          hasLengthOf,
+	"min":          hasMinOf,
+	"max":          hasMaxOf,
+	"eq":           isEq,
+	"ne":           isNe,
+	"lt":           isLt,
+	"lte":          isLte,
+	"gt":           isGt,
+	"gte":          isGte,
+	"eqfield":      isEqField,
+	"nefield":      isNeField,
+	"gtefield":     isGteField,
+	"gtfield":      isGtField,
+	"ltefield":     isLteField,
+	"ltfield":      isLtField,
+	"alpha":        isAlpha,
+	"alphanum":     isAlphanum,
+	"numeric":      isNumeric,
+	"number":       isNumber,
+	"hexadecimal":  isHexadecimal,
+	"hexcolor":     isHexcolor,
+	"rgb":          isRgb,
+	"rgba":         isRgba,
+	"hsl":          isHsl,
+	"hsla":         isHsla,
+	"email":        isEmail,
+	"url":          isURL,
+	"uri":          isURI,
+	"base64":       isBase64,
+	"contains":     contains,
+	"containsany":  containsAny,
+	"containsrune": containsRune,
+	"excludes":     excludes,
+	"excludesall":  excludesAll,
+	"excludesrune": excludesRune,
+}
+
+func excludesRune(top interface{}, current interface{}, field interface{}, param string) bool {
+	return !containsRune(top, current, field, param)
+}
+
+func excludesAll(top interface{}, current interface{}, field interface{}, param string) bool {
+	return !containsAny(top, current, field, param)
+}
+
+func excludes(top interface{}, current interface{}, field interface{}, param string) bool {
+	return !contains(top, current, field, param)
+}
+
+func containsRune(top interface{}, current interface{}, field interface{}, param string) bool {
+	r, _ := utf8.DecodeRuneInString(param)
+
+	return strings.ContainsRune(field.(string), r)
+}
+
+func containsAny(top interface{}, current interface{}, field interface{}, param string) bool {
+	return strings.ContainsAny(field.(string), param)
+}
+
+func contains(top interface{}, current interface{}, field interface{}, param string) bool {
+	return strings.Contains(field.(string), param)
+}
+
+func isNeField(top interface{}, current interface{}, field interface{}, param string) bool {
+	return !isEqField(top, current, field, param)
+}
+
+func isNe(top interface{}, current interface{}, field interface{}, param string) bool {
+	return !isEq(top, current, field, param)
+}
+
+func isEqField(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	if current == nil {
+		panic("struct not passed for cross validation")
+	}
+
+	currentVal := reflect.ValueOf(current)
+
+	if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
+		currentVal = reflect.ValueOf(currentVal.Elem().Interface())
+	}
+
+	var currentFielVal reflect.Value
+
+	switch currentVal.Kind() {
+
+	case reflect.Struct:
+
+		if currentVal.Type() == reflect.TypeOf(time.Time{}) {
+			currentFielVal = currentVal
+			break
+		}
+
+		f := currentVal.FieldByName(param)
+
+		if f.Kind() == reflect.Invalid {
+			panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
+		}
+
+		currentFielVal = f
+
+	default:
+
+		currentFielVal = currentVal
+	}
+
+	if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
+
+		currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
+	}
+
+	fv := reflect.ValueOf(field)
+
+	switch fv.Kind() {
+
+	case reflect.String:
+		return fv.String() == currentFielVal.String()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+
+		return fv.Int() == currentFielVal.Int()
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+
+		return fv.Uint() == currentFielVal.Uint()
+
+	case reflect.Float32, reflect.Float64:
+
+		return fv.Float() == currentFielVal.Float()
+	case reflect.Slice, reflect.Map, reflect.Array:
+
+		return int64(fv.Len()) == int64(currentFielVal.Len())
+	case reflect.Struct:
+
+		if fv.Type() == reflect.TypeOf(time.Time{}) {
+
+			if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
+				panic("Bad Top Level field type")
+			}
+
+			t := currentFielVal.Interface().(time.Time)
+			fieldTime := field.(time.Time)
+
+			return fieldTime.Equal(t)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isEq(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+
+		return st.String() == param
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) == p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() == p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() == p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() == p
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isBase64(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(base64Regex, field)
+}
+
+func isURI(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		_, err := url.ParseRequestURI(field.(string))
+
+		return err == nil
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isURL(top interface{}, current interface{}, field interface{}, param string) bool {
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		url, err := url.ParseRequestURI(field.(string))
+
+		if err != nil {
+			return false
+		}
+
+		if len(url.Scheme) == 0 {
+			return false
+		}
+
+		return err == nil
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isEmail(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(emailRegex, field)
+}
+
+func isHsla(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(hslaRegex, field)
+}
+
+func isHsl(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(hslRegex, field)
+}
+
+func isRgba(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(rgbaRegex, field)
+}
+
+func isRgb(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(rgbRegex, field)
+}
+
+func isHexcolor(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(hexcolorRegex, field)
+}
+
+func isHexadecimal(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(hexadecimalRegex, field)
+}
+
+func isNumber(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(numberRegex, field)
+}
+
+func isNumeric(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(numericRegex, field)
+}
+
+func isAlphanum(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(alphaNumericRegex, field)
+}
+
+func isAlpha(top interface{}, current interface{}, field interface{}, param string) bool {
+	return matchesRegex(alphaRegex, field)
+}
+
+func hasValue(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		return field != nil && int64(st.Len()) > 0
+
+	default:
+		return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface()
+	}
+}
+
+func isGteField(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	if current == nil {
+		panic("struct not passed for cross validation")
+	}
+
+	currentVal := reflect.ValueOf(current)
+
+	if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
+		currentVal = reflect.ValueOf(currentVal.Elem().Interface())
+	}
+
+	var currentFielVal reflect.Value
+
+	switch currentVal.Kind() {
+
+	case reflect.Struct:
+
+		if currentVal.Type() == reflect.TypeOf(time.Time{}) {
+			currentFielVal = currentVal
+			break
+		}
+
+		f := currentVal.FieldByName(param)
+
+		if f.Kind() == reflect.Invalid {
+			panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
+		}
+
+		currentFielVal = f
+
+	default:
+
+		currentFielVal = currentVal
+	}
+
+	if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
+
+		currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
+	}
+
+	fv := reflect.ValueOf(field)
+
+	switch fv.Kind() {
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+
+		return fv.Int() >= currentFielVal.Int()
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+
+		return fv.Uint() >= currentFielVal.Uint()
+
+	case reflect.Float32, reflect.Float64:
+
+		return fv.Float() >= currentFielVal.Float()
+
+	case reflect.Struct:
+
+		if fv.Type() == reflect.TypeOf(time.Time{}) {
+
+			if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
+				panic("Bad Top Level field type")
+			}
+
+			t := currentFielVal.Interface().(time.Time)
+			fieldTime := field.(time.Time)
+
+			return fieldTime.After(t) || fieldTime.Equal(t)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isGtField(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	if current == nil {
+		panic("struct not passed for cross validation")
+	}
+
+	currentVal := reflect.ValueOf(current)
+
+	if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
+		currentVal = reflect.ValueOf(currentVal.Elem().Interface())
+	}
+
+	var currentFielVal reflect.Value
+
+	switch currentVal.Kind() {
+
+	case reflect.Struct:
+
+		if currentVal.Type() == reflect.TypeOf(time.Time{}) {
+			currentFielVal = currentVal
+			break
+		}
+
+		f := currentVal.FieldByName(param)
+
+		if f.Kind() == reflect.Invalid {
+			panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
+		}
+
+		currentFielVal = f
+
+	default:
+
+		currentFielVal = currentVal
+	}
+
+	if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
+
+		currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
+	}
+
+	fv := reflect.ValueOf(field)
+
+	switch fv.Kind() {
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+
+		return fv.Int() > currentFielVal.Int()
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+
+		return fv.Uint() > currentFielVal.Uint()
+
+	case reflect.Float32, reflect.Float64:
+
+		return fv.Float() > currentFielVal.Float()
+
+	case reflect.Struct:
+
+		if fv.Type() == reflect.TypeOf(time.Time{}) {
+
+			if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
+				panic("Bad Top Level field type")
+			}
+
+			t := currentFielVal.Interface().(time.Time)
+			fieldTime := field.(time.Time)
+
+			return fieldTime.After(t)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isGte(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		p := asInt(param)
+
+		return int64(len(st.String())) >= p
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) >= p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() >= p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() >= p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() >= p
+
+	case reflect.Struct:
+
+		if st.Type() == reflect.TypeOf(time.Time{}) {
+
+			now := time.Now().UTC()
+			t := field.(time.Time)
+
+			return t.After(now) || t.Equal(now)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isGt(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		p := asInt(param)
+
+		return int64(len(st.String())) > p
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) > p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() > p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() > p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() > p
+	case reflect.Struct:
+
+		if st.Type() == reflect.TypeOf(time.Time{}) {
+
+			return field.(time.Time).After(time.Now().UTC())
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+// length tests whether a variable's length is equal to a given
+// value. For strings it tests the number of characters whereas
+// for maps and slices it tests the number of items.
+func hasLengthOf(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		p := asInt(param)
+
+		return int64(len(st.String())) == p
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) == p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() == p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() == p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() == p
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+// min tests whether a variable value is larger or equal to a given
+// number. For number types, it's a simple lesser-than test; for
+// strings it tests the number of characters whereas for maps
+// and slices it tests the number of items.
+func hasMinOf(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	return isGte(top, current, field, param)
+}
+
+func isLteField(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	if current == nil {
+		panic("struct not passed for cross validation")
+	}
+
+	currentVal := reflect.ValueOf(current)
+
+	if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
+		currentVal = reflect.ValueOf(currentVal.Elem().Interface())
+	}
+
+	var currentFielVal reflect.Value
+
+	switch currentVal.Kind() {
+
+	case reflect.Struct:
+
+		if currentVal.Type() == reflect.TypeOf(time.Time{}) {
+			currentFielVal = currentVal
+			break
+		}
+
+		f := currentVal.FieldByName(param)
+
+		if f.Kind() == reflect.Invalid {
+			panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
+		}
+
+		currentFielVal = f
+
+	default:
+
+		currentFielVal = currentVal
+	}
+
+	if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
+
+		currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
+	}
+
+	fv := reflect.ValueOf(field)
+
+	switch fv.Kind() {
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+
+		return fv.Int() <= currentFielVal.Int()
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+
+		return fv.Uint() <= currentFielVal.Uint()
+
+	case reflect.Float32, reflect.Float64:
+
+		return fv.Float() <= currentFielVal.Float()
+
+	case reflect.Struct:
+
+		if fv.Type() == reflect.TypeOf(time.Time{}) {
+
+			if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
+				panic("Bad Top Level field type")
+			}
+
+			t := currentFielVal.Interface().(time.Time)
+			fieldTime := field.(time.Time)
+
+			return fieldTime.Before(t) || fieldTime.Equal(t)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isLtField(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	if current == nil {
+		panic("struct not passed for cross validation")
+	}
+
+	currentVal := reflect.ValueOf(current)
+
+	if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
+		currentVal = reflect.ValueOf(currentVal.Elem().Interface())
+	}
+
+	var currentFielVal reflect.Value
+
+	switch currentVal.Kind() {
+
+	case reflect.Struct:
+
+		if currentVal.Type() == reflect.TypeOf(time.Time{}) {
+			currentFielVal = currentVal
+			break
+		}
+
+		f := currentVal.FieldByName(param)
+
+		if f.Kind() == reflect.Invalid {
+			panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
+		}
+
+		currentFielVal = f
+
+	default:
+
+		currentFielVal = currentVal
+	}
+
+	if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
+
+		currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
+	}
+
+	fv := reflect.ValueOf(field)
+
+	switch fv.Kind() {
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+
+		return fv.Int() < currentFielVal.Int()
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+
+		return fv.Uint() < currentFielVal.Uint()
+
+	case reflect.Float32, reflect.Float64:
+
+		return fv.Float() < currentFielVal.Float()
+
+	case reflect.Struct:
+
+		if fv.Type() == reflect.TypeOf(time.Time{}) {
+
+			if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
+				panic("Bad Top Level field type")
+			}
+
+			t := currentFielVal.Interface().(time.Time)
+			fieldTime := field.(time.Time)
+
+			return fieldTime.Before(t)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isLte(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		p := asInt(param)
+
+		return int64(len(st.String())) <= p
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) <= p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() <= p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() <= p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() <= p
+
+	case reflect.Struct:
+
+		if st.Type() == reflect.TypeOf(time.Time{}) {
+
+			now := time.Now().UTC()
+			t := field.(time.Time)
+
+			return t.Before(now) || t.Equal(now)
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+func isLt(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	st := reflect.ValueOf(field)
+
+	switch st.Kind() {
+
+	case reflect.String:
+		p := asInt(param)
+
+		return int64(len(st.String())) < p
+
+	case reflect.Slice, reflect.Map, reflect.Array:
+		p := asInt(param)
+
+		return int64(st.Len()) < p
+
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		p := asInt(param)
+
+		return st.Int() < p
+
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		p := asUint(param)
+
+		return st.Uint() < p
+
+	case reflect.Float32, reflect.Float64:
+		p := asFloat(param)
+
+		return st.Float() < p
+
+	case reflect.Struct:
+
+		if st.Type() == reflect.TypeOf(time.Time{}) {
+
+			return field.(time.Time).Before(time.Now().UTC())
+		}
+	}
+
+	panic(fmt.Sprintf("Bad field type %T", field))
+}
+
+// max tests whether a variable value is lesser than a given
+// value. For numbers, it's a simple lesser-than test; for
+// strings it tests the number of characters whereas for maps
+// and slices it tests the number of items.
+func hasMaxOf(top interface{}, current interface{}, field interface{}, param string) bool {
+
+	return isLte(top, current, field, param)
+}
+
+// asInt retuns the parameter as a int64
+// or panics if it can't convert
+func asInt(param string) int64 {
+
+	i, err := strconv.ParseInt(param, 0, 64)
+	panicIf(err)
+
+	return i
+}
+
+// asUint returns the parameter as a uint64
+// or panics if it can't convert
+func asUint(param string) uint64 {
+
+	i, err := strconv.ParseUint(param, 0, 64)
+	panicIf(err)
+
+	return i
+}
+
+// asFloat returns the parameter as a float64
+// or panics if it can't convert
+func asFloat(param string) float64 {
+
+	i, err := strconv.ParseFloat(param, 64)
+	panicIf(err)
+
+	return i
+}
+
+func panicIf(err error) {
+	if err != nil {
+		panic(err.Error())
+	}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
new file mode 100644
index 00000000..5282cf53
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/doc.go
@@ -0,0 +1,395 @@
+/*
+Package validator implements value validations for structs and individual fields based on tags. It can also handle Cross Field and Cross Struct validation for nested structs.
+
+Validate
+
+	validate := validator.New("validate", validator.BakedInValidators)
+
+	errs := validate.Struct(//your struct)
+	valErr := validate.Field(field, "omitempty,min=1,max=10")
+
+A simple example usage:
+
+	type UserDetail struct {
+		Details string `validate:"-"`
+	}
+
+	type User struct {
+		Name         string     `validate:"required,max=60"`
+		PreferedName string     `validate:"omitempty,max=60"`
+		Sub          UserDetail
+	}
+
+	user := &User {
+		Name: "",
+	}
+
+	// errs will contain a hierarchical list of errors
+	// using the StructErrors struct
+	// or nil if no errors exist
+	errs := validate.Struct(user)
+
+	// in this case 1 error Name is required
+	errs.Struct will be "User"
+	errs.StructErrors will be empty <-- fields that were structs
+	errs.Errors will have 1 error of type FieldError
+
+	NOTE: Anonymous Structs - they don't have names so expect the Struct name
+	within StructErrors to be blank.
+
+Error Handling
+
+The error can be used like so
+
+	fieldErr, _ := errs["Name"]
+	fieldErr.Field    // "Name"
+	fieldErr.ErrorTag // "required"
+
+Both StructErrors and FieldError implement the Error interface but it's
+intended use is for development + debugging, not a production error message.
+
+	fieldErr.Error() // Field validation for "Name" failed on the "required" tag
+	errs.Error()
+	// Struct: User
+	// Field validation for "Name" failed on the "required" tag
+
+Why not a better error message? because this library intends for you to handle your own error messages
+
+Why should I handle my own errors? Many reasons, for us building an internationalized application
+I needed to know the field and what validation failed so that I could provide an error in the users specific language.
+
+	if fieldErr.Field == "Name" {
+		switch fieldErr.ErrorTag
+		case "required":
+			return "Translated string based on field + error"
+		default:
+		return "Translated string based on field"
+	}
+
+The hierarchical error structure is hard to work with sometimes.. Agreed Flatten function to the rescue!
+Flatten will return a map of FieldError's but the field name will be namespaced.
+
+	// if UserDetail Details field failed validation
+	Field will be "Sub.Details"
+
+	// for Name
+	Field will be "Name"
+
+Custom Functions
+
+Custom functions can be added
+
+	//Structure
+	func customFunc(top interface{}, current interface{}, field interface{}, param string) bool {
+
+		if whatever {
+			return false
+		}
+
+		return true
+	}
+
+	validate.AddFunction("custom tag name", customFunc)
+	// NOTES: using the same tag name as an existing function
+	//        will overwrite the existing one
+
+Cross Field Validation
+
+Cross Field Validation can be implemented, for example Start & End Date range validation
+
+	// NOTE: when calling validate.Struct(val) val will be the top level struct passed
+	//       into the function
+	//       when calling validate.FieldWithValue(val, field, tag) val will be
+	//       whatever you pass, struct, field...
+	//       when calling validate.Field(field, tag) val will be nil
+	//
+	// Because of the specific requirements and field names within each persons project that
+	// uses this library it is likely that custom functions will need to be created for your
+	// Cross Field Validation needs, however there are some build in Generic Cross Field validations,
+	// see Baked In Validators and Tags below
+
+	func isDateRangeValid(val interface{}, field interface{}, param string) bool {
+
+		myStruct := val.(myStructType)
+
+		if myStruct.Start.After(field.(time.Time)) {
+			return false
+		}
+
+		return true
+	}
+
+Multiple Validators
+
+Multiple validators on a field will process in the order defined
+
+	type Test struct {
+		Field `validate:"max=10,min=1"`
+	}
+
+	// max will be checked then min
+
+Bad Validator definitions are not handled by the library
+
+	type Test struct {
+		Field `validate:"min=10,max=0"`
+	}
+
+	// this definition of min max will never validate
+
+Baked In Validators and Tags
+
+NOTE: Baked In Cross field validation only compares fields on the same struct,
+if cross field + cross struct validation is needed your own custom validator
+should be implemented.
+
+NOTE2: comma is the default separator of validation tags, if you wish to have a comma
+included within the parameter i.e. excludesall=, you will need to use the UTF-8 hex
+representation 0x2C, which is replaced in the code as a comma, so the above will
+become excludesall=0x2C
+
+Here is a list of the current built in validators:
+
+	-
+		Tells the validation to skip this struct field; this is particularily
+		handy in ignoring embedded structs from being validated. (Usage: -)
+
+	|
+		This is the 'or' operator allowing multiple validators to be used and
+		accepted. (Usage: rbg|rgba) <-- this would allow either rgb or rgba
+		colors to be accepted. This can also be combined with 'and' for example
+		( Usage: omitempty,rgb|rgba)
+
+	structonly
+		When a field that is a nest struct in encountered and contains this flag
+		any validation on the nested struct such as "required" will be run, but
+		none of the nested struct fields will be validated. This is usefull if
+		inside of you program you know the struct will be valid, but need to
+		verify it has been assigned.
+
+	omitempty
+		Allows conitional validation, for example if a field is not set with
+		a value (Determined by the required validator) then other validation
+		such as min or max won't run, but if a value is set validation will run.
+		(Usage: omitempty)
+
+	required
+		This validates that the value is not the data types default value.
+		For numbers ensures value is not zero. For strings ensures value is
+		not "". For slices, arrays, and maps, ensures the length is not zero.
+		(Usage: required)
+
+	len
+		For numbers, max will ensure that the value is
+		equal to the parameter given. For strings, it checks that
+		the string length is exactly that number of characters. For slices,
+		arrays, and maps, validates the number of items. (Usage: len=10)
+
+	max
+		For numbers, max will ensure that the value is
+		less than or equal to the parameter given. For strings, it checks
+		that the string length is at most that number of characters. For
+		slices, arrays, and maps, validates the number of items. (Usage: max=10)
+
+	min
+		For numbers, min will ensure that the value is
+		greater or equal to the parameter given. For strings, it checks that
+		the string length is at least that number of characters. For slices,
+		arrays, and maps, validates the number of items. (Usage: min=10)
+
+	eq
+		For strings & numbers, eq will ensure that the value is
+		equal to the parameter given. For slices, arrays, and maps,
+		validates the number of items. (Usage: eq=10)
+
+	ne
+		For strings & numbers, eq will ensure that the value is not
+		equal to the parameter given. For slices, arrays, and maps,
+		validates the number of items. (Usage: eq=10)
+
+	gt
+		For numbers, this will ensure that the value is greater than the
+		parameter given. For strings, it checks that the string length
+		is greater than that number of characters. For slices, arrays
+		and maps it validates the number of items. (Usage: gt=10)
+		For time.Time ensures the time value is greater than time.Now.UTC()
+		(Usage: gt)
+
+	gte
+		Same as 'min' above. Kept both to make terminology with 'len' easier
+		(Usage: gte=10)
+		For time.Time ensures the time value is greater than or equal to time.Now.UTC()
+		(Usage: gte)
+
+	lt
+		For numbers, this will ensure that the value is
+		less than the parameter given. For strings, it checks
+		that the string length is less than that number of characters.
+		For slices, arrays, and maps it validates the number of items.
+		(Usage: lt=10)
+		For time.Time ensures the time value is less than time.Now.UTC()
+		(Usage: lt)
+
+	lte
+		Same as 'max' above. Kept both to make terminology with 'len' easier
+		(Usage: lte=10)
+		For time.Time ensures the time value is less than or equal to time.Now.UTC()
+		(Usage: lte)
+
+	eqfield
+		This will validate the field value against another fields value either within
+		a struct or passed in field.
+		usage examples are for validation of a password and confirm password:
+		Validation on Password field using validate.Struct Usage(eqfield=ConfirmPassword)
+		Validating by field validate.FieldWithValue(password, confirmpassword, "eqfield")
+
+	nefield
+		This will validate the field value against another fields value either within
+		a struct or passed in field.
+		usage examples are for ensuring two colors are not the same:
+		Validation on Color field using validate.Struct Usage(nefield=Color2)
+		Validating by field validate.FieldWithValue(color1, color2, "nefield")
+
+	gtfield
+		Only valid for Numbers and time.Time types, this will validate the field value
+		against another fields value either within a struct or passed in field.
+		usage examples are for validation of a Start and End date:
+		Validation on End field using validate.Struct Usage(gtfield=Start)
+		Validating by field validate.FieldWithValue(start, end, "gtfield")
+
+	gtefield
+		Only valid for Numbers and time.Time types, this will validate the field value
+		against another fields value either within a struct or passed in field.
+		usage examples are for validation of a Start and End date:
+		Validation on End field using validate.Struct Usage(gtefield=Start)
+		Validating by field validate.FieldWithValue(start, end, "gtefield")
+
+	ltfield
+		Only valid for Numbers and time.Time types, this will validate the field value
+		against another fields value either within a struct or passed in field.
+		usage examples are for validation of a Start and End date:
+		Validation on End field using validate.Struct Usage(ltfield=Start)
+		Validating by field validate.FieldWithValue(start, end, "ltfield")
+
+	ltefield
+		Only valid for Numbers and time.Time types, this will validate the field value
+		against another fields value either within a struct or passed in field.
+		usage examples are for validation of a Start and End date:
+		Validation on End field using validate.Struct Usage(ltefield=Start)
+		Validating by field validate.FieldWithValue(start, end, "ltefield")
+
+	alpha
+		This validates that a string value contains alpha characters only
+		(Usage: alpha)
+
+	alphanum
+		This validates that a string value contains alphanumeric characters only
+		(Usage: alphanum)
+
+	numeric
+		This validates that a string value contains a basic numeric value.
+		basic excludes exponents etc...
+		(Usage: numeric)
+
+	hexadecimal
+		This validates that a string value contains a valid hexadecimal.
+		(Usage: hexadecimal)
+
+	hexcolor
+		This validates that a string value contains a valid hex color including
+		hashtag (#)
+		(Usage: hexcolor)
+
+	rgb
+		This validates that a string value contains a valid rgb color
+		(Usage: rgb)
+
+	rgba
+		This validates that a string value contains a valid rgba color
+		(Usage: rgba)
+
+	hsl
+		This validates that a string value contains a valid hsl color
+		(Usage: hsl)
+
+	hsla
+		This validates that a string value contains a valid hsla color
+		(Usage: hsla)
+
+	email
+		This validates that a string value contains a valid email
+		This may not conform to all possibilities of any rfc standard, but neither
+		does any email provider accept all posibilities...
+		(Usage: email)
+
+	url
+		This validates that a string value contains a valid url
+		This will accept any url the golang request uri accepts but must contain
+		a schema for example http:// or rtmp://
+		(Usage: url)
+
+	uri
+		This validates that a string value contains a valid uri
+		This will accept any uri the golang request uri accepts (Usage: uri)
+
+	base64
+		This validates that a string value contains a valid base64 value.
+		Although an empty string is valid base64 this will report an empty string
+		as an error, if you wish to accept an empty string as valid you can use
+		this with the omitempty tag. (Usage: base64)
+
+	contains
+		This validates that a string value contains the substring value.
+		(Usage: contains=@)
+
+	containsany
+		This validates that a string value contains any Unicode code points
+		in the substring value. (Usage: containsany=!@#?)
+
+	containsrune
+		This validates that a string value contains the supplied rune value.
+		(Usage: containsrune=@)
+
+	excludes
+		This validates that a string value does not contain the substring value.
+		(Usage: excludes=@)
+
+	excludesall
+		This validates that a string value does not contain any Unicode code
+		points in the substring value. (Usage: excludesall=!@#?)
+
+	excludesrune
+		This validates that a string value does not contain the supplied rune value.
+		(Usage: excludesrune=@)
+
+Validator notes:
+
+	regex
+		a regex validator won't be added because commas and = signs can be part of
+		a regex which conflict with the validation definitions, although workarounds
+		can be made, they take away from using pure regex's. Furthermore it's quick
+		and dirty but the regex's become harder to maintain and are not reusable, so
+		it's as much a programming philosiphy as anything.
+
+		In place of this new validator functions should be created; a regex can be
+		used within the validator function and even be precompiled for better efficiency
+		within regexes.go.
+
+		And the best reason, you can submit a pull request and we can keep on adding to the
+		validation library of this package!
+
+Panics
+
+This package panics when bad input is provided, this is by design, bad code like that should not make it to production.
+
+	type Test struct {
+		TestField string `validate:"nonexistantfunction=1"`
+	}
+
+	t := &Test{
+		TestField: "Test"
+	}
+
+	validate.Struct(t) // this will panic
+*/
+package validator
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/regexes.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/regexes.go
new file mode 100644
index 00000000..e5ed0fae
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/regexes.go
@@ -0,0 +1,38 @@
+package validator
+
+import "regexp"
+
+const (
+	alphaRegexString        = "^[a-zA-Z]+$"
+	alphaNumericRegexString = "^[a-zA-Z0-9]+$"
+	numericRegexString      = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
+	numberRegexString       = "^[0-9]+$"
+	hexadecimalRegexString  = "^[0-9a-fA-F]+$"
+	hexcolorRegexString     = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
+	rgbRegexString          = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
+	rgbaRegexString         = "^rgba\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*((0.[1-9]*)|[01])\\s*\\)$"
+	hslRegexString          = "^hsl\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*\\)$"
+	hslaRegexString         = "^hsla\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0.[1-9]*)|[01])\\s*\\)$"
+	emailRegexString        = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
+	base64RegexString       = "(?:^(?:[A-Za-z0-9+\\/]{4}\\n?)*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=)$)"
+)
+
+var (
+	alphaRegex        = regexp.MustCompile(alphaRegexString)
+	alphaNumericRegex = regexp.MustCompile(alphaNumericRegexString)
+	numericRegex      = regexp.MustCompile(numericRegexString)
+	numberRegex       = regexp.MustCompile(numberRegexString)
+	hexadecimalRegex  = regexp.MustCompile(hexadecimalRegexString)
+	hexcolorRegex     = regexp.MustCompile(hexcolorRegexString)
+	rgbRegex          = regexp.MustCompile(rgbRegexString)
+	rgbaRegex         = regexp.MustCompile(rgbaRegexString)
+	hslRegex          = regexp.MustCompile(hslRegexString)
+	hslaRegex         = regexp.MustCompile(hslaRegexString)
+	emailRegex        = regexp.MustCompile(emailRegexString)
+	base64Regex       = regexp.MustCompile(base64RegexString)
+)
+
+func matchesRegex(regex *regexp.Regexp, field interface{}) bool {
+	fieldAsString := field.(string) //this will panic inherently
+	return regex.MatchString(fieldAsString)
+}
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
new file mode 100644
index 00000000..33110f68
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator.go
@@ -0,0 +1,571 @@
+/**
+ * Package validator
+ *
+ * MISC:
+ * - anonymous structs - they don't have names so expect the Struct name within StructErrors to be blank
+ *
+ */
+
+package validator
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"reflect"
+	"strings"
+	"sync"
+	"time"
+	"unicode"
+)
+
+const (
+	utf8HexComma    = "0x2C"
+	tagSeparator    = ","
+	orSeparator     = "|"
+	noValidationTag = "-"
+	tagKeySeparator = "="
+	structOnlyTag   = "structonly"
+	omitempty       = "omitempty"
+	fieldErrMsg     = "Field validation for \"%s\" failed on the \"%s\" tag"
+	structErrMsg    = "Struct:%s\n"
+)
+
+var structPool *pool
+
+// Pool holds a channelStructErrors.
+type pool struct {
+	pool chan *StructErrors
+}
+
+// NewPool creates a new pool of Clients.
+func newPool(max int) *pool {
+	return &pool{
+		pool: make(chan *StructErrors, max),
+	}
+}
+
+// Borrow a StructErrors from the pool.
+func (p *pool) Borrow() *StructErrors {
+	var c *StructErrors
+
+	select {
+	case c = <-p.pool:
+	default:
+		c = &StructErrors{
+			Errors:       map[string]*FieldError{},
+			StructErrors: map[string]*StructErrors{},
+		}
+	}
+
+	return c
+}
+
+// Return returns a StructErrors to the pool.
+func (p *pool) Return(c *StructErrors) {
+
+	// c.Struct = ""
+
+	select {
+	case p.pool <- c:
+	default:
+		// let it go, let it go...
+	}
+}
+
+type cachedTags struct {
+	keyVals [][]string
+	isOrVal bool
+}
+
+type cachedField struct {
+	index  int
+	name   string
+	tags   []*cachedTags
+	tag    string
+	kind   reflect.Kind
+	typ    reflect.Type
+	isTime bool
+}
+
+type cachedStruct struct {
+	children int
+	name     string
+	kind     reflect.Kind
+	fields   []*cachedField
+}
+
+type structsCacheMap struct {
+	lock sync.RWMutex
+	m    map[reflect.Type]*cachedStruct
+}
+
+func (s *structsCacheMap) Get(key reflect.Type) (*cachedStruct, bool) {
+	s.lock.RLock()
+	defer s.lock.RUnlock()
+	value, ok := s.m[key]
+	return value, ok
+}
+
+func (s *structsCacheMap) Set(key reflect.Type, value *cachedStruct) {
+	s.lock.Lock()
+	defer s.lock.Unlock()
+	s.m[key] = value
+}
+
+var structCache = &structsCacheMap{m: map[reflect.Type]*cachedStruct{}}
+
+type fieldsCacheMap struct {
+	lock sync.RWMutex
+	m    map[string][]*cachedTags
+}
+
+func (s *fieldsCacheMap) Get(key string) ([]*cachedTags, bool) {
+	s.lock.RLock()
+	defer s.lock.RUnlock()
+	value, ok := s.m[key]
+	return value, ok
+}
+
+func (s *fieldsCacheMap) Set(key string, value []*cachedTags) {
+	s.lock.Lock()
+	defer s.lock.Unlock()
+	s.m[key] = value
+}
+
+var fieldsCache = &fieldsCacheMap{m: map[string][]*cachedTags{}}
+
+// FieldError contains a single field's validation error along
+// with other properties that may be needed for error message creation
+type FieldError struct {
+	Field string
+	Tag   string
+	Kind  reflect.Kind
+	Type  reflect.Type
+	Param string
+	Value interface{}
+}
+
+// This is intended for use in development + debugging and not intended to be a production error message.
+// it also allows FieldError to be used as an Error interface
+func (e *FieldError) Error() string {
+	return fmt.Sprintf(fieldErrMsg, e.Field, e.Tag)
+}
+
+// StructErrors is hierarchical list of field and struct validation errors
+// for a non hierarchical representation please see the Flatten method for StructErrors
+type StructErrors struct {
+	// Name of the Struct
+	Struct string
+	// Struct Field Errors
+	Errors map[string]*FieldError
+	// Struct Fields of type struct and their errors
+	// key = Field Name of current struct, but internally Struct will be the actual struct name unless anonymous struct, it will be blank
+	StructErrors map[string]*StructErrors
+}
+
+// This is intended for use in development + debugging and not intended to be a production error message.
+// it also allows StructErrors to be used as an Error interface
+func (e *StructErrors) Error() string {
+	buff := bytes.NewBufferString(fmt.Sprintf(structErrMsg, e.Struct))
+
+	for _, err := range e.Errors {
+		buff.WriteString(err.Error())
+		buff.WriteString("\n")
+	}
+
+	for _, err := range e.StructErrors {
+		buff.WriteString(err.Error())
+	}
+
+	return buff.String()
+}
+
+// Flatten flattens the StructErrors hierarchical structure into a flat namespace style field name
+// for those that want/need it
+func (e *StructErrors) Flatten() map[string]*FieldError {
+
+	if e == nil {
+		return nil
+	}
+
+	errs := map[string]*FieldError{}
+
+	for _, f := range e.Errors {
+
+		errs[f.Field] = f
+	}
+
+	for key, val := range e.StructErrors {
+
+		otherErrs := val.Flatten()
+
+		for _, f2 := range otherErrs {
+
+			f2.Field = fmt.Sprintf("%s.%s", key, f2.Field)
+			errs[f2.Field] = f2
+		}
+	}
+
+	return errs
+}
+
+// Func accepts all values needed for file and cross field validation
+// top     = top level struct when validating by struct otherwise nil
+// current = current level struct when validating by struct otherwise optional comparison value
+// f       = field value for validation
+// param   = parameter used in validation i.e. gt=0 param would be 0
+type Func func(top interface{}, current interface{}, f interface{}, param string) bool
+
+// Validate implements the Validate Struct
+// NOTE: Fields within are not thread safe and that is on purpose
+// Functions and Tags should all be predifined before use, so subscribe to the philosiphy
+// or make it thread safe on your end
+type Validate struct {
+	// tagName being used.
+	tagName string
+	// validateFuncs is a map of validation functions and the tag keys
+	validationFuncs map[string]Func
+}
+
+// New creates a new Validate instance for use.
+func New(tagName string, funcs map[string]Func) *Validate {
+
+	structPool = newPool(10)
+
+	return &Validate{
+		tagName:         tagName,
+		validationFuncs: funcs,
+	}
+}
+
+// SetTag sets tagName of the Validator to one of your choosing after creation
+// perhaps to dodge a tag name conflict in a specific section of code
+// NOTE: this method is not thread-safe
+func (v *Validate) SetTag(tagName string) {
+	v.tagName = tagName
+}
+
+// SetStructPoolMax sets the  struct pools max size. this may be usefull for fine grained
+// performance tuning towards your application, however, the default should be fine for
+// nearly all cases. only increase if you have a deeply nested struct structure.
+// NOTE: this method is not thread-safe
+// NOTE: this is only here to keep compatibility with v5, in v6 the method will be removed
+// and the max pool size will be passed into the New function
+func (v *Validate) SetMaxStructPoolSize(max int) {
+	structPool = newPool(max)
+}
+
+// AddFunction adds a validation Func to a Validate's map of validators denoted by the key
+// NOTE: if the key already exists, it will get replaced.
+// NOTE: this method is not thread-safe
+func (v *Validate) AddFunction(key string, f Func) error {
+
+	if len(key) == 0 {
+		return errors.New("Function Key cannot be empty")
+	}
+
+	if f == nil {
+		return errors.New("Function cannot be empty")
+	}
+
+	v.validationFuncs[key] = f
+
+	return nil
+}
+
+// Struct validates a struct, even it's nested structs, and returns a struct containing the errors
+// NOTE: Nested Arrays, or Maps of structs do not get validated only the Array or Map itself; the reason is that there is no good
+// way to represent or report which struct within the array has the error, besides can validate the struct prior to adding it to
+// the Array or Map.
+func (v *Validate) Struct(s interface{}) *StructErrors {
+
+	return v.structRecursive(s, s, s)
+}
+
+// structRecursive validates a struct recursivly and passes the top level and current struct around for use in validator functions and returns a struct containing the errors
+func (v *Validate) structRecursive(top interface{}, current interface{}, s interface{}) *StructErrors {
+
+	structValue := reflect.ValueOf(s)
+
+	if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
+		return v.structRecursive(top, current, structValue.Elem().Interface())
+	}
+
+	if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface {
+		panic("interface passed for validation is not a struct")
+	}
+
+	structType := reflect.TypeOf(s)
+
+	var structName string
+	var numFields int
+	var cs *cachedStruct
+	var isCached bool
+
+	cs, isCached = structCache.Get(structType)
+
+	if isCached {
+		structName = cs.name
+		numFields = cs.children
+	} else {
+		structName = structType.Name()
+		numFields = structValue.NumField()
+		cs = &cachedStruct{name: structName, children: numFields}
+		structCache.Set(structType, cs)
+	}
+
+	validationErrors := structPool.Borrow()
+	validationErrors.Struct = structName
+
+	for i := 0; i < numFields; i++ {
+
+		var valueField reflect.Value
+		var cField *cachedField
+		var typeField reflect.StructField
+
+		if isCached {
+			cField = cs.fields[i]
+			valueField = structValue.Field(cField.index)
+
+			if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
+				valueField = valueField.Elem()
+			}
+		} else {
+			valueField = structValue.Field(i)
+
+			if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
+				valueField = valueField.Elem()
+			}
+
+			typeField = structType.Field(i)
+
+			cField = &cachedField{index: i, tag: typeField.Tag.Get(v.tagName)}
+
+			if cField.tag == noValidationTag {
+				cs.children--
+				continue
+			}
+
+			// if no validation and not a struct (which may containt fields for validation)
+			if cField.tag == "" && ((valueField.Kind() != reflect.Struct && valueField.Kind() != reflect.Interface) || valueField.Type() == reflect.TypeOf(time.Time{})) {
+				cs.children--
+				continue
+			}
+
+			cField.name = typeField.Name
+			cField.kind = valueField.Kind()
+			cField.typ = valueField.Type()
+		}
+
+		// this can happen if the first cache value was nil
+		// but the second actually has a value
+		if cField.kind == reflect.Ptr {
+			cField.kind = valueField.Kind()
+		}
+
+		switch cField.kind {
+
+		case reflect.Struct, reflect.Interface:
+
+			if !unicode.IsUpper(rune(cField.name[0])) {
+				cs.children--
+				continue
+			}
+
+			if cField.isTime || valueField.Type() == reflect.TypeOf(time.Time{}) {
+
+				cField.isTime = true
+
+				if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
+					validationErrors.Errors[fieldError.Field] = fieldError
+					// free up memory reference
+					fieldError = nil
+				}
+
+			} else {
+
+				if strings.Contains(cField.tag, structOnlyTag) {
+					cs.children--
+					continue
+				}
+
+				if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
+					validationErrors.StructErrors[cField.name] = structErrors
+					// free up memory map no longer needed
+					structErrors = nil
+				}
+			}
+
+		default:
+
+			if fieldError := v.fieldWithNameAndValue(top, current, valueField.Interface(), cField.tag, cField.name, false, cField); fieldError != nil {
+				validationErrors.Errors[fieldError.Field] = fieldError
+				// free up memory reference
+				fieldError = nil
+			}
+		}
+
+		if !isCached {
+			cs.fields = append(cs.fields, cField)
+		}
+	}
+
+	if len(validationErrors.Errors) == 0 && len(validationErrors.StructErrors) == 0 {
+		structPool.Return(validationErrors)
+		return nil
+	}
+
+	return validationErrors
+}
+
+// Field allows validation of a single field, still using tag style validation to check multiple errors
+func (v *Validate) Field(f interface{}, tag string) *FieldError {
+
+	return v.FieldWithValue(nil, f, tag)
+}
+
+// FieldWithValue allows validation of a single field, possibly even against another fields value, still using tag style validation to check multiple errors
+func (v *Validate) FieldWithValue(val interface{}, f interface{}, tag string) *FieldError {
+
+	return v.fieldWithNameAndValue(nil, val, f, tag, "", true, nil)
+}
+
+func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f interface{}, tag string, name string, isSingleField bool, cacheField *cachedField) *FieldError {
+
+	var cField *cachedField
+	var isCached bool
+
+	// This is a double check if coming from validate.Struct but need to be here in case function is called directly
+	if tag == noValidationTag {
+		return nil
+	}
+
+	if strings.Contains(tag, omitempty) && !hasValue(val, current, f, "") {
+		return nil
+	}
+
+	if cacheField == nil {
+		valueField := reflect.ValueOf(f)
+
+		if valueField.Kind() == reflect.Ptr && !valueField.IsNil() {
+			valueField = valueField.Elem()
+			f = valueField.Interface()
+		}
+
+		cField = &cachedField{name: name, kind: valueField.Kind(), tag: tag, typ: valueField.Type()}
+	} else {
+		cField = cacheField
+	}
+
+	switch cField.kind {
+
+	case reflect.Struct, reflect.Interface, reflect.Invalid:
+
+		if cField.typ != reflect.TypeOf(time.Time{}) {
+			panic("Invalid field passed to ValidateFieldWithTag")
+		}
+	}
+
+	if len(cField.tags) == 0 {
+
+		if isSingleField {
+			cField.tags, isCached = fieldsCache.Get(tag)
+		}
+
+		if !isCached {
+
+			for _, t := range strings.Split(tag, tagSeparator) {
+
+				orVals := strings.Split(t, orSeparator)
+				cTag := &cachedTags{isOrVal: len(orVals) > 1, keyVals: make([][]string, len(orVals))}
+				cField.tags = append(cField.tags, cTag)
+
+				for i, val := range orVals {
+					vals := strings.SplitN(val, tagKeySeparator, 2)
+
+					key := strings.TrimSpace(vals[0])
+
+					if len(key) == 0 {
+						panic(fmt.Sprintf("Invalid validation tag on field %s", name))
+					}
+
+					param := ""
+					if len(vals) > 1 {
+						param = strings.Replace(vals[1], utf8HexComma, ",", -1)
+					}
+
+					cTag.keyVals[i] = []string{key, param}
+				}
+			}
+
+			if isSingleField {
+				fieldsCache.Set(cField.tag, cField.tags)
+			}
+		}
+	}
+
+	var fieldErr *FieldError
+	var err error
+
+	for _, cTag := range cField.tags {
+
+		if cTag.isOrVal {
+
+			errTag := ""
+
+			for _, val := range cTag.keyVals {
+
+				fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, val[0], val[1], name)
+
+				if err == nil {
+					return nil
+				}
+
+				errTag += orSeparator + fieldErr.Tag
+			}
+
+			errTag = strings.TrimLeft(errTag, orSeparator)
+
+			fieldErr.Tag = errTag
+			fieldErr.Kind = cField.kind
+			fieldErr.Type = cField.typ
+
+			return fieldErr
+		}
+
+		if fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, cTag.keyVals[0][0], cTag.keyVals[0][1], name); err != nil {
+
+			fieldErr.Kind = cField.kind
+			fieldErr.Type = cField.typ
+
+			return fieldErr
+		}
+	}
+
+	return nil
+}
+
+func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{}, f interface{}, key string, param string, name string) (*FieldError, error) {
+
+	// OK to continue because we checked it's existance before getting into this loop
+	if key == omitempty {
+		return nil, nil
+	}
+
+	valFunc, ok := v.validationFuncs[key]
+	if !ok {
+		panic(fmt.Sprintf("Undefined validation function on field %s", name))
+	}
+
+	if err := valFunc(val, current, f, param); err {
+		return nil, nil
+	}
+
+	return &FieldError{
+		Field: name,
+		Tag:   key,
+		Value: f,
+		Param: param,
+	}, errors.New(key)
+}
diff --git a/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
new file mode 100644
index 00000000..aa8c7495
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/bluesuncorp/validator.v5/validator_test.go
@@ -0,0 +1,2497 @@
+package validator
+
+import (
+	"fmt"
+	"path"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+// NOTES:
+// - Run "go test" to run tests
+// - Run "gocov test | gocov report" to report on test converage by file
+// - Run "gocov test | gocov annotate -" to report on all code and functions, those ,marked with "MISS" were never called
+//
+//
+// go test -cpuprofile cpu.out
+// ./validator.test -test.bench=. -test.cpuprofile=cpu.prof
+// go tool pprof validator.test cpu.prof
+//
+//
+// go test -memprofile mem.out
+
+type I interface {
+	Foo() string
+}
+
+type Impl struct {
+	F string `validate:"len=3"`
+}
+
+func (i *Impl) Foo() string {
+	return i.F
+}
+
+type SubTest struct {
+	Test string `validate:"required"`
+}
+
+type TestInterface struct {
+	Iface I
+}
+
+type TestString struct {
+	BlankTag  string `validate:""`
+	Required  string `validate:"required"`
+	Len       string `validate:"len=10"`
+	Min       string `validate:"min=1"`
+	Max       string `validate:"max=10"`
+	MinMax    string `validate:"min=1,max=10"`
+	Lt        string `validate:"lt=10"`
+	Lte       string `validate:"lte=10"`
+	Gt        string `validate:"gt=10"`
+	Gte       string `validate:"gte=10"`
+	OmitEmpty string `validate:"omitempty,min=1,max=10"`
+	Sub       *SubTest
+	SubIgnore *SubTest `validate:"-"`
+	Anonymous struct {
+		A string `validate:"required"`
+	}
+	Iface I
+}
+
+type TestInt32 struct {
+	Required  int `validate:"required"`
+	Len       int `validate:"len=10"`
+	Min       int `validate:"min=1"`
+	Max       int `validate:"max=10"`
+	MinMax    int `validate:"min=1,max=10"`
+	Lt        int `validate:"lt=10"`
+	Lte       int `validate:"lte=10"`
+	Gt        int `validate:"gt=10"`
+	Gte       int `validate:"gte=10"`
+	OmitEmpty int `validate:"omitempty,min=1,max=10"`
+}
+
+type TestUint64 struct {
+	Required  uint64 `validate:"required"`
+	Len       uint64 `validate:"len=10"`
+	Min       uint64 `validate:"min=1"`
+	Max       uint64 `validate:"max=10"`
+	MinMax    uint64 `validate:"min=1,max=10"`
+	OmitEmpty uint64 `validate:"omitempty,min=1,max=10"`
+}
+
+type TestFloat64 struct {
+	Required  float64 `validate:"required"`
+	Len       float64 `validate:"len=10"`
+	Min       float64 `validate:"min=1"`
+	Max       float64 `validate:"max=10"`
+	MinMax    float64 `validate:"min=1,max=10"`
+	Lte       float64 `validate:"lte=10"`
+	OmitEmpty float64 `validate:"omitempty,min=1,max=10"`
+}
+
+type TestSlice struct {
+	Required  []int `validate:"required"`
+	Len       []int `validate:"len=10"`
+	Min       []int `validate:"min=1"`
+	Max       []int `validate:"max=10"`
+	MinMax    []int `validate:"min=1,max=10"`
+	OmitEmpty []int `validate:"omitempty,min=1,max=10"`
+}
+
+var validate = New("validate", BakedInValidators)
+
+func IsEqual(t *testing.T, val1, val2 interface{}) bool {
+	v1 := reflect.ValueOf(val1)
+	v2 := reflect.ValueOf(val2)
+
+	if v1.Kind() == reflect.Ptr {
+		v1 = v1.Elem()
+	}
+
+	if v2.Kind() == reflect.Ptr {
+		v2 = v2.Elem()
+	}
+
+	if !v1.IsValid() && !v2.IsValid() {
+		return true
+	}
+
+	v1Underlying := reflect.Zero(reflect.TypeOf(v1)).Interface()
+	v2Underlying := reflect.Zero(reflect.TypeOf(v2)).Interface()
+
+	if v1 == v1Underlying {
+		if v2 == v2Underlying {
+			goto CASE4
+		} else {
+			goto CASE3
+		}
+	} else {
+		if v2 == v2Underlying {
+			goto CASE2
+		} else {
+			goto CASE1
+		}
+	}
+
+CASE1:
+	return reflect.DeepEqual(v1.Interface(), v2.Interface())
+
+CASE2:
+	return reflect.DeepEqual(v1.Interface(), v2)
+CASE3:
+	return reflect.DeepEqual(v1, v2.Interface())
+CASE4:
+	return reflect.DeepEqual(v1, v2)
+}
+
+func Equal(t *testing.T, val1, val2 interface{}) {
+	EqualSkip(t, 2, val1, val2)
+}
+
+func EqualSkip(t *testing.T, skip int, val1, val2 interface{}) {
+
+	if !IsEqual(t, val1, val2) {
+
+		_, file, line, _ := runtime.Caller(skip)
+		fmt.Printf("%s:%d %v does not equal %v\n", path.Base(file), line, val1, val2)
+		t.FailNow()
+	}
+}
+
+func NotEqual(t *testing.T, val1, val2 interface{}) {
+	NotEqualSkip(t, 2, val1, val2)
+}
+
+func NotEqualSkip(t *testing.T, skip int, val1, val2 interface{}) {
+
+	if IsEqual(t, val1, val2) {
+		_, file, line, _ := runtime.Caller(skip)
+		fmt.Printf("%s:%d %v should not be equal %v\n", path.Base(file), line, val1, val2)
+		t.FailNow()
+	}
+}
+
+func PanicMatches(t *testing.T, fn func(), matches string) {
+	PanicMatchesSkip(t, 2, fn, matches)
+}
+
+func PanicMatchesSkip(t *testing.T, skip int, fn func(), matches string) {
+
+	_, file, line, _ := runtime.Caller(skip)
+
+	defer func() {
+		if r := recover(); r != nil {
+			err := fmt.Sprintf("%s", r)
+
+			if err != matches {
+				fmt.Printf("%s:%d Panic...  expected [%s] received [%s]", path.Base(file), line, matches, err)
+				t.FailNow()
+			}
+		}
+	}()
+
+	fn()
+}
+
+func AssertStruct(t *testing.T, s *StructErrors, structFieldName string, expectedStructName string) *StructErrors {
+
+	val, ok := s.StructErrors[structFieldName]
+	EqualSkip(t, 2, ok, true)
+	NotEqualSkip(t, 2, val, nil)
+	EqualSkip(t, 2, val.Struct, expectedStructName)
+
+	return val
+}
+
+func AssertFieldError(t *testing.T, s *StructErrors, field string, expectedTag string) {
+
+	val, ok := s.Errors[field]
+	EqualSkip(t, 2, ok, true)
+	NotEqualSkip(t, 2, val, nil)
+	EqualSkip(t, 2, val.Field, field)
+	EqualSkip(t, 2, val.Tag, expectedTag)
+}
+
+func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, expectedTag string) {
+
+	val, ok := s[field]
+	EqualSkip(t, 2, ok, true)
+	NotEqualSkip(t, 2, val, nil)
+	EqualSkip(t, 2, val.Field, field)
+	EqualSkip(t, 2, val.Tag, expectedTag)
+}
+
+func TestExcludesRuneValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"excludesrune=☻"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "a☺b☻c☹d", Tag: "excludesrune=☻", ExpectedNil: false},
+		{Value: "abcd", Tag: "excludesrune=☻", ExpectedNil: true},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+}
+
+func TestExcludesAllValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"excludesall=@!{}[]"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "abcd@!jfk", Tag: "excludesall=@!{}[]", ExpectedNil: false},
+		{Value: "abcdefg", Tag: "excludesall=@!{}[]", ExpectedNil: true},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+
+	username := "joeybloggs "
+
+	err := validate.Field(username, "excludesall=@ ")
+	NotEqual(t, err, nil)
+
+	excluded := ","
+
+	err = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C?")
+	NotEqual(t, err, nil)
+
+	excluded = "="
+
+	err = validate.Field(excluded, "excludesall=!@#$%^&*()_+.0x2C=?")
+	NotEqual(t, err, nil)
+}
+
+func TestExcludesValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"excludes=@"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "abcd@!jfk", Tag: "excludes=@", ExpectedNil: false},
+		{Value: "abcdq!jfk", Tag: "excludes=@", ExpectedNil: true},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+}
+
+func TestContainsRuneValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"containsrune=☻"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "a☺b☻c☹d", Tag: "containsrune=☻", ExpectedNil: true},
+		{Value: "abcd", Tag: "containsrune=☻", ExpectedNil: false},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+}
+
+func TestContainsAnyValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"containsany=@!{}[]"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "abcd@!jfk", Tag: "containsany=@!{}[]", ExpectedNil: true},
+		{Value: "abcdefg", Tag: "containsany=@!{}[]", ExpectedNil: false},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+}
+
+func TestContainsValidation(t *testing.T) {
+
+	tests := []struct {
+		Value       string `validate:"contains=@"`
+		Tag         string
+		ExpectedNil bool
+	}{
+		{Value: "abcd@!jfk", Tag: "contains=@", ExpectedNil: true},
+		{Value: "abcdq!jfk", Tag: "contains=@", ExpectedNil: false},
+	}
+
+	for i, s := range tests {
+		err := validate.Field(s.Value, s.Tag)
+
+		if (s.ExpectedNil && err != nil) || (!s.ExpectedNil && err == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, err)
+		}
+
+		errs := validate.Struct(s)
+
+		if (s.ExpectedNil && errs != nil) || (!s.ExpectedNil && errs == nil) {
+			t.Fatalf("Index: %d failed Error: %s", i, errs)
+		}
+	}
+}
+
+func TestIsNeFieldValidation(t *testing.T) {
+
+	var j uint64
+	var k float64
+	s := "abcd"
+	i := 1
+	j = 1
+	k = 1.543
+	arr := []string{"test"}
+	now := time.Now().UTC()
+
+	var j2 uint64
+	var k2 float64
+	s2 := "abcdef"
+	i2 := 3
+	j2 = 2
+	k2 = 1.5434456
+	arr2 := []string{"test", "test2"}
+	arr3 := []string{"test"}
+	now2 := now
+
+	err := validate.FieldWithValue(s, s2, "nefield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(i2, i, "nefield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(j2, j, "nefield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(k2, k, "nefield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(arr2, arr, "nefield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(now2, now, "nefield")
+	NotEqual(t, err, nil)
+
+	err = validate.FieldWithValue(arr3, arr, "nefield")
+	NotEqual(t, err, nil)
+
+	type Test struct {
+		Start *time.Time `validate:"nefield=End"`
+		End   *time.Time
+	}
+
+	sv := &Test{
+		Start: &now,
+		End:   &now,
+	}
+
+	errs := validate.Struct(sv)
+	NotEqual(t, errs, nil)
+
+	now3 := time.Now().UTC()
+
+	sv = &Test{
+		Start: &now,
+		End:   &now3,
+	}
+
+	errs = validate.Struct(sv)
+	Equal(t, errs, nil)
+
+	channel := make(chan string)
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 1, "nefield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(5, channel, "nefield") }, "Bad field type chan string")
+	PanicMatches(t, func() { validate.FieldWithValue(5, now, "nefield") }, "Bad Top Level field type")
+
+	type Test2 struct {
+		Start *time.Time `validate:"nefield=NonExistantField"`
+		End   *time.Time
+	}
+
+	sv2 := &Test2{
+		Start: &now,
+		End:   &now,
+	}
+
+	PanicMatches(t, func() { validate.Struct(sv2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestIsNeValidation(t *testing.T) {
+
+	var j uint64
+	var k float64
+	s := "abcdef"
+	i := 3
+	j = 2
+	k = 1.5434
+	arr := []string{"test"}
+	now := time.Now().UTC()
+
+	err := validate.Field(s, "ne=abcd")
+	Equal(t, err, nil)
+
+	err = validate.Field(i, "ne=1")
+	Equal(t, err, nil)
+
+	err = validate.Field(j, "ne=1")
+	Equal(t, err, nil)
+
+	err = validate.Field(k, "ne=1.543")
+	Equal(t, err, nil)
+
+	err = validate.Field(arr, "ne=2")
+	Equal(t, err, nil)
+
+	err = validate.Field(arr, "ne=1")
+	NotEqual(t, err, nil)
+
+	PanicMatches(t, func() { validate.Field(now, "ne=now") }, "Bad field type time.Time")
+}
+
+func TestIsEqFieldValidation(t *testing.T) {
+
+	var j uint64
+	var k float64
+	s := "abcd"
+	i := 1
+	j = 1
+	k = 1.543
+	arr := []string{"test"}
+	now := time.Now().UTC()
+
+	var j2 uint64
+	var k2 float64
+	s2 := "abcd"
+	i2 := 1
+	j2 = 1
+	k2 = 1.543
+	arr2 := []string{"test"}
+	arr3 := []string{"test", "test2"}
+	now2 := now
+
+	err := validate.FieldWithValue(s, s2, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(i2, i, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(j2, j, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(k2, k, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(arr2, arr, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(now2, now, "eqfield")
+	Equal(t, err, nil)
+
+	err = validate.FieldWithValue(arr3, arr, "eqfield")
+	NotEqual(t, err, nil)
+
+	type Test struct {
+		Start *time.Time `validate:"eqfield=End"`
+		End   *time.Time
+	}
+
+	sv := &Test{
+		Start: &now,
+		End:   &now,
+	}
+
+	errs := validate.Struct(sv)
+	Equal(t, errs, nil)
+
+	now3 := time.Now().UTC()
+
+	sv = &Test{
+		Start: &now,
+		End:   &now3,
+	}
+
+	errs = validate.Struct(sv)
+	NotEqual(t, errs, nil)
+
+	channel := make(chan string)
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 1, "eqfield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(5, channel, "eqfield") }, "Bad field type chan string")
+	PanicMatches(t, func() { validate.FieldWithValue(5, now, "eqfield") }, "Bad Top Level field type")
+
+	type Test2 struct {
+		Start *time.Time `validate:"eqfield=NonExistantField"`
+		End   *time.Time
+	}
+
+	sv2 := &Test2{
+		Start: &now,
+		End:   &now,
+	}
+
+	PanicMatches(t, func() { validate.Struct(sv2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestIsEqValidation(t *testing.T) {
+
+	var j uint64
+	var k float64
+	s := "abcd"
+	i := 1
+	j = 1
+	k = 1.543
+	arr := []string{"test"}
+	now := time.Now().UTC()
+
+	err := validate.Field(s, "eq=abcd")
+	Equal(t, err, nil)
+
+	err = validate.Field(i, "eq=1")
+	Equal(t, err, nil)
+
+	err = validate.Field(j, "eq=1")
+	Equal(t, err, nil)
+
+	err = validate.Field(k, "eq=1.543")
+	Equal(t, err, nil)
+
+	err = validate.Field(arr, "eq=1")
+	Equal(t, err, nil)
+
+	err = validate.Field(arr, "eq=2")
+	NotEqual(t, err, nil)
+
+	PanicMatches(t, func() { validate.Field(now, "eq=now") }, "Bad field type time.Time")
+}
+
+func TestBase64Validation(t *testing.T) {
+
+	s := "dW5pY29ybg=="
+
+	err := validate.Field(s, "base64")
+	Equal(t, err, nil)
+
+	s = "dGhpIGlzIGEgdGVzdCBiYXNlNjQ="
+	err = validate.Field(s, "base64")
+	Equal(t, err, nil)
+
+	s = ""
+	err = validate.Field(s, "base64")
+	NotEqual(t, err, nil)
+
+	s = "dW5pY29ybg== foo bar"
+	err = validate.Field(s, "base64")
+	NotEqual(t, err, nil)
+}
+
+func TestStructOnlyValidation(t *testing.T) {
+
+	type Inner struct {
+		Test string `validate:"len=5"`
+	}
+
+	type Outer struct {
+		InnerStruct *Inner `validate:"required,structonly"`
+	}
+
+	outer := &Outer{
+		InnerStruct: nil,
+	}
+
+	errs := validate.Struct(outer).Flatten()
+	NotEqual(t, errs, nil)
+
+	inner := &Inner{
+		Test: "1234",
+	}
+
+	outer = &Outer{
+		InnerStruct: inner,
+	}
+
+	errs = validate.Struct(outer).Flatten()
+	NotEqual(t, errs, nil)
+	Equal(t, len(errs), 0)
+}
+
+func TestGtField(t *testing.T) {
+
+	type TimeTest struct {
+		Start *time.Time `validate:"required,gt"`
+		End   *time.Time `validate:"required,gt,gtfield=Start"`
+	}
+
+	now := time.Now()
+	start := now.Add(time.Hour * 24)
+	end := start.Add(time.Hour * 24)
+
+	timeTest := &TimeTest{
+		Start: &start,
+		End:   &end,
+	}
+
+	errs := validate.Struct(timeTest)
+	Equal(t, errs, nil)
+
+	timeTest = &TimeTest{
+		Start: &end,
+		End:   &start,
+	}
+
+	errs2 := validate.Struct(timeTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "End", "gtfield")
+
+	err3 := validate.FieldWithValue(&start, &end, "gtfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(&end, &start, "gtfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtfield")
+
+	type IntTest struct {
+		Val1 int `validate:"required"`
+		Val2 int `validate:"required,gtfield=Val1"`
+	}
+
+	intTest := &IntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(intTest)
+	Equal(t, errs, nil)
+
+	intTest = &IntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(intTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtfield")
+
+	err3 = validate.FieldWithValue(int(1), int(5), "gtfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(int(5), int(1), "gtfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtfield")
+
+	type UIntTest struct {
+		Val1 uint `validate:"required"`
+		Val2 uint `validate:"required,gtfield=Val1"`
+	}
+
+	uIntTest := &UIntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(uIntTest)
+	Equal(t, errs, nil)
+
+	uIntTest = &UIntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(uIntTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtfield")
+
+	err3 = validate.FieldWithValue(uint(1), uint(5), "gtfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(uint(5), uint(1), "gtfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtfield")
+
+	type FloatTest struct {
+		Val1 float64 `validate:"required"`
+		Val2 float64 `validate:"required,gtfield=Val1"`
+	}
+
+	floatTest := &FloatTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(floatTest)
+	Equal(t, errs, nil)
+
+	floatTest = &FloatTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(floatTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtfield")
+
+	err3 = validate.FieldWithValue(float32(1), float32(5), "gtfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(float32(5), float32(1), "gtfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtfield")
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 1, "gtfield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(5, "T", "gtfield") }, "Bad field type string")
+	PanicMatches(t, func() { validate.FieldWithValue(5, start, "gtfield") }, "Bad Top Level field type")
+
+	type TimeTest2 struct {
+		Start *time.Time `validate:"required"`
+		End   *time.Time `validate:"required,gtfield=NonExistantField"`
+	}
+
+	timeTest2 := &TimeTest2{
+		Start: &start,
+		End:   &end,
+	}
+
+	PanicMatches(t, func() { validate.Struct(timeTest2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestLtField(t *testing.T) {
+
+	type TimeTest struct {
+		Start *time.Time `validate:"required,lt,ltfield=End"`
+		End   *time.Time `validate:"required,lt"`
+	}
+
+	now := time.Now()
+	start := now.Add(time.Hour * 24 * -1 * 2)
+	end := start.Add(time.Hour * 24)
+
+	timeTest := &TimeTest{
+		Start: &start,
+		End:   &end,
+	}
+
+	errs := validate.Struct(timeTest)
+	Equal(t, errs, nil)
+
+	timeTest = &TimeTest{
+		Start: &end,
+		End:   &start,
+	}
+
+	errs2 := validate.Struct(timeTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Start", "ltfield")
+
+	err3 := validate.FieldWithValue(&end, &start, "ltfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(&start, &end, "ltfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltfield")
+
+	type IntTest struct {
+		Val1 int `validate:"required"`
+		Val2 int `validate:"required,ltfield=Val1"`
+	}
+
+	intTest := &IntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(intTest)
+	Equal(t, errs, nil)
+
+	intTest = &IntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(intTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltfield")
+
+	err3 = validate.FieldWithValue(int(5), int(1), "ltfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(int(1), int(5), "ltfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltfield")
+
+	type UIntTest struct {
+		Val1 uint `validate:"required"`
+		Val2 uint `validate:"required,ltfield=Val1"`
+	}
+
+	uIntTest := &UIntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(uIntTest)
+	Equal(t, errs, nil)
+
+	uIntTest = &UIntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(uIntTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltfield")
+
+	err3 = validate.FieldWithValue(uint(5), uint(1), "ltfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(uint(1), uint(5), "ltfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltfield")
+
+	type FloatTest struct {
+		Val1 float64 `validate:"required"`
+		Val2 float64 `validate:"required,ltfield=Val1"`
+	}
+
+	floatTest := &FloatTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(floatTest)
+	Equal(t, errs, nil)
+
+	floatTest = &FloatTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(floatTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltfield")
+
+	err3 = validate.FieldWithValue(float32(5), float32(1), "ltfield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(float32(1), float32(5), "ltfield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltfield")
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 5, "ltfield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(1, "T", "ltfield") }, "Bad field type string")
+	PanicMatches(t, func() { validate.FieldWithValue(1, end, "ltfield") }, "Bad Top Level field type")
+
+	type TimeTest2 struct {
+		Start *time.Time `validate:"required"`
+		End   *time.Time `validate:"required,ltfield=NonExistantField"`
+	}
+
+	timeTest2 := &TimeTest2{
+		Start: &end,
+		End:   &start,
+	}
+
+	PanicMatches(t, func() { validate.Struct(timeTest2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestLteField(t *testing.T) {
+
+	type TimeTest struct {
+		Start *time.Time `validate:"required,lte,ltefield=End"`
+		End   *time.Time `validate:"required,lte"`
+	}
+
+	now := time.Now()
+	start := now.Add(time.Hour * 24 * -1 * 2)
+	end := start.Add(time.Hour * 24)
+
+	timeTest := &TimeTest{
+		Start: &start,
+		End:   &end,
+	}
+
+	errs := validate.Struct(timeTest)
+	Equal(t, errs, nil)
+
+	timeTest = &TimeTest{
+		Start: &end,
+		End:   &start,
+	}
+
+	errs2 := validate.Struct(timeTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Start", "ltefield")
+
+	err3 := validate.FieldWithValue(&end, &start, "ltefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(&start, &end, "ltefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltefield")
+
+	type IntTest struct {
+		Val1 int `validate:"required"`
+		Val2 int `validate:"required,ltefield=Val1"`
+	}
+
+	intTest := &IntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(intTest)
+	Equal(t, errs, nil)
+
+	intTest = &IntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(intTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltefield")
+
+	err3 = validate.FieldWithValue(int(5), int(1), "ltefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(int(1), int(5), "ltefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltefield")
+
+	type UIntTest struct {
+		Val1 uint `validate:"required"`
+		Val2 uint `validate:"required,ltefield=Val1"`
+	}
+
+	uIntTest := &UIntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(uIntTest)
+	Equal(t, errs, nil)
+
+	uIntTest = &UIntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(uIntTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltefield")
+
+	err3 = validate.FieldWithValue(uint(5), uint(1), "ltefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(uint(1), uint(5), "ltefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltefield")
+
+	type FloatTest struct {
+		Val1 float64 `validate:"required"`
+		Val2 float64 `validate:"required,ltefield=Val1"`
+	}
+
+	floatTest := &FloatTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs = validate.Struct(floatTest)
+	Equal(t, errs, nil)
+
+	floatTest = &FloatTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs2 = validate.Struct(floatTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "ltefield")
+
+	err3 = validate.FieldWithValue(float32(5), float32(1), "ltefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(float32(1), float32(5), "ltefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "ltefield")
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 5, "ltefield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(1, "T", "ltefield") }, "Bad field type string")
+	PanicMatches(t, func() { validate.FieldWithValue(1, end, "ltefield") }, "Bad Top Level field type")
+
+	type TimeTest2 struct {
+		Start *time.Time `validate:"required"`
+		End   *time.Time `validate:"required,ltefield=NonExistantField"`
+	}
+
+	timeTest2 := &TimeTest2{
+		Start: &end,
+		End:   &start,
+	}
+
+	PanicMatches(t, func() { validate.Struct(timeTest2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestGteField(t *testing.T) {
+
+	type TimeTest struct {
+		Start *time.Time `validate:"required,gte"`
+		End   *time.Time `validate:"required,gte,gtefield=Start"`
+	}
+
+	now := time.Now()
+	start := now.Add(time.Hour * 24)
+	end := start.Add(time.Hour * 24)
+
+	timeTest := &TimeTest{
+		Start: &start,
+		End:   &end,
+	}
+
+	errs := validate.Struct(timeTest)
+	Equal(t, errs, nil)
+
+	timeTest = &TimeTest{
+		Start: &end,
+		End:   &start,
+	}
+
+	errs2 := validate.Struct(timeTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "End", "gtefield")
+
+	err3 := validate.FieldWithValue(&start, &end, "gtefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(&end, &start, "gtefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtefield")
+
+	type IntTest struct {
+		Val1 int `validate:"required"`
+		Val2 int `validate:"required,gtefield=Val1"`
+	}
+
+	intTest := &IntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(intTest)
+	Equal(t, errs, nil)
+
+	intTest = &IntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(intTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtefield")
+
+	err3 = validate.FieldWithValue(int(1), int(5), "gtefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(int(5), int(1), "gtefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtefield")
+
+	type UIntTest struct {
+		Val1 uint `validate:"required"`
+		Val2 uint `validate:"required,gtefield=Val1"`
+	}
+
+	uIntTest := &UIntTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(uIntTest)
+	Equal(t, errs, nil)
+
+	uIntTest = &UIntTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(uIntTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtefield")
+
+	err3 = validate.FieldWithValue(uint(1), uint(5), "gtefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(uint(5), uint(1), "gtefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtefield")
+
+	type FloatTest struct {
+		Val1 float64 `validate:"required"`
+		Val2 float64 `validate:"required,gtefield=Val1"`
+	}
+
+	floatTest := &FloatTest{
+		Val1: 1,
+		Val2: 5,
+	}
+
+	errs = validate.Struct(floatTest)
+	Equal(t, errs, nil)
+
+	floatTest = &FloatTest{
+		Val1: 5,
+		Val2: 1,
+	}
+
+	errs2 = validate.Struct(floatTest).Flatten()
+	NotEqual(t, errs2, nil)
+	AssertMapFieldError(t, errs2, "Val2", "gtefield")
+
+	err3 = validate.FieldWithValue(float32(1), float32(5), "gtefield")
+	Equal(t, err3, nil)
+
+	err3 = validate.FieldWithValue(float32(5), float32(1), "gtefield")
+	NotEqual(t, err3, nil)
+	Equal(t, err3.Tag, "gtefield")
+
+	PanicMatches(t, func() { validate.FieldWithValue(nil, 1, "gtefield") }, "struct not passed for cross validation")
+	PanicMatches(t, func() { validate.FieldWithValue(5, "T", "gtefield") }, "Bad field type string")
+	PanicMatches(t, func() { validate.FieldWithValue(5, start, "gtefield") }, "Bad Top Level field type")
+
+	type TimeTest2 struct {
+		Start *time.Time `validate:"required"`
+		End   *time.Time `validate:"required,gtefield=NonExistantField"`
+	}
+
+	timeTest2 := &TimeTest2{
+		Start: &start,
+		End:   &end,
+	}
+
+	PanicMatches(t, func() { validate.Struct(timeTest2) }, "Field \"NonExistantField\" not found in struct")
+}
+
+func TestValidateByTagAndValue(t *testing.T) {
+
+	val := "test"
+	field := "test"
+	err := validate.FieldWithValue(val, field, "required")
+	Equal(t, err, nil)
+
+	fn := func(val interface{}, current interface{}, field interface{}, param string) bool {
+
+		return current.(string) == field.(string)
+	}
+
+	validate.AddFunction("isequaltestfunc", fn)
+
+	err = validate.FieldWithValue(val, field, "isequaltestfunc")
+	Equal(t, err, nil)
+
+	val = "unequal"
+
+	err = validate.FieldWithValue(val, field, "isequaltestfunc")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "isequaltestfunc")
+}
+
+func TestAddFunctions(t *testing.T) {
+
+	fn := func(val interface{}, current interface{}, field interface{}, param string) bool {
+
+		return true
+	}
+
+	validate := New("validateme", BakedInValidators)
+
+	err := validate.AddFunction("new", fn)
+	Equal(t, err, nil)
+
+	err = validate.AddFunction("", fn)
+	NotEqual(t, err, nil)
+
+	validate.AddFunction("new", nil)
+	NotEqual(t, err, nil)
+
+	err = validate.AddFunction("new", fn)
+	Equal(t, err, nil)
+}
+
+func TestChangeTag(t *testing.T) {
+
+	validate := New("validateme", BakedInValidators)
+	validate.SetTag("val")
+
+	type Test struct {
+		Name string `val:"len=4"`
+	}
+	s := &Test{
+		Name: "TEST",
+	}
+
+	err := validate.Struct(s)
+	Equal(t, err, nil)
+}
+
+func TestUnexposedStruct(t *testing.T) {
+
+	type Test struct {
+		Name      string
+		unexposed struct {
+			A string `validate:"required"`
+		}
+	}
+
+	s := &Test{
+		Name: "TEST",
+	}
+
+	err := validate.Struct(s)
+	Equal(t, err, nil)
+}
+
+func TestBadParams(t *testing.T) {
+
+	i := 1
+	err := validate.Field(i, "-")
+	Equal(t, err, nil)
+
+	PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
+	PanicMatches(t, func() { validate.Field(i, "len=a") }, "strconv.ParseInt: parsing \"a\": invalid syntax")
+
+	var ui uint = 1
+	PanicMatches(t, func() { validate.Field(ui, "len=a") }, "strconv.ParseUint: parsing \"a\": invalid syntax")
+
+	f := 1.23
+	PanicMatches(t, func() { validate.Field(f, "len=a") }, "strconv.ParseFloat: parsing \"a\": invalid syntax")
+}
+
+func TestLength(t *testing.T) {
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "len") }, "Bad field type bool")
+}
+
+func TestIsGt(t *testing.T) {
+
+	myMap := map[string]string{}
+	err := validate.Field(myMap, "gt=0")
+	NotEqual(t, err, nil)
+
+	f := 1.23
+	err = validate.Field(f, "gt=5")
+	NotEqual(t, err, nil)
+
+	var ui uint = 5
+	err = validate.Field(ui, "gt=10")
+	NotEqual(t, err, nil)
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "gt") }, "Bad field type bool")
+
+	tm := time.Now().UTC()
+	tm = tm.Add(time.Hour * 24)
+
+	err = validate.Field(tm, "gt")
+	Equal(t, err, nil)
+
+	t2 := time.Now().UTC()
+
+	err = validate.Field(t2, "gt")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "gt")
+
+	type Test struct {
+		Now *time.Time `validate:"gt"`
+	}
+	s := &Test{
+		Now: &tm,
+	}
+
+	errs := validate.Struct(s)
+	Equal(t, errs, nil)
+
+	s = &Test{
+		Now: &t2,
+	}
+
+	errs = validate.Struct(s)
+	NotEqual(t, errs, nil)
+}
+
+func TestIsGte(t *testing.T) {
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "gte") }, "Bad field type bool")
+
+	t1 := time.Now().UTC()
+	t1 = t1.Add(time.Hour * 24)
+
+	err := validate.Field(t1, "gte")
+	Equal(t, err, nil)
+
+	t2 := time.Now().UTC()
+
+	err = validate.Field(t2, "gte")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "gte")
+	Equal(t, err.Type, reflect.TypeOf(time.Time{}))
+
+	type Test struct {
+		Now *time.Time `validate:"gte"`
+	}
+	s := &Test{
+		Now: &t1,
+	}
+
+	errs := validate.Struct(s)
+	Equal(t, errs, nil)
+
+	s = &Test{
+		Now: &t2,
+	}
+
+	errs = validate.Struct(s)
+	NotEqual(t, errs, nil)
+}
+
+func TestIsLt(t *testing.T) {
+
+	myMap := map[string]string{}
+	err := validate.Field(myMap, "lt=0")
+	NotEqual(t, err, nil)
+
+	f := 1.23
+	err = validate.Field(f, "lt=0")
+	NotEqual(t, err, nil)
+
+	var ui uint = 5
+	err = validate.Field(ui, "lt=0")
+	NotEqual(t, err, nil)
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "lt") }, "Bad field type bool")
+
+	t1 := time.Now().UTC()
+
+	err = validate.Field(t1, "lt")
+	Equal(t, err, nil)
+
+	t2 := time.Now().UTC()
+	t2 = t2.Add(time.Hour * 24)
+
+	err = validate.Field(t2, "lt")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "lt")
+
+	type Test struct {
+		Now *time.Time `validate:"lt"`
+	}
+
+	s := &Test{
+		Now: &t1,
+	}
+
+	errs := validate.Struct(s)
+	Equal(t, errs, nil)
+
+	s = &Test{
+		Now: &t2,
+	}
+
+	errs = validate.Struct(s)
+	NotEqual(t, errs, nil)
+}
+
+func TestIsLte(t *testing.T) {
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "lte") }, "Bad field type bool")
+
+	t1 := time.Now().UTC()
+
+	err := validate.Field(t1, "lte")
+	Equal(t, err, nil)
+
+	t2 := time.Now().UTC()
+	t2 = t2.Add(time.Hour * 24)
+
+	err = validate.Field(t2, "lte")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "lte")
+
+	type Test struct {
+		Now *time.Time `validate:"lte"`
+	}
+
+	s := &Test{
+		Now: &t1,
+	}
+
+	errs := validate.Struct(s)
+	Equal(t, errs, nil)
+
+	s = &Test{
+		Now: &t2,
+	}
+
+	errs = validate.Struct(s)
+	NotEqual(t, errs, nil)
+}
+
+func TestUrl(t *testing.T) {
+
+	var tests = []struct {
+		param    string
+		expected bool
+	}{
+		{"http://foo.bar#com", true},
+		{"http://foobar.com", true},
+		{"https://foobar.com", true},
+		{"foobar.com", false},
+		{"http://foobar.coffee/", true},
+		{"http://foobar.中文网/", true},
+		{"http://foobar.org/", true},
+		{"http://foobar.org:8080/", true},
+		{"ftp://foobar.ru/", true},
+		{"http://user:pass@www.foobar.com/", true},
+		{"http://127.0.0.1/", true},
+		{"http://duckduckgo.com/?q=%2F", true},
+		{"http://localhost:3000/", true},
+		{"http://foobar.com/?foo=bar#baz=qux", true},
+		{"http://foobar.com?foo=bar", true},
+		{"http://www.xn--froschgrn-x9a.net/", true},
+		{"", false},
+		{"xyz://foobar.com", true},
+		{"invalid.", false},
+		{".com", false},
+		{"rtmp://foobar.com", true},
+		{"http://www.foo_bar.com/", true},
+		{"http://localhost:3000/", true},
+		{"http://foobar.com#baz=qux", true},
+		{"http://foobar.com/t$-_.+!*\\'(),", true},
+		{"http://www.foobar.com/~foobar", true},
+		{"http://www.-foobar.com/", true},
+		{"http://www.foo---bar.com/", true},
+		{"mailto:someone@example.com", true},
+		{"irc://irc.server.org/channel", true},
+		{"irc://#channel@network", true},
+		{"/abs/test/dir", false},
+		{"./rel/test/dir", false},
+	}
+	for i, test := range tests {
+
+		err := validate.Field(test.param, "url")
+
+		if test.expected == true {
+			if !IsEqual(t, err, nil) {
+				t.Fatalf("Index: %d URL failed Error: %s", i, err)
+			}
+		} else {
+			if IsEqual(t, err, nil) || !IsEqual(t, err.Tag, "url") {
+				t.Fatalf("Index: %d URL failed Error: %s", i, err)
+			}
+		}
+	}
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "url") }, "Bad field type int")
+}
+
+func TestUri(t *testing.T) {
+
+	var tests = []struct {
+		param    string
+		expected bool
+	}{
+		{"http://foo.bar#com", true},
+		{"http://foobar.com", true},
+		{"https://foobar.com", true},
+		{"foobar.com", false},
+		{"http://foobar.coffee/", true},
+		{"http://foobar.中文网/", true},
+		{"http://foobar.org/", true},
+		{"http://foobar.org:8080/", true},
+		{"ftp://foobar.ru/", true},
+		{"http://user:pass@www.foobar.com/", true},
+		{"http://127.0.0.1/", true},
+		{"http://duckduckgo.com/?q=%2F", true},
+		{"http://localhost:3000/", true},
+		{"http://foobar.com/?foo=bar#baz=qux", true},
+		{"http://foobar.com?foo=bar", true},
+		{"http://www.xn--froschgrn-x9a.net/", true},
+		{"", false},
+		{"xyz://foobar.com", true},
+		{"invalid.", false},
+		{".com", false},
+		{"rtmp://foobar.com", true},
+		{"http://www.foo_bar.com/", true},
+		{"http://localhost:3000/", true},
+		{"http://foobar.com#baz=qux", true},
+		{"http://foobar.com/t$-_.+!*\\'(),", true},
+		{"http://www.foobar.com/~foobar", true},
+		{"http://www.-foobar.com/", true},
+		{"http://www.foo---bar.com/", true},
+		{"mailto:someone@example.com", true},
+		{"irc://irc.server.org/channel", true},
+		{"irc://#channel@network", true},
+		{"/abs/test/dir", true},
+		{"./rel/test/dir", false},
+	}
+	for i, test := range tests {
+
+		err := validate.Field(test.param, "uri")
+
+		if test.expected == true {
+			if !IsEqual(t, err, nil) {
+				t.Fatalf("Index: %d URI failed Error: %s", i, err)
+			}
+		} else {
+			if IsEqual(t, err, nil) || !IsEqual(t, err.Tag, "uri") {
+				t.Fatalf("Index: %d URI failed Error: %s", i, err)
+			}
+		}
+	}
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "uri") }, "Bad field type int")
+}
+
+func TestOrTag(t *testing.T) {
+	s := "rgba(0,31,255,0.5)"
+	err := validate.Field(s, "rgb|rgba")
+	Equal(t, err, nil)
+
+	s = "rgba(0,31,255,0.5)"
+	err = validate.Field(s, "rgb|rgba|len=18")
+	Equal(t, err, nil)
+
+	s = "this ain't right"
+	err = validate.Field(s, "rgb|rgba")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgb|rgba")
+
+	s = "this ain't right"
+	err = validate.Field(s, "rgb|rgba|len=10")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgb|rgba|len")
+
+	s = "this is right"
+	err = validate.Field(s, "rgb|rgba|len=13")
+	Equal(t, err, nil)
+
+	s = ""
+	err = validate.Field(s, "omitempty,rgb|rgba")
+	Equal(t, err, nil)
+}
+
+func TestHsla(t *testing.T) {
+
+	s := "hsla(360,100%,100%,1)"
+	err := validate.Field(s, "hsla")
+	Equal(t, err, nil)
+
+	s = "hsla(360,100%,100%,0.5)"
+	err = validate.Field(s, "hsla")
+	Equal(t, err, nil)
+
+	s = "hsla(0,0%,0%, 0)"
+	err = validate.Field(s, "hsla")
+	Equal(t, err, nil)
+
+	s = "hsl(361,100%,50%,1)"
+	err = validate.Field(s, "hsla")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsla")
+
+	s = "hsl(361,100%,50%)"
+	err = validate.Field(s, "hsla")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsla")
+
+	s = "hsla(361,100%,50%)"
+	err = validate.Field(s, "hsla")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsla")
+
+	s = "hsla(360,101%,50%)"
+	err = validate.Field(s, "hsla")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsla")
+
+	s = "hsla(360,100%,101%)"
+	err = validate.Field(s, "hsla")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsla")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "hsla") }, "interface conversion: interface is int, not string")
+}
+
+func TestHsl(t *testing.T) {
+
+	s := "hsl(360,100%,50%)"
+	err := validate.Field(s, "hsl")
+	Equal(t, err, nil)
+
+	s = "hsl(0,0%,0%)"
+	err = validate.Field(s, "hsl")
+	Equal(t, err, nil)
+
+	s = "hsl(361,100%,50%)"
+	err = validate.Field(s, "hsl")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsl")
+
+	s = "hsl(361,101%,50%)"
+	err = validate.Field(s, "hsl")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsl")
+
+	s = "hsl(361,100%,101%)"
+	err = validate.Field(s, "hsl")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsl")
+
+	s = "hsl(-10,100%,100%)"
+	err = validate.Field(s, "hsl")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hsl")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "hsl") }, "interface conversion: interface is int, not string")
+}
+
+func TestRgba(t *testing.T) {
+
+	s := "rgba(0,31,255,0.5)"
+	err := validate.Field(s, "rgba")
+	Equal(t, err, nil)
+
+	s = "rgba(0,31,255,0.12)"
+	err = validate.Field(s, "rgba")
+	Equal(t, err, nil)
+
+	s = "rgba( 0,  31, 255, 0.5)"
+	err = validate.Field(s, "rgba")
+	Equal(t, err, nil)
+
+	s = "rgb(0,  31, 255)"
+	err = validate.Field(s, "rgba")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgba")
+
+	s = "rgb(1,349,275,0.5)"
+	err = validate.Field(s, "rgba")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgba")
+
+	s = "rgb(01,31,255,0.5)"
+	err = validate.Field(s, "rgba")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgba")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "rgba") }, "interface conversion: interface is int, not string")
+}
+
+func TestRgb(t *testing.T) {
+
+	s := "rgb(0,31,255)"
+	err := validate.Field(s, "rgb")
+	Equal(t, err, nil)
+
+	s = "rgb(0,  31, 255)"
+	err = validate.Field(s, "rgb")
+	Equal(t, err, nil)
+
+	s = "rgb(1,349,275)"
+	err = validate.Field(s, "rgb")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgb")
+
+	s = "rgb(01,31,255)"
+	err = validate.Field(s, "rgb")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgb")
+
+	s = "rgba(0,31,255)"
+	err = validate.Field(s, "rgb")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "rgb")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "rgb") }, "interface conversion: interface is int, not string")
+}
+
+func TestEmail(t *testing.T) {
+
+	s := "test@mail.com"
+	err := validate.Field(s, "email")
+	Equal(t, err, nil)
+
+	s = ""
+	err = validate.Field(s, "email")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "email")
+
+	s = "test@email"
+	err = validate.Field(s, "email")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "email")
+
+	s = "test@email."
+	err = validate.Field(s, "email")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "email")
+
+	s = "@email.com"
+	err = validate.Field(s, "email")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "email")
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "email") }, "interface conversion: interface is bool, not string")
+}
+
+func TestHexColor(t *testing.T) {
+
+	s := "#fff"
+	err := validate.Field(s, "hexcolor")
+	Equal(t, err, nil)
+
+	s = "#c2c2c2"
+	err = validate.Field(s, "hexcolor")
+	Equal(t, err, nil)
+
+	s = "fff"
+	err = validate.Field(s, "hexcolor")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hexcolor")
+
+	s = "fffFF"
+	err = validate.Field(s, "hexcolor")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hexcolor")
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "hexcolor") }, "interface conversion: interface is bool, not string")
+}
+
+func TestHexadecimal(t *testing.T) {
+
+	s := "ff0044"
+	err := validate.Field(s, "hexadecimal")
+	Equal(t, err, nil)
+
+	s = "abcdefg"
+	err = validate.Field(s, "hexadecimal")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "hexadecimal")
+
+	i := true
+	PanicMatches(t, func() { validate.Field(i, "hexadecimal") }, "interface conversion: interface is bool, not string")
+}
+
+func TestNumber(t *testing.T) {
+
+	s := "1"
+	err := validate.Field(s, "number")
+	Equal(t, err, nil)
+
+	s = "+1"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "-1"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "1.12"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "+1.12"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "-1.12"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "1."
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	s = "1.o"
+	err = validate.Field(s, "number")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "number")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "number") }, "interface conversion: interface is int, not string")
+}
+
+func TestNumeric(t *testing.T) {
+
+	s := "1"
+	err := validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "+1"
+	err = validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "-1"
+	err = validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "1.12"
+	err = validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "+1.12"
+	err = validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "-1.12"
+	err = validate.Field(s, "numeric")
+	Equal(t, err, nil)
+
+	s = "1."
+	err = validate.Field(s, "numeric")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "numeric")
+
+	s = "1.o"
+	err = validate.Field(s, "numeric")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "numeric")
+
+	i := 1
+	PanicMatches(t, func() { validate.Field(i, "numeric") }, "interface conversion: interface is int, not string")
+}
+
+func TestAlphaNumeric(t *testing.T) {
+
+	s := "abcd123"
+	err := validate.Field(s, "alphanum")
+	Equal(t, err, nil)
+
+	s = "abc!23"
+	err = validate.Field(s, "alphanum")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "alphanum")
+
+	PanicMatches(t, func() { validate.Field(1, "alphanum") }, "interface conversion: interface is int, not string")
+}
+
+func TestAlpha(t *testing.T) {
+
+	s := "abcd"
+	err := validate.Field(s, "alpha")
+	Equal(t, err, nil)
+
+	s = "abc1"
+	err = validate.Field(s, "alpha")
+	NotEqual(t, err, nil)
+	Equal(t, err.Tag, "alpha")
+
+	PanicMatches(t, func() { validate.Field(1, "alpha") }, "interface conversion: interface is int, not string")
+}
+
+func TestFlattening(t *testing.T) {
+
+	tSuccess := &TestString{
+		Required:  "Required",
+		Len:       "length==10",
+		Min:       "min=1",
+		Max:       "1234567890",
+		MinMax:    "12345",
+		Lt:        "012345678",
+		Lte:       "0123456789",
+		Gt:        "01234567890",
+		Gte:       "0123456789",
+		OmitEmpty: "",
+		Sub: &SubTest{
+			Test: "1",
+		},
+		SubIgnore: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "1",
+		},
+		Iface: &Impl{
+			F: "123",
+		},
+	}
+
+	err1 := validate.Struct(tSuccess).Flatten()
+	Equal(t, len(err1), 0)
+
+	tFail := &TestString{
+		Required:  "",
+		Len:       "",
+		Min:       "",
+		Max:       "12345678901",
+		MinMax:    "",
+		OmitEmpty: "12345678901",
+		Sub: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "",
+		},
+		Iface: &Impl{
+			F: "12",
+		},
+	}
+
+	err2 := validate.Struct(tFail).Flatten()
+
+	// Assert Top Level
+	NotEqual(t, err2, nil)
+
+	// Assert Fields
+	AssertMapFieldError(t, err2, "Len", "len")
+	AssertMapFieldError(t, err2, "Gt", "gt")
+	AssertMapFieldError(t, err2, "Gte", "gte")
+
+	// Assert Struct Field
+	AssertMapFieldError(t, err2, "Sub.Test", "required")
+
+	// Assert Anonymous Struct Field
+	AssertMapFieldError(t, err2, "Anonymous.A", "required")
+
+	// Assert Interface Field
+	AssertMapFieldError(t, err2, "Iface.F", "len")
+}
+
+func TestStructStringValidation(t *testing.T) {
+
+	validate.SetMaxStructPoolSize(11)
+
+	tSuccess := &TestString{
+		Required:  "Required",
+		Len:       "length==10",
+		Min:       "min=1",
+		Max:       "1234567890",
+		MinMax:    "12345",
+		Lt:        "012345678",
+		Lte:       "0123456789",
+		Gt:        "01234567890",
+		Gte:       "0123456789",
+		OmitEmpty: "",
+		Sub: &SubTest{
+			Test: "1",
+		},
+		SubIgnore: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "1",
+		},
+		Iface: &Impl{
+			F: "123",
+		},
+	}
+
+	err := validate.Struct(tSuccess)
+	Equal(t, err, nil)
+
+	tFail := &TestString{
+		Required:  "",
+		Len:       "",
+		Min:       "",
+		Max:       "12345678901",
+		MinMax:    "",
+		Lt:        "0123456789",
+		Lte:       "01234567890",
+		Gt:        "1",
+		Gte:       "1",
+		OmitEmpty: "12345678901",
+		Sub: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "",
+		},
+		Iface: &Impl{
+			F: "12",
+		},
+	}
+
+	err = validate.Struct(tFail)
+
+	// Assert Top Level
+	NotEqual(t, err, nil)
+	Equal(t, err.Struct, "TestString")
+	Equal(t, len(err.Errors), 10)
+	Equal(t, len(err.StructErrors), 3)
+
+	// Assert Fields
+	AssertFieldError(t, err, "Required", "required")
+	AssertFieldError(t, err, "Len", "len")
+	AssertFieldError(t, err, "Min", "min")
+	AssertFieldError(t, err, "Max", "max")
+	AssertFieldError(t, err, "MinMax", "min")
+	AssertFieldError(t, err, "Gt", "gt")
+	AssertFieldError(t, err, "Gte", "gte")
+	AssertFieldError(t, err, "OmitEmpty", "max")
+
+	// Assert Anonymous embedded struct
+	AssertStruct(t, err, "Anonymous", "")
+
+	// Assert SubTest embedded struct
+	val := AssertStruct(t, err, "Sub", "SubTest")
+	Equal(t, len(val.Errors), 1)
+	Equal(t, len(val.StructErrors), 0)
+
+	AssertFieldError(t, val, "Test", "required")
+
+	errors := err.Error()
+	NotEqual(t, errors, nil)
+}
+
+func TestStructInt32Validation(t *testing.T) {
+
+	tSuccess := &TestInt32{
+		Required:  1,
+		Len:       10,
+		Min:       1,
+		Max:       10,
+		MinMax:    5,
+		Lt:        9,
+		Lte:       10,
+		Gt:        11,
+		Gte:       10,
+		OmitEmpty: 0,
+	}
+
+	err := validate.Struct(tSuccess)
+	Equal(t, err, nil)
+
+	tFail := &TestInt32{
+		Required:  0,
+		Len:       11,
+		Min:       -1,
+		Max:       11,
+		MinMax:    -1,
+		Lt:        10,
+		Lte:       11,
+		Gt:        10,
+		Gte:       9,
+		OmitEmpty: 11,
+	}
+
+	err = validate.Struct(tFail)
+
+	// Assert Top Level
+	NotEqual(t, err, nil)
+	Equal(t, err.Struct, "TestInt32")
+	Equal(t, len(err.Errors), 10)
+	Equal(t, len(err.StructErrors), 0)
+
+	// Assert Fields
+	AssertFieldError(t, err, "Required", "required")
+	AssertFieldError(t, err, "Len", "len")
+	AssertFieldError(t, err, "Min", "min")
+	AssertFieldError(t, err, "Max", "max")
+	AssertFieldError(t, err, "MinMax", "min")
+	AssertFieldError(t, err, "Lt", "lt")
+	AssertFieldError(t, err, "Lte", "lte")
+	AssertFieldError(t, err, "Gt", "gt")
+	AssertFieldError(t, err, "Gte", "gte")
+	AssertFieldError(t, err, "OmitEmpty", "max")
+}
+
+func TestStructUint64Validation(t *testing.T) {
+
+	tSuccess := &TestUint64{
+		Required:  1,
+		Len:       10,
+		Min:       1,
+		Max:       10,
+		MinMax:    5,
+		OmitEmpty: 0,
+	}
+
+	err := validate.Struct(tSuccess)
+	Equal(t, err, nil)
+
+	tFail := &TestUint64{
+		Required:  0,
+		Len:       11,
+		Min:       0,
+		Max:       11,
+		MinMax:    0,
+		OmitEmpty: 11,
+	}
+
+	err = validate.Struct(tFail)
+
+	// Assert Top Level
+	NotEqual(t, err, nil)
+	Equal(t, err.Struct, "TestUint64")
+	Equal(t, len(err.Errors), 6)
+	Equal(t, len(err.StructErrors), 0)
+
+	// Assert Fields
+	AssertFieldError(t, err, "Required", "required")
+	AssertFieldError(t, err, "Len", "len")
+	AssertFieldError(t, err, "Min", "min")
+	AssertFieldError(t, err, "Max", "max")
+	AssertFieldError(t, err, "MinMax", "min")
+	AssertFieldError(t, err, "OmitEmpty", "max")
+}
+
+func TestStructFloat64Validation(t *testing.T) {
+
+	tSuccess := &TestFloat64{
+		Required:  1,
+		Len:       10,
+		Min:       1,
+		Max:       10,
+		MinMax:    5,
+		OmitEmpty: 0,
+	}
+
+	err := validate.Struct(tSuccess)
+	Equal(t, err, nil)
+
+	tFail := &TestFloat64{
+		Required:  0,
+		Len:       11,
+		Min:       0,
+		Max:       11,
+		MinMax:    0,
+		OmitEmpty: 11,
+	}
+
+	err = validate.Struct(tFail)
+
+	// Assert Top Level
+	NotEqual(t, err, nil)
+	Equal(t, err.Struct, "TestFloat64")
+	Equal(t, len(err.Errors), 6)
+	Equal(t, len(err.StructErrors), 0)
+
+	// Assert Fields
+	AssertFieldError(t, err, "Required", "required")
+	AssertFieldError(t, err, "Len", "len")
+	AssertFieldError(t, err, "Min", "min")
+	AssertFieldError(t, err, "Max", "max")
+	AssertFieldError(t, err, "MinMax", "min")
+	AssertFieldError(t, err, "OmitEmpty", "max")
+}
+
+func TestStructSliceValidation(t *testing.T) {
+
+	tSuccess := &TestSlice{
+		Required:  []int{1},
+		Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+		Min:       []int{1, 2},
+		Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
+		MinMax:    []int{1, 2, 3, 4, 5},
+		OmitEmpty: []int{},
+	}
+
+	err := validate.Struct(tSuccess)
+	Equal(t, err, nil)
+
+	tFail := &TestSlice{
+		Required:  []int{},
+		Len:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
+		Min:       []int{},
+		Max:       []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
+		MinMax:    []int{},
+		OmitEmpty: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
+	}
+
+	err = validate.Struct(tFail)
+
+	// Assert Top Level
+	NotEqual(t, err, nil)
+	Equal(t, err.Struct, "TestSlice")
+	Equal(t, len(err.Errors), 6)
+	Equal(t, len(err.StructErrors), 0)
+
+	// Assert Fields
+	AssertFieldError(t, err, "Required", "required")
+	AssertFieldError(t, err, "Len", "len")
+	AssertFieldError(t, err, "Min", "min")
+	AssertFieldError(t, err, "Max", "max")
+	AssertFieldError(t, err, "MinMax", "min")
+	AssertFieldError(t, err, "OmitEmpty", "max")
+}
+
+func TestInvalidStruct(t *testing.T) {
+	s := &SubTest{
+		Test: "1",
+	}
+
+	PanicMatches(t, func() { validate.Struct(s.Test) }, "interface passed for validation is not a struct")
+}
+
+func TestInvalidField(t *testing.T) {
+	s := &SubTest{
+		Test: "1",
+	}
+
+	PanicMatches(t, func() { validate.Field(s, "required") }, "Invalid field passed to ValidateFieldWithTag")
+}
+
+func TestInvalidTagField(t *testing.T) {
+	s := &SubTest{
+		Test: "1",
+	}
+
+	PanicMatches(t, func() { validate.Field(s.Test, "") }, fmt.Sprintf("Invalid validation tag on field %s", ""))
+}
+
+func TestInvalidValidatorFunction(t *testing.T) {
+	s := &SubTest{
+		Test: "1",
+	}
+
+	PanicMatches(t, func() { validate.Field(s.Test, "zzxxBadFunction") }, fmt.Sprintf("Undefined validation function on field %s", ""))
+}
+
+func BenchmarkValidateField(b *testing.B) {
+	for n := 0; n < b.N; n++ {
+		validate.Field("1", "len=1")
+	}
+}
+
+func BenchmarkValidateStructSimple(b *testing.B) {
+
+	type Foo struct {
+		StringValue string `validate:"min=5,max=10"`
+		IntValue    int    `validate:"min=5,max=10"`
+	}
+
+	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
+	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
+
+	for n := 0; n < b.N; n++ {
+		validate.Struct(validFoo)
+		validate.Struct(invalidFoo)
+	}
+}
+
+// func BenchmarkTemplateParallelSimple(b *testing.B) {
+
+// 	type Foo struct {
+// 		StringValue string `validate:"min=5,max=10"`
+// 		IntValue    int    `validate:"min=5,max=10"`
+// 	}
+
+// 	validFoo := &Foo{StringValue: "Foobar", IntValue: 7}
+// 	invalidFoo := &Foo{StringValue: "Fo", IntValue: 3}
+
+// 	b.RunParallel(func(pb *testing.PB) {
+// 		for pb.Next() {
+// 			validate.Struct(validFoo)
+// 			validate.Struct(invalidFoo)
+// 		}
+// 	})
+// }
+
+func BenchmarkValidateStructLarge(b *testing.B) {
+
+	tFail := &TestString{
+		Required:  "",
+		Len:       "",
+		Min:       "",
+		Max:       "12345678901",
+		MinMax:    "",
+		Lt:        "0123456789",
+		Lte:       "01234567890",
+		Gt:        "1",
+		Gte:       "1",
+		OmitEmpty: "12345678901",
+		Sub: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "",
+		},
+		Iface: &Impl{
+			F: "12",
+		},
+	}
+
+	tSuccess := &TestString{
+		Required:  "Required",
+		Len:       "length==10",
+		Min:       "min=1",
+		Max:       "1234567890",
+		MinMax:    "12345",
+		Lt:        "012345678",
+		Lte:       "0123456789",
+		Gt:        "01234567890",
+		Gte:       "0123456789",
+		OmitEmpty: "",
+		Sub: &SubTest{
+			Test: "1",
+		},
+		SubIgnore: &SubTest{
+			Test: "",
+		},
+		Anonymous: struct {
+			A string `validate:"required"`
+		}{
+			A: "1",
+		},
+		Iface: &Impl{
+			F: "123",
+		},
+	}
+
+	for n := 0; n < b.N; n++ {
+		validate.Struct(tSuccess)
+		validate.Struct(tFail)
+	}
+}
+
+// func BenchmarkTemplateParallelLarge(b *testing.B) {
+
+// 	tFail := &TestString{
+// 		Required:  "",
+// 		Len:       "",
+// 		Min:       "",
+// 		Max:       "12345678901",
+// 		MinMax:    "",
+// 		Lt:        "0123456789",
+// 		Lte:       "01234567890",
+// 		Gt:        "1",
+// 		Gte:       "1",
+// 		OmitEmpty: "12345678901",
+// 		Sub: &SubTest{
+// 			Test: "",
+// 		},
+// 		Anonymous: struct {
+// 			A string `validate:"required"`
+// 		}{
+// 			A: "",
+// 		},
+// 		Iface: &Impl{
+// 			F: "12",
+// 		},
+// 	}
+
+// 	tSuccess := &TestString{
+// 		Required:  "Required",
+// 		Len:       "length==10",
+// 		Min:       "min=1",
+// 		Max:       "1234567890",
+// 		MinMax:    "12345",
+// 		Lt:        "012345678",
+// 		Lte:       "0123456789",
+// 		Gt:        "01234567890",
+// 		Gte:       "0123456789",
+// 		OmitEmpty: "",
+// 		Sub: &SubTest{
+// 			Test: "1",
+// 		},
+// 		SubIgnore: &SubTest{
+// 			Test: "",
+// 		},
+// 		Anonymous: struct {
+// 			A string `validate:"required"`
+// 		}{
+// 			A: "1",
+// 		},
+// 		Iface: &Impl{
+// 			F: "123",
+// 		},
+// 	}
+
+// 	b.RunParallel(func(pb *testing.PB) {
+// 		for pb.Next() {
+// 			validate.Struct(tSuccess)
+// 			validate.Struct(tFail)
+// 		}
+// 	})
+// }
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/.travis.yml b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/.travis.yml
new file mode 100644
index 00000000..b05e4c53
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/.travis.yml
@@ -0,0 +1,3 @@
+language: go
+go: 1.2
+
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/LICENSE.md b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/LICENSE.md
new file mode 100644
index 00000000..25fdaf63
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/LICENSE.md
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Fatih Arslan
+
+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.
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/README.md b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/README.md
new file mode 100644
index 00000000..23afdd98
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/README.md
@@ -0,0 +1,245 @@
+# Set [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/gopkg.in/fatih/set.v0) [![Build Status](http://img.shields.io/travis/fatih/set.svg?style=flat-square)](https://travis-ci.org/fatih/set)
+
+Set is a basic and simple, hash-based, **Set** data structure implementation
+in Go (Golang).
+
+Set provides both threadsafe and non-threadsafe implementations of a generic
+set data structure. The thread safety encompasses all operations on one set.
+Operations on multiple sets are consistent in that the elements of each set
+used was valid at exactly one point in time between the start and the end of
+the operation. Because it's thread safe, you can use it concurrently with your
+goroutines.
+
+For usage see examples below or click on the godoc badge.
+
+## Install and Usage
+
+Install the package with:
+
+```bash
+go get gopkg.in/fatih/set.v0
+```
+
+Import it with:
+
+```go
+import "gopkg.in/fatih/set.v0"
+```
+
+and use `set` as the package name inside the code.
+
+## Examples
+
+#### Initialization of a new Set
+
+```go
+
+// create a set with zero items
+s := set.New()
+s := set.NewNonTS() // non thread-safe version
+
+// ... or with some initial values
+s := set.New("istanbul", "frankfurt", 30.123, "san francisco", 1234)
+s := set.NewNonTS("kenya", "ethiopia", "sumatra")
+
+```
+
+#### Basic Operations
+
+```go
+// add items
+s.Add("istanbul")
+s.Add("istanbul") // nothing happens if you add duplicate item
+
+// add multiple items
+s.Add("ankara", "san francisco", 3.14)
+
+// remove item
+s.Remove("frankfurt")
+s.Remove("frankfurt") // nothing happes if you remove a nonexisting item
+
+// remove multiple items
+s.Remove("barcelona", 3.14, "ankara")
+
+// removes an arbitary item and return it
+item := s.Pop()
+
+// create a new copy
+other := s.Copy()
+
+// remove all items
+s.Clear()
+
+// number of items in the set
+len := s.Size()
+
+// return a list of items
+items := s.List()
+
+// string representation of set
+fmt.Printf("set is %s", s.String())
+
+```
+
+#### Check Operations
+
+```go
+// check for set emptiness, returns true if set is empty
+s.IsEmpty()
+
+// check for a single item exist
+s.Has("istanbul")
+
+// ... or for multiple items. This will return true if all of the items exist.
+s.Has("istanbul", "san francisco", 3.14)
+
+// create two sets for the following checks...
+s := s.New("1", "2", "3", "4", "5")
+t := s.New("1", "2", "3")
+
+
+// check if they are the same
+if !s.IsEqual(t) {
+    fmt.Println("s is not equal to t")
+}
+
+// if s contains all elements of t
+if s.IsSubset(t) {
+	fmt.Println("t is a subset of s")
+}
+
+// ... or if s is a superset of t
+if t.IsSuperset(s) {
+	fmt.Println("s is a superset of t")
+}
+
+
+```
+
+#### Set Operations
+
+
+```go
+// let us initialize two sets with some values
+a := set.New("ankara", "berlin", "san francisco")
+b := set.New("frankfurt", "berlin")
+
+// creates a new set with the items in a and b combined.
+// [frankfurt, berlin, ankara, san francisco]
+c := set.Union(a, b)
+
+// contains items which is in both a and b
+// [berlin]
+c := set.Intersection(a, b)
+
+// contains items which are in a but not in b
+// [ankara, san francisco]
+c := set.Difference(a, b)
+
+// contains items which are in one of either, but not in both.
+// [frankfurt, ankara, san francisco]
+c := set.SymmetricDifference(a, b)
+
+```
+
+```go
+// like Union but saves the result back into a.
+a.Merge(b)
+
+// removes the set items which are in b from a and saves the result back into a.
+a.Separate(b)
+
+```
+
+#### Multiple Set Operations
+
+```go
+a := set.New("1", "3", "4", "5")
+b := set.New("2", "3", "4", "5")
+c := set.New("4", "5", "6", "7")
+
+// creates a new set with items in a, b and c
+// [1 2 3 4 5 6 7]
+u := set.Union(a, b, c)
+
+// creates a new set with items in a but not in b and c
+// [1]
+u := set.Difference(a, b, c)
+
+// creates a new set with items that are common to a, b and c
+// [5]
+u := set.Intersection(a, b, c)
+```
+
+#### Helper methods
+
+The Slice functions below are a convenient way to extract or convert your Set data
+into basic data types.
+
+
+```go
+// create a set of mixed types
+s := set.New("ankara", "5", "8", "san francisco", 13, 21)
+
+
+// convert s into a slice of strings (type is []string)
+// [ankara 5 8 san francisco]
+t := set.StringSlice(s)
+
+
+// u contains a slice of ints (type is []int)
+// [13, 21]
+u := set.IntSlice(s)
+
+```
+
+#### Concurrent safe usage
+
+Below is an example of a concurrent way that uses set. We call ten functions
+concurrently and wait until they are finished. It basically creates a new
+string for each goroutine and adds it to our set.
+
+```go
+package main
+
+import (
+	"fmt"
+	"github.com/fatih/set"
+	"strconv"
+	"sync"
+)
+
+func main() {
+	var wg sync.WaitGroup // this is just for waiting until all goroutines finish
+
+	// Initialize our thread safe Set
+	s := set.New()
+
+	// Add items concurrently (item1, item2, and so on)
+	for i := 0; i < 10; i++ {
+		wg.Add(1)
+		go func(i int) {
+			item := "item" + strconv.Itoa(i)
+			fmt.Println("adding", item)
+			s.Add(item)
+			wg.Done()
+		}(i)
+	}
+
+	// Wait until all concurrent calls finished and print our set
+	wg.Wait()
+	fmt.Println(s)
+}
+```
+
+## Credits
+
+ * [Fatih Arslan](https://github.com/fatih)
+ * [Arne Hormann](https://github.com/arnehormann)
+ * [Sam Boyer](https://github.com/sdboyer)
+ * [Ralph Loizzo](https://github.com/friartech)
+
+## License
+
+The MIT License (MIT) - see LICENSE.md for more details
+
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set.go
new file mode 100644
index 00000000..ac0240ce
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set.go
@@ -0,0 +1,121 @@
+// Package set provides both threadsafe and non-threadsafe implementations of
+// a generic set data structure. In the threadsafe set, safety encompasses all
+// operations on one set. Operations on multiple sets are consistent in that
+// the elements of each set used was valid at exactly one point in time
+// between the start and the end of the operation.
+package set
+
+// Interface is describing a Set. Sets are an unordered, unique list of values.
+type Interface interface {
+	New(items ...interface{}) Interface
+	Add(items ...interface{})
+	Remove(items ...interface{})
+	Pop() interface{}
+	Has(items ...interface{}) bool
+	Size() int
+	Clear()
+	IsEmpty() bool
+	IsEqual(s Interface) bool
+	IsSubset(s Interface) bool
+	IsSuperset(s Interface) bool
+	Each(func(interface{}) bool)
+	String() string
+	List() []interface{}
+	Copy() Interface
+	Merge(s Interface)
+	Separate(s Interface)
+}
+
+// helpful to not write everywhere struct{}{}
+var keyExists = struct{}{}
+
+// Union is the merger of multiple sets. It returns a new set with all the
+// elements present in all the sets that are passed.
+//
+// The dynamic type of the returned set is determined by the first passed set's
+// implementation of the New() method.
+func Union(set1, set2 Interface, sets ...Interface) Interface {
+	u := set1.Copy()
+	set2.Each(func(item interface{}) bool {
+		u.Add(item)
+		return true
+	})
+	for _, set := range sets {
+		set.Each(func(item interface{}) bool {
+			u.Add(item)
+			return true
+		})
+	}
+
+	return u
+}
+
+// Difference returns a new set which contains items which are in in the first
+// set but not in the others. Unlike the Difference() method you can use this
+// function separately with multiple sets.
+func Difference(set1, set2 Interface, sets ...Interface) Interface {
+	s := set1.Copy()
+	s.Separate(set2)
+	for _, set := range sets {
+		s.Separate(set) // seperate is thread safe
+	}
+	return s
+}
+
+// Intersection returns a new set which contains items that only exist in all given sets.
+func Intersection(set1, set2 Interface, sets ...Interface) Interface {
+	all := Union(set1, set2, sets...)
+	result := Union(set1, set2, sets...)
+
+	all.Each(func(item interface{}) bool {
+		if !set1.Has(item) || !set2.Has(item) {
+			result.Remove(item)
+		}
+
+		for _, set := range sets {
+			if !set.Has(item) {
+				result.Remove(item)
+			}
+		}
+		return true
+	})
+	return result
+}
+
+// SymmetricDifference returns a new set which s is the difference of items which are in
+// one of either, but not in both.
+func SymmetricDifference(s Interface, t Interface) Interface {
+	u := Difference(s, t)
+	v := Difference(t, s)
+	return Union(u, v)
+}
+
+// StringSlice is a helper function that returns a slice of strings of s. If
+// the set contains mixed types of items only items of type string are returned.
+func StringSlice(s Interface) []string {
+	slice := make([]string, 0)
+	for _, item := range s.List() {
+		v, ok := item.(string)
+		if !ok {
+			continue
+		}
+
+		slice = append(slice, v)
+	}
+	return slice
+}
+
+// IntSlice is a helper function that returns a slice of ints of s. If
+// the set contains mixed types of items only items of type int are returned.
+func IntSlice(s Interface) []int {
+	slice := make([]int, 0)
+	for _, item := range s.List() {
+		v, ok := item.(int)
+		if !ok {
+			continue
+		}
+
+		slice = append(slice, v)
+	}
+	return slice
+}
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots.go
new file mode 100644
index 00000000..ec1ab228
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots.go
@@ -0,0 +1,195 @@
+package set
+
+import (
+	"fmt"
+	"strings"
+)
+
+// Provides a common set baseline for both threadsafe and non-ts Sets.
+type set struct {
+	m map[interface{}]struct{} // struct{} doesn't take up space
+}
+
+// SetNonTS defines a non-thread safe set data structure.
+type SetNonTS struct {
+	set
+}
+
+// NewNonTS creates and initialize a new non-threadsafe Set.
+// It accepts a variable number of arguments to populate the initial set.
+// If nothing is passed a SetNonTS with zero size is created.
+func NewNonTS(items ...interface{}) *SetNonTS {
+	s := &SetNonTS{}
+	s.m = make(map[interface{}]struct{})
+
+	// Ensure interface compliance
+	var _ Interface = s
+
+	s.Add(items...)
+	return s
+}
+
+// New creates and initalizes a new Set interface. It accepts a variable
+// number of arguments to populate the initial set. If nothing is passed a
+// zero size Set based on the struct is created.
+func (s *set) New(items ...interface{}) Interface {
+	return NewNonTS(items...)
+}
+
+// Add includes the specified items (one or more) to the set. The underlying
+// Set s is modified. If passed nothing it silently returns.
+func (s *set) Add(items ...interface{}) {
+	if len(items) == 0 {
+		return
+	}
+
+	for _, item := range items {
+		s.m[item] = keyExists
+	}
+}
+
+// Remove deletes the specified items from the set.  The underlying Set s is
+// modified. If passed nothing it silently returns.
+func (s *set) Remove(items ...interface{}) {
+	if len(items) == 0 {
+		return
+	}
+
+	for _, item := range items {
+		delete(s.m, item)
+	}
+}
+
+// Pop  deletes and return an item from the set. The underlying Set s is
+// modified. If set is empty, nil is returned.
+func (s *set) Pop() interface{} {
+	for item := range s.m {
+		delete(s.m, item)
+		return item
+	}
+	return nil
+}
+
+// Has looks for the existence of items passed. It returns false if nothing is
+// passed. For multiple items it returns true only if all of  the items exist.
+func (s *set) Has(items ...interface{}) bool {
+	// assume checked for empty item, which not exist
+	if len(items) == 0 {
+		return false
+	}
+
+	has := true
+	for _, item := range items {
+		if _, has = s.m[item]; !has {
+			break
+		}
+	}
+	return has
+}
+
+// Size returns the number of items in a set.
+func (s *set) Size() int {
+	return len(s.m)
+}
+
+// Clear removes all items from the set.
+func (s *set) Clear() {
+	s.m = make(map[interface{}]struct{})
+}
+
+// IsEmpty reports whether the Set is empty.
+func (s *set) IsEmpty() bool {
+	return s.Size() == 0
+}
+
+// IsEqual test whether s and t are the same in size and have the same items.
+func (s *set) IsEqual(t Interface) bool {
+	// Force locking only if given set is threadsafe.
+	if conv, ok := t.(*Set); ok {
+		conv.l.RLock()
+		defer conv.l.RUnlock()
+	}
+
+	// return false if they are no the same size
+	if sameSize := len(s.m) == t.Size(); !sameSize {
+		return false
+	}
+
+	equal := true
+	t.Each(func(item interface{}) bool {
+		_, equal = s.m[item]
+		return equal // if false, Each() will end
+	})
+
+	return equal
+}
+
+// IsSubset tests whether t is a subset of s.
+func (s *set) IsSubset(t Interface) (subset bool) {
+	subset = true
+
+	t.Each(func(item interface{}) bool {
+		_, subset = s.m[item]
+		return subset
+	})
+
+	return
+}
+
+// IsSuperset tests whether t is a superset of s.
+func (s *set) IsSuperset(t Interface) bool {
+	return t.IsSubset(s)
+}
+
+// Each traverses the items in the Set, calling the provided function for each
+// set member. Traversal will continue until all items in the Set have been
+// visited, or if the closure returns false.
+func (s *set) Each(f func(item interface{}) bool) {
+	for item := range s.m {
+		if !f(item) {
+			break
+		}
+	}
+}
+
+// String returns a string representation of s
+func (s *set) String() string {
+	t := make([]string, 0, len(s.List()))
+	for _, item := range s.List() {
+		t = append(t, fmt.Sprintf("%v", item))
+	}
+
+	return fmt.Sprintf("[%s]", strings.Join(t, ", "))
+}
+
+// List returns a slice of all items. There is also StringSlice() and
+// IntSlice() methods for returning slices of type string or int.
+func (s *set) List() []interface{} {
+	list := make([]interface{}, 0, len(s.m))
+
+	for item := range s.m {
+		list = append(list, item)
+	}
+
+	return list
+}
+
+// Copy returns a new Set with a copy of s.
+func (s *set) Copy() Interface {
+	return NewNonTS(s.List()...)
+}
+
+// Merge is like Union, however it modifies the current set it's applied on
+// with the given t set.
+func (s *set) Merge(t Interface) {
+	t.Each(func(item interface{}) bool {
+		s.m[item] = keyExists
+		return true
+	})
+}
+
+// it's not the opposite of Merge.
+// Separate removes the set items containing in t from set s. Please aware that
+func (s *set) Separate(t Interface) {
+	s.Remove(t.List()...)
+}
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots_test.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots_test.go
new file mode 100644
index 00000000..fd599699
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_nots_test.go
@@ -0,0 +1,282 @@
+package set
+
+import (
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestSetNonTS_NewNonTS_parameters(t *testing.T) {
+	s := NewNonTS("string", "another_string", 1, 3.14)
+
+	if s.Size() != 4 {
+		t.Error("NewNonTS: calling with parameters should create a set with size of four")
+	}
+}
+
+func TestSetNonTS_Add(t *testing.T) {
+	s := NewNonTS()
+	s.Add(1)
+	s.Add(2)
+	s.Add(2) // duplicate
+	s.Add("fatih")
+	s.Add("zeynep")
+	s.Add("zeynep") // another duplicate
+
+	if s.Size() != 4 {
+		t.Error("Add: items are not unique. The set size should be four")
+	}
+
+	if !s.Has(1, 2, "fatih", "zeynep") {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSetNonTS_Add_multiple(t *testing.T) {
+	s := NewNonTS()
+	s.Add("ankara", "san francisco", 3.14)
+
+	if s.Size() != 3 {
+		t.Error("Add: items are not unique. The set size should be three")
+	}
+
+	if !s.Has("ankara", "san francisco", 3.14) {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSetNonTS_Remove(t *testing.T) {
+	s := NewNonTS()
+	s.Add(1)
+	s.Add(2)
+	s.Add("fatih")
+
+	s.Remove(1)
+	if s.Size() != 2 {
+		t.Error("Remove: set size should be two after removing")
+	}
+
+	s.Remove(1)
+	if s.Size() != 2 {
+		t.Error("Remove: set size should be not change after trying to remove a non-existing item")
+	}
+
+	s.Remove(2)
+	s.Remove("fatih")
+	if s.Size() != 0 {
+		t.Error("Remove: set size should be zero")
+	}
+
+	s.Remove("fatih") // try to remove something from a zero length set
+}
+
+func TestSetNonTS_Remove_multiple(t *testing.T) {
+	s := NewNonTS()
+	s.Add("ankara", "san francisco", 3.14, "istanbul")
+	s.Remove("ankara", "san francisco", 3.14)
+
+	if s.Size() != 1 {
+		t.Error("Remove: items are not unique. The set size should be four")
+	}
+
+	if !s.Has("istanbul") {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSetNonTS_Pop(t *testing.T) {
+	s := NewNonTS()
+	s.Add(1)
+	s.Add(2)
+	s.Add("fatih")
+
+	a := s.Pop()
+	if s.Size() != 2 {
+		t.Error("Pop: set size should be two after popping out")
+	}
+
+	if s.Has(a) {
+		t.Error("Pop: returned item should not exist")
+	}
+
+	s.Pop()
+	s.Pop()
+	b := s.Pop()
+	if b != nil {
+		t.Error("Pop: should return nil because set is empty")
+	}
+
+	s.Pop() // try to remove something from a zero length set
+}
+
+func TestSetNonTS_Has(t *testing.T) {
+	s := NewNonTS("1", "2", "3", "4")
+
+	if !s.Has("1") {
+		t.Error("Has: the item 1 exist, but 'Has' is returning false")
+	}
+
+	if !s.Has("1", "2", "3", "4") {
+		t.Error("Has: the items all exist, but 'Has' is returning false")
+	}
+}
+
+func TestSetNonTS_Clear(t *testing.T) {
+	s := NewNonTS()
+	s.Add(1)
+	s.Add("istanbul")
+	s.Add("san francisco")
+
+	s.Clear()
+	if s.Size() != 0 {
+		t.Error("Clear: set size should be zero")
+	}
+}
+
+func TestSetNonTS_IsEmpty(t *testing.T) {
+	s := NewNonTS()
+
+	empty := s.IsEmpty()
+	if !empty {
+		t.Error("IsEmpty: set is empty, it should be true")
+	}
+
+	s.Add(2)
+	s.Add(3)
+	notEmpty := s.IsEmpty()
+
+	if notEmpty {
+		t.Error("IsEmpty: set is filled, it should be false")
+	}
+}
+
+func TestSetNonTS_IsEqual(t *testing.T) {
+	s := NewNonTS("1", "2", "3")
+	u := NewNonTS("1", "2", "3")
+
+	ok := s.IsEqual(u)
+	if !ok {
+		t.Error("IsEqual: set s and t are equal. However it returns false")
+	}
+
+	// same size, different content
+	a := NewNonTS("1", "2", "3")
+	b := NewNonTS("4", "5", "6")
+
+	ok = a.IsEqual(b)
+	if ok {
+		t.Error("IsEqual: set a and b are now equal (1). However it returns true")
+	}
+
+	// different size, similar content
+	a = NewNonTS("1", "2", "3")
+	b = NewNonTS("1", "2", "3", "4")
+
+	ok = a.IsEqual(b)
+	if ok {
+		t.Error("IsEqual: set s and t are now equal (2). However it returns true")
+	}
+
+}
+
+func TestSetNonTS_IsSubset(t *testing.T) {
+	s := NewNonTS("1", "2", "3", "4")
+	u := NewNonTS("1", "2", "3")
+
+	ok := s.IsSubset(u)
+	if !ok {
+		t.Error("IsSubset: u is a subset of s. However it returns false")
+	}
+
+	ok = u.IsSubset(s)
+	if ok {
+		t.Error("IsSubset: s is not a subset of u. However it returns true")
+	}
+
+}
+
+func TestSetNonTS_IsSuperset(t *testing.T) {
+	s := NewNonTS("1", "2", "3", "4")
+	u := NewNonTS("1", "2", "3")
+
+	ok := u.IsSuperset(s)
+	if !ok {
+		t.Error("IsSuperset: s is a superset of u. However it returns false")
+	}
+
+	ok = s.IsSuperset(u)
+	if ok {
+		t.Error("IsSuperset: u is not a superset of u. However it returns true")
+	}
+
+}
+
+func TestSetNonTS_String(t *testing.T) {
+	s := NewNonTS()
+	if s.String() != "[]" {
+		t.Errorf("String: output is not what is excepted '%s'", s.String())
+	}
+
+	s.Add("1", "2", "3", "4")
+	if !strings.HasPrefix(s.String(), "[") {
+		t.Error("String: output should begin with a square bracket")
+	}
+
+	if !strings.HasSuffix(s.String(), "]") {
+		t.Error("String: output should end with a square bracket")
+	}
+
+}
+
+func TestSetNonTS_List(t *testing.T) {
+	s := NewNonTS("1", "2", "3", "4")
+
+	// this returns a slice of interface{}
+	if len(s.List()) != 4 {
+		t.Error("List: slice size should be four.")
+	}
+
+	for _, item := range s.List() {
+		r := reflect.TypeOf(item)
+		if r.Kind().String() != "string" {
+			t.Error("List: slice item should be a string")
+		}
+	}
+}
+
+func TestSetNonTS_Copy(t *testing.T) {
+	s := NewNonTS("1", "2", "3", "4")
+	r := s.Copy()
+
+	if !s.IsEqual(r) {
+		t.Error("Copy: set s and r are not equal")
+	}
+}
+
+func TestSetNonTS_Merge(t *testing.T) {
+	s := NewNonTS("1", "2", "3")
+	r := NewNonTS("3", "4", "5")
+	s.Merge(r)
+
+	if s.Size() != 5 {
+		t.Error("Merge: the set doesn't have all items in it.")
+	}
+
+	if !s.Has("1", "2", "3", "4", "5") {
+		t.Error("Merge: merged items are not availabile in the set.")
+	}
+}
+
+func TestSetNonTS_Separate(t *testing.T) {
+	s := NewNonTS("1", "2", "3")
+	r := NewNonTS("3", "5")
+	s.Separate(r)
+
+	if s.Size() != 2 {
+		t.Error("Separate: the set doesn't have all items in it.")
+	}
+
+	if !s.Has("1", "2") {
+		t.Error("Separate: items after separation are not availabile in the set.")
+	}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_test.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_test.go
new file mode 100644
index 00000000..83dd5806
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_test.go
@@ -0,0 +1,188 @@
+package set
+
+import (
+	"reflect"
+	"testing"
+)
+
+func Test_Union(t *testing.T) {
+	s := New("1", "2", "3")
+	r := New("3", "4", "5")
+	x := NewNonTS("5", "6", "7")
+
+	u := Union(s, r, x)
+	if settype := reflect.TypeOf(u).String(); settype != "*set.Set" {
+		t.Error("Union should derive its set type from the first passed set, got", settype)
+	}
+	if u.Size() != 7 {
+		t.Error("Union: the merged set doesn't have all items in it.")
+	}
+
+	if !u.Has("1", "2", "3", "4", "5", "6", "7") {
+		t.Error("Union: merged items are not availabile in the set.")
+	}
+
+	z := Union(x, r)
+	if z.Size() != 5 {
+		t.Error("Union: Union of 2 sets doesn't have the proper number of items.")
+	}
+	if settype := reflect.TypeOf(z).String(); settype != "*set.SetNonTS" {
+		t.Error("Union should derive its set type from the first passed set, got", settype)
+	}
+
+}
+
+func Test_Difference(t *testing.T) {
+	s := New("1", "2", "3")
+	r := New("3", "4", "5")
+	x := New("5", "6", "7")
+	u := Difference(s, r, x)
+
+	if u.Size() != 2 {
+		t.Error("Difference: the set doesn't have all items in it.")
+	}
+
+	if !u.Has("1", "2") {
+		t.Error("Difference: items are not availabile in the set.")
+	}
+
+	y := Difference(r, r)
+	if y.Size() != 0 {
+		t.Error("Difference: size should be zero")
+	}
+
+}
+
+func Test_Intersection(t *testing.T) {
+	s1 := New("1", "3", "4", "5")
+	s2 := New("2", "3", "5", "6")
+	s3 := New("4", "5", "6", "7")
+	u := Intersection(s1, s2, s3)
+
+	if u.Size() != 1 {
+		t.Error("Intersection: the set doesn't have all items in it.")
+	}
+
+	if !u.Has("5") {
+		t.Error("Intersection: items after intersection are not availabile in the set.")
+	}
+}
+
+func Test_SymmetricDifference(t *testing.T) {
+	s := New("1", "2", "3")
+	r := New("3", "4", "5")
+	u := SymmetricDifference(s, r)
+
+	if u.Size() != 4 {
+		t.Error("SymmetricDifference: the set doesn't have all items in it.")
+	}
+
+	if !u.Has("1", "2", "4", "5") {
+		t.Error("SymmetricDifference: items are not availabile in the set.")
+	}
+}
+
+func Test_StringSlice(t *testing.T) {
+	s := New("san francisco", "istanbul", 3.14, 1321, "ankara")
+	u := StringSlice(s)
+
+	if len(u) != 3 {
+		t.Error("StringSlice: slice should only have three items")
+	}
+
+	for _, item := range u {
+		r := reflect.TypeOf(item)
+		if r.Kind().String() != "string" {
+			t.Error("StringSlice: slice item should be a string")
+		}
+	}
+}
+
+func Test_IntSlice(t *testing.T) {
+	s := New("san francisco", "istanbul", 3.14, 1321, "ankara", 8876)
+	u := IntSlice(s)
+
+	if len(u) != 2 {
+		t.Error("IntSlice: slice should only have two items")
+	}
+
+	for _, item := range u {
+		r := reflect.TypeOf(item)
+		if r.Kind().String() != "int" {
+			t.Error("Intslice: slice item should be a int")
+		}
+	}
+}
+
+func BenchmarkSetEquality(b *testing.B) {
+	s := New()
+	u := New()
+
+	for i := 0; i < b.N; i++ {
+		s.Add(i)
+		u.Add(i)
+	}
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		s.IsEqual(u)
+	}
+}
+
+func BenchmarkSubset(b *testing.B) {
+	s := New()
+	u := New()
+
+	for i := 0; i < b.N; i++ {
+		s.Add(i)
+		u.Add(i)
+	}
+
+	b.ResetTimer()
+
+	for i := 0; i < b.N; i++ {
+		s.IsSubset(u)
+	}
+}
+
+func benchmarkIntersection(b *testing.B, numberOfItems int) {
+	s1 := New()
+	s2 := New()
+
+	for i := 0; i < numberOfItems/2; i++ {
+		s1.Add(i)
+	}
+	for i := 0; i < numberOfItems; i++ {
+		s2.Add(i)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		Intersection(s1, s2)
+	}
+}
+
+func BenchmarkIntersection10(b *testing.B) {
+	benchmarkIntersection(b, 10)
+}
+
+func BenchmarkIntersection100(b *testing.B) {
+	benchmarkIntersection(b, 100)
+}
+
+func BenchmarkIntersection1000(b *testing.B) {
+	benchmarkIntersection(b, 1000)
+}
+
+func BenchmarkIntersection10000(b *testing.B) {
+	benchmarkIntersection(b, 10000)
+}
+
+func BenchmarkIntersection100000(b *testing.B) {
+	benchmarkIntersection(b, 100000)
+}
+
+func BenchmarkIntersection1000000(b *testing.B) {
+	benchmarkIntersection(b, 1000000)
+}
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts.go
new file mode 100644
index 00000000..50f53256
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts.go
@@ -0,0 +1,200 @@
+package set
+
+import (
+	"sync"
+)
+
+// Set defines a thread safe set data structure.
+type Set struct {
+	set
+	l sync.RWMutex // we name it because we don't want to expose it
+}
+
+// New creates and initialize a new Set. It's accept a variable number of
+// arguments to populate the initial set. If nothing passed a Set with zero
+// size is created.
+func New(items ...interface{}) *Set {
+	s := &Set{}
+	s.m = make(map[interface{}]struct{})
+
+	// Ensure interface compliance
+	var _ Interface = s
+
+	s.Add(items...)
+	return s
+}
+
+// New creates and initalizes a new Set interface. It accepts a variable
+// number of arguments to populate the initial set. If nothing is passed a
+// zero size Set based on the struct is created.
+func (s *Set) New(items ...interface{}) Interface {
+	return New(items...)
+}
+
+// Add includes the specified items (one or more) to the set. The underlying
+// Set s is modified. If passed nothing it silently returns.
+func (s *Set) Add(items ...interface{}) {
+	if len(items) == 0 {
+		return
+	}
+
+	s.l.Lock()
+	defer s.l.Unlock()
+
+	for _, item := range items {
+		s.m[item] = keyExists
+	}
+}
+
+// Remove deletes the specified items from the set.  The underlying Set s is
+// modified. If passed nothing it silently returns.
+func (s *Set) Remove(items ...interface{}) {
+	if len(items) == 0 {
+		return
+	}
+
+	s.l.Lock()
+	defer s.l.Unlock()
+
+	for _, item := range items {
+		delete(s.m, item)
+	}
+}
+
+// Pop  deletes and return an item from the set. The underlying Set s is
+// modified. If set is empty, nil is returned.
+func (s *Set) Pop() interface{} {
+	s.l.RLock()
+	for item := range s.m {
+		s.l.RUnlock()
+		s.l.Lock()
+		delete(s.m, item)
+		s.l.Unlock()
+		return item
+	}
+	s.l.RUnlock()
+	return nil
+}
+
+// Has looks for the existence of items passed. It returns false if nothing is
+// passed. For multiple items it returns true only if all of  the items exist.
+func (s *Set) Has(items ...interface{}) bool {
+	// assume checked for empty item, which not exist
+	if len(items) == 0 {
+		return false
+	}
+
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	has := true
+	for _, item := range items {
+		if _, has = s.m[item]; !has {
+			break
+		}
+	}
+	return has
+}
+
+// Size returns the number of items in a set.
+func (s *Set) Size() int {
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	l := len(s.m)
+	return l
+}
+
+// Clear removes all items from the set.
+func (s *Set) Clear() {
+	s.l.Lock()
+	defer s.l.Unlock()
+
+	s.m = make(map[interface{}]struct{})
+}
+
+// IsEqual test whether s and t are the same in size and have the same items.
+func (s *Set) IsEqual(t Interface) bool {
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	// Force locking only if given set is threadsafe.
+	if conv, ok := t.(*Set); ok {
+		conv.l.RLock()
+		defer conv.l.RUnlock()
+	}
+
+	// return false if they are no the same size
+	if sameSize := len(s.m) == t.Size(); !sameSize {
+		return false
+	}
+
+	equal := true
+	t.Each(func(item interface{}) bool {
+		_, equal = s.m[item]
+		return equal // if false, Each() will end
+	})
+
+	return equal
+}
+
+// IsSubset tests whether t is a subset of s.
+func (s *Set) IsSubset(t Interface) (subset bool) {
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	subset = true
+
+	t.Each(func(item interface{}) bool {
+		_, subset = s.m[item]
+		return subset
+	})
+
+	return
+}
+
+// Each traverses the items in the Set, calling the provided function for each
+// set member. Traversal will continue until all items in the Set have been
+// visited, or if the closure returns false.
+func (s *Set) Each(f func(item interface{}) bool) {
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	for item := range s.m {
+		if !f(item) {
+			break
+		}
+	}
+}
+
+// List returns a slice of all items. There is also StringSlice() and
+// IntSlice() methods for returning slices of type string or int.
+func (s *Set) List() []interface{} {
+	s.l.RLock()
+	defer s.l.RUnlock()
+
+	list := make([]interface{}, 0, len(s.m))
+
+	for item := range s.m {
+		list = append(list, item)
+	}
+
+	return list
+}
+
+// Copy returns a new Set with a copy of s.
+func (s *Set) Copy() Interface {
+	return New(s.List()...)
+}
+
+// Merge is like Union, however it modifies the current set it's applied on
+// with the given t set.
+func (s *Set) Merge(t Interface) {
+	s.l.Lock()
+	defer s.l.Unlock()
+
+	t.Each(func(item interface{}) bool {
+		s.m[item] = keyExists
+		return true
+	})
+}
diff --git a/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts_test.go b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts_test.go
new file mode 100644
index 00000000..8d2f509d
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/fatih/set.v0/set_ts_test.go
@@ -0,0 +1,321 @@
+package set
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestSet_New(t *testing.T) {
+	s := New()
+
+	if s.Size() != 0 {
+		t.Error("New: calling without any parameters should create a set with zero size")
+	}
+
+	u := s.New()
+	if u.Size() != 0 {
+		t.Error("New: creating a new set via s.New() should create a set with zero size")
+	}
+}
+
+func TestSet_New_parameters(t *testing.T) {
+	s := New("string", "another_string", 1, 3.14)
+
+	if s.Size() != 4 {
+		t.Error("New: calling with parameters should create a set with size of four")
+	}
+}
+
+func TestSet_Add(t *testing.T) {
+	s := New()
+	s.Add(1)
+	s.Add(2)
+	s.Add(2) // duplicate
+	s.Add("fatih")
+	s.Add("zeynep")
+	s.Add("zeynep") // another duplicate
+
+	if s.Size() != 4 {
+		t.Error("Add: items are not unique. The set size should be four")
+	}
+
+	if !s.Has(1, 2, "fatih", "zeynep") {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSet_Add_multiple(t *testing.T) {
+	s := New()
+	s.Add("ankara", "san francisco", 3.14)
+
+	if s.Size() != 3 {
+		t.Error("Add: items are not unique. The set size should be three")
+	}
+
+	if !s.Has("ankara", "san francisco", 3.14) {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSet_Remove(t *testing.T) {
+	s := New()
+	s.Add(1)
+	s.Add(2)
+	s.Add("fatih")
+
+	s.Remove(1)
+	if s.Size() != 2 {
+		t.Error("Remove: set size should be two after removing")
+	}
+
+	s.Remove(1)
+	if s.Size() != 2 {
+		t.Error("Remove: set size should be not change after trying to remove a non-existing item")
+	}
+
+	s.Remove(2)
+	s.Remove("fatih")
+	if s.Size() != 0 {
+		t.Error("Remove: set size should be zero")
+	}
+
+	s.Remove("fatih") // try to remove something from a zero length set
+}
+
+func TestSet_Remove_multiple(t *testing.T) {
+	s := New()
+	s.Add("ankara", "san francisco", 3.14, "istanbul")
+	s.Remove("ankara", "san francisco", 3.14)
+
+	if s.Size() != 1 {
+		t.Error("Remove: items are not unique. The set size should be four")
+	}
+
+	if !s.Has("istanbul") {
+		t.Error("Add: added items are not availabile in the set.")
+	}
+}
+
+func TestSet_Pop(t *testing.T) {
+	s := New()
+	s.Add(1)
+	s.Add(2)
+	s.Add("fatih")
+
+	a := s.Pop()
+	if s.Size() != 2 {
+		t.Error("Pop: set size should be two after popping out")
+	}
+
+	if s.Has(a) {
+		t.Error("Pop: returned item should not exist")
+	}
+
+	s.Pop()
+	s.Pop()
+	b := s.Pop()
+	if b != nil {
+		t.Error("Pop: should return nil because set is empty")
+	}
+
+	s.Pop() // try to remove something from a zero length set
+}
+
+func TestSet_Has(t *testing.T) {
+	s := New("1", "2", "3", "4")
+
+	if !s.Has("1") {
+		t.Error("Has: the item 1 exist, but 'Has' is returning false")
+	}
+
+	if !s.Has("1", "2", "3", "4") {
+		t.Error("Has: the items all exist, but 'Has' is returning false")
+	}
+}
+
+func TestSet_Clear(t *testing.T) {
+	s := New()
+	s.Add(1)
+	s.Add("istanbul")
+	s.Add("san francisco")
+
+	s.Clear()
+	if s.Size() != 0 {
+		t.Error("Clear: set size should be zero")
+	}
+}
+
+func TestSet_IsEmpty(t *testing.T) {
+	s := New()
+
+	empty := s.IsEmpty()
+	if !empty {
+		t.Error("IsEmpty: set is empty, it should be true")
+	}
+
+	s.Add(2)
+	s.Add(3)
+	notEmpty := s.IsEmpty()
+
+	if notEmpty {
+		t.Error("IsEmpty: set is filled, it should be false")
+	}
+}
+
+func TestSet_IsEqual(t *testing.T) {
+	s := New("1", "2", "3")
+	u := New("1", "2", "3")
+
+	ok := s.IsEqual(u)
+	if !ok {
+		t.Error("IsEqual: set s and t are equal. However it returns false")
+	}
+
+	// same size, different content
+	a := New("1", "2", "3")
+	b := New("4", "5", "6")
+
+	ok = a.IsEqual(b)
+	if ok {
+		t.Error("IsEqual: set a and b are now equal (1). However it returns true")
+	}
+
+	// different size, similar content
+	a = New("1", "2", "3")
+	b = New("1", "2", "3", "4")
+
+	ok = a.IsEqual(b)
+	if ok {
+		t.Error("IsEqual: set s and t are now equal (2). However it returns true")
+	}
+
+}
+
+func TestSet_IsSubset(t *testing.T) {
+	s := New("1", "2", "3", "4")
+	u := New("1", "2", "3")
+
+	ok := s.IsSubset(u)
+	if !ok {
+		t.Error("IsSubset: u is a subset of s. However it returns false")
+	}
+
+	ok = u.IsSubset(s)
+	if ok {
+		t.Error("IsSubset: s is not a subset of u. However it returns true")
+	}
+
+}
+
+func TestSet_IsSuperset(t *testing.T) {
+	s := New("1", "2", "3", "4")
+	u := New("1", "2", "3")
+
+	ok := u.IsSuperset(s)
+	if !ok {
+		t.Error("IsSuperset: s is a superset of u. However it returns false")
+	}
+
+	ok = s.IsSuperset(u)
+	if ok {
+		t.Error("IsSuperset: u is not a superset of u. However it returns true")
+	}
+
+}
+
+func TestSet_String(t *testing.T) {
+	s := New()
+	if s.String() != "[]" {
+		t.Errorf("String: output is not what is excepted '%s'", s.String())
+	}
+
+	s.Add("1", "2", "3", "4")
+	if !strings.HasPrefix(s.String(), "[") {
+		t.Error("String: output should begin with a square bracket")
+	}
+
+	if !strings.HasSuffix(s.String(), "]") {
+		t.Error("String: output should end with a square bracket")
+	}
+}
+
+func TestSet_List(t *testing.T) {
+	s := New("1", "2", "3", "4")
+
+	// this returns a slice of interface{}
+	if len(s.List()) != 4 {
+		t.Error("List: slice size should be four.")
+	}
+
+	for _, item := range s.List() {
+		r := reflect.TypeOf(item)
+		if r.Kind().String() != "string" {
+			t.Error("List: slice item should be a string")
+		}
+	}
+}
+
+func TestSet_Copy(t *testing.T) {
+	s := New("1", "2", "3", "4")
+	r := s.Copy()
+
+	if !s.IsEqual(r) {
+		t.Error("Copy: set s and r are not equal")
+	}
+}
+
+func TestSet_Merge(t *testing.T) {
+	s := New("1", "2", "3")
+	r := New("3", "4", "5")
+	s.Merge(r)
+
+	if s.Size() != 5 {
+		t.Error("Merge: the set doesn't have all items in it.")
+	}
+
+	if !s.Has("1", "2", "3", "4", "5") {
+		t.Error("Merge: merged items are not availabile in the set.")
+	}
+}
+
+func TestSet_Separate(t *testing.T) {
+	s := New("1", "2", "3")
+	r := New("3", "5")
+	s.Separate(r)
+
+	if s.Size() != 2 {
+		t.Error("Separate: the set doesn't have all items in it.")
+	}
+
+	if !s.Has("1", "2") {
+		t.Error("Separate: items after separation are not availabile in the set.")
+	}
+}
+
+func TestSet_RaceAdd(t *testing.T) {
+	// Create two sets. Add concurrently items to each of them. Remove from the
+	// other one.
+	// "go test -race" should detect this if the library is not thread-safe.
+	s := New()
+	u := New()
+
+	go func() {
+		for i := 0; i < 1000; i++ {
+			item := "item" + strconv.Itoa(i)
+			go func(i int) {
+				s.Add(item)
+				u.Add(item)
+			}(i)
+		}
+	}()
+
+	for i := 0; i < 1000; i++ {
+		item := "item" + strconv.Itoa(i)
+		go func(i int) {
+			s.Add(item)
+			u.Add(item)
+		}(i)
+	}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/.gitignore b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/.gitignore
new file mode 100644
index 00000000..83656241
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/.gitignore
@@ -0,0 +1,23 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/LICENSE b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/LICENSE
new file mode 100644
index 00000000..a4f2f281
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Tyler Bunnell
+
+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.
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/README.md b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/README.md
new file mode 100644
index 00000000..531249a7
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/README.md
@@ -0,0 +1,137 @@
+graceful [![GoDoc](https://godoc.org/github.com/tylerb/graceful?status.png)](http://godoc.org/github.com/tylerb/graceful) [![Build Status](https://drone.io/github.com/tylerb/graceful/status.png)](https://drone.io/github.com/tylerb/graceful/latest) [![Coverage Status](https://coveralls.io/repos/tylerb/graceful/badge.svg?branch=dronedebug)](https://coveralls.io/r/tylerb/graceful?branch=dronedebug) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tylerb/graceful?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+========
+
+Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers.
+
+## Installation
+
+To install, simply execute:
+
+```
+go get gopkg.in/tylerb/graceful.v1
+```
+
+I am using [gopkg.in](http://labix.org/gopkg.in) to control releases.
+
+## Usage
+
+Using Graceful is easy. Simply create your http.Handler and pass it to the `Run` function:
+
+```go
+package main
+
+import (
+  "gopkg.in/tylerb/graceful.v1"
+  "net/http"
+  "fmt"
+  "time"
+)
+
+func main() {
+  mux := http.NewServeMux()
+  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+    fmt.Fprintf(w, "Welcome to the home page!")
+  })
+
+  graceful.Run(":3001",10*time.Second,mux)
+}
+```
+
+Another example, using [Negroni](https://github.com/codegangsta/negroni), functions in much the same manner:
+
+```go
+package main
+
+import (
+  "github.com/codegangsta/negroni"
+  "gopkg.in/tylerb/graceful.v1"
+  "net/http"
+  "fmt"
+  "time"
+)
+
+func main() {
+  mux := http.NewServeMux()
+  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+    fmt.Fprintf(w, "Welcome to the home page!")
+  })
+
+  n := negroni.Classic()
+  n.UseHandler(mux)
+  //n.Run(":3000")
+  graceful.Run(":3001",10*time.Second,n)
+}
+```
+
+In addition to Run there are the http.Server counterparts ListenAndServe, ListenAndServeTLS and Serve, which allow you to configure HTTPS, custom timeouts and error handling.
+Graceful may also be used by instantiating its Server type directly, which embeds an http.Server:
+
+```go
+mux := // ...
+
+srv := &graceful.Server{
+  Timeout: 10 * time.Second,
+
+  Server: &http.Server{
+    Addr: ":1234",
+    Handler: mux,
+  },
+}
+
+srv.ListenAndServe()
+```
+
+This form allows you to set the ConnState callback, which works in the same way as in http.Server:
+
+```go
+mux := // ...
+
+srv := &graceful.Server{
+  Timeout: 10 * time.Second,
+
+  ConnState: func(conn net.Conn, state http.ConnState) {
+    // conn has a new state
+  },
+
+  Server: &http.Server{
+    Addr: ":1234",
+    Handler: mux,
+  },
+}
+
+srv.ListenAndServe()
+```
+
+## Behaviour
+
+When Graceful is sent a SIGINT or SIGTERM (possibly from ^C or a kill command), it:
+
+1. Disables keepalive connections.
+2. Closes the listening socket, allowing another process to listen on that port immediately.
+3. Starts a timer of `timeout` duration to give active requests a chance to finish.
+4. When timeout expires, closes all active connections.
+5. Closes the `stopChan`, waking up any blocking goroutines.
+6. Returns from the function, allowing the server to terminate.
+
+## Notes
+
+If the `timeout` argument to `Run` is 0, the server never times out, allowing all active requests to complete.
+
+If you wish to stop the server in some way other than an OS signal, you may call the `Stop()` function.
+This function stops the server, gracefully, using the new timeout value you provide. The `StopChan()` function
+returns a channel on which you can block while waiting for the server to stop. This channel will be closed when
+the server is stopped, allowing your execution to proceed. Multiple goroutines can block on this channel at the
+same time and all will be signalled when stopping is complete.
+
+## Contributing
+
+If you would like to contribute, please:
+
+1. Create a GitHub issue regarding the contribution. Features and bugs should be discussed beforehand.
+2. Fork the repository.
+3. Create a pull request with your solution. This pull request should reference and close the issues (Fix #2).
+
+All pull requests should:
+
+1. Pass [gometalinter -t .](https://github.com/alecthomas/gometalinter) with no warnings.
+2. Be `go fmt` formatted.
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful.go b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful.go
new file mode 100644
index 00000000..0951e08e
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful.go
@@ -0,0 +1,319 @@
+package graceful
+
+import (
+	"crypto/tls"
+	"log"
+	"net"
+	"net/http"
+	"os"
+	"os/signal"
+	"sync"
+	"syscall"
+	"time"
+
+	"golang.org/x/net/netutil"
+)
+
+// Server wraps an http.Server with graceful connection handling.
+// It may be used directly in the same way as http.Server, or may
+// be constructed with the global functions in this package.
+//
+// Example:
+//	srv := &graceful.Server{
+//		Timeout: 5 * time.Second,
+//		Server: &http.Server{Addr: ":1234", Handler: handler},
+//	}
+//	srv.ListenAndServe()
+type Server struct {
+	*http.Server
+
+	// Timeout is the duration to allow outstanding requests to survive
+	// before forcefully terminating them.
+	Timeout time.Duration
+
+	// Limit the number of outstanding requests
+	ListenLimit int
+
+	// ConnState specifies an optional callback function that is
+	// called when a client connection changes state. This is a proxy
+	// to the underlying http.Server's ConnState, and the original
+	// must not be set directly.
+	ConnState func(net.Conn, http.ConnState)
+
+	// ShutdownInitiated is an optional callback function that is called
+	// when shutdown is initiated. It can be used to notify the client
+	// side of long lived connections (e.g. websockets) to reconnect.
+	ShutdownInitiated func()
+
+	// NoSignalHandling prevents graceful from automatically shutting down
+	// on SIGINT and SIGTERM. If set to true, you must shut down the server
+	// manually with Stop().
+	NoSignalHandling bool
+
+	// interrupt signals the listener to stop serving connections,
+	// and the server to shut down.
+	interrupt chan os.Signal
+
+	// stopChan is the channel on which callers may block while waiting for
+	// the server to stop.
+	stopChan chan struct{}
+
+	// stopLock is used to protect access to the stopChan.
+	stopLock sync.RWMutex
+
+	// connections holds all connections managed by graceful
+	connections map[net.Conn]struct{}
+}
+
+// Run serves the http.Handler with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func Run(addr string, timeout time.Duration, n http.Handler) {
+	srv := &Server{
+		Timeout: timeout,
+		Server:  &http.Server{Addr: addr, Handler: n},
+	}
+
+	if err := srv.ListenAndServe(); err != nil {
+		if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
+			logger := log.New(os.Stdout, "[graceful] ", 0)
+			logger.Fatal(err)
+		}
+	}
+}
+
+// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func ListenAndServe(server *http.Server, timeout time.Duration) error {
+	srv := &Server{Timeout: timeout, Server: server}
+	return srv.ListenAndServe()
+}
+
+// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled.
+func (srv *Server) ListenAndServe() error {
+	// Create the listener so we can control their lifetime
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":http"
+	}
+	l, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+
+	if srv.ListenLimit != 0 {
+		l = netutil.LimitListener(l, srv.ListenLimit)
+	}
+	return srv.Serve(l)
+}
+
+// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func ListenAndServeTLS(server *http.Server, certFile, keyFile string, timeout time.Duration) error {
+	srv := &Server{Timeout: timeout, Server: server}
+	return srv.ListenAndServeTLS(certFile, keyFile)
+}
+
+// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
+func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
+	// Create the listener ourselves so we can control its lifetime
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":https"
+	}
+
+	config := &tls.Config{}
+	if srv.TLSConfig != nil {
+		*config = *srv.TLSConfig
+	}
+	if config.NextProtos == nil {
+		config.NextProtos = []string{"http/1.1"}
+	}
+
+	var err error
+	config.Certificates = make([]tls.Certificate, 1)
+	config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+	if err != nil {
+		return err
+	}
+
+	conn, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+
+	tlsListener := tls.NewListener(conn, config)
+	return srv.Serve(tlsListener)
+}
+
+// ListenAndServeTLSConfig can be used with an existing TLS config and is equivalent to
+// http.Server.ListenAndServeTLS with graceful shutdown enabled,
+func (srv *Server) ListenAndServeTLSConfig(config *tls.Config) error {
+	addr := srv.Addr
+	if addr == "" {
+		addr = ":https"
+	}
+
+	conn, err := net.Listen("tcp", addr)
+	if err != nil {
+		return err
+	}
+
+	tlsListener := tls.NewListener(conn, config)
+	return srv.Serve(tlsListener)
+}
+
+// Serve is equivalent to http.Server.Serve with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func Serve(server *http.Server, l net.Listener, timeout time.Duration) error {
+	srv := &Server{Timeout: timeout, Server: server}
+	return srv.Serve(l)
+}
+
+// Serve is equivalent to http.Server.Serve with graceful shutdown enabled.
+func (srv *Server) Serve(listener net.Listener) error {
+	// Track connection state
+	add := make(chan net.Conn)
+	remove := make(chan net.Conn)
+
+	srv.Server.ConnState = func(conn net.Conn, state http.ConnState) {
+		switch state {
+		case http.StateNew:
+			add <- conn
+		case http.StateClosed, http.StateHijacked:
+			remove <- conn
+		}
+		if srv.ConnState != nil {
+			srv.ConnState(conn, state)
+		}
+	}
+
+	// Manage open connections
+	shutdown := make(chan chan struct{})
+	kill := make(chan struct{})
+	go srv.manageConnections(add, remove, shutdown, kill)
+
+	interrupt := srv.interruptChan()
+
+	// Set up the interrupt handler
+	if !srv.NoSignalHandling {
+		signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
+	}
+
+	go srv.handleInterrupt(interrupt, listener)
+
+	// Serve with graceful listener.
+	// Execution blocks here until listener.Close() is called, above.
+	err := srv.Server.Serve(listener)
+
+	srv.shutdown(shutdown, kill)
+
+	return err
+}
+
+// Stop instructs the type to halt operations and close
+// the stop channel when it is finished.
+//
+// timeout is grace period for which to wait before shutting
+// down the server. The timeout value passed here will override the
+// timeout given when constructing the server, as this is an explicit
+// command to stop the server.
+func (srv *Server) Stop(timeout time.Duration) {
+	srv.Timeout = timeout
+	interrupt := srv.interruptChan()
+	interrupt <- syscall.SIGINT
+}
+
+// StopChan gets the stop channel which will block until
+// stopping has completed, at which point it is closed.
+// Callers should never close the stop channel.
+func (srv *Server) StopChan() <-chan struct{} {
+	srv.stopLock.Lock()
+	if srv.stopChan == nil {
+		srv.stopChan = make(chan struct{})
+	}
+	srv.stopLock.Unlock()
+	return srv.stopChan
+}
+
+func (srv *Server) manageConnections(add, remove chan net.Conn, shutdown chan chan struct{}, kill chan struct{}) {
+	{
+		var done chan struct{}
+		srv.connections = map[net.Conn]struct{}{}
+		for {
+			select {
+			case conn := <-add:
+				srv.connections[conn] = struct{}{}
+			case conn := <-remove:
+				delete(srv.connections, conn)
+				if done != nil && len(srv.connections) == 0 {
+					done <- struct{}{}
+					return
+				}
+			case done = <-shutdown:
+				if len(srv.connections) == 0 {
+					done <- struct{}{}
+					return
+				}
+			case <-kill:
+				for k := range srv.connections {
+					_ = k.Close() // nothing to do here if it errors
+				}
+				return
+			}
+		}
+	}
+}
+
+func (srv *Server) interruptChan() chan os.Signal {
+	srv.stopLock.Lock()
+	if srv.interrupt == nil {
+		srv.interrupt = make(chan os.Signal, 1)
+	}
+	srv.stopLock.Unlock()
+
+	return srv.interrupt
+}
+
+func (srv *Server) handleInterrupt(interrupt chan os.Signal, listener net.Listener) {
+	<-interrupt
+
+	srv.SetKeepAlivesEnabled(false)
+	_ = listener.Close() // we are shutting down anyway. ignore error.
+
+	if srv.ShutdownInitiated != nil {
+		srv.ShutdownInitiated()
+	}
+
+	signal.Stop(interrupt)
+	close(interrupt)
+}
+
+func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) {
+	// Request done notification
+	done := make(chan struct{})
+	shutdown <- done
+
+	if srv.Timeout > 0 {
+		select {
+		case <-done:
+		case <-time.After(srv.Timeout):
+			close(kill)
+		}
+	} else {
+		<-done
+	}
+	// Close the stopChan to wake up any blocked goroutines.
+	srv.stopLock.Lock()
+	if srv.stopChan != nil {
+		close(srv.stopChan)
+	}
+	srv.stopLock.Unlock()
+}
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful_test.go b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful_test.go
new file mode 100644
index 00000000..c7382736
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/graceful_test.go
@@ -0,0 +1,379 @@
+package graceful
+
+import (
+	"fmt"
+	"io"
+	"net"
+	"net/http"
+	"net/url"
+	"os"
+	"reflect"
+	"sync"
+	"syscall"
+	"testing"
+	"time"
+)
+
+var (
+	killTime    = 500 * time.Millisecond
+	timeoutTime = 1000 * time.Millisecond
+	waitTime    = 100 * time.Millisecond
+)
+
+func runQuery(t *testing.T, expected int, shouldErr bool, wg *sync.WaitGroup, once *sync.Once) {
+	wg.Add(1)
+	defer wg.Done()
+	client := http.Client{}
+	r, err := client.Get("http://localhost:3000")
+	if shouldErr && err == nil {
+		once.Do(func() {
+			t.Fatal("Expected an error but none was encountered.")
+		})
+	} else if shouldErr && err != nil {
+		if checkErr(t, err, once) {
+			return
+		}
+	}
+	if r != nil && r.StatusCode != expected {
+		once.Do(func() {
+			t.Fatalf("Incorrect status code on response. Expected %d. Got %d", expected, r.StatusCode)
+		})
+	} else if r == nil {
+		once.Do(func() {
+			t.Fatal("No response when a response was expected.")
+		})
+	}
+}
+
+func checkErr(t *testing.T, err error, once *sync.Once) bool {
+	if err.(*url.Error).Err == io.EOF {
+		return true
+	}
+	errno := err.(*url.Error).Err.(*net.OpError).Err.(syscall.Errno)
+	if errno == syscall.ECONNREFUSED {
+		return true
+	} else if err != nil {
+		once.Do(func() {
+			t.Fatal("Error on Get:", err)
+		})
+	}
+	return false
+}
+
+func createListener(sleep time.Duration) (*http.Server, net.Listener, error) {
+	mux := http.NewServeMux()
+	mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
+		time.Sleep(sleep)
+		rw.WriteHeader(http.StatusOK)
+	})
+
+	server := &http.Server{Addr: ":3000", Handler: mux}
+	l, err := net.Listen("tcp", ":3000")
+	if err != nil {
+		fmt.Println(err)
+	}
+	return server, l, err
+}
+
+func runServer(timeout, sleep time.Duration, c chan os.Signal) error {
+	server, l, err := createListener(sleep)
+	if err != nil {
+		return err
+	}
+
+	srv := &Server{Timeout: timeout, Server: server, interrupt: c}
+	return srv.Serve(l)
+}
+
+func launchTestQueries(t *testing.T, wg *sync.WaitGroup, c chan os.Signal) {
+	var once sync.Once
+	for i := 0; i < 8; i++ {
+		go runQuery(t, http.StatusOK, false, wg, &once)
+	}
+
+	time.Sleep(waitTime)
+	c <- os.Interrupt
+	time.Sleep(waitTime)
+
+	for i := 0; i < 8; i++ {
+		go runQuery(t, 0, true, wg, &once)
+	}
+
+	wg.Done()
+}
+
+func TestGracefulRun(t *testing.T) {
+	c := make(chan os.Signal, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	go func() {
+		runServer(killTime, killTime/2, c)
+		wg.Done()
+	}()
+
+	wg.Add(1)
+	go launchTestQueries(t, &wg, c)
+	wg.Wait()
+}
+
+func TestGracefulRunTimesOut(t *testing.T) {
+	c := make(chan os.Signal, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	go func() {
+		runServer(killTime, killTime*10, c)
+		wg.Done()
+	}()
+
+	var once sync.Once
+	wg.Add(1)
+	go func() {
+		for i := 0; i < 8; i++ {
+			go runQuery(t, 0, true, &wg, &once)
+		}
+		time.Sleep(waitTime)
+		c <- os.Interrupt
+		time.Sleep(waitTime)
+		for i := 0; i < 8; i++ {
+			go runQuery(t, 0, true, &wg, &once)
+		}
+		wg.Done()
+	}()
+
+	wg.Wait()
+
+}
+
+func TestGracefulRunDoesntTimeOut(t *testing.T) {
+	c := make(chan os.Signal, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	go func() {
+		runServer(0, killTime*2, c)
+		wg.Done()
+	}()
+
+	wg.Add(1)
+	go launchTestQueries(t, &wg, c)
+	wg.Wait()
+}
+
+func TestGracefulRunNoRequests(t *testing.T) {
+	c := make(chan os.Signal, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	go func() {
+		runServer(0, killTime*2, c)
+		wg.Done()
+	}()
+
+	c <- os.Interrupt
+
+	wg.Wait()
+
+}
+
+func TestGracefulForwardsConnState(t *testing.T) {
+	c := make(chan os.Signal, 1)
+	states := make(map[http.ConnState]int)
+	var stateLock sync.Mutex
+
+	connState := func(conn net.Conn, state http.ConnState) {
+		stateLock.Lock()
+		states[state]++
+		stateLock.Unlock()
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	expected := map[http.ConnState]int{
+		http.StateNew:    8,
+		http.StateActive: 8,
+		http.StateClosed: 8,
+	}
+
+	go func() {
+		server, l, _ := createListener(killTime / 2)
+		srv := &Server{
+			ConnState: connState,
+			Timeout:   killTime,
+			Server:    server,
+			interrupt: c,
+		}
+		srv.Serve(l)
+
+		wg.Done()
+	}()
+
+	wg.Add(1)
+	go launchTestQueries(t, &wg, c)
+	wg.Wait()
+
+	stateLock.Lock()
+	if !reflect.DeepEqual(states, expected) {
+		t.Errorf("Incorrect connection state tracking.\n  actual: %v\nexpected: %v\n", states, expected)
+	}
+	stateLock.Unlock()
+}
+
+func TestGracefulExplicitStop(t *testing.T) {
+	server, l, err := createListener(1 * time.Millisecond)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv := &Server{Timeout: killTime, Server: server}
+
+	go func() {
+		go srv.Serve(l)
+		time.Sleep(waitTime)
+		srv.Stop(killTime)
+	}()
+
+	// block on the stopChan until the server has shut down
+	select {
+	case <-srv.StopChan():
+	case <-time.After(timeoutTime):
+		t.Fatal("Timed out while waiting for explicit stop to complete")
+	}
+}
+
+func TestGracefulExplicitStopOverride(t *testing.T) {
+	server, l, err := createListener(1 * time.Millisecond)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv := &Server{Timeout: killTime, Server: server}
+
+	go func() {
+		go srv.Serve(l)
+		time.Sleep(waitTime)
+		srv.Stop(killTime / 2)
+	}()
+
+	// block on the stopChan until the server has shut down
+	select {
+	case <-srv.StopChan():
+	case <-time.After(killTime):
+		t.Fatal("Timed out while waiting for explicit stop to complete")
+	}
+}
+
+func TestShutdownInitiatedCallback(t *testing.T) {
+	server, l, err := createListener(1 * time.Millisecond)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	called := make(chan struct{})
+	cb := func() { close(called) }
+
+	srv := &Server{Server: server, ShutdownInitiated: cb}
+
+	go func() {
+		go srv.Serve(l)
+		time.Sleep(waitTime)
+		srv.Stop(killTime)
+	}()
+
+	select {
+	case <-called:
+	case <-time.After(killTime):
+		t.Fatal("Timed out while waiting for ShutdownInitiated callback to be called")
+	}
+}
+func hijackingListener(srv *Server) (*http.Server, net.Listener, error) {
+	mux := http.NewServeMux()
+	mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
+		conn, bufrw, err := rw.(http.Hijacker).Hijack()
+		if err != nil {
+			http.Error(rw, "webserver doesn't support hijacking", http.StatusInternalServerError)
+			return
+		}
+
+		defer conn.Close()
+
+		bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
+		bufrw.Flush()
+	})
+
+	server := &http.Server{Addr: ":3000", Handler: mux}
+	l, err := net.Listen("tcp", ":3000")
+	return server, l, err
+}
+
+func TestNotifyClosed(t *testing.T) {
+	c := make(chan os.Signal, 1)
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+
+	srv := &Server{Timeout: killTime, interrupt: c}
+	server, l, err := hijackingListener(srv)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv.Server = server
+
+	go func() {
+		srv.Serve(l)
+		wg.Done()
+	}()
+
+	var once sync.Once
+	for i := 0; i < 8; i++ {
+		runQuery(t, http.StatusOK, false, &wg, &once)
+	}
+
+	srv.Stop(0)
+
+	// block on the stopChan until the server has shut down
+	select {
+	case <-srv.StopChan():
+	case <-time.After(timeoutTime):
+		t.Fatal("Timed out while waiting for explicit stop to complete")
+	}
+
+	if len(srv.connections) > 0 {
+		t.Fatal("hijacked connections should not be managed")
+	}
+
+}
+
+func TestStopDeadlock(t *testing.T) {
+	c := make(chan struct{})
+
+	server, l, err := createListener(1 * time.Millisecond)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	srv := &Server{Server: server, NoSignalHandling: true}
+
+	go func() {
+		time.Sleep(waitTime)
+		srv.Serve(l)
+	}()
+
+	go func() {
+		srv.Stop(0)
+		close(c)
+	}()
+
+	select {
+	case <-c:
+	case <-time.After(timeoutTime):
+		t.Fatal("Timed out while waiting for explicit stop to complete")
+	}
+}
diff --git a/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/tests/main.go b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/tests/main.go
new file mode 100644
index 00000000..8c8fa204
--- /dev/null
+++ b/Godeps/_workspace/src/gopkg.in/tylerb/graceful.v1/tests/main.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+	"fmt"
+	"sync"
+
+	"github.com/codegangsta/negroni"
+	"github.com/tylerb/graceful"
+)
+
+func main() {
+
+	var wg sync.WaitGroup
+
+	wg.Add(3)
+	go func() {
+		n := negroni.New()
+		fmt.Println("Launching server on :3000")
+		graceful.Run(":3000", 0, n)
+		fmt.Println("Terminated server on :3000")
+		wg.Done()
+	}()
+	go func() {
+		n := negroni.New()
+		fmt.Println("Launching server on :3001")
+		graceful.Run(":3001", 0, n)
+		fmt.Println("Terminated server on :3001")
+		wg.Done()
+	}()
+	go func() {
+		n := negroni.New()
+		fmt.Println("Launching server on :3002")
+		graceful.Run(":3002", 0, n)
+		fmt.Println("Terminated server on :3002")
+		wg.Done()
+	}()
+	fmt.Println("Press ctrl+c. All servers should terminate.")
+	wg.Wait()
+
+}
-- 
GitLab