+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/README.md b/Godeps/_workspace/src/github.com/samalba/dockerclient/README.md
new file mode 100644
index 0000000000..26f2528959
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/README.md
@@ -0,0 +1,63 @@
+Docker client library in Go
+===========================
+[](http://godoc.org/github.com/samalba/dockerclient)
+
+Well maintained docker client library.
+
+Example:
+
+```go
+package main
+
+import (
+ "github.com/samalba/dockerclient"
+ "log"
+ "time"
+)
+
+// Callback used to listen to Docker's events
+func eventCallback(event *dockerclient.Event, ec chan error, args ...interface{}) {
+ log.Printf("Received event: %#v\n", *event)
+}
+
+func main() {
+ // Init the client
+ docker, _ := dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
+
+ // Get only running containers
+ containers, err := docker.ListContainers(false)
+ if err != nil {
+ log.Fatal(err)
+ }
+ for _, c := range containers {
+ log.Println(c.Id, c.Names)
+ }
+
+ // Inspect the first container returned
+ if len(containers) > 0 {
+ id := containers[0].Id
+ info, _ := docker.InspectContainer(id)
+ log.Println(info)
+ }
+
+ // Create a container
+ containerConfig := &dockerclient.ContainerConfig{Image: "ubuntu:12.04", Cmd: []string{"bash"}}
+ containerId, err := docker.CreateContainer(containerConfig)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Start the container
+ err = docker.StartContainer(containerId)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Stop the container (with 5 seconds timeout)
+ docker.StopContainer(containerId, 5)
+
+ // Listen to events
+ docker.StartMonitorEvents(eventCallback, nil)
+ time.Sleep(3600 * time.Second)
+}
+```
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/auth.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/auth.go
new file mode 100644
index 0000000000..022d3ddfdb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/auth.go
@@ -0,0 +1,21 @@
+package dockerclient
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+)
+
+// AuthConfig hold parameters for authenticating with the docker registry
+type AuthConfig struct {
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty"`
+ Email string `json:"email,omitempty"`
+}
+
+// encode the auth configuration struct into base64 for the X-Registry-Auth header
+func (c *AuthConfig) encode() string {
+ var buf bytes.Buffer
+ json.NewEncoder(&buf).Encode(c)
+ return base64.URLEncoding.EncodeToString(buf.Bytes())
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/auth_test.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/auth_test.go
new file mode 100644
index 0000000000..f6eac9926e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/auth_test.go
@@ -0,0 +1,15 @@
+package dockerclient
+
+import (
+ "testing"
+)
+
+func TestAuthEncode(t *testing.T) {
+ a := AuthConfig{Username: "foo", Password: "password", Email: "bar@baz.com"}
+ expected := "eyJ1c2VybmFtZSI6ImZvbyIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImJhckBiYXouY29tIn0K"
+ got := a.encode()
+
+ if expected != got {
+ t.Errorf("testAuthEncode failed. Expected [%s] got [%s]", expected, got)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient.go
new file mode 100644
index 0000000000..0bc2018a00
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient.go
@@ -0,0 +1,380 @@
+package dockerclient
+
+import (
+ "bytes"
+ "crypto/tls"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "sync/atomic"
+ "time"
+)
+
+const (
+ APIVersion = "v1.15"
+)
+
+var (
+ ErrNotFound = errors.New("Not found")
+
+ defaultTimeout = 30 * time.Second
+)
+
+type DockerClient struct {
+ URL *url.URL
+ HTTPClient *http.Client
+ TLSConfig *tls.Config
+ monitorEvents int32
+}
+
+type Error struct {
+ StatusCode int
+ Status string
+ msg string
+}
+
+func (e Error) Error() string {
+ return fmt.Sprintf("%s: %s", e.Status, e.msg)
+}
+
+func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, error) {
+ return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout))
+}
+
+func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration) (*DockerClient, error) {
+ u, err := url.Parse(daemonUrl)
+ if err != nil {
+ return nil, err
+ }
+ if u.Scheme == "" || u.Scheme == "tcp" {
+ if tlsConfig == nil {
+ u.Scheme = "http"
+ } else {
+ u.Scheme = "https"
+ }
+ }
+ httpClient := newHTTPClient(u, tlsConfig, timeout)
+ return &DockerClient{u, httpClient, tlsConfig, 0}, nil
+}
+
+func (client *DockerClient) doRequest(method string, path string, body []byte, headers map[string]string) ([]byte, error) {
+ b := bytes.NewBuffer(body)
+ req, err := http.NewRequest(method, client.URL.String()+path, b)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Add("Content-Type", "application/json")
+ if headers != nil {
+ for header, value := range headers {
+ req.Header.Add(header, value)
+ }
+ }
+ resp, err := client.HTTPClient.Do(req)
+ if err != nil {
+ if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
+ return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
+ }
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ if resp.StatusCode == 404 {
+ return nil, ErrNotFound
+ }
+ if resp.StatusCode >= 400 {
+ return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)}
+ }
+ return data, nil
+}
+
+func (client *DockerClient) Info() (*Info, error) {
+ uri := fmt.Sprintf("/%s/info", APIVersion)
+ data, err := client.doRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ ret := &Info{}
+ err = json.Unmarshal(data, &ret)
+ if err != nil {
+ return nil, err
+ }
+ return ret, nil
+}
+
+func (client *DockerClient) ListContainers(all bool, size bool, filters string) ([]Container, error) {
+ argAll := 0
+ if all == true {
+ argAll = 1
+ }
+ showSize := 0
+ if size == true {
+ showSize = 1
+ }
+ uri := fmt.Sprintf("/%s/containers/json?all=%d&size=%d", APIVersion, argAll, showSize)
+
+ if filters != "" {
+ uri += "&filters=" + filters
+ }
+
+ data, err := client.doRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ ret := []Container{}
+ err = json.Unmarshal(data, &ret)
+ if err != nil {
+ return nil, err
+ }
+ return ret, nil
+}
+
+func (client *DockerClient) InspectContainer(id string) (*ContainerInfo, error) {
+ uri := fmt.Sprintf("/%s/containers/%s/json", APIVersion, id)
+ data, err := client.doRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ info := &ContainerInfo{}
+ err = json.Unmarshal(data, info)
+ if err != nil {
+ return nil, err
+ }
+ return info, nil
+}
+
+func (client *DockerClient) CreateContainer(config *ContainerConfig, name string) (string, error) {
+ data, err := json.Marshal(config)
+ if err != nil {
+ return "", err
+ }
+ uri := fmt.Sprintf("/%s/containers/create", APIVersion)
+ if name != "" {
+ v := url.Values{}
+ v.Set("name", name)
+ uri = fmt.Sprintf("%s?%s", uri, v.Encode())
+ }
+ data, err = client.doRequest("POST", uri, data, nil)
+ if err != nil {
+ return "", err
+ }
+ result := &RespContainersCreate{}
+ err = json.Unmarshal(data, result)
+ if err != nil {
+ return "", err
+ }
+ return result.Id, nil
+}
+
+func (client *DockerClient) ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error) {
+ v := url.Values{}
+ v.Add("follow", strconv.FormatBool(options.Follow))
+ v.Add("stdout", strconv.FormatBool(options.Stdout))
+ v.Add("stderr", strconv.FormatBool(options.Stderr))
+ v.Add("timestamps", strconv.FormatBool(options.Timestamps))
+ if options.Tail > 0 {
+ v.Add("tail", strconv.FormatInt(options.Tail, 10))
+ }
+
+ uri := fmt.Sprintf("/%s/containers/%s/logs?%s", APIVersion, id, v.Encode())
+ req, err := http.NewRequest("GET", client.URL.String()+uri, nil)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Add("Content-Type", "application/json")
+ resp, err := client.HTTPClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ return resp.Body, nil
+}
+
+func (client *DockerClient) StartContainer(id string, config *HostConfig) error {
+ data, err := json.Marshal(config)
+ if err != nil {
+ return err
+ }
+ uri := fmt.Sprintf("/%s/containers/%s/start", APIVersion, id)
+ _, err = client.doRequest("POST", uri, data, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (client *DockerClient) StopContainer(id string, timeout int) error {
+ uri := fmt.Sprintf("/%s/containers/%s/stop?t=%d", APIVersion, id, timeout)
+ _, err := client.doRequest("POST", uri, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (client *DockerClient) RestartContainer(id string, timeout int) error {
+ uri := fmt.Sprintf("/%s/containers/%s/restart?t=%d", APIVersion, id, timeout)
+ _, err := client.doRequest("POST", uri, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (client *DockerClient) KillContainer(id, signal string) error {
+ uri := fmt.Sprintf("/%s/containers/%s/kill?signal=%s", APIVersion, id, signal)
+ _, err := client.doRequest("POST", uri, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (client *DockerClient) StartMonitorEvents(cb Callback, ec chan error, args ...interface{}) {
+ atomic.StoreInt32(&client.monitorEvents, 1)
+ go client.getEvents(cb, ec, args...)
+}
+
+func (client *DockerClient) getEvents(cb Callback, ec chan error, args ...interface{}) {
+ uri := fmt.Sprintf("%s/%s/events", client.URL.String(), APIVersion)
+ resp, err := client.HTTPClient.Get(uri)
+ if err != nil {
+ log.Printf("GET %s failed: %v", uri, err)
+ ec <- err
+ return
+ }
+ defer resp.Body.Close()
+
+ dec := json.NewDecoder(resp.Body)
+ for atomic.LoadInt32(&client.monitorEvents) > 0 {
+ var event *Event
+ if err := dec.Decode(&event); err != nil {
+ log.Printf("Event decoding failed: %v", err)
+ ec <- err
+ return
+ }
+ cb(event, ec, args...)
+ }
+}
+
+func (client *DockerClient) StopAllMonitorEvents() {
+ atomic.StoreInt32(&client.monitorEvents, 0)
+}
+
+func (client *DockerClient) Version() (*Version, error) {
+ uri := fmt.Sprintf("/%s/version", APIVersion)
+ data, err := client.doRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ version := &Version{}
+ err = json.Unmarshal(data, version)
+ if err != nil {
+ return nil, err
+ }
+ return version, nil
+}
+
+func (client *DockerClient) PullImage(name string, auth *AuthConfig) error {
+ v := url.Values{}
+ v.Set("fromImage", name)
+ uri := fmt.Sprintf("/%s/images/create?%s", APIVersion, v.Encode())
+ req, err := http.NewRequest("POST", client.URL.String()+uri, nil)
+ if auth != nil {
+ req.Header.Add("X-Registry-Auth", auth.encode())
+ }
+ resp, err := client.HTTPClient.Do(req)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ var finalObj map[string]interface{}
+ for decoder := json.NewDecoder(resp.Body); err == nil; err = decoder.Decode(&finalObj) {
+ }
+ if err != io.EOF {
+ return err
+ }
+ if err, ok := finalObj["error"]; ok {
+ return fmt.Errorf("%v", err)
+ }
+ return nil
+}
+
+func (client *DockerClient) RemoveContainer(id string, force bool) error {
+ argForce := 0
+ if force == true {
+ argForce = 1
+ }
+ args := fmt.Sprintf("force=%d", argForce)
+ uri := fmt.Sprintf("/%s/containers/%s?%s", APIVersion, id, args)
+ _, err := client.doRequest("DELETE", uri, nil, nil)
+ return err
+}
+
+func (client *DockerClient) ListImages() ([]*Image, error) {
+ uri := fmt.Sprintf("/%s/images/json", APIVersion)
+ data, err := client.doRequest("GET", uri, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ var images []*Image
+ if err := json.Unmarshal(data, &images); err != nil {
+ return nil, err
+ }
+ return images, nil
+}
+
+func (client *DockerClient) RemoveImage(name string) error {
+ uri := fmt.Sprintf("/%s/images/%s", APIVersion, name)
+ _, err := client.doRequest("DELETE", uri, nil, nil)
+ return err
+}
+
+func (client *DockerClient) PauseContainer(id string) error {
+ uri := fmt.Sprintf("/%s/containers/%s/pause", APIVersion, id)
+ _, err := client.doRequest("POST", uri, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+func (client *DockerClient) UnpauseContainer(id string) error {
+ uri := fmt.Sprintf("/%s/containers/%s/unpause", APIVersion, id)
+ _, err := client.doRequest("POST", uri, nil, nil)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (client *DockerClient) Exec(config *ExecConfig) (string, error) {
+ data, err := json.Marshal(config)
+ if err != nil {
+ return "", err
+ }
+ uri := fmt.Sprintf("/containers/%s/exec", config.Container)
+ resp, err := client.doRequest("POST", uri, data, nil)
+ if err != nil {
+ return "", err
+ }
+ var createExecResp struct {
+ Id string
+ }
+ if err = json.Unmarshal(resp, &createExecResp); err != nil {
+ return "", err
+ }
+ uri = fmt.Sprintf("/exec/%s/start", createExecResp.Id)
+ resp, err = client.doRequest("POST", uri, data, nil)
+ if err != nil {
+ return "", err
+ }
+ return createExecResp.Id, nil
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient_test.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient_test.go
new file mode 100644
index 0000000000..8d3ec2ccc4
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient_test.go
@@ -0,0 +1,153 @@
+package dockerclient
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+
+ "github.com/docker/docker/pkg/stdcopy"
+)
+
+func assertEqual(t *testing.T, a interface{}, b interface{}, message string) {
+ if a == b {
+ return
+ }
+ if len(message) == 0 {
+ message = fmt.Sprintf("%v != %v", a, b)
+ }
+ t.Fatal(message)
+}
+
+func testDockerClient(t *testing.T) *DockerClient {
+ client, err := NewDockerClient(testHTTPServer.URL, nil)
+ if err != nil {
+ t.Fatal("Cannot init the docker client")
+ }
+ return client
+}
+
+func TestInfo(t *testing.T) {
+ client := testDockerClient(t)
+ info, err := client.Info()
+ if err != nil {
+ t.Fatal("Cannot get server info")
+ }
+ assertEqual(t, info.Images, int64(1), "")
+ assertEqual(t, info.Containers, int64(2), "")
+}
+
+func TestKillContainer(t *testing.T) {
+ client := testDockerClient(t)
+ if err := client.KillContainer("23132acf2ac", "5"); err != nil {
+ t.Fatal("cannot kill container: %s", err)
+ }
+}
+
+func TestPullImage(t *testing.T) {
+ client := testDockerClient(t)
+ err := client.PullImage("busybox", nil)
+ if err != nil {
+ t.Fatal("unable to pull busybox")
+ }
+
+ err = client.PullImage("haproxy", nil)
+ if err != nil {
+ t.Fatal("unable to pull haproxy")
+ }
+
+ err = client.PullImage("wrongimg", nil)
+ if err == nil {
+ t.Fatal("should return error when it fails to pull wrongimg")
+ }
+}
+
+func TestListContainers(t *testing.T) {
+ client := testDockerClient(t)
+ containers, err := client.ListContainers(true, false, "")
+ if err != nil {
+ t.Fatal("cannot get containers: %s", err)
+ }
+ assertEqual(t, len(containers), 1, "")
+ cnt := containers[0]
+ assertEqual(t, cnt.SizeRw, int64(0), "")
+}
+
+func TestListContainersWithSize(t *testing.T) {
+ client := testDockerClient(t)
+ containers, err := client.ListContainers(true, true, "")
+ if err != nil {
+ t.Fatal("cannot get containers: %s", err)
+ }
+ assertEqual(t, len(containers), 1, "")
+ cnt := containers[0]
+ assertEqual(t, cnt.SizeRw, int64(123), "")
+}
+func TestListContainersWithFilters(t *testing.T) {
+ client := testDockerClient(t)
+ containers, err := client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}")
+ if err != nil {
+ t.Fatal("cannot get containers: %s", err)
+ }
+ assertEqual(t, len(containers), 1, "")
+
+ containers, err = client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688cf']}")
+ if err != nil {
+ t.Fatal("cannot get containers: %s", err)
+ }
+ assertEqual(t, len(containers), 0, "")
+}
+
+func TestContainerLogs(t *testing.T) {
+ client := testDockerClient(t)
+ containerId := "foobar"
+ logOptions := &LogOptions{
+ Follow: true,
+ Stdout: true,
+ Stderr: true,
+ Timestamps: true,
+ Tail: 10,
+ }
+ logsReader, err := client.ContainerLogs(containerId, logOptions)
+ if err != nil {
+ t.Fatal("cannot read logs from server")
+ }
+
+ stdoutBuffer := new(bytes.Buffer)
+ stderrBuffer := new(bytes.Buffer)
+ if _, err = stdcopy.StdCopy(stdoutBuffer, stderrBuffer, logsReader); err != nil {
+ t.Fatal("cannot read logs from logs reader")
+ }
+ stdoutLogs := strings.TrimSpace(stdoutBuffer.String())
+ stderrLogs := strings.TrimSpace(stderrBuffer.String())
+ stdoutLogLines := strings.Split(stdoutLogs, "\n")
+ stderrLogLines := strings.Split(stderrLogs, "\n")
+ if len(stdoutLogLines) != 5 {
+ t.Fatalf("wrong number of stdout logs: len=%d", len(stdoutLogLines))
+ }
+ if len(stderrLogLines) != 5 {
+ t.Fatalf("wrong number of stderr logs: len=%d", len(stdoutLogLines))
+ }
+ for i, line := range stdoutLogLines {
+ expectedSuffix := fmt.Sprintf("Z line %d", 41+2*i)
+ if !strings.HasSuffix(line, expectedSuffix) {
+ t.Fatalf("expected stdout log line \"%s\" to end with \"%s\"", line, expectedSuffix)
+ }
+ }
+ for i, line := range stderrLogLines {
+ expectedSuffix := fmt.Sprintf("Z line %d", 40+2*i)
+ if !strings.HasSuffix(line, expectedSuffix) {
+ t.Fatalf("expected stderr log line \"%s\" to end with \"%s\"", line, expectedSuffix)
+ }
+ }
+}
+
+func TestDockerClientInterface(t *testing.T) {
+ iface := reflect.TypeOf((*Client)(nil)).Elem()
+ test := testDockerClient(t)
+
+ if !reflect.TypeOf(test).Implements(iface) {
+ t.Fatalf("DockerClient does not implement the Client interface")
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/engine_mock_test.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/engine_mock_test.go
new file mode 100644
index 0000000000..4d0e6a7e92
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/engine_mock_test.go
@@ -0,0 +1,210 @@
+package dockerclient
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "log"
+ "net/http"
+ "net/http/httptest"
+ "strconv"
+ "time"
+
+ "github.com/docker/docker/pkg/jsonlog"
+ "github.com/docker/docker/pkg/stdcopy"
+ "github.com/docker/docker/pkg/timeutils"
+ "github.com/docker/docker/utils"
+ "github.com/gorilla/mux"
+)
+
+var (
+ testHTTPServer *httptest.Server
+)
+
+func init() {
+ r := mux.NewRouter()
+ baseURL := "/" + APIVersion
+ r.HandleFunc(baseURL+"/info", handlerGetInfo).Methods("GET")
+ r.HandleFunc(baseURL+"/containers/json", handlerGetContainers).Methods("GET")
+ r.HandleFunc(baseURL+"/containers/{id}/logs", handleContainerLogs).Methods("GET")
+ r.HandleFunc(baseURL+"/containers/{id}/kill", handleContainerKill).Methods("POST")
+ r.HandleFunc(baseURL+"/images/create", handleImagePull).Methods("POST")
+ testHTTPServer = httptest.NewServer(handlerAccessLog(r))
+}
+
+func handlerAccessLog(handler http.Handler) http.Handler {
+ logHandler := func(w http.ResponseWriter, r *http.Request) {
+ log.Printf("%s \"%s %s\"", r.RemoteAddr, r.Method, r.URL)
+ handler.ServeHTTP(w, r)
+ }
+ return http.HandlerFunc(logHandler)
+}
+
+func handleContainerKill(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "{%q:%q", "Id", "421373210afd132")
+}
+
+func handleImagePull(w http.ResponseWriter, r *http.Request) {
+ imageName := r.URL.Query()["fromImage"][0]
+ responses := []map[string]interface{}{{
+ "status": fmt.Sprintf("Pulling repository mydockerregistry/%s", imageName),
+ }}
+ switch imageName {
+ case "busybox":
+ responses = append(responses, map[string]interface{}{
+ "status": "Status: Image is up to date for mydockerregistry/busybox",
+ })
+ case "haproxy":
+ fmt.Fprintf(w, haproxyPullOutput)
+ return
+ default:
+ errorMsg := fmt.Sprintf("Error: image %s not found", imageName)
+ responses = append(responses, map[string]interface{}{
+ "errorDetail": map[string]interface{}{
+ "message": errorMsg,
+ },
+ "error": errorMsg,
+ })
+ }
+ for _, response := range responses {
+ json.NewEncoder(w).Encode(response)
+ }
+}
+
+func handleContainerLogs(w http.ResponseWriter, r *http.Request) {
+ var outStream, errStream io.Writer
+ outStream = utils.NewWriteFlusher(w)
+
+ // not sure how to test follow
+ if err := r.ParseForm(); err != nil {
+ http.Error(w, err.Error(), 500)
+ }
+ stdout, stderr := getBoolValue(r.Form.Get("stdout")), getBoolValue(r.Form.Get("stderr"))
+ if stderr {
+ errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
+ }
+ if stdout {
+ outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
+ }
+ var i int
+ if tail, err := strconv.Atoi(r.Form.Get("tail")); err == nil && tail > 0 {
+ i = 50 - tail
+ if i < 0 {
+ i = 0
+ }
+ }
+ for ; i < 50; i++ {
+ line := fmt.Sprintf("line %d", i)
+ if getBoolValue(r.Form.Get("timestamps")) {
+ l := &jsonlog.JSONLog{Log: line, Created: time.Now()}
+ line = fmt.Sprintf("%s %s", l.Created.Format(timeutils.RFC3339NanoFixed), line)
+ }
+ if i%2 == 0 && stderr {
+ fmt.Fprintln(errStream, line)
+ } else if i%2 == 1 && stdout {
+ fmt.Fprintln(outStream, line)
+ }
+ }
+}
+
+func getBoolValue(boolString string) bool {
+ switch boolString {
+ case "1":
+ return true
+ case "True":
+ return true
+ case "true":
+ return true
+ default:
+ return false
+ }
+}
+
+func writeHeaders(w http.ResponseWriter, code int, jobName string) {
+ h := w.Header()
+ h.Add("Content-Type", "application/json")
+ if jobName != "" {
+ h.Add("Job-Name", jobName)
+ }
+ w.WriteHeader(code)
+}
+
+func handlerGetInfo(w http.ResponseWriter, r *http.Request) {
+ writeHeaders(w, 200, "info")
+ body := `{
+ "Containers": 2,
+ "Debug": 1,
+ "Driver": "aufs",
+ "DriverStatus": [["Root Dir", "/mnt/sda1/var/lib/docker/aufs"],
+ ["Dirs", "0"]],
+ "ExecutionDriver": "native-0.2",
+ "IPv4Forwarding": 1,
+ "Images": 1,
+ "IndexServerAddress": "https://index.docker.io/v1/",
+ "InitPath": "/usr/local/bin/docker",
+ "InitSha1": "",
+ "KernelVersion": "3.16.4-tinycore64",
+ "MemoryLimit": 1,
+ "NEventsListener": 0,
+ "NFd": 10,
+ "NGoroutines": 11,
+ "OperatingSystem": "Boot2Docker 1.3.1 (TCL 5.4); master : a083df4 - Thu Jan 01 00:00:00 UTC 1970",
+ "SwapLimit": 1}`
+ w.Write([]byte(body))
+}
+
+func handlerGetContainers(w http.ResponseWriter, r *http.Request) {
+ writeHeaders(w, 200, "containers")
+ body := `[
+ {
+ "Status": "Up 39 seconds",
+ "Ports": [
+ {
+ "Type": "tcp",
+ "PublicPort": 49163,
+ "PrivatePort": 8080,
+ "IP": "0.0.0.0"
+ }
+ ],
+ "Names": [
+ "/trusting_heisenberg"
+ ],
+ "Image": "foo:latest",
+ "Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
+ "Created": 1415720105,
+ "Command": "/bin/go-run"
+ }
+ ]`
+ if v, ok := r.URL.Query()["size"]; ok {
+ if v[0] == "1" {
+ body = `[
+ {
+ "Status": "Up 39 seconds",
+ "Ports": [
+ {
+ "Type": "tcp",
+ "PublicPort": 49163,
+ "PrivatePort": 8080,
+ "IP": "0.0.0.0"
+ }
+ ],
+ "Names": [
+ "/trusting_heisenberg"
+ ],
+ "Image": "foo:latest",
+ "Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
+ "Created": 1415720105,
+ "SizeRootFs": 12345,
+ "SizeRW": 123,
+ "Command": "/bin/go-run"
+ }
+ ]`
+ }
+ }
+ if v, ok := r.URL.Query()["filters"]; ok {
+ if v[0] != "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}" {
+ body = "[]"
+ }
+ }
+ w.Write([]byte(body))
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/example_responses.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/example_responses.go
new file mode 100644
index 0000000000..9f683f1dd9
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/example_responses.go
@@ -0,0 +1,11 @@
+package dockerclient
+
+var haproxyPullOutput = `{"status":"The image you are pulling has been verified","id":"haproxy:1"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.4.25"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"63a1b9929e14"}{"status":"Already exists","progressDetail":{},"id":"af43bf7d176e"}{"status":"Already exists","progressDetail":{},"id":"851aac2d69aa"}{"status":"Already exists","progressDetail":{},"id":"345053a92c95"}{"status":"Already exists","progressDetail":{},"id":"b41231d429c9"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.10"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"The image you are pulling has been verified","id":"haproxy:1.5.9"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"3d894e6f7e63"}{"status":"Already exists","progressDetail":{},"id":"4d949c40bc77"}{"status":"Already exists","progressDetail":{},"id":"55e031889365"}{"status":"Already exists","progressDetail":{},"id":"c7aa675e1876"}{"status":"The image you are pulling has been verified","id":"haproxy:latest"}
+{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"Status: Image is up to date for haproxy"}
+`
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/examples/events.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/examples/events.go
new file mode 100644
index 0000000000..07d05dfc1c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/examples/events.go
@@ -0,0 +1,32 @@
+package main
+
+import (
+ "github.com/samalba/dockerclient"
+ "log"
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+func eventCallback(e *dockerclient.Event, ec chan error, args ...interface{}) {
+ log.Println(e)
+}
+
+func waitForInterrupt() {
+ sigChan := make(chan os.Signal, 1)
+ signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
+ for _ = range sigChan {
+ os.Exit(0)
+ }
+}
+
+func main() {
+ docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST"), nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ docker.StartMonitorEvents(eventCallback, nil)
+
+ waitForInterrupt()
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/interface.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/interface.go
new file mode 100644
index 0000000000..6a270f15b5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/interface.go
@@ -0,0 +1,29 @@
+package dockerclient
+
+import (
+ "io"
+)
+
+type Callback func(*Event, chan error, ...interface{})
+
+type Client interface {
+ Info() (*Info, error)
+ ListContainers(all, size bool, filters string) ([]Container, error)
+ InspectContainer(id string) (*ContainerInfo, error)
+ CreateContainer(config *ContainerConfig, name string) (string, error)
+ ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error)
+ Exec(config *ExecConfig) (string, error)
+ StartContainer(id string, config *HostConfig) error
+ StopContainer(id string, timeout int) error
+ RestartContainer(id string, timeout int) error
+ KillContainer(id, signal string) error
+ StartMonitorEvents(cb Callback, ec chan error, args ...interface{})
+ StopAllMonitorEvents()
+ Version() (*Version, error)
+ PullImage(name string, auth *AuthConfig) error
+ RemoveContainer(id string, force bool) error
+ ListImages() ([]*Image, error)
+ RemoveImage(name string) error
+ PauseContainer(name string) error
+ UnpauseContainer(name string) error
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock.go
new file mode 100644
index 0000000000..1d4f5c32cb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock.go
@@ -0,0 +1,109 @@
+package mockclient
+
+import (
+ "io"
+
+ "github.com/samalba/dockerclient"
+ "github.com/stretchr/testify/mock"
+)
+
+type MockClient struct {
+ mock.Mock
+}
+
+func NewMockClient() *MockClient {
+ return &MockClient{}
+}
+
+func (client *MockClient) Info() (*dockerclient.Info, error) {
+ args := client.Mock.Called()
+ return args.Get(0).(*dockerclient.Info), args.Error(1)
+}
+
+func (client *MockClient) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) {
+ args := client.Mock.Called(all, size, filters)
+ return args.Get(0).([]dockerclient.Container), args.Error(1)
+}
+
+func (client *MockClient) InspectContainer(id string) (*dockerclient.ContainerInfo, error) {
+ args := client.Mock.Called(id)
+ return args.Get(0).(*dockerclient.ContainerInfo), args.Error(1)
+}
+
+func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string) (string, error) {
+ args := client.Mock.Called(config, name)
+ return args.String(0), args.Error(1)
+}
+
+func (client *MockClient) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) {
+ args := client.Mock.Called(id, options)
+ return args.Get(0).(io.ReadCloser), args.Error(1)
+}
+
+func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error {
+ args := client.Mock.Called(id, config)
+ return args.Error(0)
+}
+
+func (client *MockClient) StopContainer(id string, timeout int) error {
+ args := client.Mock.Called(id, timeout)
+ return args.Error(0)
+}
+
+func (client *MockClient) RestartContainer(id string, timeout int) error {
+ args := client.Mock.Called(id, timeout)
+ return args.Error(0)
+}
+
+func (client *MockClient) KillContainer(id, signal string) error {
+ args := client.Mock.Called(id, signal)
+ return args.Error(0)
+}
+
+func (client *MockClient) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) {
+ client.Mock.Called(cb, ec, args)
+}
+
+func (client *MockClient) StopAllMonitorEvents() {
+ client.Mock.Called()
+}
+
+func (client *MockClient) Version() (*dockerclient.Version, error) {
+ args := client.Mock.Called()
+ return args.Get(0).(*dockerclient.Version), args.Error(1)
+}
+
+func (client *MockClient) PullImage(name string, auth *dockerclient.AuthConfig) error {
+ args := client.Mock.Called(name, auth)
+ return args.Error(0)
+}
+
+func (client *MockClient) RemoveContainer(id string, force bool) error {
+ args := client.Mock.Called(id, force)
+ return args.Error(0)
+}
+
+func (client *MockClient) ListImages() ([]*dockerclient.Image, error) {
+ args := client.Mock.Called()
+ return args.Get(0).([]*dockerclient.Image), args.Error(1)
+}
+
+func (client *MockClient) RemoveImage(name string) error {
+ args := client.Mock.Called(name)
+ return args.Error(0)
+}
+
+func (client *MockClient) PauseContainer(name string) error {
+ args := client.Mock.Called(name)
+ return args.Error(0)
+}
+
+func (client *MockClient) UnpauseContainer(name string) error {
+ args := client.Mock.Called(name)
+ return args.Error(0)
+}
+
+func (client *MockClient) Exec(config *dockerclient.ExecConfig) (string, error) {
+ args := client.Mock.Called(config)
+ return args.String(0), args.Error(1)
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock_test.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock_test.go
new file mode 100644
index 0000000000..8d91bcf6c5
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock_test.go
@@ -0,0 +1,32 @@
+package mockclient
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/samalba/dockerclient"
+)
+
+func TestMock(t *testing.T) {
+ mock := NewMockClient()
+ mock.On("Version").Return(&dockerclient.Version{Version: "foo"}, nil).Once()
+
+ v, err := mock.Version()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if v.Version != "foo" {
+ t.Fatal(v)
+ }
+
+ mock.Mock.AssertExpectations(t)
+}
+
+func TestMockInterface(t *testing.T) {
+ iface := reflect.TypeOf((*dockerclient.Client)(nil)).Elem()
+ mock := NewMockClient()
+
+ if !reflect.TypeOf(mock).Implements(iface) {
+ t.Fatalf("Mock does not implement the Client interface")
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/types.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/types.go
new file mode 100644
index 0000000000..6504e8fa3b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/types.go
@@ -0,0 +1,168 @@
+package dockerclient
+
+import "time"
+
+type ContainerConfig struct {
+ Hostname string
+ Domainname string
+ User string
+ Memory int64
+ MemorySwap int64
+ CpuShares int64
+ Cpuset string
+ AttachStdin bool
+ AttachStdout bool
+ AttachStderr bool
+ PortSpecs []string
+ ExposedPorts map[string]struct{}
+ Tty bool
+ OpenStdin bool
+ StdinOnce bool
+ Env []string
+ Cmd []string
+ Image string
+ Volumes map[string]struct{}
+ WorkingDir string
+ Entrypoint []string
+ NetworkDisabled bool
+ OnBuild []string
+
+ // This is used only by the create command
+ HostConfig HostConfig
+}
+
+type HostConfig struct {
+ Binds []string
+ ContainerIDFile string
+ LxcConf []map[string]string
+ Privileged bool
+ PortBindings map[string][]PortBinding
+ Links []string
+ PublishAllPorts bool
+ Dns []string
+ DnsSearch []string
+ VolumesFrom []string
+ NetworkMode string
+ RestartPolicy RestartPolicy
+}
+
+type ExecConfig struct {
+ AttachStdin bool
+ AttachStdout bool
+ AttachStderr bool
+ Tty bool
+ Cmd []string
+ Container string
+ Detach bool
+}
+
+type LogOptions struct {
+ Follow bool
+ Stdout bool
+ Stderr bool
+ Timestamps bool
+ Tail int64
+}
+
+type RestartPolicy struct {
+ Name string
+ MaximumRetryCount int64
+}
+
+type PortBinding struct {
+ HostIp string
+ HostPort string
+}
+
+type ContainerInfo struct {
+ Id string
+ Created string
+ Path string
+ Name string
+ Args []string
+ ExecIDs []string
+ Config *ContainerConfig
+ State struct {
+ Running bool
+ Paused bool
+ Restarting bool
+ Pid int
+ ExitCode int
+ StartedAt time.Time
+ FinishedAt time.Time
+ Ghost bool
+ }
+ Image string
+ NetworkSettings struct {
+ IpAddress string
+ IpPrefixLen int
+ Gateway string
+ Bridge string
+ Ports map[string][]PortBinding
+ }
+ SysInitPath string
+ ResolvConfPath string
+ Volumes map[string]string
+ HostConfig *HostConfig
+}
+
+type Port struct {
+ IP string
+ PrivatePort int
+ PublicPort int
+ Type string
+}
+
+type Container struct {
+ Id string
+ Names []string
+ Image string
+ Command string
+ Created int64
+ Status string
+ Ports []Port
+ SizeRw int64
+ SizeRootFs int64
+}
+
+type Event struct {
+ Id string
+ Status string
+ From string
+ Time int64
+}
+
+type Version struct {
+ Version string
+ GitCommit string
+ GoVersion string
+}
+
+type RespContainersCreate struct {
+ Id string
+ Warnings []string
+}
+
+type Image struct {
+ Created int64
+ Id string
+ ParentId string
+ RepoTags []string
+ Size int64
+ VirtualSize int64
+}
+
+type Info struct {
+ ID string
+ Containers int64
+ Driver string
+ DriverStatus [][]string
+ ExecutionDriver string
+ Images int64
+ KernelVersion string
+ OperatingSystem string
+ NCPU int64
+ MemTotal int64
+ Name string
+ Labels []string
+}
diff --git a/Godeps/_workspace/src/github.com/samalba/dockerclient/utils.go b/Godeps/_workspace/src/github.com/samalba/dockerclient/utils.go
new file mode 100644
index 0000000000..806f1b3e6a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samalba/dockerclient/utils.go
@@ -0,0 +1,33 @@
+package dockerclient
+
+import (
+ "crypto/tls"
+ "net"
+ "net/http"
+ "net/url"
+ "time"
+)
+
+func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
+ httpTransport := &http.Transport{
+ TLSClientConfig: tlsConfig,
+ }
+
+ switch u.Scheme {
+ default:
+ httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
+ return net.DialTimeout(proto, addr, timeout)
+ }
+ case "unix":
+ socketPath := u.Path
+ unixDial := func(proto, addr string) (net.Conn, error) {
+ return net.DialTimeout("unix", socketPath, timeout)
+ }
+ httpTransport.Dial = unixDial
+ // Override the main URL object so the HTTP lib won't complain
+ u.Scheme = "http"
+ u.Host = "unix.sock"
+ u.Path = ""
+ }
+ return &http.Client{Transport: httpTransport}
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/cluster_test.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/cluster_test.go
new file mode 100644
index 0000000000..bf48d92c87
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/cluster_test.go
@@ -0,0 +1,130 @@
+package zk
+
+import (
+ "testing"
+ "time"
+)
+
+type logWriter struct {
+ t *testing.T
+ p string
+}
+
+func (lw logWriter) Write(b []byte) (int, error) {
+ lw.t.Logf("%s%s", lw.p, string(b))
+ return len(b), nil
+}
+
+func TestBasicCluster(t *testing.T) {
+ ts, err := StartTestCluster(3, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk1, err := ts.Connect(0)
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk1.Close()
+ zk2, err := ts.Connect(1)
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk2.Close()
+
+ time.Sleep(time.Second * 5)
+
+ if _, err := zk1.Create("/gozk-test", []byte("foo-cluster"), 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create failed on node 1: %+v", err)
+ }
+ if by, _, err := zk2.Get("/gozk-test"); err != nil {
+ t.Fatalf("Get failed on node 2: %+v", err)
+ } else if string(by) != "foo-cluster" {
+ t.Fatal("Wrong data for node 2")
+ }
+}
+
+func TestClientClusterFailover(t *testing.T) {
+ ts, err := StartTestCluster(3, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ if _, err := zk.Create("/gozk-test", []byte("foo-cluster"), 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create failed on node 1: %+v", err)
+ }
+
+ ts.Servers[0].Srv.Stop()
+
+ if by, _, err := zk.Get("/gozk-test"); err != nil {
+ t.Fatalf("Get failed on node 2: %+v", err)
+ } else if string(by) != "foo-cluster" {
+ t.Fatal("Wrong data for node 2")
+ }
+}
+
+func TestWaitForClose(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.Connect(0)
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ timeout := time.After(30 * time.Second)
+CONNECTED:
+ for {
+ select {
+ case ev := <-zk.eventChan:
+ if ev.State == StateConnected {
+ break CONNECTED
+ }
+ case <-timeout:
+ zk.Close()
+ t.Fatal("Timeout")
+ }
+ }
+ zk.Close()
+ for {
+ select {
+ case _, ok := <-zk.eventChan:
+ if !ok {
+ return
+ }
+ case <-timeout:
+ t.Fatal("Timeout")
+ }
+ }
+}
+
+func TestBadSession(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ zk.conn.Close()
+ time.Sleep(time.Millisecond * 100)
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/conn.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/conn.go
new file mode 100644
index 0000000000..0a3f9b774c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/conn.go
@@ -0,0 +1,812 @@
+package zk
+
+/*
+TODO:
+* make sure a ping response comes back in a reasonable time
+
+Possible watcher events:
+* Event{Type: EventNotWatching, State: StateDisconnected, Path: path, Err: err}
+*/
+
+import (
+ "crypto/rand"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+var ErrNoServer = errors.New("zk: could not connect to a server")
+
+const (
+ bufferSize = 1536 * 1024
+ eventChanSize = 6
+ sendChanSize = 16
+ protectedPrefix = "_c_"
+)
+
+type watchType int
+
+const (
+ watchTypeData = iota
+ watchTypeExist = iota
+ watchTypeChild = iota
+)
+
+type watchPathType struct {
+ path string
+ wType watchType
+}
+
+type Dialer func(network, address string, timeout time.Duration) (net.Conn, error)
+
+type Conn struct {
+ lastZxid int64
+ sessionID int64
+ state State // must be 32-bit aligned
+ xid int32
+ timeout int32 // session timeout in milliseconds
+ passwd []byte
+
+ dialer Dialer
+ servers []string
+ serverIndex int
+ conn net.Conn
+ eventChan chan Event
+ shouldQuit chan bool
+ pingInterval time.Duration
+ recvTimeout time.Duration
+ connectTimeout time.Duration
+
+ sendChan chan *request
+ requests map[int32]*request // Xid -> pending request
+ requestsLock sync.Mutex
+ watchers map[watchPathType][]chan Event
+ watchersLock sync.Mutex
+
+ // Debug (used by unit tests)
+ reconnectDelay time.Duration
+}
+
+type request struct {
+ xid int32
+ opcode int32
+ pkt interface{}
+ recvStruct interface{}
+ recvChan chan response
+
+ // Because sending and receiving happen in separate go routines, there's
+ // a possible race condition when creating watches from outside the read
+ // loop. We must ensure that a watcher gets added to the list synchronously
+ // with the response from the server on any request that creates a watch.
+ // In order to not hard code the watch logic for each opcode in the recv
+ // loop the caller can use recvFunc to insert some synchronously code
+ // after a response.
+ recvFunc func(*request, *responseHeader, error)
+}
+
+type response struct {
+ zxid int64
+ err error
+}
+
+type Event struct {
+ Type EventType
+ State State
+ Path string // For non-session events, the path of the watched node.
+ Err error
+}
+
+// Connect establishes a new connection to a pool of zookeeper servers
+// using the default net.Dialer. See ConnectWithDialer for further
+// information about session timeout.
+func Connect(servers []string, sessionTimeout time.Duration) (*Conn, <-chan Event, error) {
+ return ConnectWithDialer(servers, sessionTimeout, nil)
+}
+
+// ConnectWithDialer establishes a new connection to a pool of zookeeper
+// servers. The provided session timeout sets the amount of time for which
+// a session is considered valid after losing connection to a server. Within
+// the session timeout it's possible to reestablish a connection to a different
+// server and keep the same session. This is means any ephemeral nodes and
+// watches are maintained.
+func ConnectWithDialer(servers []string, sessionTimeout time.Duration, dialer Dialer) (*Conn, <-chan Event, error) {
+ // Randomize the order of the servers to avoid creating hotspots
+ stringShuffle(servers)
+
+ recvTimeout := sessionTimeout * 2 / 3
+
+ for i, addr := range servers {
+ if !strings.Contains(addr, ":") {
+ servers[i] = addr + ":" + strconv.Itoa(DefaultPort)
+ }
+ }
+ ec := make(chan Event, eventChanSize)
+ if dialer == nil {
+ dialer = net.DialTimeout
+ }
+ conn := Conn{
+ dialer: dialer,
+ servers: servers,
+ serverIndex: 0,
+ conn: nil,
+ state: StateDisconnected,
+ eventChan: ec,
+ shouldQuit: make(chan bool),
+ recvTimeout: recvTimeout,
+ pingInterval: recvTimeout / 2,
+ connectTimeout: 1 * time.Second,
+ sendChan: make(chan *request, sendChanSize),
+ requests: make(map[int32]*request),
+ watchers: make(map[watchPathType][]chan Event),
+ passwd: emptyPassword,
+ timeout: int32(sessionTimeout.Nanoseconds() / 1e6),
+
+ // Debug
+ reconnectDelay: 0,
+ }
+ go func() {
+ conn.loop()
+ conn.flushRequests(ErrClosing)
+ conn.invalidateWatches(ErrClosing)
+ close(conn.eventChan)
+ }()
+ return &conn, ec, nil
+}
+
+func (c *Conn) Close() {
+ close(c.shouldQuit)
+
+ select {
+ case <-c.queueRequest(opClose, &closeRequest{}, &closeResponse{}, nil):
+ case <-time.After(time.Second):
+ }
+}
+
+func (c *Conn) State() State {
+ return State(atomic.LoadInt32((*int32)(&c.state)))
+}
+
+func (c *Conn) setState(state State) {
+ atomic.StoreInt32((*int32)(&c.state), int32(state))
+ select {
+ case c.eventChan <- Event{Type: EventSession, State: state}:
+ default:
+ // panic("zk: event channel full - it must be monitored and never allowed to be full")
+ }
+}
+
+func (c *Conn) connect() {
+ c.serverIndex = (c.serverIndex + 1) % len(c.servers)
+ startIndex := c.serverIndex
+ c.setState(StateConnecting)
+ for {
+ zkConn, err := c.dialer("tcp", c.servers[c.serverIndex], c.connectTimeout)
+ if err == nil {
+ c.conn = zkConn
+ c.setState(StateConnected)
+ return
+ }
+
+ log.Printf("Failed to connect to %s: %+v", c.servers[c.serverIndex], err)
+
+ c.serverIndex = (c.serverIndex + 1) % len(c.servers)
+ if c.serverIndex == startIndex {
+ c.flushUnsentRequests(ErrNoServer)
+ time.Sleep(time.Second)
+ }
+ }
+}
+
+func (c *Conn) loop() {
+ for {
+ c.connect()
+ err := c.authenticate()
+ switch {
+ case err == ErrSessionExpired:
+ c.invalidateWatches(err)
+ case err != nil && c.conn != nil:
+ c.conn.Close()
+ case err == nil:
+ closeChan := make(chan bool) // channel to tell send loop stop
+ var wg sync.WaitGroup
+
+ wg.Add(1)
+ go func() {
+ c.sendLoop(c.conn, closeChan)
+ c.conn.Close() // causes recv loop to EOF/exit
+ wg.Done()
+ }()
+
+ wg.Add(1)
+ go func() {
+ err = c.recvLoop(c.conn)
+ if err == nil {
+ panic("zk: recvLoop should never return nil error")
+ }
+ close(closeChan) // tell send loop to exit
+ wg.Done()
+ }()
+
+ wg.Wait()
+ }
+
+ c.setState(StateDisconnected)
+
+ // Yeesh
+ if err != io.EOF && err != ErrSessionExpired && !strings.Contains(err.Error(), "use of closed network connection") {
+ log.Println(err)
+ }
+
+ select {
+ case <-c.shouldQuit:
+ c.flushRequests(ErrClosing)
+ return
+ default:
+ }
+
+ if err != ErrSessionExpired {
+ err = ErrConnectionClosed
+ }
+ c.flushRequests(err)
+
+ if c.reconnectDelay > 0 {
+ select {
+ case <-c.shouldQuit:
+ return
+ case <-time.After(c.reconnectDelay):
+ }
+ }
+ }
+}
+
+func (c *Conn) flushUnsentRequests(err error) {
+ for {
+ select {
+ default:
+ return
+ case req := <-c.sendChan:
+ req.recvChan <- response{-1, err}
+ }
+ }
+}
+
+// Send error to all pending requests and clear request map
+func (c *Conn) flushRequests(err error) {
+ c.requestsLock.Lock()
+ for _, req := range c.requests {
+ req.recvChan <- response{-1, err}
+ }
+ c.requests = make(map[int32]*request)
+ c.requestsLock.Unlock()
+}
+
+// Send error to all watchers and clear watchers map
+func (c *Conn) invalidateWatches(err error) {
+ c.watchersLock.Lock()
+ defer c.watchersLock.Unlock()
+
+ if len(c.watchers) >= 0 {
+ for pathType, watchers := range c.watchers {
+ ev := Event{Type: EventNotWatching, State: StateDisconnected, Path: pathType.path, Err: err}
+ for _, ch := range watchers {
+ ch <- ev
+ close(ch)
+ }
+ }
+ c.watchers = make(map[watchPathType][]chan Event)
+ }
+}
+
+func (c *Conn) sendSetWatches() {
+ c.watchersLock.Lock()
+ defer c.watchersLock.Unlock()
+
+ if len(c.watchers) == 0 {
+ return
+ }
+
+ req := &setWatchesRequest{
+ RelativeZxid: c.lastZxid,
+ DataWatches: make([]string, 0),
+ ExistWatches: make([]string, 0),
+ ChildWatches: make([]string, 0),
+ }
+ n := 0
+ for pathType, watchers := range c.watchers {
+ if len(watchers) == 0 {
+ continue
+ }
+ switch pathType.wType {
+ case watchTypeData:
+ req.DataWatches = append(req.DataWatches, pathType.path)
+ case watchTypeExist:
+ req.ExistWatches = append(req.ExistWatches, pathType.path)
+ case watchTypeChild:
+ req.ChildWatches = append(req.ChildWatches, pathType.path)
+ }
+ n++
+ }
+ if n == 0 {
+ return
+ }
+
+ go func() {
+ res := &setWatchesResponse{}
+ _, err := c.request(opSetWatches, req, res, nil)
+ if err != nil {
+ log.Printf("Failed to set previous watches: %s", err.Error())
+ }
+ }()
+}
+
+func (c *Conn) authenticate() error {
+ buf := make([]byte, 256)
+
+ // connect request
+
+ n, err := encodePacket(buf[4:], &connectRequest{
+ ProtocolVersion: protocolVersion,
+ LastZxidSeen: c.lastZxid,
+ TimeOut: c.timeout,
+ SessionID: c.sessionID,
+ Passwd: c.passwd,
+ })
+ if err != nil {
+ return err
+ }
+
+ binary.BigEndian.PutUint32(buf[:4], uint32(n))
+
+ c.conn.SetWriteDeadline(time.Now().Add(c.recvTimeout * 10))
+ _, err = c.conn.Write(buf[:n+4])
+ c.conn.SetWriteDeadline(time.Time{})
+ if err != nil {
+ return err
+ }
+
+ c.sendSetWatches()
+
+ // connect response
+
+ // package length
+ c.conn.SetReadDeadline(time.Now().Add(c.recvTimeout * 10))
+ _, err = io.ReadFull(c.conn, buf[:4])
+ c.conn.SetReadDeadline(time.Time{})
+ if err != nil {
+ return err
+ }
+
+ blen := int(binary.BigEndian.Uint32(buf[:4]))
+ if cap(buf) < blen {
+ buf = make([]byte, blen)
+ }
+
+ _, err = io.ReadFull(c.conn, buf[:blen])
+ if err != nil {
+ return err
+ }
+
+ r := connectResponse{}
+ _, err = decodePacket(buf[:blen], &r)
+ if err != nil {
+ return err
+ }
+ if r.SessionID == 0 {
+ c.sessionID = 0
+ c.passwd = emptyPassword
+ c.lastZxid = 0
+ c.setState(StateExpired)
+ return ErrSessionExpired
+ }
+
+ if c.sessionID != r.SessionID {
+ atomic.StoreInt32(&c.xid, 0)
+ }
+ c.timeout = r.TimeOut
+ c.sessionID = r.SessionID
+ c.passwd = r.Passwd
+ c.setState(StateHasSession)
+
+ return nil
+}
+
+func (c *Conn) sendLoop(conn net.Conn, closeChan <-chan bool) error {
+ pingTicker := time.NewTicker(c.pingInterval)
+ defer pingTicker.Stop()
+
+ buf := make([]byte, bufferSize)
+ for {
+ select {
+ case req := <-c.sendChan:
+ header := &requestHeader{req.xid, req.opcode}
+ n, err := encodePacket(buf[4:], header)
+ if err != nil {
+ req.recvChan <- response{-1, err}
+ continue
+ }
+
+ n2, err := encodePacket(buf[4+n:], req.pkt)
+ if err != nil {
+ req.recvChan <- response{-1, err}
+ continue
+ }
+
+ n += n2
+
+ binary.BigEndian.PutUint32(buf[:4], uint32(n))
+
+ c.requestsLock.Lock()
+ select {
+ case <-closeChan:
+ req.recvChan <- response{-1, ErrConnectionClosed}
+ c.requestsLock.Unlock()
+ return ErrConnectionClosed
+ default:
+ }
+ c.requests[req.xid] = req
+ c.requestsLock.Unlock()
+
+ conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
+ _, err = conn.Write(buf[:n+4])
+ conn.SetWriteDeadline(time.Time{})
+ if err != nil {
+ req.recvChan <- response{-1, err}
+ conn.Close()
+ return err
+ }
+ case <-pingTicker.C:
+ n, err := encodePacket(buf[4:], &requestHeader{Xid: -2, Opcode: opPing})
+ if err != nil {
+ panic("zk: opPing should never fail to serialize")
+ }
+
+ binary.BigEndian.PutUint32(buf[:4], uint32(n))
+
+ conn.SetWriteDeadline(time.Now().Add(c.recvTimeout))
+ _, err = conn.Write(buf[:n+4])
+ conn.SetWriteDeadline(time.Time{})
+ if err != nil {
+ conn.Close()
+ return err
+ }
+ case <-closeChan:
+ return nil
+ }
+ }
+}
+
+func (c *Conn) recvLoop(conn net.Conn) error {
+ buf := make([]byte, bufferSize)
+ for {
+ // package length
+ conn.SetReadDeadline(time.Now().Add(c.recvTimeout))
+ _, err := io.ReadFull(conn, buf[:4])
+ if err != nil {
+ return err
+ }
+
+ blen := int(binary.BigEndian.Uint32(buf[:4]))
+ if cap(buf) < blen {
+ buf = make([]byte, blen)
+ }
+
+ _, err = io.ReadFull(conn, buf[:blen])
+ conn.SetReadDeadline(time.Time{})
+ if err != nil {
+ return err
+ }
+
+ res := responseHeader{}
+ _, err = decodePacket(buf[:16], &res)
+ if err != nil {
+ return err
+ }
+
+ if res.Xid == -1 {
+ res := &watcherEvent{}
+ _, err := decodePacket(buf[16:16+blen], res)
+ if err != nil {
+ return err
+ }
+ ev := Event{
+ Type: res.Type,
+ State: res.State,
+ Path: res.Path,
+ Err: nil,
+ }
+ select {
+ case c.eventChan <- ev:
+ default:
+ }
+ wTypes := make([]watchType, 0, 2)
+ switch res.Type {
+ case EventNodeCreated:
+ wTypes = append(wTypes, watchTypeExist)
+ case EventNodeDeleted, EventNodeDataChanged:
+ wTypes = append(wTypes, watchTypeExist, watchTypeData, watchTypeChild)
+ case EventNodeChildrenChanged:
+ wTypes = append(wTypes, watchTypeChild)
+ }
+ c.watchersLock.Lock()
+ for _, t := range wTypes {
+ wpt := watchPathType{res.Path, t}
+ if watchers := c.watchers[wpt]; watchers != nil && len(watchers) > 0 {
+ for _, ch := range watchers {
+ ch <- ev
+ close(ch)
+ }
+ delete(c.watchers, wpt)
+ }
+ }
+ c.watchersLock.Unlock()
+ } else if res.Xid == -2 {
+ // Ping response. Ignore.
+ } else if res.Xid < 0 {
+ log.Printf("Xid < 0 (%d) but not ping or watcher event", res.Xid)
+ } else {
+ if res.Zxid > 0 {
+ c.lastZxid = res.Zxid
+ }
+
+ c.requestsLock.Lock()
+ req, ok := c.requests[res.Xid]
+ if ok {
+ delete(c.requests, res.Xid)
+ }
+ c.requestsLock.Unlock()
+
+ if !ok {
+ log.Printf("Response for unknown request with xid %d", res.Xid)
+ } else {
+ if res.Err != 0 {
+ err = res.Err.toError()
+ } else {
+ _, err = decodePacket(buf[16:16+blen], req.recvStruct)
+ }
+ if req.recvFunc != nil {
+ req.recvFunc(req, &res, err)
+ }
+ req.recvChan <- response{res.Zxid, err}
+ if req.opcode == opClose {
+ return io.EOF
+ }
+ }
+ }
+ }
+}
+
+func (c *Conn) nextXid() int32 {
+ return atomic.AddInt32(&c.xid, 1)
+}
+
+func (c *Conn) addWatcher(path string, watchType watchType) <-chan Event {
+ c.watchersLock.Lock()
+ defer c.watchersLock.Unlock()
+
+ ch := make(chan Event, 1)
+ wpt := watchPathType{path, watchType}
+ c.watchers[wpt] = append(c.watchers[wpt], ch)
+ return ch
+}
+
+func (c *Conn) queueRequest(opcode int32, req interface{}, res interface{}, recvFunc func(*request, *responseHeader, error)) <-chan response {
+ rq := &request{
+ xid: c.nextXid(),
+ opcode: opcode,
+ pkt: req,
+ recvStruct: res,
+ recvChan: make(chan response, 1),
+ recvFunc: recvFunc,
+ }
+ c.sendChan <- rq
+ return rq.recvChan
+}
+
+func (c *Conn) request(opcode int32, req interface{}, res interface{}, recvFunc func(*request, *responseHeader, error)) (int64, error) {
+ r := <-c.queueRequest(opcode, req, res, recvFunc)
+ return r.zxid, r.err
+}
+
+func (c *Conn) AddAuth(scheme string, auth []byte) error {
+ _, err := c.request(opSetAuth, &setAuthRequest{Type: 0, Scheme: scheme, Auth: auth}, &setAuthResponse{}, nil)
+ return err
+}
+
+func (c *Conn) Children(path string) ([]string, *Stat, error) {
+ res := &getChildren2Response{}
+ _, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: false}, res, nil)
+ return res.Children, &res.Stat, err
+}
+
+func (c *Conn) ChildrenW(path string) ([]string, *Stat, <-chan Event, error) {
+ var ech <-chan Event
+ res := &getChildren2Response{}
+ _, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
+ if err == nil {
+ ech = c.addWatcher(path, watchTypeChild)
+ }
+ })
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ return res.Children, &res.Stat, ech, err
+}
+
+func (c *Conn) Get(path string) ([]byte, *Stat, error) {
+ res := &getDataResponse{}
+ _, err := c.request(opGetData, &getDataRequest{Path: path, Watch: false}, res, nil)
+ return res.Data, &res.Stat, err
+}
+
+// GetW returns the contents of a znode and sets a watch
+func (c *Conn) GetW(path string) ([]byte, *Stat, <-chan Event, error) {
+ var ech <-chan Event
+ res := &getDataResponse{}
+ _, err := c.request(opGetData, &getDataRequest{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
+ if err == nil {
+ ech = c.addWatcher(path, watchTypeData)
+ }
+ })
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ return res.Data, &res.Stat, ech, err
+}
+
+func (c *Conn) Set(path string, data []byte, version int32) (*Stat, error) {
+ res := &setDataResponse{}
+ _, err := c.request(opSetData, &SetDataRequest{path, data, version}, res, nil)
+ return &res.Stat, err
+}
+
+func (c *Conn) Create(path string, data []byte, flags int32, acl []ACL) (string, error) {
+ res := &createResponse{}
+ _, err := c.request(opCreate, &CreateRequest{path, data, acl, flags}, res, nil)
+ return res.Path, err
+}
+
+// CreateProtectedEphemeralSequential fixes a race condition if the server crashes
+// after it creates the node. On reconnect the session may still be valid so the
+// ephemeral node still exists. Therefore, on reconnect we need to check if a node
+// with a GUID generated on create exists.
+func (c *Conn) CreateProtectedEphemeralSequential(path string, data []byte, acl []ACL) (string, error) {
+ var guid [16]byte
+ _, err := io.ReadFull(rand.Reader, guid[:16])
+ if err != nil {
+ return "", err
+ }
+ guidStr := fmt.Sprintf("%x", guid)
+
+ parts := strings.Split(path, "/")
+ parts[len(parts)-1] = fmt.Sprintf("%s%s-%s", protectedPrefix, guidStr, parts[len(parts)-1])
+ rootPath := strings.Join(parts[:len(parts)-1], "/")
+ protectedPath := strings.Join(parts, "/")
+
+ var newPath string
+ for i := 0; i < 3; i++ {
+ newPath, err = c.Create(protectedPath, data, FlagEphemeral|FlagSequence, acl)
+ switch err {
+ case ErrSessionExpired:
+ // No need to search for the node since it can't exist. Just try again.
+ case ErrConnectionClosed:
+ children, _, err := c.Children(rootPath)
+ if err != nil {
+ return "", err
+ }
+ for _, p := range children {
+ parts := strings.Split(p, "/")
+ if pth := parts[len(parts)-1]; strings.HasPrefix(pth, protectedPrefix) {
+ if g := pth[len(protectedPrefix) : len(protectedPrefix)+32]; g == guidStr {
+ return rootPath + "/" + p, nil
+ }
+ }
+ }
+ case nil:
+ return newPath, nil
+ default:
+ return "", err
+ }
+ }
+ return "", err
+}
+
+func (c *Conn) Delete(path string, version int32) error {
+ _, err := c.request(opDelete, &DeleteRequest{path, version}, &deleteResponse{}, nil)
+ return err
+}
+
+func (c *Conn) Exists(path string) (bool, *Stat, error) {
+ res := &existsResponse{}
+ _, err := c.request(opExists, &existsRequest{Path: path, Watch: false}, res, nil)
+ exists := true
+ if err == ErrNoNode {
+ exists = false
+ err = nil
+ }
+ return exists, &res.Stat, err
+}
+
+func (c *Conn) ExistsW(path string) (bool, *Stat, <-chan Event, error) {
+ var ech <-chan Event
+ res := &existsResponse{}
+ _, err := c.request(opExists, &existsRequest{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
+ if err == nil {
+ ech = c.addWatcher(path, watchTypeData)
+ } else if err == ErrNoNode {
+ ech = c.addWatcher(path, watchTypeExist)
+ }
+ })
+ exists := true
+ if err == ErrNoNode {
+ exists = false
+ err = nil
+ }
+ if err != nil {
+ return false, nil, nil, err
+ }
+ return exists, &res.Stat, ech, err
+}
+
+func (c *Conn) GetACL(path string) ([]ACL, *Stat, error) {
+ res := &getAclResponse{}
+ _, err := c.request(opGetAcl, &getAclRequest{Path: path}, res, nil)
+ return res.Acl, &res.Stat, err
+}
+
+func (c *Conn) SetACL(path string, acl []ACL, version int32) (*Stat, error) {
+ res := &setAclResponse{}
+ _, err := c.request(opSetAcl, &setAclRequest{Path: path, Acl: acl, Version: version}, res, nil)
+ return &res.Stat, err
+}
+
+func (c *Conn) Sync(path string) (string, error) {
+ res := &syncResponse{}
+ _, err := c.request(opSync, &syncRequest{Path: path}, res, nil)
+ return res.Path, err
+}
+
+type MultiResponse struct {
+ Stat *Stat
+ String string
+}
+
+// Multi executes multiple ZooKeeper operations or none of them. The provided
+// ops must be one of *CreateRequest, *DeleteRequest, *SetDataRequest, or
+// *CheckVersionRequest.
+func (c *Conn) Multi(ops ...interface{}) ([]MultiResponse, error) {
+ req := &multiRequest{
+ Ops: make([]multiRequestOp, 0, len(ops)),
+ DoneHeader: multiHeader{Type: -1, Done: true, Err: -1},
+ }
+ for _, op := range ops {
+ var opCode int32
+ switch op.(type) {
+ case *CreateRequest:
+ opCode = opCreate
+ case *SetDataRequest:
+ opCode = opSetData
+ case *DeleteRequest:
+ opCode = opDelete
+ case *CheckVersionRequest:
+ opCode = opCheck
+ default:
+ return nil, fmt.Errorf("uknown operation type %T", op)
+ }
+ req.Ops = append(req.Ops, multiRequestOp{multiHeader{opCode, false, -1}, op})
+ }
+ res := &multiResponse{}
+ _, err := c.request(opMulti, req, res, nil)
+ mr := make([]MultiResponse, len(res.Ops))
+ for i, op := range res.Ops {
+ mr[i] = MultiResponse{Stat: op.Stat, String: op.String}
+ }
+ return mr, err
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/constants.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/constants.go
new file mode 100644
index 0000000000..ee8772437b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/constants.go
@@ -0,0 +1,217 @@
+package zk
+
+import (
+ "errors"
+)
+
+const (
+ protocolVersion = 0
+
+ DefaultPort = 2181
+)
+
+const (
+ opNotify = 0
+ opCreate = 1
+ opDelete = 2
+ opExists = 3
+ opGetData = 4
+ opSetData = 5
+ opGetAcl = 6
+ opSetAcl = 7
+ opGetChildren = 8
+ opSync = 9
+ opPing = 11
+ opGetChildren2 = 12
+ opCheck = 13
+ opMulti = 14
+ opClose = -11
+ opSetAuth = 100
+ opSetWatches = 101
+ // Not in protocol, used internally
+ opWatcherEvent = -2
+)
+
+const (
+ EventNodeCreated = EventType(1)
+ EventNodeDeleted = EventType(2)
+ EventNodeDataChanged = EventType(3)
+ EventNodeChildrenChanged = EventType(4)
+
+ EventSession = EventType(-1)
+ EventNotWatching = EventType(-2)
+)
+
+var (
+ eventNames = map[EventType]string{
+ EventNodeCreated: "EventNodeCreated",
+ EventNodeDeleted: "EventNodeDeleted",
+ EventNodeDataChanged: "EventNodeDataChanged",
+ EventNodeChildrenChanged: "EventNodeChildrenChanged",
+ EventSession: "EventSession",
+ EventNotWatching: "EventNotWatching",
+ }
+)
+
+const (
+ StateUnknown = State(-1)
+ StateDisconnected = State(0)
+ StateConnecting = State(1)
+ StateSyncConnected = State(3)
+ StateAuthFailed = State(4)
+ StateConnectedReadOnly = State(5)
+ StateSaslAuthenticated = State(6)
+ StateExpired = State(-112)
+ // StateAuthFailed = State(-113)
+
+ StateConnected = State(100)
+ StateHasSession = State(101)
+)
+
+const (
+ FlagEphemeral = 1
+ FlagSequence = 2
+)
+
+var (
+ stateNames = map[State]string{
+ StateUnknown: "StateUnknown",
+ StateDisconnected: "StateDisconnected",
+ StateSyncConnected: "StateSyncConnected",
+ StateConnectedReadOnly: "StateConnectedReadOnly",
+ StateSaslAuthenticated: "StateSaslAuthenticated",
+ StateExpired: "StateExpired",
+ StateAuthFailed: "StateAuthFailed",
+ StateConnecting: "StateConnecting",
+ StateConnected: "StateConnected",
+ StateHasSession: "StateHasSession",
+ }
+)
+
+type State int32
+
+func (s State) String() string {
+ if name := stateNames[s]; name != "" {
+ return name
+ }
+ return "Unknown"
+}
+
+type ErrCode int32
+
+var (
+ ErrConnectionClosed = errors.New("zk: connection closed")
+ ErrUnknown = errors.New("zk: unknown error")
+ ErrAPIError = errors.New("zk: api error")
+ ErrNoNode = errors.New("zk: node does not exist")
+ ErrNoAuth = errors.New("zk: not authenticated")
+ ErrBadVersion = errors.New("zk: version conflict")
+ ErrNoChildrenForEphemerals = errors.New("zk: ephemeral nodes may not have children")
+ ErrNodeExists = errors.New("zk: node already exists")
+ ErrNotEmpty = errors.New("zk: node has children")
+ ErrSessionExpired = errors.New("zk: session has been expired by the server")
+ ErrInvalidACL = errors.New("zk: invalid ACL specified")
+ ErrAuthFailed = errors.New("zk: client authentication failed")
+ ErrClosing = errors.New("zk: zookeeper is closing")
+ ErrNothing = errors.New("zk: no server responsees to process")
+ ErrSessionMoved = errors.New("zk: session moved to another server, so operation is ignored")
+
+ // ErrInvalidCallback = errors.New("zk: invalid callback specified")
+ errCodeToError = map[ErrCode]error{
+ 0: nil,
+ errAPIError: ErrAPIError,
+ errNoNode: ErrNoNode,
+ errNoAuth: ErrNoAuth,
+ errBadVersion: ErrBadVersion,
+ errNoChildrenForEphemerals: ErrNoChildrenForEphemerals,
+ errNodeExists: ErrNodeExists,
+ errNotEmpty: ErrNotEmpty,
+ errSessionExpired: ErrSessionExpired,
+ // errInvalidCallback: ErrInvalidCallback,
+ errInvalidAcl: ErrInvalidACL,
+ errAuthFailed: ErrAuthFailed,
+ errClosing: ErrClosing,
+ errNothing: ErrNothing,
+ errSessionMoved: ErrSessionMoved,
+ }
+)
+
+func (e ErrCode) toError() error {
+ if err, ok := errCodeToError[e]; ok {
+ return err
+ }
+ return ErrUnknown
+}
+
+const (
+ errOk = 0
+ // System and server-side errors
+ errSystemError = -1
+ errRuntimeInconsistency = -2
+ errDataInconsistency = -3
+ errConnectionLoss = -4
+ errMarshallingError = -5
+ errUnimplemented = -6
+ errOperationTimeout = -7
+ errBadArguments = -8
+ errInvalidState = -9
+ // API errors
+ errAPIError = ErrCode(-100)
+ errNoNode = ErrCode(-101) // *
+ errNoAuth = ErrCode(-102)
+ errBadVersion = ErrCode(-103) // *
+ errNoChildrenForEphemerals = ErrCode(-108)
+ errNodeExists = ErrCode(-110) // *
+ errNotEmpty = ErrCode(-111)
+ errSessionExpired = ErrCode(-112)
+ errInvalidCallback = ErrCode(-113)
+ errInvalidAcl = ErrCode(-114)
+ errAuthFailed = ErrCode(-115)
+ errClosing = ErrCode(-116)
+ errNothing = ErrCode(-117)
+ errSessionMoved = ErrCode(-118)
+)
+
+// Constants for ACL permissions
+const (
+ PermRead = 1 << iota
+ PermWrite
+ PermCreate
+ PermDelete
+ PermAdmin
+ PermAll = 0x1f
+)
+
+var (
+ emptyPassword = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ opNames = map[int32]string{
+ opNotify: "notify",
+ opCreate: "create",
+ opDelete: "delete",
+ opExists: "exists",
+ opGetData: "getData",
+ opSetData: "setData",
+ opGetAcl: "getACL",
+ opSetAcl: "setACL",
+ opGetChildren: "getChildren",
+ opSync: "sync",
+ opPing: "ping",
+ opGetChildren2: "getChildren2",
+ opCheck: "check",
+ opMulti: "multi",
+ opClose: "close",
+ opSetAuth: "setAuth",
+ opSetWatches: "setWatches",
+
+ opWatcherEvent: "watcherEvent",
+ }
+)
+
+type EventType int32
+
+func (t EventType) String() string {
+ if name := eventNames[t]; name != "" {
+ return name
+ }
+ return "Unknown"
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock.go
new file mode 100644
index 0000000000..fb77e4a538
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock.go
@@ -0,0 +1,131 @@
+package zk
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+var (
+ ErrDeadlock = errors.New("zk: trying to acquire a lock twice")
+ ErrNotLocked = errors.New("zk: not locked")
+)
+
+type Lock struct {
+ c *Conn
+ path string
+ acl []ACL
+ lockPath string
+ seq int
+}
+
+func NewLock(c *Conn, path string, acl []ACL) *Lock {
+ return &Lock{
+ c: c,
+ path: path,
+ acl: acl,
+ }
+}
+
+func parseSeq(path string) (int, error) {
+ parts := strings.Split(path, "-")
+ return strconv.Atoi(parts[len(parts)-1])
+}
+
+func (l *Lock) Lock() error {
+ if l.lockPath != "" {
+ return ErrDeadlock
+ }
+
+ prefix := fmt.Sprintf("%s/lock-", l.path)
+
+ path := ""
+ var err error
+ for i := 0; i < 3; i++ {
+ path, err = l.c.CreateProtectedEphemeralSequential(prefix, []byte{}, l.acl)
+ if err == ErrNoNode {
+ // Create parent node.
+ parts := strings.Split(l.path, "/")
+ pth := ""
+ for _, p := range parts[1:] {
+ pth += "/" + p
+ _, err := l.c.Create(pth, []byte{}, 0, l.acl)
+ if err != nil && err != ErrNodeExists {
+ return err
+ }
+ }
+ } else if err == nil {
+ break
+ } else {
+ return err
+ }
+ }
+ if err != nil {
+ return err
+ }
+
+ seq, err := parseSeq(path)
+ if err != nil {
+ return err
+ }
+
+ for {
+ children, _, err := l.c.Children(l.path)
+ if err != nil {
+ return err
+ }
+
+ lowestSeq := seq
+ prevSeq := 0
+ prevSeqPath := ""
+ for _, p := range children {
+ s, err := parseSeq(p)
+ if err != nil {
+ return err
+ }
+ if s < lowestSeq {
+ lowestSeq = s
+ }
+ if s < seq && s > prevSeq {
+ prevSeq = s
+ prevSeqPath = p
+ }
+ }
+
+ if seq == lowestSeq {
+ // Acquired the lock
+ break
+ }
+
+ // Wait on the node next in line for the lock
+ _, _, ch, err := l.c.GetW(l.path + "/" + prevSeqPath)
+ if err != nil && err != ErrNoNode {
+ return err
+ } else if err != nil && err == ErrNoNode {
+ // try again
+ continue
+ }
+
+ ev := <-ch
+ if ev.Err != nil {
+ return ev.Err
+ }
+ }
+
+ l.seq = seq
+ l.lockPath = path
+ return nil
+}
+
+func (l *Lock) Unlock() error {
+ if l.lockPath == "" {
+ return ErrNotLocked
+ }
+ if err := l.c.Delete(l.lockPath, -1); err != nil {
+ return err
+ }
+ l.lockPath = ""
+ l.seq = 0
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock_test.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock_test.go
new file mode 100644
index 0000000000..ad31ffb6e1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/lock_test.go
@@ -0,0 +1,94 @@
+package zk
+
+import (
+ "testing"
+ "time"
+)
+
+func TestLock(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ acls := WorldACL(PermAll)
+
+ l := NewLock(zk, "/test", acls)
+ if err := l.Lock(); err != nil {
+ t.Fatal(err)
+ }
+ if err := l.Unlock(); err != nil {
+ t.Fatal(err)
+ }
+
+ val := make(chan int, 3)
+
+ if err := l.Lock(); err != nil {
+ t.Fatal(err)
+ }
+
+ l2 := NewLock(zk, "/test", acls)
+ go func() {
+ if err := l2.Lock(); err != nil {
+ t.Fatal(err)
+ }
+ val <- 2
+ if err := l2.Unlock(); err != nil {
+ t.Fatal(err)
+ }
+ val <- 3
+ }()
+ time.Sleep(time.Millisecond * 100)
+
+ val <- 1
+ if err := l.Unlock(); err != nil {
+ t.Fatal(err)
+ }
+ if x := <-val; x != 1 {
+ t.Fatalf("Expected 1 instead of %d", x)
+ }
+ if x := <-val; x != 2 {
+ t.Fatalf("Expected 2 instead of %d", x)
+ }
+ if x := <-val; x != 3 {
+ t.Fatalf("Expected 3 instead of %d", x)
+ }
+}
+
+// This tests creating a lock with a path that's more than 1 node deep (e.g. "/test-multi-level/lock"),
+// when a part of that path already exists (i.e. "/test-multi-level" node already exists).
+func TestMultiLevelLock(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ acls := WorldACL(PermAll)
+ path := "/test-multi-level"
+ if p, err := zk.Create(path, []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if p != path {
+ t.Fatalf("Create returned different path '%s' != '%s'", p, path)
+ }
+ l := NewLock(zk, "/test-multi-level/lock", acls)
+ defer zk.Delete("/test-multi-level", -1) // Clean up what we've created for this test
+ defer zk.Delete("/test-multi-level/lock", -1)
+ if err := l.Lock(); err != nil {
+ t.Fatal(err)
+ }
+ if err := l.Unlock(); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_help.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_help.go
new file mode 100644
index 0000000000..7f561b2904
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_help.go
@@ -0,0 +1,115 @@
+package zk
+
+import (
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "path/filepath"
+ "time"
+)
+
+type TestServer struct {
+ Port int
+ Path string
+ Srv *Server
+}
+
+type TestCluster struct {
+ Path string
+ Servers []TestServer
+}
+
+func StartTestCluster(size int, stdout, stderr io.Writer) (*TestCluster, error) {
+ tmpPath, err := ioutil.TempDir("", "gozk")
+ if err != nil {
+ return nil, err
+ }
+ success := false
+ startPort := int(rand.Int31n(6000) + 10000)
+ cluster := &TestCluster{Path: tmpPath}
+ defer func() {
+ if !success {
+ cluster.Stop()
+ }
+ }()
+ for serverN := 0; serverN < size; serverN++ {
+ srvPath := filepath.Join(tmpPath, fmt.Sprintf("srv%d", serverN))
+ if err := os.Mkdir(srvPath, 0700); err != nil {
+ return nil, err
+ }
+ port := startPort + serverN*3
+ cfg := ServerConfig{
+ ClientPort: port,
+ DataDir: srvPath,
+ }
+ for i := 0; i < size; i++ {
+ cfg.Servers = append(cfg.Servers, ServerConfigServer{
+ ID: i + 1,
+ Host: "127.0.0.1",
+ PeerPort: startPort + i*3 + 1,
+ LeaderElectionPort: startPort + i*3 + 2,
+ })
+ }
+ cfgPath := filepath.Join(srvPath, "zoo.cfg")
+ fi, err := os.Create(cfgPath)
+ if err != nil {
+ return nil, err
+ }
+ err = cfg.Marshall(fi)
+ fi.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ fi, err = os.Create(filepath.Join(srvPath, "myid"))
+ if err != nil {
+ return nil, err
+ }
+ _, err = fmt.Fprintf(fi, "%d\n", serverN+1)
+ fi.Close()
+ if err != nil {
+ return nil, err
+ }
+
+ srv := &Server{
+ ConfigPath: cfgPath,
+ Stdout: stdout,
+ Stderr: stderr,
+ }
+ if err := srv.Start(); err != nil {
+ return nil, err
+ }
+ cluster.Servers = append(cluster.Servers, TestServer{
+ Path: srvPath,
+ Port: cfg.ClientPort,
+ Srv: srv,
+ })
+ }
+ success = true
+ time.Sleep(time.Second) // Give the server time to become active. Should probably actually attempt to connect to verify.
+ return cluster, nil
+}
+
+func (ts *TestCluster) Connect(idx int) (*Conn, error) {
+ zk, _, err := Connect([]string{fmt.Sprintf("127.0.0.1:%d", ts.Servers[idx].Port)}, time.Second*15)
+ return zk, err
+}
+
+func (ts *TestCluster) ConnectAll() (*Conn, error) {
+ hosts := make([]string, len(ts.Servers))
+ for i, srv := range ts.Servers {
+ hosts[i] = fmt.Sprintf("127.0.0.1:%d", srv.Port)
+ }
+ zk, _, err := Connect(hosts, time.Second*15)
+ return zk, err
+}
+
+func (ts *TestCluster) Stop() error {
+ for _, srv := range ts.Servers {
+ srv.Srv.Stop()
+ }
+ defer os.RemoveAll(ts.Path)
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_java.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_java.go
new file mode 100644
index 0000000000..e553ec1d9f
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/server_java.go
@@ -0,0 +1,136 @@
+package zk
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+type ErrMissingServerConfigField string
+
+func (e ErrMissingServerConfigField) Error() string {
+ return fmt.Sprintf("zk: missing server config field '%s'", string(e))
+}
+
+const (
+ DefaultServerTickTime = 2000
+ DefaultServerInitLimit = 10
+ DefaultServerSyncLimit = 5
+ DefaultServerAutoPurgeSnapRetainCount = 3
+ DefaultPeerPort = 2888
+ DefaultLeaderElectionPort = 3888
+)
+
+type ServerConfigServer struct {
+ ID int
+ Host string
+ PeerPort int
+ LeaderElectionPort int
+}
+
+type ServerConfig struct {
+ TickTime int // Number of milliseconds of each tick
+ InitLimit int // Number of ticks that the initial synchronization phase can take
+ SyncLimit int // Number of ticks that can pass between sending a request and getting an acknowledgement
+ DataDir string // Direcrory where the snapshot is stored
+ ClientPort int // Port at which clients will connect
+ AutoPurgeSnapRetainCount int // Number of snapshots to retain in dataDir
+ AutoPurgePurgeInterval int // Purge task internal in hours (0 to disable auto purge)
+ Servers []ServerConfigServer
+}
+
+func (sc ServerConfig) Marshall(w io.Writer) error {
+ if sc.DataDir == "" {
+ return ErrMissingServerConfigField("dataDir")
+ }
+ fmt.Fprintf(w, "dataDir=%s\n", sc.DataDir)
+ if sc.TickTime <= 0 {
+ sc.TickTime = DefaultServerTickTime
+ }
+ fmt.Fprintf(w, "tickTime=%d\n", sc.TickTime)
+ if sc.InitLimit <= 0 {
+ sc.InitLimit = DefaultServerInitLimit
+ }
+ fmt.Fprintf(w, "initLimit=%d\n", sc.InitLimit)
+ if sc.SyncLimit <= 0 {
+ sc.SyncLimit = DefaultServerSyncLimit
+ }
+ fmt.Fprintf(w, "syncLimit=%d\n", sc.SyncLimit)
+ if sc.ClientPort <= 0 {
+ sc.ClientPort = DefaultPort
+ }
+ fmt.Fprintf(w, "clientPort=%d\n", sc.ClientPort)
+ if sc.AutoPurgePurgeInterval > 0 {
+ if sc.AutoPurgeSnapRetainCount <= 0 {
+ sc.AutoPurgeSnapRetainCount = DefaultServerAutoPurgeSnapRetainCount
+ }
+ fmt.Fprintf(w, "autopurge.snapRetainCount=%d\n", sc.AutoPurgeSnapRetainCount)
+ fmt.Fprintf(w, "autopurge.purgeInterval=%d\n", sc.AutoPurgePurgeInterval)
+ }
+ if len(sc.Servers) > 0 {
+ for _, srv := range sc.Servers {
+ if srv.PeerPort <= 0 {
+ srv.PeerPort = DefaultPeerPort
+ }
+ if srv.LeaderElectionPort <= 0 {
+ srv.LeaderElectionPort = DefaultLeaderElectionPort
+ }
+ fmt.Fprintf(w, "server.%d=%s:%d:%d\n", srv.ID, srv.Host, srv.PeerPort, srv.LeaderElectionPort)
+ }
+ }
+ return nil
+}
+
+var jarSearchPaths = []string{
+ "zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
+ "../zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
+ "/usr/share/java/zookeeper-*.jar",
+ "/usr/local/zookeeper-*/contrib/fatjar/zookeeper-*-fatjar.jar",
+ "/usr/local/Cellar/zookeeper/*/libexec/contrib/fatjar/zookeeper-*-fatjar.jar",
+}
+
+func findZookeeperFatJar() string {
+ var paths []string
+ zkPath := os.Getenv("ZOOKEEPER_PATH")
+ if zkPath == "" {
+ paths = jarSearchPaths
+ } else {
+ paths = []string{filepath.Join(zkPath, "contrib/fatjar/zookeeper-*-fatjar.jar")}
+ }
+ for _, path := range paths {
+ matches, _ := filepath.Glob(path)
+ // TODO: could sort by version and pick latest
+ if len(matches) > 0 {
+ return matches[0]
+ }
+ }
+ return ""
+}
+
+type Server struct {
+ JarPath string
+ ConfigPath string
+ Stdout, Stderr io.Writer
+
+ cmd *exec.Cmd
+}
+
+func (srv *Server) Start() error {
+ if srv.JarPath == "" {
+ srv.JarPath = findZookeeperFatJar()
+ if srv.JarPath == "" {
+ return fmt.Errorf("zk: unable to find server jar")
+ }
+ }
+ srv.cmd = exec.Command("java", "-jar", srv.JarPath, "server", srv.ConfigPath)
+ srv.cmd.Stdout = srv.Stdout
+ srv.cmd.Stderr = srv.Stderr
+ return srv.cmd.Start()
+}
+
+func (srv *Server) Stop() error {
+ srv.cmd.Process.Signal(os.Kill)
+ return srv.cmd.Wait()
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs.go
new file mode 100644
index 0000000000..fd1285e46a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs.go
@@ -0,0 +1,584 @@
+package zk
+
+import (
+ "encoding/binary"
+ "errors"
+ "reflect"
+ "runtime"
+)
+
+var (
+ ErrUnhandledFieldType = errors.New("zk: unhandled field type")
+ ErrPtrExpected = errors.New("zk: encode/decode expect a non-nil pointer to struct")
+ ErrShortBuffer = errors.New("zk: buffer too small")
+)
+
+type ACL struct {
+ Perms int32
+ Scheme string
+ ID string
+}
+
+type Stat struct {
+ Czxid int64 // The zxid of the change that caused this znode to be created.
+ Mzxid int64 // The zxid of the change that last modified this znode.
+ Ctime int64 // The time in milliseconds from epoch when this znode was created.
+ Mtime int64 // The time in milliseconds from epoch when this znode was last modified.
+ Version int32 // The number of changes to the data of this znode.
+ Cversion int32 // The number of changes to the children of this znode.
+ Aversion int32 // The number of changes to the ACL of this znode.
+ EphemeralOwner int64 // The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero.
+ DataLength int32 // The length of the data field of this znode.
+ NumChildren int32 // The number of children of this znode.
+ Pzxid int64 // last modified children
+}
+
+type requestHeader struct {
+ Xid int32
+ Opcode int32
+}
+
+type responseHeader struct {
+ Xid int32
+ Zxid int64
+ Err ErrCode
+}
+
+type multiHeader struct {
+ Type int32
+ Done bool
+ Err ErrCode
+}
+
+type auth struct {
+ Type int32
+ Scheme string
+ Auth []byte
+}
+
+// Generic request structs
+
+type pathRequest struct {
+ Path string
+}
+
+type PathVersionRequest struct {
+ Path string
+ Version int32
+}
+
+type pathWatchRequest struct {
+ Path string
+ Watch bool
+}
+
+type pathResponse struct {
+ Path string
+}
+
+type statResponse struct {
+ Stat Stat
+}
+
+//
+
+type CheckVersionRequest PathVersionRequest
+type closeRequest struct{}
+type closeResponse struct{}
+
+type connectRequest struct {
+ ProtocolVersion int32
+ LastZxidSeen int64
+ TimeOut int32
+ SessionID int64
+ Passwd []byte
+}
+
+type connectResponse struct {
+ ProtocolVersion int32
+ TimeOut int32
+ SessionID int64
+ Passwd []byte
+}
+
+type CreateRequest struct {
+ Path string
+ Data []byte
+ Acl []ACL
+ Flags int32
+}
+
+type createResponse pathResponse
+type DeleteRequest PathVersionRequest
+type deleteResponse struct{}
+
+type errorResponse struct {
+ Err int32
+}
+
+type existsRequest pathWatchRequest
+type existsResponse statResponse
+type getAclRequest pathRequest
+
+type getAclResponse struct {
+ Acl []ACL
+ Stat Stat
+}
+
+type getChildrenRequest pathRequest
+
+type getChildrenResponse struct {
+ Children []string
+}
+
+type getChildren2Request pathWatchRequest
+
+type getChildren2Response struct {
+ Children []string
+ Stat Stat
+}
+
+type getDataRequest pathWatchRequest
+
+type getDataResponse struct {
+ Data []byte
+ Stat Stat
+}
+
+type getMaxChildrenRequest pathRequest
+
+type getMaxChildrenResponse struct {
+ Max int32
+}
+
+type getSaslRequest struct {
+ Token []byte
+}
+
+type pingRequest struct{}
+type pingResponse struct{}
+
+type setAclRequest struct {
+ Path string
+ Acl []ACL
+ Version int32
+}
+
+type setAclResponse statResponse
+
+type SetDataRequest struct {
+ Path string
+ Data []byte
+ Version int32
+}
+
+type setDataResponse statResponse
+
+type setMaxChildren struct {
+ Path string
+ Max int32
+}
+
+type setSaslRequest struct {
+ Token string
+}
+
+type setSaslResponse struct {
+ Token string
+}
+
+type setWatchesRequest struct {
+ RelativeZxid int64
+ DataWatches []string
+ ExistWatches []string
+ ChildWatches []string
+}
+
+type setWatchesResponse struct{}
+
+type syncRequest pathRequest
+type syncResponse pathResponse
+
+type setAuthRequest auth
+type setAuthResponse struct{}
+
+type multiRequestOp struct {
+ Header multiHeader
+ Op interface{}
+}
+type multiRequest struct {
+ Ops []multiRequestOp
+ DoneHeader multiHeader
+}
+type multiResponseOp struct {
+ Header multiHeader
+ String string
+ Stat *Stat
+}
+type multiResponse struct {
+ Ops []multiResponseOp
+ DoneHeader multiHeader
+}
+
+func (r *multiRequest) Encode(buf []byte) (int, error) {
+ total := 0
+ for _, op := range r.Ops {
+ op.Header.Done = false
+ n, err := encodePacketValue(buf[total:], reflect.ValueOf(op))
+ if err != nil {
+ return total, err
+ }
+ total += n
+ }
+ r.DoneHeader.Done = true
+ n, err := encodePacketValue(buf[total:], reflect.ValueOf(r.DoneHeader))
+ if err != nil {
+ return total, err
+ }
+ total += n
+
+ return total, nil
+}
+
+func (r *multiRequest) Decode(buf []byte) (int, error) {
+ r.Ops = make([]multiRequestOp, 0)
+ r.DoneHeader = multiHeader{-1, true, -1}
+ total := 0
+ for {
+ header := &multiHeader{}
+ n, err := decodePacketValue(buf[total:], reflect.ValueOf(header))
+ if err != nil {
+ return total, err
+ }
+ total += n
+ if header.Done {
+ r.DoneHeader = *header
+ break
+ }
+
+ req := requestStructForOp(header.Type)
+ if req == nil {
+ return total, ErrAPIError
+ }
+ n, err = decodePacketValue(buf[total:], reflect.ValueOf(req))
+ if err != nil {
+ return total, err
+ }
+ total += n
+ r.Ops = append(r.Ops, multiRequestOp{*header, req})
+ }
+ return total, nil
+}
+
+func (r *multiResponse) Decode(buf []byte) (int, error) {
+ r.Ops = make([]multiResponseOp, 0)
+ r.DoneHeader = multiHeader{-1, true, -1}
+ total := 0
+ for {
+ header := &multiHeader{}
+ n, err := decodePacketValue(buf[total:], reflect.ValueOf(header))
+ if err != nil {
+ return total, err
+ }
+ total += n
+ if header.Done {
+ r.DoneHeader = *header
+ break
+ }
+
+ res := multiResponseOp{Header: *header}
+ var w reflect.Value
+ switch header.Type {
+ default:
+ return total, ErrAPIError
+ case opCreate:
+ w = reflect.ValueOf(&res.String)
+ case opSetData:
+ res.Stat = new(Stat)
+ w = reflect.ValueOf(res.Stat)
+ case opCheck, opDelete:
+ }
+ if w.IsValid() {
+ n, err := decodePacketValue(buf[total:], w)
+ if err != nil {
+ return total, err
+ }
+ total += n
+ }
+ r.Ops = append(r.Ops, res)
+ }
+ return total, nil
+}
+
+type watcherEvent struct {
+ Type EventType
+ State State
+ Path string
+}
+
+type decoder interface {
+ Decode(buf []byte) (int, error)
+}
+
+type encoder interface {
+ Encode(buf []byte) (int, error)
+}
+
+func decodePacket(buf []byte, st interface{}) (n int, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
+ err = ErrShortBuffer
+ } else {
+ panic(r)
+ }
+ }
+ }()
+
+ v := reflect.ValueOf(st)
+ if v.Kind() != reflect.Ptr || v.IsNil() {
+ return 0, ErrPtrExpected
+ }
+ return decodePacketValue(buf, v)
+}
+
+func decodePacketValue(buf []byte, v reflect.Value) (int, error) {
+ rv := v
+ kind := v.Kind()
+ if kind == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ kind = v.Kind()
+ }
+
+ n := 0
+ switch kind {
+ default:
+ return n, ErrUnhandledFieldType
+ case reflect.Struct:
+ if de, ok := rv.Interface().(decoder); ok {
+ return de.Decode(buf)
+ } else if de, ok := v.Interface().(decoder); ok {
+ return de.Decode(buf)
+ } else {
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ n2, err := decodePacketValue(buf[n:], field)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ }
+ case reflect.Bool:
+ v.SetBool(buf[n] != 0)
+ n++
+ case reflect.Int32:
+ v.SetInt(int64(binary.BigEndian.Uint32(buf[n : n+4])))
+ n += 4
+ case reflect.Int64:
+ v.SetInt(int64(binary.BigEndian.Uint64(buf[n : n+8])))
+ n += 8
+ case reflect.String:
+ ln := int(binary.BigEndian.Uint32(buf[n : n+4]))
+ v.SetString(string(buf[n+4 : n+4+ln]))
+ n += 4 + ln
+ case reflect.Slice:
+ switch v.Type().Elem().Kind() {
+ default:
+ count := int(binary.BigEndian.Uint32(buf[n : n+4]))
+ n += 4
+ values := reflect.MakeSlice(v.Type(), count, count)
+ v.Set(values)
+ for i := 0; i < count; i++ {
+ n2, err := decodePacketValue(buf[n:], values.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ case reflect.Uint8:
+ ln := int(int32(binary.BigEndian.Uint32(buf[n : n+4])))
+ if ln < 0 {
+ n += 4
+ v.SetBytes(nil)
+ } else {
+ bytes := make([]byte, ln)
+ copy(bytes, buf[n+4:n+4+ln])
+ v.SetBytes(bytes)
+ n += 4 + ln
+ }
+ }
+ }
+ return n, nil
+}
+
+func encodePacket(buf []byte, st interface{}) (n int, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ if e, ok := r.(runtime.Error); ok && e.Error() == "runtime error: slice bounds out of range" {
+ err = ErrShortBuffer
+ } else {
+ panic(r)
+ }
+ }
+ }()
+
+ v := reflect.ValueOf(st)
+ if v.Kind() != reflect.Ptr || v.IsNil() {
+ return 0, ErrPtrExpected
+ }
+ return encodePacketValue(buf, v)
+}
+
+func encodePacketValue(buf []byte, v reflect.Value) (int, error) {
+ rv := v
+ for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
+ v = v.Elem()
+ }
+
+ n := 0
+ switch v.Kind() {
+ default:
+ return n, ErrUnhandledFieldType
+ case reflect.Struct:
+ if en, ok := rv.Interface().(encoder); ok {
+ return en.Encode(buf)
+ } else if en, ok := v.Interface().(encoder); ok {
+ return en.Encode(buf)
+ } else {
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ n2, err := encodePacketValue(buf[n:], field)
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ }
+ case reflect.Bool:
+ if v.Bool() {
+ buf[n] = 1
+ } else {
+ buf[n] = 0
+ }
+ n++
+ case reflect.Int32:
+ binary.BigEndian.PutUint32(buf[n:n+4], uint32(v.Int()))
+ n += 4
+ case reflect.Int64:
+ binary.BigEndian.PutUint64(buf[n:n+8], uint64(v.Int()))
+ n += 8
+ case reflect.String:
+ str := v.String()
+ binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(str)))
+ copy(buf[n+4:n+4+len(str)], []byte(str))
+ n += 4 + len(str)
+ case reflect.Slice:
+ switch v.Type().Elem().Kind() {
+ default:
+ count := v.Len()
+ startN := n
+ n += 4
+ for i := 0; i < count; i++ {
+ n2, err := encodePacketValue(buf[n:], v.Index(i))
+ n += n2
+ if err != nil {
+ return n, err
+ }
+ }
+ binary.BigEndian.PutUint32(buf[startN:startN+4], uint32(count))
+ case reflect.Uint8:
+ if v.IsNil() {
+ binary.BigEndian.PutUint32(buf[n:n+4], uint32(0xffffffff))
+ n += 4
+ } else {
+ bytes := v.Bytes()
+ binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(bytes)))
+ copy(buf[n+4:n+4+len(bytes)], bytes)
+ n += 4 + len(bytes)
+ }
+ }
+ }
+ return n, nil
+}
+
+func requestStructForOp(op int32) interface{} {
+ switch op {
+ case opClose:
+ return &closeRequest{}
+ case opCreate:
+ return &CreateRequest{}
+ case opDelete:
+ return &DeleteRequest{}
+ case opExists:
+ return &existsRequest{}
+ case opGetAcl:
+ return &getAclRequest{}
+ case opGetChildren:
+ return &getChildrenRequest{}
+ case opGetChildren2:
+ return &getChildren2Request{}
+ case opGetData:
+ return &getDataRequest{}
+ case opPing:
+ return &pingRequest{}
+ case opSetAcl:
+ return &setAclRequest{}
+ case opSetData:
+ return &SetDataRequest{}
+ case opSetWatches:
+ return &setWatchesRequest{}
+ case opSync:
+ return &syncRequest{}
+ case opSetAuth:
+ return &setAuthRequest{}
+ case opCheck:
+ return &CheckVersionRequest{}
+ case opMulti:
+ return &multiRequest{}
+ }
+ return nil
+}
+
+func responseStructForOp(op int32) interface{} {
+ switch op {
+ case opClose:
+ return &closeResponse{}
+ case opCreate:
+ return &createResponse{}
+ case opDelete:
+ return &deleteResponse{}
+ case opExists:
+ return &existsResponse{}
+ case opGetAcl:
+ return &getAclResponse{}
+ case opGetChildren:
+ return &getChildrenResponse{}
+ case opGetChildren2:
+ return &getChildren2Response{}
+ case opGetData:
+ return &getDataResponse{}
+ case opPing:
+ return &pingResponse{}
+ case opSetAcl:
+ return &setAclResponse{}
+ case opSetData:
+ return &setDataResponse{}
+ case opSetWatches:
+ return &setWatchesResponse{}
+ case opSync:
+ return &syncResponse{}
+ case opWatcherEvent:
+ return &watcherEvent{}
+ case opSetAuth:
+ return &setAuthResponse{}
+ // case opCheck:
+ // return &checkVersionResponse{}
+ case opMulti:
+ return &multiResponse{}
+ }
+ return nil
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs_test.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs_test.go
new file mode 100644
index 0000000000..64f18e8d3e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/structs_test.go
@@ -0,0 +1,60 @@
+package zk
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestEncodeDecodePacket(t *testing.T) {
+ encodeDecodeTest(t, &requestHeader{-2, 5})
+ encodeDecodeTest(t, &connectResponse{1, 2, 3, nil})
+ encodeDecodeTest(t, &connectResponse{1, 2, 3, []byte{4, 5, 6}})
+ encodeDecodeTest(t, &getAclResponse{[]ACL{{12, "s", "anyone"}}, Stat{}})
+ encodeDecodeTest(t, &getChildrenResponse{[]string{"foo", "bar"}})
+ encodeDecodeTest(t, &pathWatchRequest{"path", true})
+ encodeDecodeTest(t, &pathWatchRequest{"path", false})
+ encodeDecodeTest(t, &CheckVersionRequest{"/", -1})
+ encodeDecodeTest(t, &multiRequest{Ops: []multiRequestOp{{multiHeader{opCheck, false, -1}, &CheckVersionRequest{"/", -1}}}})
+}
+
+func encodeDecodeTest(t *testing.T, r interface{}) {
+ buf := make([]byte, 1024)
+ n, err := encodePacket(buf, r)
+ if err != nil {
+ t.Errorf("encodePacket returned non-nil error %+v\n", err)
+ return
+ }
+ t.Logf("%+v %x", r, buf[:n])
+ r2 := reflect.New(reflect.ValueOf(r).Elem().Type()).Interface()
+ n2, err := decodePacket(buf[:n], r2)
+ if err != nil {
+ t.Errorf("decodePacket returned non-nil error %+v\n", err)
+ return
+ }
+ if n != n2 {
+ t.Errorf("sizes don't match: %d != %d", n, n2)
+ return
+ }
+ if !reflect.DeepEqual(r, r2) {
+ t.Errorf("results don't match: %+v != %+v", r, r2)
+ return
+ }
+}
+
+func TestEncodeShortBuffer(t *testing.T) {
+ buf := make([]byte, 0)
+ _, err := encodePacket(buf, &requestHeader{1, 2})
+ if err != ErrShortBuffer {
+ t.Errorf("encodePacket should return ErrShortBuffer on a short buffer instead of '%+v'", err)
+ return
+ }
+}
+
+func TestDecodeShortBuffer(t *testing.T) {
+ buf := make([]byte, 0)
+ _, err := decodePacket(buf, &responseHeader{})
+ if err != ErrShortBuffer {
+ t.Errorf("decodePacket should return ErrShortBuffer on a short buffer instead of '%+v'", err)
+ return
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/tracer.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/tracer.go
new file mode 100644
index 0000000000..7af2e96bbc
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/tracer.go
@@ -0,0 +1,148 @@
+package zk
+
+import (
+ "encoding/binary"
+ "fmt"
+ "io"
+ "net"
+ "sync"
+)
+
+var (
+ requests = make(map[int32]int32) // Map of Xid -> Opcode
+ requestsLock = &sync.Mutex{}
+)
+
+func trace(conn1, conn2 net.Conn, client bool) {
+ defer conn1.Close()
+ defer conn2.Close()
+ buf := make([]byte, 10*1024)
+ init := true
+ for {
+ _, err := io.ReadFull(conn1, buf[:4])
+ if err != nil {
+ fmt.Println("1>", client, err)
+ return
+ }
+
+ blen := int(binary.BigEndian.Uint32(buf[:4]))
+
+ _, err = io.ReadFull(conn1, buf[4:4+blen])
+ if err != nil {
+ fmt.Println("2>", client, err)
+ return
+ }
+
+ var cr interface{}
+ opcode := int32(-1)
+ readHeader := true
+ if client {
+ if init {
+ cr = &connectRequest{}
+ readHeader = false
+ } else {
+ xid := int32(binary.BigEndian.Uint32(buf[4:8]))
+ opcode = int32(binary.BigEndian.Uint32(buf[8:12]))
+ requestsLock.Lock()
+ requests[xid] = opcode
+ requestsLock.Unlock()
+ cr = requestStructForOp(opcode)
+ if cr == nil {
+ fmt.Printf("Unknown opcode %d\n", opcode)
+ }
+ }
+ } else {
+ if init {
+ cr = &connectResponse{}
+ readHeader = false
+ } else {
+ xid := int32(binary.BigEndian.Uint32(buf[4:8]))
+ zxid := int64(binary.BigEndian.Uint64(buf[8:16]))
+ errnum := int32(binary.BigEndian.Uint32(buf[16:20]))
+ if xid != -1 || zxid != -1 {
+ requestsLock.Lock()
+ found := false
+ opcode, found = requests[xid]
+ if !found {
+ opcode = 0
+ }
+ delete(requests, xid)
+ requestsLock.Unlock()
+ } else {
+ opcode = opWatcherEvent
+ }
+ cr = responseStructForOp(opcode)
+ if cr == nil {
+ fmt.Printf("Unknown opcode %d\n", opcode)
+ }
+ if errnum != 0 {
+ cr = &struct{}{}
+ }
+ }
+ }
+ opname := "."
+ if opcode != -1 {
+ opname = opNames[opcode]
+ }
+ if cr == nil {
+ fmt.Printf("%+v %s %+v\n", client, opname, buf[4:4+blen])
+ } else {
+ n := 4
+ hdrStr := ""
+ if readHeader {
+ var hdr interface{}
+ if client {
+ hdr = &requestHeader{}
+ } else {
+ hdr = &responseHeader{}
+ }
+ if n2, err := decodePacket(buf[n:n+blen], hdr); err != nil {
+ fmt.Println(err)
+ } else {
+ n += n2
+ }
+ hdrStr = fmt.Sprintf(" %+v", hdr)
+ }
+ if _, err := decodePacket(buf[n:n+blen], cr); err != nil {
+ fmt.Println(err)
+ }
+ fmt.Printf("%+v %s%s %+v\n", client, opname, hdrStr, cr)
+ }
+
+ init = false
+
+ written, err := conn2.Write(buf[:4+blen])
+ if err != nil {
+ fmt.Println("3>", client, err)
+ return
+ } else if written != 4+blen {
+ fmt.Printf("Written != read: %d != %d\n", written, blen)
+ return
+ }
+ }
+}
+
+func handleConnection(addr string, conn net.Conn) {
+ zkConn, err := net.Dial("tcp", addr)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ go trace(conn, zkConn, true)
+ trace(zkConn, conn, false)
+}
+
+func StartTracer(listenAddr, serverAddr string) {
+ ln, err := net.Listen("tcp", listenAddr)
+ if err != nil {
+ panic(err)
+ }
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ fmt.Println(err)
+ continue
+ }
+ go handleConnection(serverAddr, conn)
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/util.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/util.go
new file mode 100644
index 0000000000..741095b427
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/util.go
@@ -0,0 +1,40 @@
+package zk
+
+import (
+ "crypto/sha1"
+ "encoding/base64"
+ "fmt"
+ "math/rand"
+)
+
+// AuthACL produces an ACL list containing a single ACL which uses the
+// provided permissions, with the scheme "auth", and ID "", which is used
+// by ZooKeeper to represent any authenticated user.
+func AuthACL(perms int32) []ACL {
+ return []ACL{{perms, "auth", ""}}
+}
+
+// WorldACL produces an ACL list containing a single ACL which uses the
+// provided permissions, with the scheme "world", and ID "anyone", which
+// is used by ZooKeeper to represent any user at all.
+func WorldACL(perms int32) []ACL {
+ return []ACL{{perms, "world", "anyone"}}
+}
+
+func DigestACL(perms int32, user, password string) []ACL {
+ userPass := []byte(fmt.Sprintf("%s:%s", user, password))
+ h := sha1.New()
+ if n, err := h.Write(userPass); err != nil || n != len(userPass) {
+ panic("SHA1 failed")
+ }
+ digest := base64.StdEncoding.EncodeToString(h.Sum(nil))
+ return []ACL{{perms, "digest", fmt.Sprintf("%s:%s", user, digest)}}
+}
+
+// stringShuffle performs a Fisher-Yates shuffle on a slice of strings
+func stringShuffle(s []string) {
+ for i := len(s) - 1; i > 0; i-- {
+ j := rand.Intn(i + 1)
+ s[i], s[j] = s[j], s[i]
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/zk_test.go b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/zk_test.go
new file mode 100644
index 0000000000..4ea305a48c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/samuel/go-zookeeper/zk/zk_test.go
@@ -0,0 +1,518 @@
+package zk
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "strings"
+ "testing"
+ "time"
+
+ "camlistore.org/pkg/throttle"
+)
+
+func TestCreate(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ path := "/gozk-test"
+
+ if err := zk.Delete(path, -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+ if p, err := zk.Create(path, []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if p != path {
+ t.Fatalf("Create returned different path '%s' != '%s'", p, path)
+ }
+ if data, stat, err := zk.Get(path); err != nil {
+ t.Fatalf("Get returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Get returned nil stat")
+ } else if len(data) < 4 {
+ t.Fatal("Get returned wrong size data")
+ }
+}
+
+func TestMulti(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ path := "/gozk-test"
+
+ if err := zk.Delete(path, -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+ ops := []interface{}{
+ &CreateRequest{Path: path, Data: []byte{1, 2, 3, 4}, Acl: WorldACL(PermAll)},
+ &SetDataRequest{Path: path, Data: []byte{1, 2, 3, 4}, Version: -1},
+ }
+ if res, err := zk.Multi(ops...); err != nil {
+ t.Fatalf("Multi returned error: %+v", err)
+ } else if len(res) != 2 {
+ t.Fatalf("Expected 2 responses got %d", len(res))
+ } else {
+ t.Logf("%+v", res)
+ }
+ if data, stat, err := zk.Get(path); err != nil {
+ t.Fatalf("Get returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Get returned nil stat")
+ } else if len(data) < 4 {
+ t.Fatal("Get returned wrong size data")
+ }
+}
+
+func TestGetSetACL(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ if err := zk.AddAuth("digest", []byte("blah")); err != nil {
+ t.Fatalf("AddAuth returned error %+v", err)
+ }
+
+ path := "/gozk-test"
+
+ if err := zk.Delete(path, -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+ if path, err := zk.Create(path, []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if path != "/gozk-test" {
+ t.Fatalf("Create returned different path '%s' != '/gozk-test'", path)
+ }
+
+ expected := WorldACL(PermAll)
+
+ if acl, stat, err := zk.GetACL(path); err != nil {
+ t.Fatalf("GetACL returned error %+v", err)
+ } else if stat == nil {
+ t.Fatalf("GetACL returned nil Stat")
+ } else if len(acl) != 1 || expected[0] != acl[0] {
+ t.Fatalf("GetACL mismatch expected %+v instead of %+v", expected, acl)
+ }
+
+ expected = []ACL{{PermAll, "ip", "127.0.0.1"}}
+
+ if stat, err := zk.SetACL(path, expected, -1); err != nil {
+ t.Fatalf("SetACL returned error %+v", err)
+ } else if stat == nil {
+ t.Fatalf("SetACL returned nil Stat")
+ }
+
+ if acl, stat, err := zk.GetACL(path); err != nil {
+ t.Fatalf("GetACL returned error %+v", err)
+ } else if stat == nil {
+ t.Fatalf("GetACL returned nil Stat")
+ } else if len(acl) != 1 || expected[0] != acl[0] {
+ t.Fatalf("GetACL mismatch expected %+v instead of %+v", expected, acl)
+ }
+}
+
+func TestAuth(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ path := "/gozk-digest-test"
+ if err := zk.Delete(path, -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ acl := DigestACL(PermAll, "user", "password")
+
+ if p, err := zk.Create(path, []byte{1, 2, 3, 4}, 0, acl); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if p != path {
+ t.Fatalf("Create returned different path '%s' != '%s'", p, path)
+ }
+
+ if a, stat, err := zk.GetACL(path); err != nil {
+ t.Fatalf("GetACL returned error %+v", err)
+ } else if stat == nil {
+ t.Fatalf("GetACL returned nil Stat")
+ } else if len(a) != 1 || acl[0] != a[0] {
+ t.Fatalf("GetACL mismatch expected %+v instead of %+v", acl, a)
+ }
+
+ if _, _, err := zk.Get(path); err != ErrNoAuth {
+ t.Fatalf("Get returned error %+v instead of ErrNoAuth", err)
+ }
+
+ if err := zk.AddAuth("digest", []byte("user:password")); err != nil {
+ t.Fatalf("AddAuth returned error %+v", err)
+ }
+
+ if data, stat, err := zk.Get(path); err != nil {
+ t.Fatalf("Get returned error %+v", err)
+ } else if stat == nil {
+ t.Fatalf("Get returned nil Stat")
+ } else if len(data) != 4 {
+ t.Fatalf("Get returned wrong data length")
+ }
+}
+
+func TestChildWatch(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ children, stat, childCh, err := zk.ChildrenW("/")
+ if err != nil {
+ t.Fatalf("Children returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Children returned nil stat")
+ } else if len(children) < 1 {
+ t.Fatal("Children should return at least 1 child")
+ }
+
+ if path, err := zk.Create("/gozk-test", []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if path != "/gozk-test" {
+ t.Fatalf("Create returned different path '%s' != '/gozk-test'", path)
+ }
+
+ select {
+ case ev := <-childCh:
+ if ev.Err != nil {
+ t.Fatalf("Child watcher error %+v", ev.Err)
+ }
+ if ev.Path != "/" {
+ t.Fatalf("Child watcher wrong path %s instead of %s", ev.Path, "/")
+ }
+ case _ = <-time.After(time.Second * 2):
+ t.Fatal("Child watcher timed out")
+ }
+
+ // Delete of the watched node should trigger the watch
+
+ children, stat, childCh, err = zk.ChildrenW("/gozk-test")
+ if err != nil {
+ t.Fatalf("Children returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Children returned nil stat")
+ } else if len(children) != 0 {
+ t.Fatal("Children should return 0 children")
+ }
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ select {
+ case ev := <-childCh:
+ if ev.Err != nil {
+ t.Fatalf("Child watcher error %+v", ev.Err)
+ }
+ if ev.Path != "/gozk-test" {
+ t.Fatalf("Child watcher wrong path %s instead of %s", ev.Path, "/")
+ }
+ case _ = <-time.After(time.Second * 2):
+ t.Fatal("Child watcher timed out")
+ }
+}
+
+func TestSetWatchers(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ zk.reconnectDelay = time.Second
+
+ zk2, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk2.Close()
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ testPath, err := zk.Create("/gozk-test-2", []byte{}, 0, WorldACL(PermAll))
+ if err != nil {
+ t.Fatalf("Create returned: %+v", err)
+ }
+
+ _, _, testEvCh, err := zk.GetW(testPath)
+ if err != nil {
+ t.Fatalf("GetW returned: %+v", err)
+ }
+
+ children, stat, childCh, err := zk.ChildrenW("/")
+ if err != nil {
+ t.Fatalf("Children returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Children returned nil stat")
+ } else if len(children) < 1 {
+ t.Fatal("Children should return at least 1 child")
+ }
+
+ zk.conn.Close()
+ if err := zk2.Delete(testPath, -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+ time.Sleep(time.Millisecond * 100)
+
+ if path, err := zk2.Create("/gozk-test", []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatalf("Create returned error: %+v", err)
+ } else if path != "/gozk-test" {
+ t.Fatalf("Create returned different path '%s' != '/gozk-test'", path)
+ }
+
+ select {
+ case ev := <-testEvCh:
+ if ev.Err != nil {
+ t.Fatalf("GetW watcher error %+v", ev.Err)
+ }
+ if ev.Path != testPath {
+ t.Fatalf("GetW watcher wrong path %s instead of %s", ev.Path, testPath)
+ }
+ case <-time.After(2 * time.Second):
+ t.Fatal("GetW watcher timed out")
+ }
+
+ select {
+ case ev := <-childCh:
+ if ev.Err != nil {
+ t.Fatalf("Child watcher error %+v", ev.Err)
+ }
+ if ev.Path != "/" {
+ t.Fatalf("Child watcher wrong path %s instead of %s", ev.Path, "/")
+ }
+ case <-time.After(2 * time.Second):
+ t.Fatal("Child watcher timed out")
+ }
+}
+
+func TestExpiringWatch(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+ zk, err := ts.ConnectAll()
+ if err != nil {
+ t.Fatalf("Connect returned error: %+v", err)
+ }
+ defer zk.Close()
+
+ if err := zk.Delete("/gozk-test", -1); err != nil && err != ErrNoNode {
+ t.Fatalf("Delete returned error: %+v", err)
+ }
+
+ children, stat, childCh, err := zk.ChildrenW("/")
+ if err != nil {
+ t.Fatalf("Children returned error: %+v", err)
+ } else if stat == nil {
+ t.Fatal("Children returned nil stat")
+ } else if len(children) < 1 {
+ t.Fatal("Children should return at least 1 child")
+ }
+
+ zk.sessionID = 99999
+ zk.conn.Close()
+
+ select {
+ case ev := <-childCh:
+ if ev.Err != ErrSessionExpired {
+ t.Fatalf("Child watcher error %+v instead of expected ErrSessionExpired", ev.Err)
+ }
+ if ev.Path != "/" {
+ t.Fatalf("Child watcher wrong path %s instead of %s", ev.Path, "/")
+ }
+ case <-time.After(2 * time.Second):
+ t.Fatal("Child watcher timed out")
+ }
+}
+
+func TestRequestFail(t *testing.T) {
+ // If connecting fails to all servers in the list then pending requests
+ // should be errored out so they don't hang forever.
+
+ zk, _, err := Connect([]string{"127.0.0.1:32444"}, time.Second*15)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer zk.Close()
+
+ ch := make(chan error)
+ go func() {
+ _, _, err := zk.Get("/blah")
+ ch <- err
+ }()
+ select {
+ case err := <-ch:
+ if err == nil {
+ t.Fatal("Expected non-nil error on failed request due to connection failure")
+ }
+ case <-time.After(time.Second * 2):
+ t.Fatal("Get hung when connection could not be made")
+ }
+}
+
+func TestSlowServer(t *testing.T) {
+ ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ts.Stop()
+
+ realAddr := fmt.Sprintf("127.0.0.1:%d", ts.Servers[0].Port)
+ proxyAddr, stopCh, err := startSlowProxy(t,
+ throttle.Rate{}, throttle.Rate{},
+ realAddr, func(ln *throttle.Listener) {
+ if ln.Up.Latency == 0 {
+ ln.Up.Latency = time.Millisecond * 2000
+ ln.Down.Latency = time.Millisecond * 2000
+ } else {
+ ln.Up.Latency = 0
+ ln.Down.Latency = 0
+ }
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer close(stopCh)
+
+ zk, _, err := Connect([]string{proxyAddr}, time.Millisecond*500)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer zk.Close()
+
+ _, _, wch, err := zk.ChildrenW("/")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Force a reconnect to get a throttled connection
+ zk.conn.Close()
+
+ time.Sleep(time.Millisecond * 100)
+
+ if err := zk.Delete("/gozk-test", -1); err == nil {
+ t.Fatal("Delete should have failed")
+ }
+
+ // The previous request should have timed out causing the server to be disconnected and reconnected
+
+ if _, err := zk.Create("/gozk-test", []byte{1, 2, 3, 4}, 0, WorldACL(PermAll)); err != nil {
+ t.Fatal(err)
+ }
+
+ // Make sure event is still returned because the session should not have been affected
+ select {
+ case ev := <-wch:
+ t.Logf("Received event: %+v", ev)
+ case <-time.After(time.Second):
+ t.Fatal("Expected to receive a watch event")
+ }
+}
+
+func startSlowProxy(t *testing.T, up, down throttle.Rate, upstream string, adj func(ln *throttle.Listener)) (string, chan bool, error) {
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ return "", nil, err
+ }
+ tln := &throttle.Listener{
+ Listener: ln,
+ Up: up,
+ Down: down,
+ }
+ stopCh := make(chan bool)
+ go func() {
+ <-stopCh
+ tln.Close()
+ }()
+ go func() {
+ for {
+ cn, err := tln.Accept()
+ if err != nil {
+ if !strings.Contains(err.Error(), "use of closed network connection") {
+ t.Fatalf("Accept failed: %s", err.Error())
+ }
+ return
+ }
+ if adj != nil {
+ adj(tln)
+ }
+ go func(cn net.Conn) {
+ defer cn.Close()
+ upcn, err := net.Dial("tcp", upstream)
+ if err != nil {
+ t.Log(err)
+ return
+ }
+ // This will leave hanging goroutines util stopCh is closed
+ // but it doesn't matter in the context of running tests.
+ go func() {
+ <-stopCh
+ upcn.Close()
+ }()
+ go func() {
+ if _, err := io.Copy(upcn, cn); err != nil {
+ if !strings.Contains(err.Error(), "use of closed network connection") {
+ // log.Printf("Upstream write failed: %s", err.Error())
+ }
+ }
+ }()
+ if _, err := io.Copy(cn, upcn); err != nil {
+ if !strings.Contains(err.Error(), "use of closed network connection") {
+ // log.Printf("Upstream read failed: %s", err.Error())
+ }
+ }
+ }(cn)
+ }
+ }()
+ return ln.Addr().String(), stopCh, nil
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore b/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore
new file mode 100644
index 0000000000..00268614f0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore
@@ -0,0 +1,22 @@
+# 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
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md b/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md
new file mode 100644
index 0000000000..2199945813
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md
@@ -0,0 +1,23 @@
+objx - by Mat Ryer and Tyler Bunnell
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Stretchr, Inc.
+
+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/github.com/stretchr/objx/README.md b/Godeps/_workspace/src/github.com/stretchr/objx/README.md
new file mode 100644
index 0000000000..4aa180687a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/README.md
@@ -0,0 +1,3 @@
+# objx
+
+ * Jump into the [API Documentation](http://godoc.org/github.com/stretchr/objx)
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go b/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go
new file mode 100644
index 0000000000..721bcac799
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go
@@ -0,0 +1,179 @@
+package objx
+
+import (
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// arrayAccesRegexString is the regex used to extract the array number
+// from the access path
+const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
+
+// arrayAccesRegex is the compiled arrayAccesRegexString
+var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
+
+// Get gets the value using the specified selector and
+// returns it inside a new Obj object.
+//
+// If it cannot find the value, Get will return a nil
+// value inside an instance of Obj.
+//
+// Get can only operate directly on map[string]interface{} and []interface.
+//
+// Example
+//
+// To access the title of the third chapter of the second book, do:
+//
+// o.Get("books[1].chapters[2].title")
+func (m Map) Get(selector string) *Value {
+ rawObj := access(m, selector, nil, false, false)
+ return &Value{data: rawObj}
+}
+
+// Set sets the value using the specified selector and
+// returns the object on which Set was called.
+//
+// Set can only operate directly on map[string]interface{} and []interface
+//
+// Example
+//
+// To set the title of the third chapter of the second book, do:
+//
+// o.Set("books[1].chapters[2].title","Time to Go")
+func (m Map) Set(selector string, value interface{}) Map {
+ access(m, selector, value, true, false)
+ return m
+}
+
+// access accesses the object using the selector and performs the
+// appropriate action.
+func access(current, selector, value interface{}, isSet, panics bool) interface{} {
+
+ switch selector.(type) {
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
+
+ if array, ok := current.([]interface{}); ok {
+ index := intFromInterface(selector)
+
+ if index >= len(array) {
+ if panics {
+ panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
+ }
+ return nil
+ }
+
+ return array[index]
+ }
+
+ return nil
+
+ case string:
+
+ selStr := selector.(string)
+ selSegs := strings.SplitN(selStr, PathSeparator, 2)
+ thisSel := selSegs[0]
+ index := -1
+ var err error
+
+ // https://github.com/stretchr/objx/issues/12
+ if strings.Contains(thisSel, "[") {
+
+ arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel)
+
+ if len(arrayMatches) > 0 {
+
+ // Get the key into the map
+ thisSel = arrayMatches[1]
+
+ // Get the index into the array at the key
+ index, err = strconv.Atoi(arrayMatches[2])
+
+ if err != nil {
+ // This should never happen. If it does, something has gone
+ // seriously wrong. Panic.
+ panic("objx: Array index is not an integer. Must use array[int].")
+ }
+
+ }
+ }
+
+ if curMap, ok := current.(Map); ok {
+ current = map[string]interface{}(curMap)
+ }
+
+ // get the object in question
+ switch current.(type) {
+ case map[string]interface{}:
+ curMSI := current.(map[string]interface{})
+ if len(selSegs) <= 1 && isSet {
+ curMSI[thisSel] = value
+ return nil
+ } else {
+ current = curMSI[thisSel]
+ }
+ default:
+ current = nil
+ }
+
+ if current == nil && panics {
+ panic(fmt.Sprintf("objx: '%v' invalid on object.", selector))
+ }
+
+ // do we need to access the item of an array?
+ if index > -1 {
+ if array, ok := current.([]interface{}); ok {
+ if index < len(array) {
+ current = array[index]
+ } else {
+ if panics {
+ panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
+ }
+ current = nil
+ }
+ }
+ }
+
+ if len(selSegs) > 1 {
+ current = access(current, selSegs[1], value, isSet, panics)
+ }
+
+ }
+
+ return current
+
+}
+
+// intFromInterface converts an interface object to the largest
+// representation of an unsigned integer using a type switch and
+// assertions
+func intFromInterface(selector interface{}) int {
+ var value int
+ switch selector.(type) {
+ case int:
+ value = selector.(int)
+ case int8:
+ value = int(selector.(int8))
+ case int16:
+ value = int(selector.(int16))
+ case int32:
+ value = int(selector.(int32))
+ case int64:
+ value = int(selector.(int64))
+ case uint:
+ value = int(selector.(uint))
+ case uint8:
+ value = int(selector.(uint8))
+ case uint16:
+ value = int(selector.(uint16))
+ case uint32:
+ value = int(selector.(uint32))
+ case uint64:
+ value = int(selector.(uint64))
+ default:
+ panic("objx: array access argument is not an integer type (this should never happen)")
+ }
+
+ return value
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go
new file mode 100644
index 0000000000..ce5d8e4aa1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go
@@ -0,0 +1,145 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestAccessorsAccessGetSingleField(t *testing.T) {
+
+ current := map[string]interface{}{"name": "Tyler"}
+ assert.Equal(t, "Tyler", access(current, "name", nil, false, true))
+
+}
+func TestAccessorsAccessGetDeep(t *testing.T) {
+
+ current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}}
+ assert.Equal(t, "Tyler", access(current, "name.first", nil, false, true))
+ assert.Equal(t, "Bunnell", access(current, "name.last", nil, false, true))
+
+}
+func TestAccessorsAccessGetDeepDeep(t *testing.T) {
+
+ current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}}
+ assert.Equal(t, 4, access(current, "one.two.three.four", nil, false, true))
+
+}
+func TestAccessorsAccessGetInsideArray(t *testing.T) {
+
+ current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}}
+ assert.Equal(t, "Tyler", access(current, "names[0].first", nil, false, true))
+ assert.Equal(t, "Bunnell", access(current, "names[0].last", nil, false, true))
+ assert.Equal(t, "Capitol", access(current, "names[1].first", nil, false, true))
+ assert.Equal(t, "Bollocks", access(current, "names[1].last", nil, false, true))
+
+ assert.Panics(t, func() {
+ access(current, "names[2]", nil, false, true)
+ })
+ assert.Nil(t, access(current, "names[2]", nil, false, false))
+
+}
+
+func TestAccessorsAccessGetFromArrayWithInt(t *testing.T) {
+
+ current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}
+ one := access(current, 0, nil, false, false)
+ two := access(current, 1, nil, false, false)
+ three := access(current, 2, nil, false, false)
+
+ assert.Equal(t, "Tyler", one.(map[string]interface{})["first"])
+ assert.Equal(t, "Capitol", two.(map[string]interface{})["first"])
+ assert.Nil(t, three)
+
+}
+
+func TestAccessorsGet(t *testing.T) {
+
+ current := New(map[string]interface{}{"name": "Tyler"})
+ assert.Equal(t, "Tyler", current.Get("name").data)
+
+}
+
+func TestAccessorsAccessSetSingleField(t *testing.T) {
+
+ current := map[string]interface{}{"name": "Tyler"}
+ access(current, "name", "Mat", true, false)
+ assert.Equal(t, current["name"], "Mat")
+
+ access(current, "age", 29, true, true)
+ assert.Equal(t, current["age"], 29)
+
+}
+
+func TestAccessorsAccessSetSingleFieldNotExisting(t *testing.T) {
+
+ current := map[string]interface{}{}
+ access(current, "name", "Mat", true, false)
+ assert.Equal(t, current["name"], "Mat")
+
+}
+
+func TestAccessorsAccessSetDeep(t *testing.T) {
+
+ current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}}
+
+ access(current, "name.first", "Mat", true, true)
+ access(current, "name.last", "Ryer", true, true)
+
+ assert.Equal(t, "Mat", access(current, "name.first", nil, false, true))
+ assert.Equal(t, "Ryer", access(current, "name.last", nil, false, true))
+
+}
+func TestAccessorsAccessSetDeepDeep(t *testing.T) {
+
+ current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}}
+
+ access(current, "one.two.three.four", 5, true, true)
+
+ assert.Equal(t, 5, access(current, "one.two.three.four", nil, false, true))
+
+}
+func TestAccessorsAccessSetArray(t *testing.T) {
+
+ current := map[string]interface{}{"names": []interface{}{"Tyler"}}
+
+ access(current, "names[0]", "Mat", true, true)
+
+ assert.Equal(t, "Mat", access(current, "names[0]", nil, false, true))
+
+}
+func TestAccessorsAccessSetInsideArray(t *testing.T) {
+
+ current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}}
+
+ access(current, "names[0].first", "Mat", true, true)
+ access(current, "names[0].last", "Ryer", true, true)
+ access(current, "names[1].first", "Captain", true, true)
+ access(current, "names[1].last", "Underpants", true, true)
+
+ assert.Equal(t, "Mat", access(current, "names[0].first", nil, false, true))
+ assert.Equal(t, "Ryer", access(current, "names[0].last", nil, false, true))
+ assert.Equal(t, "Captain", access(current, "names[1].first", nil, false, true))
+ assert.Equal(t, "Underpants", access(current, "names[1].last", nil, false, true))
+
+}
+
+func TestAccessorsAccessSetFromArrayWithInt(t *testing.T) {
+
+ current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}
+ one := access(current, 0, nil, false, false)
+ two := access(current, 1, nil, false, false)
+ three := access(current, 2, nil, false, false)
+
+ assert.Equal(t, "Tyler", one.(map[string]interface{})["first"])
+ assert.Equal(t, "Capitol", two.(map[string]interface{})["first"])
+ assert.Nil(t, three)
+
+}
+
+func TestAccessorsSet(t *testing.T) {
+
+ current := New(map[string]interface{}{"name": "Tyler"})
+ current.Set("name", "Mat")
+ assert.Equal(t, "Mat", current.Get("name").data)
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
new file mode 100644
index 0000000000..3060234751
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
@@ -0,0 +1,14 @@
+ case []{1}:
+ a := object.([]{1})
+ if isSet {
+ a[index] = value.({1})
+ } else {
+ if index >= len(a) {
+ if panics {
+ panic(fmt.Sprintf("objx: Index %d is out of range because the []{1} only contains %d items.", index, len(a)))
+ }
+ return nil
+ } else {
+ return a[index]
+ }
+ }
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
new file mode 100644
index 0000000000..379ffc3c0e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
@@ -0,0 +1,86 @@
+
+
+
+ Codegen
+
+
+
+
+
+
+ Template
+
+
+ Use {x} as a placeholder for each argument.
+
+
+
+
+ Arguments (comma separated)
+
+
+ One block per line
+
+
+
+
+ Output
+
+
+
+
+
+
+
+
+
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
new file mode 100644
index 0000000000..b396900b8a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
@@ -0,0 +1,286 @@
+/*
+ {4} ({1} and []{1})
+ --------------------------------------------------
+*/
+
+// {4} gets the value as a {1}, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) {4}(optionalDefault ...{1}) {1} {
+ if s, ok := v.data.({1}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return {3}
+}
+
+// Must{4} gets the value as a {1}.
+//
+// Panics if the object is not a {1}.
+func (v *Value) Must{4}() {1} {
+ return v.data.({1})
+}
+
+// {4}Slice gets the value as a []{1}, returns the optionalDefault
+// value or nil if the value is not a []{1}.
+func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} {
+ if s, ok := v.data.([]{1}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// Must{4}Slice gets the value as a []{1}.
+//
+// Panics if the object is not a []{1}.
+func (v *Value) Must{4}Slice() []{1} {
+ return v.data.([]{1})
+}
+
+// Is{4} gets whether the object contained is a {1} or not.
+func (v *Value) Is{4}() bool {
+ _, ok := v.data.({1})
+ return ok
+}
+
+// Is{4}Slice gets whether the object contained is a []{1} or not.
+func (v *Value) Is{4}Slice() bool {
+ _, ok := v.data.([]{1})
+ return ok
+}
+
+// Each{4} calls the specified callback for each object
+// in the []{1}.
+//
+// Panics if the object is the wrong type.
+func (v *Value) Each{4}(callback func(int, {1}) bool) *Value {
+
+ for index, val := range v.Must{4}Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// Where{4} uses the specified decider function to select items
+// from the []{1}. The object contained in the result will contain
+// only the selected items.
+func (v *Value) Where{4}(decider func(int, {1}) bool) *Value {
+
+ var selected []{1}
+
+ v.Each{4}(func(index int, val {1}) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data:selected}
+
+}
+
+// Group{4} uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]{1}.
+func (v *Value) Group{4}(grouper func(int, {1}) string) *Value {
+
+ groups := make(map[string][]{1})
+
+ v.Each{4}(func(index int, val {1}) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]{1}, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data:groups}
+
+}
+
+// Replace{4} uses the specified function to replace each {1}s
+// by iterating each item. The data in the returned result will be a
+// []{1} containing the replaced items.
+func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value {
+
+ arr := v.Must{4}Slice()
+ replaced := make([]{1}, len(arr))
+
+ v.Each{4}(func(index int, val {1}) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data:replaced}
+
+}
+
+// Collect{4} uses the specified collector function to collect a value
+// for each of the {1}s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value {
+
+ arr := v.Must{4}Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.Each{4}(func(index int, val {1}) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data:collected}
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func Test{4}(t *testing.T) {
+
+ val := {1}( {2} )
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").{4}())
+ assert.Equal(t, val, New(m).Get("value").Must{4}())
+ assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}())
+ assert.Equal(t, val, New(m).Get("nothing").{4}({2}))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").Must{4}()
+ })
+
+}
+
+func Test{4}Slice(t *testing.T) {
+
+ val := {1}( {2} )
+ m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").{4}Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0])
+ assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice())
+ assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").Must{4}Slice()
+ })
+
+}
+
+func TestIs{4}(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: {1}({2})}
+ assert.True(t, v.Is{4}())
+
+ v = &Value{data: []{1}{ {1}({2}) }}
+ assert.True(t, v.Is{4}Slice())
+
+}
+
+func TestEach{4}(t *testing.T) {
+
+ v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
+ count := 0
+ replacedVals := make([]{1}, 0)
+ assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0])
+ assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1])
+ assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2])
+
+}
+
+func TestWhere{4}(t *testing.T) {
+
+ v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
+
+ selected := v.Where{4}(func(i int, val {1}) bool {
+ return i%2==0
+ }).Must{4}Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroup{4}(t *testing.T) {
+
+ v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
+
+ grouped := v.Group{4}(func(i int, val {1}) string {
+ return fmt.Sprintf("%v", i%2==0)
+ }).data.(map[string][]{1})
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplace{4}(t *testing.T) {
+
+ v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
+
+ rawArr := v.Must{4}Slice()
+
+ replaced := v.Replace{4}(func(index int, val {1}) {1} {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.Must{4}Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollect{4}(t *testing.T) {
+
+ v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
+
+ collected := v.Collect{4}(func(index int, val {1}) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
new file mode 100644
index 0000000000..069d43d8ec
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
@@ -0,0 +1,20 @@
+Interface,interface{},"something",nil,Inter
+Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI
+ObjxMap,(Map),New(1),New(nil),ObjxMap
+Bool,bool,true,false,Bool
+String,string,"hello","",Str
+Int,int,1,0,Int
+Int8,int8,1,0,Int8
+Int16,int16,1,0,Int16
+Int32,int32,1,0,Int32
+Int64,int64,1,0,Int64
+Uint,uint,1,0,Uint
+Uint8,uint8,1,0,Uint8
+Uint16,uint16,1,0,Uint16
+Uint32,uint32,1,0,Uint32
+Uint64,uint64,1,0,Uint64
+Uintptr,uintptr,1,0,Uintptr
+Float32,float32,1,0,Float32
+Float64,float64,1,0,Float64
+Complex64,complex64,1,0,Complex64
+Complex128,complex128,1,0,Complex128
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/constants.go b/Godeps/_workspace/src/github.com/stretchr/objx/constants.go
new file mode 100644
index 0000000000..f9eb42a25e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/constants.go
@@ -0,0 +1,13 @@
+package objx
+
+const (
+ // PathSeparator is the character used to separate the elements
+ // of the keypath.
+ //
+ // For example, `location.address.city`
+ PathSeparator string = "."
+
+ // SignatureSeparator is the character that is used to
+ // separate the Base64 string from the security signature.
+ SignatureSeparator = "_"
+)
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go b/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go
new file mode 100644
index 0000000000..9cdfa9f9f6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go
@@ -0,0 +1,117 @@
+package objx
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/url"
+)
+
+// JSON converts the contained object to a JSON string
+// representation
+func (m Map) JSON() (string, error) {
+
+ result, err := json.Marshal(m)
+
+ if err != nil {
+ err = errors.New("objx: JSON encode failed with: " + err.Error())
+ }
+
+ return string(result), err
+
+}
+
+// MustJSON converts the contained object to a JSON string
+// representation and panics if there is an error
+func (m Map) MustJSON() string {
+ result, err := m.JSON()
+ if err != nil {
+ panic(err.Error())
+ }
+ return result
+}
+
+// Base64 converts the contained object to a Base64 string
+// representation of the JSON string representation
+func (m Map) Base64() (string, error) {
+
+ var buf bytes.Buffer
+
+ jsonData, err := m.JSON()
+ if err != nil {
+ return "", err
+ }
+
+ encoder := base64.NewEncoder(base64.StdEncoding, &buf)
+ encoder.Write([]byte(jsonData))
+ encoder.Close()
+
+ return buf.String(), nil
+
+}
+
+// MustBase64 converts the contained object to a Base64 string
+// representation of the JSON string representation and panics
+// if there is an error
+func (m Map) MustBase64() string {
+ result, err := m.Base64()
+ if err != nil {
+ panic(err.Error())
+ }
+ return result
+}
+
+// SignedBase64 converts the contained object to a Base64 string
+// representation of the JSON string representation and signs it
+// using the provided key.
+func (m Map) SignedBase64(key string) (string, error) {
+
+ base64, err := m.Base64()
+ if err != nil {
+ return "", err
+ }
+
+ sig := HashWithKey(base64, key)
+
+ return base64 + SignatureSeparator + sig, nil
+
+}
+
+// MustSignedBase64 converts the contained object to a Base64 string
+// representation of the JSON string representation and signs it
+// using the provided key and panics if there is an error
+func (m Map) MustSignedBase64(key string) string {
+ result, err := m.SignedBase64(key)
+ if err != nil {
+ panic(err.Error())
+ }
+ return result
+}
+
+/*
+ URL Query
+ ------------------------------------------------
+*/
+
+// URLValues creates a url.Values object from an Obj. This
+// function requires that the wrapped object be a map[string]interface{}
+func (m Map) URLValues() url.Values {
+
+ vals := make(url.Values)
+
+ for k, v := range m {
+ //TODO: can this be done without sprintf?
+ vals.Set(k, fmt.Sprintf("%v", v))
+ }
+
+ return vals
+}
+
+// URLQuery gets an encoded URL query representing the given
+// Obj. This function requires that the wrapped object be a
+// map[string]interface{}
+func (m Map) URLQuery() (string, error) {
+ return m.URLValues().Encode(), nil
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go
new file mode 100644
index 0000000000..e9ccd2987b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go
@@ -0,0 +1,94 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestConversionJSON(t *testing.T) {
+
+ jsonString := `{"name":"Mat"}`
+ o := MustFromJSON(jsonString)
+
+ result, err := o.JSON()
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, jsonString, result)
+ }
+
+ assert.Equal(t, jsonString, o.MustJSON())
+
+}
+
+func TestConversionJSONWithError(t *testing.T) {
+
+ o := MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustJSON()
+ })
+
+ _, err := o.JSON()
+
+ assert.Error(t, err)
+
+}
+
+func TestConversionBase64(t *testing.T) {
+
+ o := New(map[string]interface{}{"name": "Mat"})
+
+ result, err := o.Base64()
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", result)
+ }
+
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", o.MustBase64())
+
+}
+
+func TestConversionBase64WithError(t *testing.T) {
+
+ o := MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustBase64()
+ })
+
+ _, err := o.Base64()
+
+ assert.Error(t, err)
+
+}
+
+func TestConversionSignedBase64(t *testing.T) {
+
+ o := New(map[string]interface{}{"name": "Mat"})
+
+ result, err := o.SignedBase64("key")
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", result)
+ }
+
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", o.MustSignedBase64("key"))
+
+}
+
+func TestConversionSignedBase64WithError(t *testing.T) {
+
+ o := MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustSignedBase64("key")
+ })
+
+ _, err := o.SignedBase64("key")
+
+ assert.Error(t, err)
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/doc.go b/Godeps/_workspace/src/github.com/stretchr/objx/doc.go
new file mode 100644
index 0000000000..47bf85e463
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/doc.go
@@ -0,0 +1,72 @@
+// objx - Go package for dealing with maps, slices, JSON and other data.
+//
+// Overview
+//
+// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes
+// a powerful `Get` method (among others) that allows you to easily and quickly get
+// access to data within the map, without having to worry too much about type assertions,
+// missing data, default values etc.
+//
+// Pattern
+//
+// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s
+// easy.
+//
+// Call one of the `objx.` functions to create your `objx.Map` to get going:
+//
+// m, err := objx.FromJSON(json)
+//
+// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong,
+// the rest will be optimistic and try to figure things out without panicking.
+//
+// Use `Get` to access the value you're interested in. You can use dot and array
+// notation too:
+//
+// m.Get("places[0].latlng")
+//
+// Once you have saught the `Value` you're interested in, you can use the `Is*` methods
+// to determine its type.
+//
+// if m.Get("code").IsStr() { /* ... */ }
+//
+// Or you can just assume the type, and use one of the strong type methods to
+// extract the real value:
+//
+// m.Get("code").Int()
+//
+// If there's no value there (or if it's the wrong type) then a default value
+// will be returned, or you can be explicit about the default value.
+//
+// Get("code").Int(-1)
+//
+// If you're dealing with a slice of data as a value, Objx provides many useful
+// methods for iterating, manipulating and selecting that data. You can find out more
+// by exploring the index below.
+//
+// Reading data
+//
+// A simple example of how to use Objx:
+//
+// // use MustFromJSON to make an objx.Map from some JSON
+// m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`)
+//
+// // get the details
+// name := m.Get("name").Str()
+// age := m.Get("age").Int()
+//
+// // get their nickname (or use their name if they
+// // don't have one)
+// nickname := m.Get("nickname").Str(name)
+//
+// Ranging
+//
+// Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For
+// example, to `range` the data, do what you would expect:
+//
+// m := objx.MustFromJSON(json)
+// for key, value := range m {
+//
+// /* ... do your magic ... */
+//
+// }
+package objx
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go
new file mode 100644
index 0000000000..27f7d9049a
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go
@@ -0,0 +1,98 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+var fixtures = []struct {
+ // name is the name of the fixture (used for reporting
+ // failures)
+ name string
+ // data is the JSON data to be worked on
+ data string
+ // get is the argument(s) to pass to Get
+ get interface{}
+ // output is the expected output
+ output interface{}
+}{
+ {
+ name: "Simple get",
+ data: `{"name": "Mat"}`,
+ get: "name",
+ output: "Mat",
+ },
+ {
+ name: "Get with dot notation",
+ data: `{"address": {"city": "Boulder"}}`,
+ get: "address.city",
+ output: "Boulder",
+ },
+ {
+ name: "Deep get with dot notation",
+ data: `{"one": {"two": {"three": {"four": "hello"}}}}`,
+ get: "one.two.three.four",
+ output: "hello",
+ },
+ {
+ name: "Get missing with dot notation",
+ data: `{"one": {"two": {"three": {"four": "hello"}}}}`,
+ get: "one.ten",
+ output: nil,
+ },
+ {
+ name: "Get with array notation",
+ data: `{"tags": ["one", "two", "three"]}`,
+ get: "tags[1]",
+ output: "two",
+ },
+ {
+ name: "Get with array and dot notation",
+ data: `{"types": { "tags": ["one", "two", "three"]}}`,
+ get: "types.tags[1]",
+ output: "two",
+ },
+ {
+ name: "Get with array and dot notation - field after array",
+ data: `{"tags": [{"name":"one"}, {"name":"two"}, {"name":"three"}]}`,
+ get: "tags[1].name",
+ output: "two",
+ },
+ {
+ name: "Complex get with array and dot notation",
+ data: `{"tags": [{"list": [{"one":"pizza"}]}]}`,
+ get: "tags[0].list[0].one",
+ output: "pizza",
+ },
+ {
+ name: "Get field from within string should be nil",
+ data: `{"name":"Tyler"}`,
+ get: "name.something",
+ output: nil,
+ },
+ {
+ name: "Get field from within string (using array accessor) should be nil",
+ data: `{"numbers":["one", "two", "three"]}`,
+ get: "numbers[0].nope",
+ output: nil,
+ },
+}
+
+func TestFixtures(t *testing.T) {
+
+ for _, fixture := range fixtures {
+
+ m := MustFromJSON(fixture.data)
+
+ // get the value
+ t.Logf("Running get fixture: \"%s\" (%v)", fixture.name, fixture)
+ value := m.Get(fixture.get.(string))
+
+ // make sure it matches
+ assert.Equal(t, fixture.output, value.data,
+ "Get fixture \"%s\" failed: %v", fixture.name, fixture,
+ )
+
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map.go b/Godeps/_workspace/src/github.com/stretchr/objx/map.go
new file mode 100644
index 0000000000..eb6ed8e285
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/map.go
@@ -0,0 +1,222 @@
+package objx
+
+import (
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "io/ioutil"
+ "net/url"
+ "strings"
+)
+
+// MSIConvertable is an interface that defines methods for converting your
+// custom types to a map[string]interface{} representation.
+type MSIConvertable interface {
+ // MSI gets a map[string]interface{} (msi) representing the
+ // object.
+ MSI() map[string]interface{}
+}
+
+// Map provides extended functionality for working with
+// untyped data, in particular map[string]interface (msi).
+type Map map[string]interface{}
+
+// Value returns the internal value instance
+func (m Map) Value() *Value {
+ return &Value{data: m}
+}
+
+// Nil represents a nil Map.
+var Nil Map = New(nil)
+
+// New creates a new Map containing the map[string]interface{} in the data argument.
+// If the data argument is not a map[string]interface, New attempts to call the
+// MSI() method on the MSIConvertable interface to create one.
+func New(data interface{}) Map {
+ if _, ok := data.(map[string]interface{}); !ok {
+ if converter, ok := data.(MSIConvertable); ok {
+ data = converter.MSI()
+ } else {
+ return nil
+ }
+ }
+ return Map(data.(map[string]interface{}))
+}
+
+// MSI creates a map[string]interface{} and puts it inside a new Map.
+//
+// The arguments follow a key, value pattern.
+//
+// Panics
+//
+// Panics if any key arugment is non-string or if there are an odd number of arguments.
+//
+// Example
+//
+// To easily create Maps:
+//
+// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true))
+//
+// // creates an Map equivalent to
+// m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}})
+func MSI(keyAndValuePairs ...interface{}) Map {
+
+ newMap := make(map[string]interface{})
+ keyAndValuePairsLen := len(keyAndValuePairs)
+
+ if keyAndValuePairsLen%2 != 0 {
+ panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.")
+ }
+
+ for i := 0; i < keyAndValuePairsLen; i = i + 2 {
+
+ key := keyAndValuePairs[i]
+ value := keyAndValuePairs[i+1]
+
+ // make sure the key is a string
+ keyString, keyStringOK := key.(string)
+ if !keyStringOK {
+ panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.")
+ }
+
+ newMap[keyString] = value
+
+ }
+
+ return New(newMap)
+}
+
+// ****** Conversion Constructors
+
+// MustFromJSON creates a new Map containing the data specified in the
+// jsonString.
+//
+// Panics if the JSON is invalid.
+func MustFromJSON(jsonString string) Map {
+ o, err := FromJSON(jsonString)
+
+ if err != nil {
+ panic("objx: MustFromJSON failed with error: " + err.Error())
+ }
+
+ return o
+}
+
+// FromJSON creates a new Map containing the data specified in the
+// jsonString.
+//
+// Returns an error if the JSON is invalid.
+func FromJSON(jsonString string) (Map, error) {
+
+ var data interface{}
+ err := json.Unmarshal([]byte(jsonString), &data)
+
+ if err != nil {
+ return Nil, err
+ }
+
+ return New(data), nil
+
+}
+
+// FromBase64 creates a new Obj containing the data specified
+// in the Base64 string.
+//
+// The string is an encoded JSON string returned by Base64
+func FromBase64(base64String string) (Map, error) {
+
+ decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String))
+
+ decoded, err := ioutil.ReadAll(decoder)
+ if err != nil {
+ return nil, err
+ }
+
+ return FromJSON(string(decoded))
+}
+
+// MustFromBase64 creates a new Obj containing the data specified
+// in the Base64 string and panics if there is an error.
+//
+// The string is an encoded JSON string returned by Base64
+func MustFromBase64(base64String string) Map {
+
+ result, err := FromBase64(base64String)
+
+ if err != nil {
+ panic("objx: MustFromBase64 failed with error: " + err.Error())
+ }
+
+ return result
+}
+
+// FromSignedBase64 creates a new Obj containing the data specified
+// in the Base64 string.
+//
+// The string is an encoded JSON string returned by SignedBase64
+func FromSignedBase64(base64String, key string) (Map, error) {
+ parts := strings.Split(base64String, SignatureSeparator)
+ if len(parts) != 2 {
+ return nil, errors.New("objx: Signed base64 string is malformed.")
+ }
+
+ sig := HashWithKey(parts[0], key)
+ if parts[1] != sig {
+ return nil, errors.New("objx: Signature for base64 data does not match.")
+ }
+
+ return FromBase64(parts[0])
+}
+
+// MustFromSignedBase64 creates a new Obj containing the data specified
+// in the Base64 string and panics if there is an error.
+//
+// The string is an encoded JSON string returned by Base64
+func MustFromSignedBase64(base64String, key string) Map {
+
+ result, err := FromSignedBase64(base64String, key)
+
+ if err != nil {
+ panic("objx: MustFromSignedBase64 failed with error: " + err.Error())
+ }
+
+ return result
+}
+
+// FromURLQuery generates a new Obj by parsing the specified
+// query.
+//
+// For queries with multiple values, the first value is selected.
+func FromURLQuery(query string) (Map, error) {
+
+ vals, err := url.ParseQuery(query)
+
+ if err != nil {
+ return nil, err
+ }
+
+ m := make(map[string]interface{})
+ for k, vals := range vals {
+ m[k] = vals[0]
+ }
+
+ return New(m), nil
+}
+
+// MustFromURLQuery generates a new Obj by parsing the specified
+// query.
+//
+// For queries with multiple values, the first value is selected.
+//
+// Panics if it encounters an error
+func MustFromURLQuery(query string) Map {
+
+ o, err := FromURLQuery(query)
+
+ if err != nil {
+ panic("objx: MustFromURLQuery failed with error: " + err.Error())
+ }
+
+ return o
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go
new file mode 100644
index 0000000000..6beb506756
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go
@@ -0,0 +1,10 @@
+package objx
+
+var TestMap map[string]interface{} = map[string]interface{}{
+ "name": "Tyler",
+ "address": map[string]interface{}{
+ "city": "Salt Lake City",
+ "state": "UT",
+ },
+ "numbers": []interface{}{"one", "two", "three", "four", "five"},
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go
new file mode 100644
index 0000000000..1f8b45c617
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go
@@ -0,0 +1,147 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+type Convertable struct {
+ name string
+}
+
+func (c *Convertable) MSI() map[string]interface{} {
+ return map[string]interface{}{"name": c.name}
+}
+
+type Unconvertable struct {
+ name string
+}
+
+func TestMapCreation(t *testing.T) {
+
+ o := New(nil)
+ assert.Nil(t, o)
+
+ o = New("Tyler")
+ assert.Nil(t, o)
+
+ unconvertable := &Unconvertable{name: "Tyler"}
+ o = New(unconvertable)
+ assert.Nil(t, o)
+
+ convertable := &Convertable{name: "Tyler"}
+ o = New(convertable)
+ if assert.NotNil(t, convertable) {
+ assert.Equal(t, "Tyler", o["name"], "Tyler")
+ }
+
+ o = MSI()
+ if assert.NotNil(t, o) {
+ assert.NotNil(t, o)
+ }
+
+ o = MSI("name", "Tyler")
+ if assert.NotNil(t, o) {
+ if assert.NotNil(t, o) {
+ assert.Equal(t, o["name"], "Tyler")
+ }
+ }
+
+}
+
+func TestMapMustFromJSONWithError(t *testing.T) {
+
+ _, err := FromJSON(`"name":"Mat"}`)
+ assert.Error(t, err)
+
+}
+
+func TestMapFromJSON(t *testing.T) {
+
+ o := MustFromJSON(`{"name":"Mat"}`)
+
+ if assert.NotNil(t, o) {
+ if assert.NotNil(t, o) {
+ assert.Equal(t, "Mat", o["name"])
+ }
+ }
+
+}
+
+func TestMapFromJSONWithError(t *testing.T) {
+
+ var m Map
+
+ assert.Panics(t, func() {
+ m = MustFromJSON(`"name":"Mat"}`)
+ })
+
+ assert.Nil(t, m)
+
+}
+
+func TestMapFromBase64String(t *testing.T) {
+
+ base64String := "eyJuYW1lIjoiTWF0In0="
+
+ o, err := FromBase64(base64String)
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, o.Get("name").Str(), "Mat")
+ }
+
+ assert.Equal(t, MustFromBase64(base64String).Get("name").Str(), "Mat")
+
+}
+
+func TestMapFromBase64StringWithError(t *testing.T) {
+
+ base64String := "eyJuYW1lIjoiTWFasd0In0="
+
+ _, err := FromBase64(base64String)
+
+ assert.Error(t, err)
+
+ assert.Panics(t, func() {
+ MustFromBase64(base64String)
+ })
+
+}
+
+func TestMapFromSignedBase64String(t *testing.T) {
+
+ base64String := "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
+
+ o, err := FromSignedBase64(base64String, "key")
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, o.Get("name").Str(), "Mat")
+ }
+
+ assert.Equal(t, MustFromSignedBase64(base64String, "key").Get("name").Str(), "Mat")
+
+}
+
+func TestMapFromSignedBase64StringWithError(t *testing.T) {
+
+ base64String := "eyJuYW1lasdIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
+
+ _, err := FromSignedBase64(base64String, "key")
+
+ assert.Error(t, err)
+
+ assert.Panics(t, func() {
+ MustFromSignedBase64(base64String, "key")
+ })
+
+}
+
+func TestMapFromURLQuery(t *testing.T) {
+
+ m, err := FromURLQuery("name=tyler&state=UT")
+ if assert.NoError(t, err) && assert.NotNil(t, m) {
+ assert.Equal(t, "tyler", m.Get("name").Str())
+ assert.Equal(t, "UT", m.Get("state").Str())
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go b/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go
new file mode 100644
index 0000000000..b35c86392b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go
@@ -0,0 +1,81 @@
+package objx
+
+// Exclude returns a new Map with the keys in the specified []string
+// excluded.
+func (d Map) Exclude(exclude []string) Map {
+
+ excluded := make(Map)
+ for k, v := range d {
+ var shouldInclude bool = true
+ for _, toExclude := range exclude {
+ if k == toExclude {
+ shouldInclude = false
+ break
+ }
+ }
+ if shouldInclude {
+ excluded[k] = v
+ }
+ }
+
+ return excluded
+}
+
+// Copy creates a shallow copy of the Obj.
+func (m Map) Copy() Map {
+ copied := make(map[string]interface{})
+ for k, v := range m {
+ copied[k] = v
+ }
+ return New(copied)
+}
+
+// Merge blends the specified map with a copy of this map and returns the result.
+//
+// Keys that appear in both will be selected from the specified map.
+// This method requires that the wrapped object be a map[string]interface{}
+func (m Map) Merge(merge Map) Map {
+ return m.Copy().MergeHere(merge)
+}
+
+// Merge blends the specified map with this map and returns the current map.
+//
+// Keys that appear in both will be selected from the specified map. The original map
+// will be modified. This method requires that
+// the wrapped object be a map[string]interface{}
+func (m Map) MergeHere(merge Map) Map {
+
+ for k, v := range merge {
+ m[k] = v
+ }
+
+ return m
+
+}
+
+// Transform builds a new Obj giving the transformer a chance
+// to change the keys and values as it goes. This method requires that
+// the wrapped object be a map[string]interface{}
+func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map {
+ newMap := make(map[string]interface{})
+ for k, v := range m {
+ modifiedKey, modifiedVal := transformer(k, v)
+ newMap[modifiedKey] = modifiedVal
+ }
+ return New(newMap)
+}
+
+// TransformKeys builds a new map using the specified key mapping.
+//
+// Unspecified keys will be unaltered.
+// This method requires that the wrapped object be a map[string]interface{}
+func (m Map) TransformKeys(mapping map[string]string) Map {
+ return m.Transform(func(key string, value interface{}) (string, interface{}) {
+
+ if newKey, ok := mapping[key]; ok {
+ return newKey, value
+ }
+
+ return key, value
+ })
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go
new file mode 100644
index 0000000000..e20ee23bc4
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go
@@ -0,0 +1,77 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestExclude(t *testing.T) {
+
+ d := make(Map)
+ d["name"] = "Mat"
+ d["age"] = 29
+ d["secret"] = "ABC"
+
+ excluded := d.Exclude([]string{"secret"})
+
+ assert.Equal(t, d["name"], excluded["name"])
+ assert.Equal(t, d["age"], excluded["age"])
+ assert.False(t, excluded.Has("secret"), "secret should be excluded")
+
+}
+
+func TestCopy(t *testing.T) {
+
+ d1 := make(map[string]interface{})
+ d1["name"] = "Tyler"
+ d1["location"] = "UT"
+
+ d1Obj := New(d1)
+ d2Obj := d1Obj.Copy()
+
+ d2Obj["name"] = "Mat"
+
+ assert.Equal(t, d1Obj.Get("name").Str(), "Tyler")
+ assert.Equal(t, d2Obj.Get("name").Str(), "Mat")
+
+}
+
+func TestMerge(t *testing.T) {
+
+ d := make(map[string]interface{})
+ d["name"] = "Mat"
+
+ d1 := make(map[string]interface{})
+ d1["name"] = "Tyler"
+ d1["location"] = "UT"
+
+ dObj := New(d)
+ d1Obj := New(d1)
+
+ merged := dObj.Merge(d1Obj)
+
+ assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str())
+ assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str())
+ assert.Empty(t, dObj.Get("location").Str())
+
+}
+
+func TestMergeHere(t *testing.T) {
+
+ d := make(map[string]interface{})
+ d["name"] = "Mat"
+
+ d1 := make(map[string]interface{})
+ d1["name"] = "Tyler"
+ d1["location"] = "UT"
+
+ dObj := New(d)
+ d1Obj := New(d1)
+
+ merged := dObj.MergeHere(d1Obj)
+
+ assert.Equal(t, dObj, merged, "With MergeHere, it should return the first modified map")
+ assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str())
+ assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str())
+ assert.Equal(t, merged.Get("location").Str(), dObj.Get("location").Str())
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/security.go b/Godeps/_workspace/src/github.com/stretchr/objx/security.go
new file mode 100644
index 0000000000..fdd6be9cfb
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/security.go
@@ -0,0 +1,14 @@
+package objx
+
+import (
+ "crypto/sha1"
+ "encoding/hex"
+)
+
+// HashWithKey hashes the specified string using the security
+// key.
+func HashWithKey(data, key string) string {
+ hash := sha1.New()
+ hash.Write([]byte(data + ":" + key))
+ return hex.EncodeToString(hash.Sum(nil))
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go
new file mode 100644
index 0000000000..8f0898f62c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go
@@ -0,0 +1,12 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestHashWithKey(t *testing.T) {
+
+ assert.Equal(t, "0ce84d8d01f2c7b6e0882b784429c54d280ea2d9", HashWithKey("abc", "def"))
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go
new file mode 100644
index 0000000000..5408c7fd3d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go
@@ -0,0 +1,41 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestSimpleExample(t *testing.T) {
+
+ // build a map from a JSON object
+ o := MustFromJSON(`{"name":"Mat","foods":["indian","chinese"], "location":{"county":"hobbiton","city":"the shire"}}`)
+
+ // Map can be used as a straight map[string]interface{}
+ assert.Equal(t, o["name"], "Mat")
+
+ // Get an Value object
+ v := o.Get("name")
+ assert.Equal(t, v, &Value{data: "Mat"})
+
+ // Test the contained value
+ assert.False(t, v.IsInt())
+ assert.False(t, v.IsBool())
+ assert.True(t, v.IsStr())
+
+ // Get the contained value
+ assert.Equal(t, v.Str(), "Mat")
+
+ // Get a default value if the contained value is not of the expected type or does not exist
+ assert.Equal(t, 1, v.Int(1))
+
+ // Get a value by using array notation
+ assert.Equal(t, "indian", o.Get("foods[0]").Data())
+
+ // Set a value by using array notation
+ o.Set("foods[0]", "italian")
+ assert.Equal(t, "italian", o.Get("foods[0]").Str())
+
+ // Get a value by using dot notation
+ assert.Equal(t, "hobbiton", o.Get("location.county").Str())
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/tests.go b/Godeps/_workspace/src/github.com/stretchr/objx/tests.go
new file mode 100644
index 0000000000..d9e0b479a4
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/tests.go
@@ -0,0 +1,17 @@
+package objx
+
+// Has gets whether there is something at the specified selector
+// or not.
+//
+// If m is nil, Has will always return false.
+func (m Map) Has(selector string) bool {
+ if m == nil {
+ return false
+ }
+ return !m.Get(selector).IsNil()
+}
+
+// IsNil gets whether the data is nil or not.
+func (v *Value) IsNil() bool {
+ return v == nil || v.data == nil
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go
new file mode 100644
index 0000000000..bcc1eb03d0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go
@@ -0,0 +1,24 @@
+package objx
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestHas(t *testing.T) {
+
+ m := New(TestMap)
+
+ assert.True(t, m.Has("name"))
+ assert.True(t, m.Has("address.state"))
+ assert.True(t, m.Has("numbers[4]"))
+
+ assert.False(t, m.Has("address.state.nope"))
+ assert.False(t, m.Has("address.nope"))
+ assert.False(t, m.Has("nope"))
+ assert.False(t, m.Has("numbers[5]"))
+
+ m = nil
+ assert.False(t, m.Has("nothing"))
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go
new file mode 100644
index 0000000000..f3ecb29b95
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go
@@ -0,0 +1,2881 @@
+package objx
+
+/*
+ Inter (interface{} and []interface{})
+ --------------------------------------------------
+*/
+
+// Inter gets the value as a interface{}, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Inter(optionalDefault ...interface{}) interface{} {
+ if s, ok := v.data.(interface{}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInter gets the value as a interface{}.
+//
+// Panics if the object is not a interface{}.
+func (v *Value) MustInter() interface{} {
+ return v.data.(interface{})
+}
+
+// InterSlice gets the value as a []interface{}, returns the optionalDefault
+// value or nil if the value is not a []interface{}.
+func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} {
+ if s, ok := v.data.([]interface{}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInterSlice gets the value as a []interface{}.
+//
+// Panics if the object is not a []interface{}.
+func (v *Value) MustInterSlice() []interface{} {
+ return v.data.([]interface{})
+}
+
+// IsInter gets whether the object contained is a interface{} or not.
+func (v *Value) IsInter() bool {
+ _, ok := v.data.(interface{})
+ return ok
+}
+
+// IsInterSlice gets whether the object contained is a []interface{} or not.
+func (v *Value) IsInterSlice() bool {
+ _, ok := v.data.([]interface{})
+ return ok
+}
+
+// EachInter calls the specified callback for each object
+// in the []interface{}.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInter(callback func(int, interface{}) bool) *Value {
+
+ for index, val := range v.MustInterSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInter uses the specified decider function to select items
+// from the []interface{}. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value {
+
+ var selected []interface{}
+
+ v.EachInter(func(index int, val interface{}) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInter uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]interface{}.
+func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value {
+
+ groups := make(map[string][]interface{})
+
+ v.EachInter(func(index int, val interface{}) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]interface{}, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInter uses the specified function to replace each interface{}s
+// by iterating each item. The data in the returned result will be a
+// []interface{} containing the replaced items.
+func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value {
+
+ arr := v.MustInterSlice()
+ replaced := make([]interface{}, len(arr))
+
+ v.EachInter(func(index int, val interface{}) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInter uses the specified collector function to collect a value
+// for each of the interface{}s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value {
+
+ arr := v.MustInterSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInter(func(index int, val interface{}) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ MSI (map[string]interface{} and []map[string]interface{})
+ --------------------------------------------------
+*/
+
+// MSI gets the value as a map[string]interface{}, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} {
+ if s, ok := v.data.(map[string]interface{}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustMSI gets the value as a map[string]interface{}.
+//
+// Panics if the object is not a map[string]interface{}.
+func (v *Value) MustMSI() map[string]interface{} {
+ return v.data.(map[string]interface{})
+}
+
+// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault
+// value or nil if the value is not a []map[string]interface{}.
+func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} {
+ if s, ok := v.data.([]map[string]interface{}); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustMSISlice gets the value as a []map[string]interface{}.
+//
+// Panics if the object is not a []map[string]interface{}.
+func (v *Value) MustMSISlice() []map[string]interface{} {
+ return v.data.([]map[string]interface{})
+}
+
+// IsMSI gets whether the object contained is a map[string]interface{} or not.
+func (v *Value) IsMSI() bool {
+ _, ok := v.data.(map[string]interface{})
+ return ok
+}
+
+// IsMSISlice gets whether the object contained is a []map[string]interface{} or not.
+func (v *Value) IsMSISlice() bool {
+ _, ok := v.data.([]map[string]interface{})
+ return ok
+}
+
+// EachMSI calls the specified callback for each object
+// in the []map[string]interface{}.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value {
+
+ for index, val := range v.MustMSISlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereMSI uses the specified decider function to select items
+// from the []map[string]interface{}. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value {
+
+ var selected []map[string]interface{}
+
+ v.EachMSI(func(index int, val map[string]interface{}) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupMSI uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]map[string]interface{}.
+func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value {
+
+ groups := make(map[string][]map[string]interface{})
+
+ v.EachMSI(func(index int, val map[string]interface{}) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]map[string]interface{}, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceMSI uses the specified function to replace each map[string]interface{}s
+// by iterating each item. The data in the returned result will be a
+// []map[string]interface{} containing the replaced items.
+func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value {
+
+ arr := v.MustMSISlice()
+ replaced := make([]map[string]interface{}, len(arr))
+
+ v.EachMSI(func(index int, val map[string]interface{}) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectMSI uses the specified collector function to collect a value
+// for each of the map[string]interface{}s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value {
+
+ arr := v.MustMSISlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachMSI(func(index int, val map[string]interface{}) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ ObjxMap ((Map) and [](Map))
+ --------------------------------------------------
+*/
+
+// ObjxMap gets the value as a (Map), returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {
+ if s, ok := v.data.((Map)); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return New(nil)
+}
+
+// MustObjxMap gets the value as a (Map).
+//
+// Panics if the object is not a (Map).
+func (v *Value) MustObjxMap() Map {
+ return v.data.((Map))
+}
+
+// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault
+// value or nil if the value is not a [](Map).
+func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) {
+ if s, ok := v.data.([](Map)); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustObjxMapSlice gets the value as a [](Map).
+//
+// Panics if the object is not a [](Map).
+func (v *Value) MustObjxMapSlice() [](Map) {
+ return v.data.([](Map))
+}
+
+// IsObjxMap gets whether the object contained is a (Map) or not.
+func (v *Value) IsObjxMap() bool {
+ _, ok := v.data.((Map))
+ return ok
+}
+
+// IsObjxMapSlice gets whether the object contained is a [](Map) or not.
+func (v *Value) IsObjxMapSlice() bool {
+ _, ok := v.data.([](Map))
+ return ok
+}
+
+// EachObjxMap calls the specified callback for each object
+// in the [](Map).
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value {
+
+ for index, val := range v.MustObjxMapSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereObjxMap uses the specified decider function to select items
+// from the [](Map). The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value {
+
+ var selected [](Map)
+
+ v.EachObjxMap(func(index int, val Map) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupObjxMap uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][](Map).
+func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value {
+
+ groups := make(map[string][](Map))
+
+ v.EachObjxMap(func(index int, val Map) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([](Map), 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceObjxMap uses the specified function to replace each (Map)s
+// by iterating each item. The data in the returned result will be a
+// [](Map) containing the replaced items.
+func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value {
+
+ arr := v.MustObjxMapSlice()
+ replaced := make([](Map), len(arr))
+
+ v.EachObjxMap(func(index int, val Map) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectObjxMap uses the specified collector function to collect a value
+// for each of the (Map)s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value {
+
+ arr := v.MustObjxMapSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachObjxMap(func(index int, val Map) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Bool (bool and []bool)
+ --------------------------------------------------
+*/
+
+// Bool gets the value as a bool, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Bool(optionalDefault ...bool) bool {
+ if s, ok := v.data.(bool); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return false
+}
+
+// MustBool gets the value as a bool.
+//
+// Panics if the object is not a bool.
+func (v *Value) MustBool() bool {
+ return v.data.(bool)
+}
+
+// BoolSlice gets the value as a []bool, returns the optionalDefault
+// value or nil if the value is not a []bool.
+func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool {
+ if s, ok := v.data.([]bool); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustBoolSlice gets the value as a []bool.
+//
+// Panics if the object is not a []bool.
+func (v *Value) MustBoolSlice() []bool {
+ return v.data.([]bool)
+}
+
+// IsBool gets whether the object contained is a bool or not.
+func (v *Value) IsBool() bool {
+ _, ok := v.data.(bool)
+ return ok
+}
+
+// IsBoolSlice gets whether the object contained is a []bool or not.
+func (v *Value) IsBoolSlice() bool {
+ _, ok := v.data.([]bool)
+ return ok
+}
+
+// EachBool calls the specified callback for each object
+// in the []bool.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachBool(callback func(int, bool) bool) *Value {
+
+ for index, val := range v.MustBoolSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereBool uses the specified decider function to select items
+// from the []bool. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereBool(decider func(int, bool) bool) *Value {
+
+ var selected []bool
+
+ v.EachBool(func(index int, val bool) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupBool uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]bool.
+func (v *Value) GroupBool(grouper func(int, bool) string) *Value {
+
+ groups := make(map[string][]bool)
+
+ v.EachBool(func(index int, val bool) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]bool, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceBool uses the specified function to replace each bools
+// by iterating each item. The data in the returned result will be a
+// []bool containing the replaced items.
+func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value {
+
+ arr := v.MustBoolSlice()
+ replaced := make([]bool, len(arr))
+
+ v.EachBool(func(index int, val bool) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectBool uses the specified collector function to collect a value
+// for each of the bools in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value {
+
+ arr := v.MustBoolSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachBool(func(index int, val bool) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Str (string and []string)
+ --------------------------------------------------
+*/
+
+// Str gets the value as a string, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Str(optionalDefault ...string) string {
+ if s, ok := v.data.(string); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return ""
+}
+
+// MustStr gets the value as a string.
+//
+// Panics if the object is not a string.
+func (v *Value) MustStr() string {
+ return v.data.(string)
+}
+
+// StrSlice gets the value as a []string, returns the optionalDefault
+// value or nil if the value is not a []string.
+func (v *Value) StrSlice(optionalDefault ...[]string) []string {
+ if s, ok := v.data.([]string); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustStrSlice gets the value as a []string.
+//
+// Panics if the object is not a []string.
+func (v *Value) MustStrSlice() []string {
+ return v.data.([]string)
+}
+
+// IsStr gets whether the object contained is a string or not.
+func (v *Value) IsStr() bool {
+ _, ok := v.data.(string)
+ return ok
+}
+
+// IsStrSlice gets whether the object contained is a []string or not.
+func (v *Value) IsStrSlice() bool {
+ _, ok := v.data.([]string)
+ return ok
+}
+
+// EachStr calls the specified callback for each object
+// in the []string.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachStr(callback func(int, string) bool) *Value {
+
+ for index, val := range v.MustStrSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereStr uses the specified decider function to select items
+// from the []string. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereStr(decider func(int, string) bool) *Value {
+
+ var selected []string
+
+ v.EachStr(func(index int, val string) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupStr uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]string.
+func (v *Value) GroupStr(grouper func(int, string) string) *Value {
+
+ groups := make(map[string][]string)
+
+ v.EachStr(func(index int, val string) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]string, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceStr uses the specified function to replace each strings
+// by iterating each item. The data in the returned result will be a
+// []string containing the replaced items.
+func (v *Value) ReplaceStr(replacer func(int, string) string) *Value {
+
+ arr := v.MustStrSlice()
+ replaced := make([]string, len(arr))
+
+ v.EachStr(func(index int, val string) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectStr uses the specified collector function to collect a value
+// for each of the strings in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectStr(collector func(int, string) interface{}) *Value {
+
+ arr := v.MustStrSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachStr(func(index int, val string) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Int (int and []int)
+ --------------------------------------------------
+*/
+
+// Int gets the value as a int, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Int(optionalDefault ...int) int {
+ if s, ok := v.data.(int); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustInt gets the value as a int.
+//
+// Panics if the object is not a int.
+func (v *Value) MustInt() int {
+ return v.data.(int)
+}
+
+// IntSlice gets the value as a []int, returns the optionalDefault
+// value or nil if the value is not a []int.
+func (v *Value) IntSlice(optionalDefault ...[]int) []int {
+ if s, ok := v.data.([]int); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustIntSlice gets the value as a []int.
+//
+// Panics if the object is not a []int.
+func (v *Value) MustIntSlice() []int {
+ return v.data.([]int)
+}
+
+// IsInt gets whether the object contained is a int or not.
+func (v *Value) IsInt() bool {
+ _, ok := v.data.(int)
+ return ok
+}
+
+// IsIntSlice gets whether the object contained is a []int or not.
+func (v *Value) IsIntSlice() bool {
+ _, ok := v.data.([]int)
+ return ok
+}
+
+// EachInt calls the specified callback for each object
+// in the []int.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInt(callback func(int, int) bool) *Value {
+
+ for index, val := range v.MustIntSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInt uses the specified decider function to select items
+// from the []int. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInt(decider func(int, int) bool) *Value {
+
+ var selected []int
+
+ v.EachInt(func(index int, val int) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInt uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]int.
+func (v *Value) GroupInt(grouper func(int, int) string) *Value {
+
+ groups := make(map[string][]int)
+
+ v.EachInt(func(index int, val int) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]int, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInt uses the specified function to replace each ints
+// by iterating each item. The data in the returned result will be a
+// []int containing the replaced items.
+func (v *Value) ReplaceInt(replacer func(int, int) int) *Value {
+
+ arr := v.MustIntSlice()
+ replaced := make([]int, len(arr))
+
+ v.EachInt(func(index int, val int) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInt uses the specified collector function to collect a value
+// for each of the ints in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInt(collector func(int, int) interface{}) *Value {
+
+ arr := v.MustIntSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInt(func(index int, val int) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Int8 (int8 and []int8)
+ --------------------------------------------------
+*/
+
+// Int8 gets the value as a int8, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Int8(optionalDefault ...int8) int8 {
+ if s, ok := v.data.(int8); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustInt8 gets the value as a int8.
+//
+// Panics if the object is not a int8.
+func (v *Value) MustInt8() int8 {
+ return v.data.(int8)
+}
+
+// Int8Slice gets the value as a []int8, returns the optionalDefault
+// value or nil if the value is not a []int8.
+func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 {
+ if s, ok := v.data.([]int8); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInt8Slice gets the value as a []int8.
+//
+// Panics if the object is not a []int8.
+func (v *Value) MustInt8Slice() []int8 {
+ return v.data.([]int8)
+}
+
+// IsInt8 gets whether the object contained is a int8 or not.
+func (v *Value) IsInt8() bool {
+ _, ok := v.data.(int8)
+ return ok
+}
+
+// IsInt8Slice gets whether the object contained is a []int8 or not.
+func (v *Value) IsInt8Slice() bool {
+ _, ok := v.data.([]int8)
+ return ok
+}
+
+// EachInt8 calls the specified callback for each object
+// in the []int8.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInt8(callback func(int, int8) bool) *Value {
+
+ for index, val := range v.MustInt8Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInt8 uses the specified decider function to select items
+// from the []int8. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInt8(decider func(int, int8) bool) *Value {
+
+ var selected []int8
+
+ v.EachInt8(func(index int, val int8) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInt8 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]int8.
+func (v *Value) GroupInt8(grouper func(int, int8) string) *Value {
+
+ groups := make(map[string][]int8)
+
+ v.EachInt8(func(index int, val int8) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]int8, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInt8 uses the specified function to replace each int8s
+// by iterating each item. The data in the returned result will be a
+// []int8 containing the replaced items.
+func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value {
+
+ arr := v.MustInt8Slice()
+ replaced := make([]int8, len(arr))
+
+ v.EachInt8(func(index int, val int8) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInt8 uses the specified collector function to collect a value
+// for each of the int8s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value {
+
+ arr := v.MustInt8Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInt8(func(index int, val int8) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Int16 (int16 and []int16)
+ --------------------------------------------------
+*/
+
+// Int16 gets the value as a int16, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Int16(optionalDefault ...int16) int16 {
+ if s, ok := v.data.(int16); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustInt16 gets the value as a int16.
+//
+// Panics if the object is not a int16.
+func (v *Value) MustInt16() int16 {
+ return v.data.(int16)
+}
+
+// Int16Slice gets the value as a []int16, returns the optionalDefault
+// value or nil if the value is not a []int16.
+func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 {
+ if s, ok := v.data.([]int16); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInt16Slice gets the value as a []int16.
+//
+// Panics if the object is not a []int16.
+func (v *Value) MustInt16Slice() []int16 {
+ return v.data.([]int16)
+}
+
+// IsInt16 gets whether the object contained is a int16 or not.
+func (v *Value) IsInt16() bool {
+ _, ok := v.data.(int16)
+ return ok
+}
+
+// IsInt16Slice gets whether the object contained is a []int16 or not.
+func (v *Value) IsInt16Slice() bool {
+ _, ok := v.data.([]int16)
+ return ok
+}
+
+// EachInt16 calls the specified callback for each object
+// in the []int16.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInt16(callback func(int, int16) bool) *Value {
+
+ for index, val := range v.MustInt16Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInt16 uses the specified decider function to select items
+// from the []int16. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInt16(decider func(int, int16) bool) *Value {
+
+ var selected []int16
+
+ v.EachInt16(func(index int, val int16) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInt16 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]int16.
+func (v *Value) GroupInt16(grouper func(int, int16) string) *Value {
+
+ groups := make(map[string][]int16)
+
+ v.EachInt16(func(index int, val int16) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]int16, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInt16 uses the specified function to replace each int16s
+// by iterating each item. The data in the returned result will be a
+// []int16 containing the replaced items.
+func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value {
+
+ arr := v.MustInt16Slice()
+ replaced := make([]int16, len(arr))
+
+ v.EachInt16(func(index int, val int16) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInt16 uses the specified collector function to collect a value
+// for each of the int16s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value {
+
+ arr := v.MustInt16Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInt16(func(index int, val int16) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Int32 (int32 and []int32)
+ --------------------------------------------------
+*/
+
+// Int32 gets the value as a int32, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Int32(optionalDefault ...int32) int32 {
+ if s, ok := v.data.(int32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustInt32 gets the value as a int32.
+//
+// Panics if the object is not a int32.
+func (v *Value) MustInt32() int32 {
+ return v.data.(int32)
+}
+
+// Int32Slice gets the value as a []int32, returns the optionalDefault
+// value or nil if the value is not a []int32.
+func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 {
+ if s, ok := v.data.([]int32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInt32Slice gets the value as a []int32.
+//
+// Panics if the object is not a []int32.
+func (v *Value) MustInt32Slice() []int32 {
+ return v.data.([]int32)
+}
+
+// IsInt32 gets whether the object contained is a int32 or not.
+func (v *Value) IsInt32() bool {
+ _, ok := v.data.(int32)
+ return ok
+}
+
+// IsInt32Slice gets whether the object contained is a []int32 or not.
+func (v *Value) IsInt32Slice() bool {
+ _, ok := v.data.([]int32)
+ return ok
+}
+
+// EachInt32 calls the specified callback for each object
+// in the []int32.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInt32(callback func(int, int32) bool) *Value {
+
+ for index, val := range v.MustInt32Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInt32 uses the specified decider function to select items
+// from the []int32. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInt32(decider func(int, int32) bool) *Value {
+
+ var selected []int32
+
+ v.EachInt32(func(index int, val int32) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInt32 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]int32.
+func (v *Value) GroupInt32(grouper func(int, int32) string) *Value {
+
+ groups := make(map[string][]int32)
+
+ v.EachInt32(func(index int, val int32) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]int32, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInt32 uses the specified function to replace each int32s
+// by iterating each item. The data in the returned result will be a
+// []int32 containing the replaced items.
+func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value {
+
+ arr := v.MustInt32Slice()
+ replaced := make([]int32, len(arr))
+
+ v.EachInt32(func(index int, val int32) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInt32 uses the specified collector function to collect a value
+// for each of the int32s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value {
+
+ arr := v.MustInt32Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInt32(func(index int, val int32) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Int64 (int64 and []int64)
+ --------------------------------------------------
+*/
+
+// Int64 gets the value as a int64, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Int64(optionalDefault ...int64) int64 {
+ if s, ok := v.data.(int64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustInt64 gets the value as a int64.
+//
+// Panics if the object is not a int64.
+func (v *Value) MustInt64() int64 {
+ return v.data.(int64)
+}
+
+// Int64Slice gets the value as a []int64, returns the optionalDefault
+// value or nil if the value is not a []int64.
+func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 {
+ if s, ok := v.data.([]int64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustInt64Slice gets the value as a []int64.
+//
+// Panics if the object is not a []int64.
+func (v *Value) MustInt64Slice() []int64 {
+ return v.data.([]int64)
+}
+
+// IsInt64 gets whether the object contained is a int64 or not.
+func (v *Value) IsInt64() bool {
+ _, ok := v.data.(int64)
+ return ok
+}
+
+// IsInt64Slice gets whether the object contained is a []int64 or not.
+func (v *Value) IsInt64Slice() bool {
+ _, ok := v.data.([]int64)
+ return ok
+}
+
+// EachInt64 calls the specified callback for each object
+// in the []int64.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachInt64(callback func(int, int64) bool) *Value {
+
+ for index, val := range v.MustInt64Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereInt64 uses the specified decider function to select items
+// from the []int64. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereInt64(decider func(int, int64) bool) *Value {
+
+ var selected []int64
+
+ v.EachInt64(func(index int, val int64) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupInt64 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]int64.
+func (v *Value) GroupInt64(grouper func(int, int64) string) *Value {
+
+ groups := make(map[string][]int64)
+
+ v.EachInt64(func(index int, val int64) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]int64, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceInt64 uses the specified function to replace each int64s
+// by iterating each item. The data in the returned result will be a
+// []int64 containing the replaced items.
+func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value {
+
+ arr := v.MustInt64Slice()
+ replaced := make([]int64, len(arr))
+
+ v.EachInt64(func(index int, val int64) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectInt64 uses the specified collector function to collect a value
+// for each of the int64s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value {
+
+ arr := v.MustInt64Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachInt64(func(index int, val int64) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uint (uint and []uint)
+ --------------------------------------------------
+*/
+
+// Uint gets the value as a uint, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uint(optionalDefault ...uint) uint {
+ if s, ok := v.data.(uint); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUint gets the value as a uint.
+//
+// Panics if the object is not a uint.
+func (v *Value) MustUint() uint {
+ return v.data.(uint)
+}
+
+// UintSlice gets the value as a []uint, returns the optionalDefault
+// value or nil if the value is not a []uint.
+func (v *Value) UintSlice(optionalDefault ...[]uint) []uint {
+ if s, ok := v.data.([]uint); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUintSlice gets the value as a []uint.
+//
+// Panics if the object is not a []uint.
+func (v *Value) MustUintSlice() []uint {
+ return v.data.([]uint)
+}
+
+// IsUint gets whether the object contained is a uint or not.
+func (v *Value) IsUint() bool {
+ _, ok := v.data.(uint)
+ return ok
+}
+
+// IsUintSlice gets whether the object contained is a []uint or not.
+func (v *Value) IsUintSlice() bool {
+ _, ok := v.data.([]uint)
+ return ok
+}
+
+// EachUint calls the specified callback for each object
+// in the []uint.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUint(callback func(int, uint) bool) *Value {
+
+ for index, val := range v.MustUintSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUint uses the specified decider function to select items
+// from the []uint. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUint(decider func(int, uint) bool) *Value {
+
+ var selected []uint
+
+ v.EachUint(func(index int, val uint) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUint uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uint.
+func (v *Value) GroupUint(grouper func(int, uint) string) *Value {
+
+ groups := make(map[string][]uint)
+
+ v.EachUint(func(index int, val uint) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uint, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUint uses the specified function to replace each uints
+// by iterating each item. The data in the returned result will be a
+// []uint containing the replaced items.
+func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value {
+
+ arr := v.MustUintSlice()
+ replaced := make([]uint, len(arr))
+
+ v.EachUint(func(index int, val uint) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUint uses the specified collector function to collect a value
+// for each of the uints in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value {
+
+ arr := v.MustUintSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUint(func(index int, val uint) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uint8 (uint8 and []uint8)
+ --------------------------------------------------
+*/
+
+// Uint8 gets the value as a uint8, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uint8(optionalDefault ...uint8) uint8 {
+ if s, ok := v.data.(uint8); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUint8 gets the value as a uint8.
+//
+// Panics if the object is not a uint8.
+func (v *Value) MustUint8() uint8 {
+ return v.data.(uint8)
+}
+
+// Uint8Slice gets the value as a []uint8, returns the optionalDefault
+// value or nil if the value is not a []uint8.
+func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 {
+ if s, ok := v.data.([]uint8); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUint8Slice gets the value as a []uint8.
+//
+// Panics if the object is not a []uint8.
+func (v *Value) MustUint8Slice() []uint8 {
+ return v.data.([]uint8)
+}
+
+// IsUint8 gets whether the object contained is a uint8 or not.
+func (v *Value) IsUint8() bool {
+ _, ok := v.data.(uint8)
+ return ok
+}
+
+// IsUint8Slice gets whether the object contained is a []uint8 or not.
+func (v *Value) IsUint8Slice() bool {
+ _, ok := v.data.([]uint8)
+ return ok
+}
+
+// EachUint8 calls the specified callback for each object
+// in the []uint8.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUint8(callback func(int, uint8) bool) *Value {
+
+ for index, val := range v.MustUint8Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUint8 uses the specified decider function to select items
+// from the []uint8. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value {
+
+ var selected []uint8
+
+ v.EachUint8(func(index int, val uint8) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUint8 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uint8.
+func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value {
+
+ groups := make(map[string][]uint8)
+
+ v.EachUint8(func(index int, val uint8) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uint8, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUint8 uses the specified function to replace each uint8s
+// by iterating each item. The data in the returned result will be a
+// []uint8 containing the replaced items.
+func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value {
+
+ arr := v.MustUint8Slice()
+ replaced := make([]uint8, len(arr))
+
+ v.EachUint8(func(index int, val uint8) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUint8 uses the specified collector function to collect a value
+// for each of the uint8s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value {
+
+ arr := v.MustUint8Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUint8(func(index int, val uint8) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uint16 (uint16 and []uint16)
+ --------------------------------------------------
+*/
+
+// Uint16 gets the value as a uint16, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uint16(optionalDefault ...uint16) uint16 {
+ if s, ok := v.data.(uint16); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUint16 gets the value as a uint16.
+//
+// Panics if the object is not a uint16.
+func (v *Value) MustUint16() uint16 {
+ return v.data.(uint16)
+}
+
+// Uint16Slice gets the value as a []uint16, returns the optionalDefault
+// value or nil if the value is not a []uint16.
+func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 {
+ if s, ok := v.data.([]uint16); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUint16Slice gets the value as a []uint16.
+//
+// Panics if the object is not a []uint16.
+func (v *Value) MustUint16Slice() []uint16 {
+ return v.data.([]uint16)
+}
+
+// IsUint16 gets whether the object contained is a uint16 or not.
+func (v *Value) IsUint16() bool {
+ _, ok := v.data.(uint16)
+ return ok
+}
+
+// IsUint16Slice gets whether the object contained is a []uint16 or not.
+func (v *Value) IsUint16Slice() bool {
+ _, ok := v.data.([]uint16)
+ return ok
+}
+
+// EachUint16 calls the specified callback for each object
+// in the []uint16.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUint16(callback func(int, uint16) bool) *Value {
+
+ for index, val := range v.MustUint16Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUint16 uses the specified decider function to select items
+// from the []uint16. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value {
+
+ var selected []uint16
+
+ v.EachUint16(func(index int, val uint16) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUint16 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uint16.
+func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value {
+
+ groups := make(map[string][]uint16)
+
+ v.EachUint16(func(index int, val uint16) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uint16, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUint16 uses the specified function to replace each uint16s
+// by iterating each item. The data in the returned result will be a
+// []uint16 containing the replaced items.
+func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value {
+
+ arr := v.MustUint16Slice()
+ replaced := make([]uint16, len(arr))
+
+ v.EachUint16(func(index int, val uint16) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUint16 uses the specified collector function to collect a value
+// for each of the uint16s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value {
+
+ arr := v.MustUint16Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUint16(func(index int, val uint16) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uint32 (uint32 and []uint32)
+ --------------------------------------------------
+*/
+
+// Uint32 gets the value as a uint32, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uint32(optionalDefault ...uint32) uint32 {
+ if s, ok := v.data.(uint32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUint32 gets the value as a uint32.
+//
+// Panics if the object is not a uint32.
+func (v *Value) MustUint32() uint32 {
+ return v.data.(uint32)
+}
+
+// Uint32Slice gets the value as a []uint32, returns the optionalDefault
+// value or nil if the value is not a []uint32.
+func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 {
+ if s, ok := v.data.([]uint32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUint32Slice gets the value as a []uint32.
+//
+// Panics if the object is not a []uint32.
+func (v *Value) MustUint32Slice() []uint32 {
+ return v.data.([]uint32)
+}
+
+// IsUint32 gets whether the object contained is a uint32 or not.
+func (v *Value) IsUint32() bool {
+ _, ok := v.data.(uint32)
+ return ok
+}
+
+// IsUint32Slice gets whether the object contained is a []uint32 or not.
+func (v *Value) IsUint32Slice() bool {
+ _, ok := v.data.([]uint32)
+ return ok
+}
+
+// EachUint32 calls the specified callback for each object
+// in the []uint32.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUint32(callback func(int, uint32) bool) *Value {
+
+ for index, val := range v.MustUint32Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUint32 uses the specified decider function to select items
+// from the []uint32. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value {
+
+ var selected []uint32
+
+ v.EachUint32(func(index int, val uint32) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUint32 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uint32.
+func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value {
+
+ groups := make(map[string][]uint32)
+
+ v.EachUint32(func(index int, val uint32) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uint32, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUint32 uses the specified function to replace each uint32s
+// by iterating each item. The data in the returned result will be a
+// []uint32 containing the replaced items.
+func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value {
+
+ arr := v.MustUint32Slice()
+ replaced := make([]uint32, len(arr))
+
+ v.EachUint32(func(index int, val uint32) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUint32 uses the specified collector function to collect a value
+// for each of the uint32s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value {
+
+ arr := v.MustUint32Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUint32(func(index int, val uint32) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uint64 (uint64 and []uint64)
+ --------------------------------------------------
+*/
+
+// Uint64 gets the value as a uint64, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uint64(optionalDefault ...uint64) uint64 {
+ if s, ok := v.data.(uint64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUint64 gets the value as a uint64.
+//
+// Panics if the object is not a uint64.
+func (v *Value) MustUint64() uint64 {
+ return v.data.(uint64)
+}
+
+// Uint64Slice gets the value as a []uint64, returns the optionalDefault
+// value or nil if the value is not a []uint64.
+func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 {
+ if s, ok := v.data.([]uint64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUint64Slice gets the value as a []uint64.
+//
+// Panics if the object is not a []uint64.
+func (v *Value) MustUint64Slice() []uint64 {
+ return v.data.([]uint64)
+}
+
+// IsUint64 gets whether the object contained is a uint64 or not.
+func (v *Value) IsUint64() bool {
+ _, ok := v.data.(uint64)
+ return ok
+}
+
+// IsUint64Slice gets whether the object contained is a []uint64 or not.
+func (v *Value) IsUint64Slice() bool {
+ _, ok := v.data.([]uint64)
+ return ok
+}
+
+// EachUint64 calls the specified callback for each object
+// in the []uint64.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUint64(callback func(int, uint64) bool) *Value {
+
+ for index, val := range v.MustUint64Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUint64 uses the specified decider function to select items
+// from the []uint64. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value {
+
+ var selected []uint64
+
+ v.EachUint64(func(index int, val uint64) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUint64 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uint64.
+func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value {
+
+ groups := make(map[string][]uint64)
+
+ v.EachUint64(func(index int, val uint64) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uint64, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUint64 uses the specified function to replace each uint64s
+// by iterating each item. The data in the returned result will be a
+// []uint64 containing the replaced items.
+func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value {
+
+ arr := v.MustUint64Slice()
+ replaced := make([]uint64, len(arr))
+
+ v.EachUint64(func(index int, val uint64) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUint64 uses the specified collector function to collect a value
+// for each of the uint64s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value {
+
+ arr := v.MustUint64Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUint64(func(index int, val uint64) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Uintptr (uintptr and []uintptr)
+ --------------------------------------------------
+*/
+
+// Uintptr gets the value as a uintptr, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr {
+ if s, ok := v.data.(uintptr); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustUintptr gets the value as a uintptr.
+//
+// Panics if the object is not a uintptr.
+func (v *Value) MustUintptr() uintptr {
+ return v.data.(uintptr)
+}
+
+// UintptrSlice gets the value as a []uintptr, returns the optionalDefault
+// value or nil if the value is not a []uintptr.
+func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr {
+ if s, ok := v.data.([]uintptr); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustUintptrSlice gets the value as a []uintptr.
+//
+// Panics if the object is not a []uintptr.
+func (v *Value) MustUintptrSlice() []uintptr {
+ return v.data.([]uintptr)
+}
+
+// IsUintptr gets whether the object contained is a uintptr or not.
+func (v *Value) IsUintptr() bool {
+ _, ok := v.data.(uintptr)
+ return ok
+}
+
+// IsUintptrSlice gets whether the object contained is a []uintptr or not.
+func (v *Value) IsUintptrSlice() bool {
+ _, ok := v.data.([]uintptr)
+ return ok
+}
+
+// EachUintptr calls the specified callback for each object
+// in the []uintptr.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value {
+
+ for index, val := range v.MustUintptrSlice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereUintptr uses the specified decider function to select items
+// from the []uintptr. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value {
+
+ var selected []uintptr
+
+ v.EachUintptr(func(index int, val uintptr) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupUintptr uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]uintptr.
+func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value {
+
+ groups := make(map[string][]uintptr)
+
+ v.EachUintptr(func(index int, val uintptr) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]uintptr, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceUintptr uses the specified function to replace each uintptrs
+// by iterating each item. The data in the returned result will be a
+// []uintptr containing the replaced items.
+func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value {
+
+ arr := v.MustUintptrSlice()
+ replaced := make([]uintptr, len(arr))
+
+ v.EachUintptr(func(index int, val uintptr) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectUintptr uses the specified collector function to collect a value
+// for each of the uintptrs in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value {
+
+ arr := v.MustUintptrSlice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachUintptr(func(index int, val uintptr) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Float32 (float32 and []float32)
+ --------------------------------------------------
+*/
+
+// Float32 gets the value as a float32, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Float32(optionalDefault ...float32) float32 {
+ if s, ok := v.data.(float32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustFloat32 gets the value as a float32.
+//
+// Panics if the object is not a float32.
+func (v *Value) MustFloat32() float32 {
+ return v.data.(float32)
+}
+
+// Float32Slice gets the value as a []float32, returns the optionalDefault
+// value or nil if the value is not a []float32.
+func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 {
+ if s, ok := v.data.([]float32); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustFloat32Slice gets the value as a []float32.
+//
+// Panics if the object is not a []float32.
+func (v *Value) MustFloat32Slice() []float32 {
+ return v.data.([]float32)
+}
+
+// IsFloat32 gets whether the object contained is a float32 or not.
+func (v *Value) IsFloat32() bool {
+ _, ok := v.data.(float32)
+ return ok
+}
+
+// IsFloat32Slice gets whether the object contained is a []float32 or not.
+func (v *Value) IsFloat32Slice() bool {
+ _, ok := v.data.([]float32)
+ return ok
+}
+
+// EachFloat32 calls the specified callback for each object
+// in the []float32.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachFloat32(callback func(int, float32) bool) *Value {
+
+ for index, val := range v.MustFloat32Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereFloat32 uses the specified decider function to select items
+// from the []float32. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value {
+
+ var selected []float32
+
+ v.EachFloat32(func(index int, val float32) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupFloat32 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]float32.
+func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value {
+
+ groups := make(map[string][]float32)
+
+ v.EachFloat32(func(index int, val float32) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]float32, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceFloat32 uses the specified function to replace each float32s
+// by iterating each item. The data in the returned result will be a
+// []float32 containing the replaced items.
+func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value {
+
+ arr := v.MustFloat32Slice()
+ replaced := make([]float32, len(arr))
+
+ v.EachFloat32(func(index int, val float32) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectFloat32 uses the specified collector function to collect a value
+// for each of the float32s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value {
+
+ arr := v.MustFloat32Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachFloat32(func(index int, val float32) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Float64 (float64 and []float64)
+ --------------------------------------------------
+*/
+
+// Float64 gets the value as a float64, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Float64(optionalDefault ...float64) float64 {
+ if s, ok := v.data.(float64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustFloat64 gets the value as a float64.
+//
+// Panics if the object is not a float64.
+func (v *Value) MustFloat64() float64 {
+ return v.data.(float64)
+}
+
+// Float64Slice gets the value as a []float64, returns the optionalDefault
+// value or nil if the value is not a []float64.
+func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 {
+ if s, ok := v.data.([]float64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustFloat64Slice gets the value as a []float64.
+//
+// Panics if the object is not a []float64.
+func (v *Value) MustFloat64Slice() []float64 {
+ return v.data.([]float64)
+}
+
+// IsFloat64 gets whether the object contained is a float64 or not.
+func (v *Value) IsFloat64() bool {
+ _, ok := v.data.(float64)
+ return ok
+}
+
+// IsFloat64Slice gets whether the object contained is a []float64 or not.
+func (v *Value) IsFloat64Slice() bool {
+ _, ok := v.data.([]float64)
+ return ok
+}
+
+// EachFloat64 calls the specified callback for each object
+// in the []float64.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachFloat64(callback func(int, float64) bool) *Value {
+
+ for index, val := range v.MustFloat64Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereFloat64 uses the specified decider function to select items
+// from the []float64. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value {
+
+ var selected []float64
+
+ v.EachFloat64(func(index int, val float64) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupFloat64 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]float64.
+func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value {
+
+ groups := make(map[string][]float64)
+
+ v.EachFloat64(func(index int, val float64) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]float64, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceFloat64 uses the specified function to replace each float64s
+// by iterating each item. The data in the returned result will be a
+// []float64 containing the replaced items.
+func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value {
+
+ arr := v.MustFloat64Slice()
+ replaced := make([]float64, len(arr))
+
+ v.EachFloat64(func(index int, val float64) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectFloat64 uses the specified collector function to collect a value
+// for each of the float64s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value {
+
+ arr := v.MustFloat64Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachFloat64(func(index int, val float64) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Complex64 (complex64 and []complex64)
+ --------------------------------------------------
+*/
+
+// Complex64 gets the value as a complex64, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Complex64(optionalDefault ...complex64) complex64 {
+ if s, ok := v.data.(complex64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustComplex64 gets the value as a complex64.
+//
+// Panics if the object is not a complex64.
+func (v *Value) MustComplex64() complex64 {
+ return v.data.(complex64)
+}
+
+// Complex64Slice gets the value as a []complex64, returns the optionalDefault
+// value or nil if the value is not a []complex64.
+func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 {
+ if s, ok := v.data.([]complex64); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustComplex64Slice gets the value as a []complex64.
+//
+// Panics if the object is not a []complex64.
+func (v *Value) MustComplex64Slice() []complex64 {
+ return v.data.([]complex64)
+}
+
+// IsComplex64 gets whether the object contained is a complex64 or not.
+func (v *Value) IsComplex64() bool {
+ _, ok := v.data.(complex64)
+ return ok
+}
+
+// IsComplex64Slice gets whether the object contained is a []complex64 or not.
+func (v *Value) IsComplex64Slice() bool {
+ _, ok := v.data.([]complex64)
+ return ok
+}
+
+// EachComplex64 calls the specified callback for each object
+// in the []complex64.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value {
+
+ for index, val := range v.MustComplex64Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereComplex64 uses the specified decider function to select items
+// from the []complex64. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value {
+
+ var selected []complex64
+
+ v.EachComplex64(func(index int, val complex64) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupComplex64 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]complex64.
+func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value {
+
+ groups := make(map[string][]complex64)
+
+ v.EachComplex64(func(index int, val complex64) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]complex64, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceComplex64 uses the specified function to replace each complex64s
+// by iterating each item. The data in the returned result will be a
+// []complex64 containing the replaced items.
+func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value {
+
+ arr := v.MustComplex64Slice()
+ replaced := make([]complex64, len(arr))
+
+ v.EachComplex64(func(index int, val complex64) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectComplex64 uses the specified collector function to collect a value
+// for each of the complex64s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value {
+
+ arr := v.MustComplex64Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachComplex64(func(index int, val complex64) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
+
+/*
+ Complex128 (complex128 and []complex128)
+ --------------------------------------------------
+*/
+
+// Complex128 gets the value as a complex128, returns the optionalDefault
+// value or a system default object if the value is the wrong type.
+func (v *Value) Complex128(optionalDefault ...complex128) complex128 {
+ if s, ok := v.data.(complex128); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return 0
+}
+
+// MustComplex128 gets the value as a complex128.
+//
+// Panics if the object is not a complex128.
+func (v *Value) MustComplex128() complex128 {
+ return v.data.(complex128)
+}
+
+// Complex128Slice gets the value as a []complex128, returns the optionalDefault
+// value or nil if the value is not a []complex128.
+func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 {
+ if s, ok := v.data.([]complex128); ok {
+ return s
+ }
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ }
+ return nil
+}
+
+// MustComplex128Slice gets the value as a []complex128.
+//
+// Panics if the object is not a []complex128.
+func (v *Value) MustComplex128Slice() []complex128 {
+ return v.data.([]complex128)
+}
+
+// IsComplex128 gets whether the object contained is a complex128 or not.
+func (v *Value) IsComplex128() bool {
+ _, ok := v.data.(complex128)
+ return ok
+}
+
+// IsComplex128Slice gets whether the object contained is a []complex128 or not.
+func (v *Value) IsComplex128Slice() bool {
+ _, ok := v.data.([]complex128)
+ return ok
+}
+
+// EachComplex128 calls the specified callback for each object
+// in the []complex128.
+//
+// Panics if the object is the wrong type.
+func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value {
+
+ for index, val := range v.MustComplex128Slice() {
+ carryon := callback(index, val)
+ if carryon == false {
+ break
+ }
+ }
+
+ return v
+
+}
+
+// WhereComplex128 uses the specified decider function to select items
+// from the []complex128. The object contained in the result will contain
+// only the selected items.
+func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value {
+
+ var selected []complex128
+
+ v.EachComplex128(func(index int, val complex128) bool {
+ shouldSelect := decider(index, val)
+ if shouldSelect == false {
+ selected = append(selected, val)
+ }
+ return true
+ })
+
+ return &Value{data: selected}
+
+}
+
+// GroupComplex128 uses the specified grouper function to group the items
+// keyed by the return of the grouper. The object contained in the
+// result will contain a map[string][]complex128.
+func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value {
+
+ groups := make(map[string][]complex128)
+
+ v.EachComplex128(func(index int, val complex128) bool {
+ group := grouper(index, val)
+ if _, ok := groups[group]; !ok {
+ groups[group] = make([]complex128, 0)
+ }
+ groups[group] = append(groups[group], val)
+ return true
+ })
+
+ return &Value{data: groups}
+
+}
+
+// ReplaceComplex128 uses the specified function to replace each complex128s
+// by iterating each item. The data in the returned result will be a
+// []complex128 containing the replaced items.
+func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value {
+
+ arr := v.MustComplex128Slice()
+ replaced := make([]complex128, len(arr))
+
+ v.EachComplex128(func(index int, val complex128) bool {
+ replaced[index] = replacer(index, val)
+ return true
+ })
+
+ return &Value{data: replaced}
+
+}
+
+// CollectComplex128 uses the specified collector function to collect a value
+// for each of the complex128s in the slice. The data returned will be a
+// []interface{}.
+func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value {
+
+ arr := v.MustComplex128Slice()
+ collected := make([]interface{}, len(arr))
+
+ v.EachComplex128(func(index int, val complex128) bool {
+ collected[index] = collector(index, val)
+ return true
+ })
+
+ return &Value{data: collected}
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go
new file mode 100644
index 0000000000..f7a4fceea3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go
@@ -0,0 +1,2867 @@
+package objx
+
+import (
+ "fmt"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInter(t *testing.T) {
+
+ val := interface{}("something")
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Inter())
+ assert.Equal(t, val, New(m).Get("value").MustInter())
+ assert.Equal(t, interface{}(nil), New(m).Get("nothing").Inter())
+ assert.Equal(t, val, New(m).Get("nothing").Inter("something"))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInter()
+ })
+
+}
+
+func TestInterSlice(t *testing.T) {
+
+ val := interface{}("something")
+ m := map[string]interface{}{"value": []interface{}{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").InterSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustInterSlice()[0])
+ assert.Equal(t, []interface{}(nil), New(m).Get("nothing").InterSlice())
+ assert.Equal(t, val, New(m).Get("nothing").InterSlice([]interface{}{interface{}("something")})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustInterSlice()
+ })
+
+}
+
+func TestIsInter(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: interface{}("something")}
+ assert.True(t, v.IsInter())
+
+ v = &Value{data: []interface{}{interface{}("something")}}
+ assert.True(t, v.IsInterSlice())
+
+}
+
+func TestEachInter(t *testing.T) {
+
+ v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ count := 0
+ replacedVals := make([]interface{}, 0)
+ assert.Equal(t, v, v.EachInter(func(i int, val interface{}) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustInterSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustInterSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustInterSlice()[2])
+
+}
+
+func TestWhereInter(t *testing.T) {
+
+ v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+
+ selected := v.WhereInter(func(i int, val interface{}) bool {
+ return i%2 == 0
+ }).MustInterSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInter(t *testing.T) {
+
+ v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+
+ grouped := v.GroupInter(func(i int, val interface{}) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]interface{})
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInter(t *testing.T) {
+
+ v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+
+ rawArr := v.MustInterSlice()
+
+ replaced := v.ReplaceInter(func(index int, val interface{}) interface{} {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustInterSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInter(t *testing.T) {
+
+ v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+
+ collected := v.CollectInter(func(index int, val interface{}) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestMSI(t *testing.T) {
+
+ val := map[string]interface{}(map[string]interface{}{"name": "Tyler"})
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").MSI())
+ assert.Equal(t, val, New(m).Get("value").MustMSI())
+ assert.Equal(t, map[string]interface{}(nil), New(m).Get("nothing").MSI())
+ assert.Equal(t, val, New(m).Get("nothing").MSI(map[string]interface{}{"name": "Tyler"}))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustMSI()
+ })
+
+}
+
+func TestMSISlice(t *testing.T) {
+
+ val := map[string]interface{}(map[string]interface{}{"name": "Tyler"})
+ m := map[string]interface{}{"value": []map[string]interface{}{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").MSISlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustMSISlice()[0])
+ assert.Equal(t, []map[string]interface{}(nil), New(m).Get("nothing").MSISlice())
+ assert.Equal(t, val, New(m).Get("nothing").MSISlice([]map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustMSISlice()
+ })
+
+}
+
+func TestIsMSI(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: map[string]interface{}(map[string]interface{}{"name": "Tyler"})}
+ assert.True(t, v.IsMSI())
+
+ v = &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+ assert.True(t, v.IsMSISlice())
+
+}
+
+func TestEachMSI(t *testing.T) {
+
+ v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+ count := 0
+ replacedVals := make([]map[string]interface{}, 0)
+ assert.Equal(t, v, v.EachMSI(func(i int, val map[string]interface{}) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustMSISlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustMSISlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustMSISlice()[2])
+
+}
+
+func TestWhereMSI(t *testing.T) {
+
+ v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+
+ selected := v.WhereMSI(func(i int, val map[string]interface{}) bool {
+ return i%2 == 0
+ }).MustMSISlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupMSI(t *testing.T) {
+
+ v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+
+ grouped := v.GroupMSI(func(i int, val map[string]interface{}) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]map[string]interface{})
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceMSI(t *testing.T) {
+
+ v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+
+ rawArr := v.MustMSISlice()
+
+ replaced := v.ReplaceMSI(func(index int, val map[string]interface{}) map[string]interface{} {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustMSISlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectMSI(t *testing.T) {
+
+ v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}}
+
+ collected := v.CollectMSI(func(index int, val map[string]interface{}) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestObjxMap(t *testing.T) {
+
+ val := (Map)(New(1))
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").ObjxMap())
+ assert.Equal(t, val, New(m).Get("value").MustObjxMap())
+ assert.Equal(t, (Map)(New(nil)), New(m).Get("nothing").ObjxMap())
+ assert.Equal(t, val, New(m).Get("nothing").ObjxMap(New(1)))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustObjxMap()
+ })
+
+}
+
+func TestObjxMapSlice(t *testing.T) {
+
+ val := (Map)(New(1))
+ m := map[string]interface{}{"value": [](Map){val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").ObjxMapSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustObjxMapSlice()[0])
+ assert.Equal(t, [](Map)(nil), New(m).Get("nothing").ObjxMapSlice())
+ assert.Equal(t, val, New(m).Get("nothing").ObjxMapSlice([](Map){(Map)(New(1))})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustObjxMapSlice()
+ })
+
+}
+
+func TestIsObjxMap(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: (Map)(New(1))}
+ assert.True(t, v.IsObjxMap())
+
+ v = &Value{data: [](Map){(Map)(New(1))}}
+ assert.True(t, v.IsObjxMapSlice())
+
+}
+
+func TestEachObjxMap(t *testing.T) {
+
+ v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
+ count := 0
+ replacedVals := make([](Map), 0)
+ assert.Equal(t, v, v.EachObjxMap(func(i int, val Map) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustObjxMapSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustObjxMapSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustObjxMapSlice()[2])
+
+}
+
+func TestWhereObjxMap(t *testing.T) {
+
+ v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
+
+ selected := v.WhereObjxMap(func(i int, val Map) bool {
+ return i%2 == 0
+ }).MustObjxMapSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupObjxMap(t *testing.T) {
+
+ v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
+
+ grouped := v.GroupObjxMap(func(i int, val Map) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][](Map))
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceObjxMap(t *testing.T) {
+
+ v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
+
+ rawArr := v.MustObjxMapSlice()
+
+ replaced := v.ReplaceObjxMap(func(index int, val Map) Map {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustObjxMapSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectObjxMap(t *testing.T) {
+
+ v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}}
+
+ collected := v.CollectObjxMap(func(index int, val Map) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestBool(t *testing.T) {
+
+ val := bool(true)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Bool())
+ assert.Equal(t, val, New(m).Get("value").MustBool())
+ assert.Equal(t, bool(false), New(m).Get("nothing").Bool())
+ assert.Equal(t, val, New(m).Get("nothing").Bool(true))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustBool()
+ })
+
+}
+
+func TestBoolSlice(t *testing.T) {
+
+ val := bool(true)
+ m := map[string]interface{}{"value": []bool{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").BoolSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustBoolSlice()[0])
+ assert.Equal(t, []bool(nil), New(m).Get("nothing").BoolSlice())
+ assert.Equal(t, val, New(m).Get("nothing").BoolSlice([]bool{bool(true)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustBoolSlice()
+ })
+
+}
+
+func TestIsBool(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: bool(true)}
+ assert.True(t, v.IsBool())
+
+ v = &Value{data: []bool{bool(true)}}
+ assert.True(t, v.IsBoolSlice())
+
+}
+
+func TestEachBool(t *testing.T) {
+
+ v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ count := 0
+ replacedVals := make([]bool, 0)
+ assert.Equal(t, v, v.EachBool(func(i int, val bool) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustBoolSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustBoolSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustBoolSlice()[2])
+
+}
+
+func TestWhereBool(t *testing.T) {
+
+ v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+
+ selected := v.WhereBool(func(i int, val bool) bool {
+ return i%2 == 0
+ }).MustBoolSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupBool(t *testing.T) {
+
+ v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+
+ grouped := v.GroupBool(func(i int, val bool) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]bool)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceBool(t *testing.T) {
+
+ v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+
+ rawArr := v.MustBoolSlice()
+
+ replaced := v.ReplaceBool(func(index int, val bool) bool {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustBoolSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectBool(t *testing.T) {
+
+ v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+
+ collected := v.CollectBool(func(index int, val bool) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestStr(t *testing.T) {
+
+ val := string("hello")
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Str())
+ assert.Equal(t, val, New(m).Get("value").MustStr())
+ assert.Equal(t, string(""), New(m).Get("nothing").Str())
+ assert.Equal(t, val, New(m).Get("nothing").Str("hello"))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustStr()
+ })
+
+}
+
+func TestStrSlice(t *testing.T) {
+
+ val := string("hello")
+ m := map[string]interface{}{"value": []string{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").StrSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustStrSlice()[0])
+ assert.Equal(t, []string(nil), New(m).Get("nothing").StrSlice())
+ assert.Equal(t, val, New(m).Get("nothing").StrSlice([]string{string("hello")})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustStrSlice()
+ })
+
+}
+
+func TestIsStr(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: string("hello")}
+ assert.True(t, v.IsStr())
+
+ v = &Value{data: []string{string("hello")}}
+ assert.True(t, v.IsStrSlice())
+
+}
+
+func TestEachStr(t *testing.T) {
+
+ v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ count := 0
+ replacedVals := make([]string, 0)
+ assert.Equal(t, v, v.EachStr(func(i int, val string) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustStrSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustStrSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustStrSlice()[2])
+
+}
+
+func TestWhereStr(t *testing.T) {
+
+ v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+
+ selected := v.WhereStr(func(i int, val string) bool {
+ return i%2 == 0
+ }).MustStrSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupStr(t *testing.T) {
+
+ v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+
+ grouped := v.GroupStr(func(i int, val string) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]string)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceStr(t *testing.T) {
+
+ v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+
+ rawArr := v.MustStrSlice()
+
+ replaced := v.ReplaceStr(func(index int, val string) string {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustStrSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectStr(t *testing.T) {
+
+ v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+
+ collected := v.CollectStr(func(index int, val string) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInt(t *testing.T) {
+
+ val := int(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int())
+ assert.Equal(t, val, New(m).Get("value").MustInt())
+ assert.Equal(t, int(0), New(m).Get("nothing").Int())
+ assert.Equal(t, val, New(m).Get("nothing").Int(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInt()
+ })
+
+}
+
+func TestIntSlice(t *testing.T) {
+
+ val := int(1)
+ m := map[string]interface{}{"value": []int{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").IntSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustIntSlice()[0])
+ assert.Equal(t, []int(nil), New(m).Get("nothing").IntSlice())
+ assert.Equal(t, val, New(m).Get("nothing").IntSlice([]int{int(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustIntSlice()
+ })
+
+}
+
+func TestIsInt(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: int(1)}
+ assert.True(t, v.IsInt())
+
+ v = &Value{data: []int{int(1)}}
+ assert.True(t, v.IsIntSlice())
+
+}
+
+func TestEachInt(t *testing.T) {
+
+ v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1)}}
+ count := 0
+ replacedVals := make([]int, 0)
+ assert.Equal(t, v, v.EachInt(func(i int, val int) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustIntSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustIntSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustIntSlice()[2])
+
+}
+
+func TestWhereInt(t *testing.T) {
+
+ v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+
+ selected := v.WhereInt(func(i int, val int) bool {
+ return i%2 == 0
+ }).MustIntSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInt(t *testing.T) {
+
+ v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+
+ grouped := v.GroupInt(func(i int, val int) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]int)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInt(t *testing.T) {
+
+ v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+
+ rawArr := v.MustIntSlice()
+
+ replaced := v.ReplaceInt(func(index int, val int) int {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustIntSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInt(t *testing.T) {
+
+ v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+
+ collected := v.CollectInt(func(index int, val int) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInt8(t *testing.T) {
+
+ val := int8(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int8())
+ assert.Equal(t, val, New(m).Get("value").MustInt8())
+ assert.Equal(t, int8(0), New(m).Get("nothing").Int8())
+ assert.Equal(t, val, New(m).Get("nothing").Int8(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInt8()
+ })
+
+}
+
+func TestInt8Slice(t *testing.T) {
+
+ val := int8(1)
+ m := map[string]interface{}{"value": []int8{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int8Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustInt8Slice()[0])
+ assert.Equal(t, []int8(nil), New(m).Get("nothing").Int8Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Int8Slice([]int8{int8(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustInt8Slice()
+ })
+
+}
+
+func TestIsInt8(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: int8(1)}
+ assert.True(t, v.IsInt8())
+
+ v = &Value{data: []int8{int8(1)}}
+ assert.True(t, v.IsInt8Slice())
+
+}
+
+func TestEachInt8(t *testing.T) {
+
+ v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ count := 0
+ replacedVals := make([]int8, 0)
+ assert.Equal(t, v, v.EachInt8(func(i int, val int8) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustInt8Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustInt8Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustInt8Slice()[2])
+
+}
+
+func TestWhereInt8(t *testing.T) {
+
+ v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+
+ selected := v.WhereInt8(func(i int, val int8) bool {
+ return i%2 == 0
+ }).MustInt8Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInt8(t *testing.T) {
+
+ v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+
+ grouped := v.GroupInt8(func(i int, val int8) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]int8)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInt8(t *testing.T) {
+
+ v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+
+ rawArr := v.MustInt8Slice()
+
+ replaced := v.ReplaceInt8(func(index int, val int8) int8 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustInt8Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInt8(t *testing.T) {
+
+ v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+
+ collected := v.CollectInt8(func(index int, val int8) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInt16(t *testing.T) {
+
+ val := int16(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int16())
+ assert.Equal(t, val, New(m).Get("value").MustInt16())
+ assert.Equal(t, int16(0), New(m).Get("nothing").Int16())
+ assert.Equal(t, val, New(m).Get("nothing").Int16(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInt16()
+ })
+
+}
+
+func TestInt16Slice(t *testing.T) {
+
+ val := int16(1)
+ m := map[string]interface{}{"value": []int16{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int16Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustInt16Slice()[0])
+ assert.Equal(t, []int16(nil), New(m).Get("nothing").Int16Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Int16Slice([]int16{int16(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustInt16Slice()
+ })
+
+}
+
+func TestIsInt16(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: int16(1)}
+ assert.True(t, v.IsInt16())
+
+ v = &Value{data: []int16{int16(1)}}
+ assert.True(t, v.IsInt16Slice())
+
+}
+
+func TestEachInt16(t *testing.T) {
+
+ v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ count := 0
+ replacedVals := make([]int16, 0)
+ assert.Equal(t, v, v.EachInt16(func(i int, val int16) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustInt16Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustInt16Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustInt16Slice()[2])
+
+}
+
+func TestWhereInt16(t *testing.T) {
+
+ v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+
+ selected := v.WhereInt16(func(i int, val int16) bool {
+ return i%2 == 0
+ }).MustInt16Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInt16(t *testing.T) {
+
+ v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+
+ grouped := v.GroupInt16(func(i int, val int16) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]int16)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInt16(t *testing.T) {
+
+ v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+
+ rawArr := v.MustInt16Slice()
+
+ replaced := v.ReplaceInt16(func(index int, val int16) int16 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustInt16Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInt16(t *testing.T) {
+
+ v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+
+ collected := v.CollectInt16(func(index int, val int16) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInt32(t *testing.T) {
+
+ val := int32(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int32())
+ assert.Equal(t, val, New(m).Get("value").MustInt32())
+ assert.Equal(t, int32(0), New(m).Get("nothing").Int32())
+ assert.Equal(t, val, New(m).Get("nothing").Int32(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInt32()
+ })
+
+}
+
+func TestInt32Slice(t *testing.T) {
+
+ val := int32(1)
+ m := map[string]interface{}{"value": []int32{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int32Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustInt32Slice()[0])
+ assert.Equal(t, []int32(nil), New(m).Get("nothing").Int32Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Int32Slice([]int32{int32(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustInt32Slice()
+ })
+
+}
+
+func TestIsInt32(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: int32(1)}
+ assert.True(t, v.IsInt32())
+
+ v = &Value{data: []int32{int32(1)}}
+ assert.True(t, v.IsInt32Slice())
+
+}
+
+func TestEachInt32(t *testing.T) {
+
+ v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ count := 0
+ replacedVals := make([]int32, 0)
+ assert.Equal(t, v, v.EachInt32(func(i int, val int32) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustInt32Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustInt32Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustInt32Slice()[2])
+
+}
+
+func TestWhereInt32(t *testing.T) {
+
+ v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+
+ selected := v.WhereInt32(func(i int, val int32) bool {
+ return i%2 == 0
+ }).MustInt32Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInt32(t *testing.T) {
+
+ v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+
+ grouped := v.GroupInt32(func(i int, val int32) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]int32)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInt32(t *testing.T) {
+
+ v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+
+ rawArr := v.MustInt32Slice()
+
+ replaced := v.ReplaceInt32(func(index int, val int32) int32 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustInt32Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInt32(t *testing.T) {
+
+ v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+
+ collected := v.CollectInt32(func(index int, val int32) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestInt64(t *testing.T) {
+
+ val := int64(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int64())
+ assert.Equal(t, val, New(m).Get("value").MustInt64())
+ assert.Equal(t, int64(0), New(m).Get("nothing").Int64())
+ assert.Equal(t, val, New(m).Get("nothing").Int64(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustInt64()
+ })
+
+}
+
+func TestInt64Slice(t *testing.T) {
+
+ val := int64(1)
+ m := map[string]interface{}{"value": []int64{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Int64Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustInt64Slice()[0])
+ assert.Equal(t, []int64(nil), New(m).Get("nothing").Int64Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Int64Slice([]int64{int64(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustInt64Slice()
+ })
+
+}
+
+func TestIsInt64(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: int64(1)}
+ assert.True(t, v.IsInt64())
+
+ v = &Value{data: []int64{int64(1)}}
+ assert.True(t, v.IsInt64Slice())
+
+}
+
+func TestEachInt64(t *testing.T) {
+
+ v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ count := 0
+ replacedVals := make([]int64, 0)
+ assert.Equal(t, v, v.EachInt64(func(i int, val int64) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustInt64Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustInt64Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustInt64Slice()[2])
+
+}
+
+func TestWhereInt64(t *testing.T) {
+
+ v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+
+ selected := v.WhereInt64(func(i int, val int64) bool {
+ return i%2 == 0
+ }).MustInt64Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupInt64(t *testing.T) {
+
+ v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+
+ grouped := v.GroupInt64(func(i int, val int64) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]int64)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceInt64(t *testing.T) {
+
+ v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+
+ rawArr := v.MustInt64Slice()
+
+ replaced := v.ReplaceInt64(func(index int, val int64) int64 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustInt64Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectInt64(t *testing.T) {
+
+ v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+
+ collected := v.CollectInt64(func(index int, val int64) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUint(t *testing.T) {
+
+ val := uint(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint())
+ assert.Equal(t, val, New(m).Get("value").MustUint())
+ assert.Equal(t, uint(0), New(m).Get("nothing").Uint())
+ assert.Equal(t, val, New(m).Get("nothing").Uint(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUint()
+ })
+
+}
+
+func TestUintSlice(t *testing.T) {
+
+ val := uint(1)
+ m := map[string]interface{}{"value": []uint{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").UintSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUintSlice()[0])
+ assert.Equal(t, []uint(nil), New(m).Get("nothing").UintSlice())
+ assert.Equal(t, val, New(m).Get("nothing").UintSlice([]uint{uint(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUintSlice()
+ })
+
+}
+
+func TestIsUint(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uint(1)}
+ assert.True(t, v.IsUint())
+
+ v = &Value{data: []uint{uint(1)}}
+ assert.True(t, v.IsUintSlice())
+
+}
+
+func TestEachUint(t *testing.T) {
+
+ v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ count := 0
+ replacedVals := make([]uint, 0)
+ assert.Equal(t, v, v.EachUint(func(i int, val uint) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUintSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUintSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUintSlice()[2])
+
+}
+
+func TestWhereUint(t *testing.T) {
+
+ v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+
+ selected := v.WhereUint(func(i int, val uint) bool {
+ return i%2 == 0
+ }).MustUintSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUint(t *testing.T) {
+
+ v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+
+ grouped := v.GroupUint(func(i int, val uint) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uint)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUint(t *testing.T) {
+
+ v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+
+ rawArr := v.MustUintSlice()
+
+ replaced := v.ReplaceUint(func(index int, val uint) uint {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUintSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUint(t *testing.T) {
+
+ v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+
+ collected := v.CollectUint(func(index int, val uint) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUint8(t *testing.T) {
+
+ val := uint8(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint8())
+ assert.Equal(t, val, New(m).Get("value").MustUint8())
+ assert.Equal(t, uint8(0), New(m).Get("nothing").Uint8())
+ assert.Equal(t, val, New(m).Get("nothing").Uint8(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUint8()
+ })
+
+}
+
+func TestUint8Slice(t *testing.T) {
+
+ val := uint8(1)
+ m := map[string]interface{}{"value": []uint8{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint8Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUint8Slice()[0])
+ assert.Equal(t, []uint8(nil), New(m).Get("nothing").Uint8Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Uint8Slice([]uint8{uint8(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUint8Slice()
+ })
+
+}
+
+func TestIsUint8(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uint8(1)}
+ assert.True(t, v.IsUint8())
+
+ v = &Value{data: []uint8{uint8(1)}}
+ assert.True(t, v.IsUint8Slice())
+
+}
+
+func TestEachUint8(t *testing.T) {
+
+ v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ count := 0
+ replacedVals := make([]uint8, 0)
+ assert.Equal(t, v, v.EachUint8(func(i int, val uint8) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUint8Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUint8Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUint8Slice()[2])
+
+}
+
+func TestWhereUint8(t *testing.T) {
+
+ v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+
+ selected := v.WhereUint8(func(i int, val uint8) bool {
+ return i%2 == 0
+ }).MustUint8Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUint8(t *testing.T) {
+
+ v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+
+ grouped := v.GroupUint8(func(i int, val uint8) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uint8)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUint8(t *testing.T) {
+
+ v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+
+ rawArr := v.MustUint8Slice()
+
+ replaced := v.ReplaceUint8(func(index int, val uint8) uint8 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUint8Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUint8(t *testing.T) {
+
+ v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+
+ collected := v.CollectUint8(func(index int, val uint8) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUint16(t *testing.T) {
+
+ val := uint16(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint16())
+ assert.Equal(t, val, New(m).Get("value").MustUint16())
+ assert.Equal(t, uint16(0), New(m).Get("nothing").Uint16())
+ assert.Equal(t, val, New(m).Get("nothing").Uint16(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUint16()
+ })
+
+}
+
+func TestUint16Slice(t *testing.T) {
+
+ val := uint16(1)
+ m := map[string]interface{}{"value": []uint16{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint16Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUint16Slice()[0])
+ assert.Equal(t, []uint16(nil), New(m).Get("nothing").Uint16Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Uint16Slice([]uint16{uint16(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUint16Slice()
+ })
+
+}
+
+func TestIsUint16(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uint16(1)}
+ assert.True(t, v.IsUint16())
+
+ v = &Value{data: []uint16{uint16(1)}}
+ assert.True(t, v.IsUint16Slice())
+
+}
+
+func TestEachUint16(t *testing.T) {
+
+ v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ count := 0
+ replacedVals := make([]uint16, 0)
+ assert.Equal(t, v, v.EachUint16(func(i int, val uint16) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUint16Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUint16Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUint16Slice()[2])
+
+}
+
+func TestWhereUint16(t *testing.T) {
+
+ v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+
+ selected := v.WhereUint16(func(i int, val uint16) bool {
+ return i%2 == 0
+ }).MustUint16Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUint16(t *testing.T) {
+
+ v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+
+ grouped := v.GroupUint16(func(i int, val uint16) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uint16)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUint16(t *testing.T) {
+
+ v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+
+ rawArr := v.MustUint16Slice()
+
+ replaced := v.ReplaceUint16(func(index int, val uint16) uint16 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUint16Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUint16(t *testing.T) {
+
+ v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+
+ collected := v.CollectUint16(func(index int, val uint16) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUint32(t *testing.T) {
+
+ val := uint32(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint32())
+ assert.Equal(t, val, New(m).Get("value").MustUint32())
+ assert.Equal(t, uint32(0), New(m).Get("nothing").Uint32())
+ assert.Equal(t, val, New(m).Get("nothing").Uint32(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUint32()
+ })
+
+}
+
+func TestUint32Slice(t *testing.T) {
+
+ val := uint32(1)
+ m := map[string]interface{}{"value": []uint32{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint32Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUint32Slice()[0])
+ assert.Equal(t, []uint32(nil), New(m).Get("nothing").Uint32Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Uint32Slice([]uint32{uint32(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUint32Slice()
+ })
+
+}
+
+func TestIsUint32(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uint32(1)}
+ assert.True(t, v.IsUint32())
+
+ v = &Value{data: []uint32{uint32(1)}}
+ assert.True(t, v.IsUint32Slice())
+
+}
+
+func TestEachUint32(t *testing.T) {
+
+ v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ count := 0
+ replacedVals := make([]uint32, 0)
+ assert.Equal(t, v, v.EachUint32(func(i int, val uint32) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUint32Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUint32Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUint32Slice()[2])
+
+}
+
+func TestWhereUint32(t *testing.T) {
+
+ v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+
+ selected := v.WhereUint32(func(i int, val uint32) bool {
+ return i%2 == 0
+ }).MustUint32Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUint32(t *testing.T) {
+
+ v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+
+ grouped := v.GroupUint32(func(i int, val uint32) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uint32)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUint32(t *testing.T) {
+
+ v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+
+ rawArr := v.MustUint32Slice()
+
+ replaced := v.ReplaceUint32(func(index int, val uint32) uint32 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUint32Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUint32(t *testing.T) {
+
+ v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+
+ collected := v.CollectUint32(func(index int, val uint32) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUint64(t *testing.T) {
+
+ val := uint64(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint64())
+ assert.Equal(t, val, New(m).Get("value").MustUint64())
+ assert.Equal(t, uint64(0), New(m).Get("nothing").Uint64())
+ assert.Equal(t, val, New(m).Get("nothing").Uint64(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUint64()
+ })
+
+}
+
+func TestUint64Slice(t *testing.T) {
+
+ val := uint64(1)
+ m := map[string]interface{}{"value": []uint64{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uint64Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUint64Slice()[0])
+ assert.Equal(t, []uint64(nil), New(m).Get("nothing").Uint64Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Uint64Slice([]uint64{uint64(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUint64Slice()
+ })
+
+}
+
+func TestIsUint64(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uint64(1)}
+ assert.True(t, v.IsUint64())
+
+ v = &Value{data: []uint64{uint64(1)}}
+ assert.True(t, v.IsUint64Slice())
+
+}
+
+func TestEachUint64(t *testing.T) {
+
+ v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ count := 0
+ replacedVals := make([]uint64, 0)
+ assert.Equal(t, v, v.EachUint64(func(i int, val uint64) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUint64Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUint64Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUint64Slice()[2])
+
+}
+
+func TestWhereUint64(t *testing.T) {
+
+ v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+
+ selected := v.WhereUint64(func(i int, val uint64) bool {
+ return i%2 == 0
+ }).MustUint64Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUint64(t *testing.T) {
+
+ v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+
+ grouped := v.GroupUint64(func(i int, val uint64) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uint64)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUint64(t *testing.T) {
+
+ v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+
+ rawArr := v.MustUint64Slice()
+
+ replaced := v.ReplaceUint64(func(index int, val uint64) uint64 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUint64Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUint64(t *testing.T) {
+
+ v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+
+ collected := v.CollectUint64(func(index int, val uint64) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestUintptr(t *testing.T) {
+
+ val := uintptr(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Uintptr())
+ assert.Equal(t, val, New(m).Get("value").MustUintptr())
+ assert.Equal(t, uintptr(0), New(m).Get("nothing").Uintptr())
+ assert.Equal(t, val, New(m).Get("nothing").Uintptr(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustUintptr()
+ })
+
+}
+
+func TestUintptrSlice(t *testing.T) {
+
+ val := uintptr(1)
+ m := map[string]interface{}{"value": []uintptr{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").UintptrSlice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustUintptrSlice()[0])
+ assert.Equal(t, []uintptr(nil), New(m).Get("nothing").UintptrSlice())
+ assert.Equal(t, val, New(m).Get("nothing").UintptrSlice([]uintptr{uintptr(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustUintptrSlice()
+ })
+
+}
+
+func TestIsUintptr(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: uintptr(1)}
+ assert.True(t, v.IsUintptr())
+
+ v = &Value{data: []uintptr{uintptr(1)}}
+ assert.True(t, v.IsUintptrSlice())
+
+}
+
+func TestEachUintptr(t *testing.T) {
+
+ v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ count := 0
+ replacedVals := make([]uintptr, 0)
+ assert.Equal(t, v, v.EachUintptr(func(i int, val uintptr) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustUintptrSlice()[0])
+ assert.Equal(t, replacedVals[1], v.MustUintptrSlice()[1])
+ assert.Equal(t, replacedVals[2], v.MustUintptrSlice()[2])
+
+}
+
+func TestWhereUintptr(t *testing.T) {
+
+ v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+
+ selected := v.WhereUintptr(func(i int, val uintptr) bool {
+ return i%2 == 0
+ }).MustUintptrSlice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupUintptr(t *testing.T) {
+
+ v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+
+ grouped := v.GroupUintptr(func(i int, val uintptr) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]uintptr)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceUintptr(t *testing.T) {
+
+ v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+
+ rawArr := v.MustUintptrSlice()
+
+ replaced := v.ReplaceUintptr(func(index int, val uintptr) uintptr {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustUintptrSlice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectUintptr(t *testing.T) {
+
+ v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+
+ collected := v.CollectUintptr(func(index int, val uintptr) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestFloat32(t *testing.T) {
+
+ val := float32(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Float32())
+ assert.Equal(t, val, New(m).Get("value").MustFloat32())
+ assert.Equal(t, float32(0), New(m).Get("nothing").Float32())
+ assert.Equal(t, val, New(m).Get("nothing").Float32(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustFloat32()
+ })
+
+}
+
+func TestFloat32Slice(t *testing.T) {
+
+ val := float32(1)
+ m := map[string]interface{}{"value": []float32{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Float32Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustFloat32Slice()[0])
+ assert.Equal(t, []float32(nil), New(m).Get("nothing").Float32Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Float32Slice([]float32{float32(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustFloat32Slice()
+ })
+
+}
+
+func TestIsFloat32(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: float32(1)}
+ assert.True(t, v.IsFloat32())
+
+ v = &Value{data: []float32{float32(1)}}
+ assert.True(t, v.IsFloat32Slice())
+
+}
+
+func TestEachFloat32(t *testing.T) {
+
+ v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ count := 0
+ replacedVals := make([]float32, 0)
+ assert.Equal(t, v, v.EachFloat32(func(i int, val float32) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustFloat32Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustFloat32Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustFloat32Slice()[2])
+
+}
+
+func TestWhereFloat32(t *testing.T) {
+
+ v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+
+ selected := v.WhereFloat32(func(i int, val float32) bool {
+ return i%2 == 0
+ }).MustFloat32Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupFloat32(t *testing.T) {
+
+ v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+
+ grouped := v.GroupFloat32(func(i int, val float32) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]float32)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceFloat32(t *testing.T) {
+
+ v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+
+ rawArr := v.MustFloat32Slice()
+
+ replaced := v.ReplaceFloat32(func(index int, val float32) float32 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustFloat32Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectFloat32(t *testing.T) {
+
+ v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+
+ collected := v.CollectFloat32(func(index int, val float32) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestFloat64(t *testing.T) {
+
+ val := float64(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Float64())
+ assert.Equal(t, val, New(m).Get("value").MustFloat64())
+ assert.Equal(t, float64(0), New(m).Get("nothing").Float64())
+ assert.Equal(t, val, New(m).Get("nothing").Float64(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustFloat64()
+ })
+
+}
+
+func TestFloat64Slice(t *testing.T) {
+
+ val := float64(1)
+ m := map[string]interface{}{"value": []float64{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Float64Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustFloat64Slice()[0])
+ assert.Equal(t, []float64(nil), New(m).Get("nothing").Float64Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Float64Slice([]float64{float64(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustFloat64Slice()
+ })
+
+}
+
+func TestIsFloat64(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: float64(1)}
+ assert.True(t, v.IsFloat64())
+
+ v = &Value{data: []float64{float64(1)}}
+ assert.True(t, v.IsFloat64Slice())
+
+}
+
+func TestEachFloat64(t *testing.T) {
+
+ v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ count := 0
+ replacedVals := make([]float64, 0)
+ assert.Equal(t, v, v.EachFloat64(func(i int, val float64) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustFloat64Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustFloat64Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustFloat64Slice()[2])
+
+}
+
+func TestWhereFloat64(t *testing.T) {
+
+ v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+
+ selected := v.WhereFloat64(func(i int, val float64) bool {
+ return i%2 == 0
+ }).MustFloat64Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupFloat64(t *testing.T) {
+
+ v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+
+ grouped := v.GroupFloat64(func(i int, val float64) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]float64)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceFloat64(t *testing.T) {
+
+ v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+
+ rawArr := v.MustFloat64Slice()
+
+ replaced := v.ReplaceFloat64(func(index int, val float64) float64 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustFloat64Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectFloat64(t *testing.T) {
+
+ v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+
+ collected := v.CollectFloat64(func(index int, val float64) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestComplex64(t *testing.T) {
+
+ val := complex64(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Complex64())
+ assert.Equal(t, val, New(m).Get("value").MustComplex64())
+ assert.Equal(t, complex64(0), New(m).Get("nothing").Complex64())
+ assert.Equal(t, val, New(m).Get("nothing").Complex64(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustComplex64()
+ })
+
+}
+
+func TestComplex64Slice(t *testing.T) {
+
+ val := complex64(1)
+ m := map[string]interface{}{"value": []complex64{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Complex64Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustComplex64Slice()[0])
+ assert.Equal(t, []complex64(nil), New(m).Get("nothing").Complex64Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Complex64Slice([]complex64{complex64(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustComplex64Slice()
+ })
+
+}
+
+func TestIsComplex64(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: complex64(1)}
+ assert.True(t, v.IsComplex64())
+
+ v = &Value{data: []complex64{complex64(1)}}
+ assert.True(t, v.IsComplex64Slice())
+
+}
+
+func TestEachComplex64(t *testing.T) {
+
+ v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ count := 0
+ replacedVals := make([]complex64, 0)
+ assert.Equal(t, v, v.EachComplex64(func(i int, val complex64) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustComplex64Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustComplex64Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustComplex64Slice()[2])
+
+}
+
+func TestWhereComplex64(t *testing.T) {
+
+ v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+
+ selected := v.WhereComplex64(func(i int, val complex64) bool {
+ return i%2 == 0
+ }).MustComplex64Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupComplex64(t *testing.T) {
+
+ v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+
+ grouped := v.GroupComplex64(func(i int, val complex64) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]complex64)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceComplex64(t *testing.T) {
+
+ v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+
+ rawArr := v.MustComplex64Slice()
+
+ replaced := v.ReplaceComplex64(func(index int, val complex64) complex64 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustComplex64Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectComplex64(t *testing.T) {
+
+ v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+
+ collected := v.CollectComplex64(func(index int, val complex64) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
+
+// ************************************************************
+// TESTS
+// ************************************************************
+
+func TestComplex128(t *testing.T) {
+
+ val := complex128(1)
+ m := map[string]interface{}{"value": val, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Complex128())
+ assert.Equal(t, val, New(m).Get("value").MustComplex128())
+ assert.Equal(t, complex128(0), New(m).Get("nothing").Complex128())
+ assert.Equal(t, val, New(m).Get("nothing").Complex128(1))
+
+ assert.Panics(t, func() {
+ New(m).Get("age").MustComplex128()
+ })
+
+}
+
+func TestComplex128Slice(t *testing.T) {
+
+ val := complex128(1)
+ m := map[string]interface{}{"value": []complex128{val}, "nothing": nil}
+ assert.Equal(t, val, New(m).Get("value").Complex128Slice()[0])
+ assert.Equal(t, val, New(m).Get("value").MustComplex128Slice()[0])
+ assert.Equal(t, []complex128(nil), New(m).Get("nothing").Complex128Slice())
+ assert.Equal(t, val, New(m).Get("nothing").Complex128Slice([]complex128{complex128(1)})[0])
+
+ assert.Panics(t, func() {
+ New(m).Get("nothing").MustComplex128Slice()
+ })
+
+}
+
+func TestIsComplex128(t *testing.T) {
+
+ var v *Value
+
+ v = &Value{data: complex128(1)}
+ assert.True(t, v.IsComplex128())
+
+ v = &Value{data: []complex128{complex128(1)}}
+ assert.True(t, v.IsComplex128Slice())
+
+}
+
+func TestEachComplex128(t *testing.T) {
+
+ v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ count := 0
+ replacedVals := make([]complex128, 0)
+ assert.Equal(t, v, v.EachComplex128(func(i int, val complex128) bool {
+
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ if i == 2 {
+ return false
+ }
+
+ return true
+
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], v.MustComplex128Slice()[0])
+ assert.Equal(t, replacedVals[1], v.MustComplex128Slice()[1])
+ assert.Equal(t, replacedVals[2], v.MustComplex128Slice()[2])
+
+}
+
+func TestWhereComplex128(t *testing.T) {
+
+ v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+
+ selected := v.WhereComplex128(func(i int, val complex128) bool {
+ return i%2 == 0
+ }).MustComplex128Slice()
+
+ assert.Equal(t, 3, len(selected))
+
+}
+
+func TestGroupComplex128(t *testing.T) {
+
+ v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+
+ grouped := v.GroupComplex128(func(i int, val complex128) string {
+ return fmt.Sprintf("%v", i%2 == 0)
+ }).data.(map[string][]complex128)
+
+ assert.Equal(t, 2, len(grouped))
+ assert.Equal(t, 3, len(grouped["true"]))
+ assert.Equal(t, 3, len(grouped["false"]))
+
+}
+
+func TestReplaceComplex128(t *testing.T) {
+
+ v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+
+ rawArr := v.MustComplex128Slice()
+
+ replaced := v.ReplaceComplex128(func(index int, val complex128) complex128 {
+ if index < len(rawArr)-1 {
+ return rawArr[index+1]
+ }
+ return rawArr[0]
+ })
+
+ replacedArr := replaced.MustComplex128Slice()
+ if assert.Equal(t, 6, len(replacedArr)) {
+ assert.Equal(t, replacedArr[0], rawArr[1])
+ assert.Equal(t, replacedArr[1], rawArr[2])
+ assert.Equal(t, replacedArr[2], rawArr[3])
+ assert.Equal(t, replacedArr[3], rawArr[4])
+ assert.Equal(t, replacedArr[4], rawArr[5])
+ assert.Equal(t, replacedArr[5], rawArr[0])
+ }
+
+}
+
+func TestCollectComplex128(t *testing.T) {
+
+ v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+
+ collected := v.CollectComplex128(func(index int, val complex128) interface{} {
+ return index
+ })
+
+ collectedArr := collected.MustInterSlice()
+ if assert.Equal(t, 6, len(collectedArr)) {
+ assert.Equal(t, collectedArr[0], 0)
+ assert.Equal(t, collectedArr[1], 1)
+ assert.Equal(t, collectedArr[2], 2)
+ assert.Equal(t, collectedArr[3], 3)
+ assert.Equal(t, collectedArr[4], 4)
+ assert.Equal(t, collectedArr[5], 5)
+ }
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/value.go b/Godeps/_workspace/src/github.com/stretchr/objx/value.go
new file mode 100644
index 0000000000..7aaef06b1c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/value.go
@@ -0,0 +1,13 @@
+package objx
+
+// Value provides methods for extracting interface{} data in various
+// types.
+type Value struct {
+ // data contains the raw data being managed by this Value
+ data interface{}
+}
+
+// Data returns the raw data contained by this Value
+func (v *Value) Data() interface{} {
+ return v.data
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go b/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
new file mode 100644
index 0000000000..0bc65d92c1
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
@@ -0,0 +1 @@
+package objx
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
new file mode 100644
index 0000000000..8af3157ca3
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
@@ -0,0 +1,782 @@
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strings"
+ "time"
+)
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Errorf(format string, args ...interface{})
+}
+
+// Comparison a custom function that returns true on success and false on failure
+type Comparison func() (success bool)
+
+/*
+ Helper functions
+*/
+
+// ObjectsAreEqual determines if two objects are considered equal.
+//
+// This function does no assertion of any kind.
+func ObjectsAreEqual(expected, actual interface{}) bool {
+
+ if expected == nil || actual == nil {
+ return expected == actual
+ }
+
+ if reflect.DeepEqual(expected, actual) {
+ return true
+ }
+
+ expectedValue := reflect.ValueOf(expected)
+ actualValue := reflect.ValueOf(actual)
+ if expectedValue == actualValue {
+ return true
+ }
+
+ // Attempt comparison after type conversion
+ if actualValue.Type().ConvertibleTo(expectedValue.Type()) && expectedValue == actualValue.Convert(expectedValue.Type()) {
+ return true
+ }
+
+ // Last ditch effort
+ if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) {
+ return true
+ }
+
+ return false
+
+}
+
+/* CallerInfo is necessary because the assert functions use the testing object
+internally, causing it to print the file:line of the assert method, rather than where
+the problem actually occured in calling code.*/
+
+// CallerInfo returns a string containing the file and line number of the assert call
+// that failed.
+func CallerInfo() string {
+
+ file := ""
+ line := 0
+ ok := false
+
+ for i := 0; ; i++ {
+ _, file, line, ok = runtime.Caller(i)
+ if !ok {
+ return ""
+ }
+ parts := strings.Split(file, "/")
+ dir := parts[len(parts)-2]
+ file = parts[len(parts)-1]
+ if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" {
+ break
+ }
+ }
+
+ return fmt.Sprintf("%s:%d", file, line)
+}
+
+// getWhitespaceString returns a string that is long enough to overwrite the default
+// output from the go testing framework.
+func getWhitespaceString() string {
+
+ _, file, line, ok := runtime.Caller(1)
+ if !ok {
+ return ""
+ }
+ parts := strings.Split(file, "/")
+ file = parts[len(parts)-1]
+
+ return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line)))
+
+}
+
+func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
+ if len(msgAndArgs) == 0 || msgAndArgs == nil {
+ return ""
+ }
+ if len(msgAndArgs) == 1 {
+ return msgAndArgs[0].(string)
+ }
+ if len(msgAndArgs) > 1 {
+ return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
+ }
+ return ""
+}
+
+// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's
+// test printing (see inner comment for specifics)
+func indentMessageLines(message string, tabs int) string {
+ outBuf := new(bytes.Buffer)
+
+ for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ {
+ if i != 0 {
+ outBuf.WriteRune('\n')
+ }
+ for ii := 0; ii < tabs; ii++ {
+ outBuf.WriteRune('\t')
+ // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter
+ // by 1 prematurely.
+ if ii == 0 && i > 0 {
+ ii++
+ }
+ }
+ outBuf.WriteString(scanner.Text())
+ }
+
+ return outBuf.String()
+}
+
+// Fail reports a failure through
+func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+
+ if len(message) > 0 {
+ t.Errorf("\r%s\r\tLocation:\t%s\n"+
+ "\r\tError:%s\n"+
+ "\r\tMessages:\t%s\n\r",
+ getWhitespaceString(),
+ CallerInfo(),
+ indentMessageLines(failureMessage, 2),
+ message)
+ } else {
+ t.Errorf("\r%s\r\tLocation:\t%s\n"+
+ "\r\tError:%s\n\r",
+ getWhitespaceString(),
+ CallerInfo(),
+ indentMessageLines(failureMessage, 2))
+ }
+
+ return false
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject")
+func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+
+ interfaceType := reflect.TypeOf(interfaceObject).Elem()
+
+ if !reflect.TypeOf(object).Implements(interfaceType) {
+ return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// IsType asserts that the specified objects are of the same type.
+func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+
+ if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) {
+ return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...)
+ }
+
+ return true
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(t, 123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ if !ObjectsAreEqual(expected, actual) {
+ return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
+ " != %#v (actual)", expected, actual), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ aType := reflect.TypeOf(expected)
+ bType := reflect.TypeOf(actual)
+
+ if aType != bType {
+ return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
+ }
+
+ return Equal(t, expected, actual, msgAndArgs...)
+
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(t, err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+
+ success := true
+
+ if object == nil {
+ success = false
+ } else {
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
+ success = false
+ }
+ }
+
+ if !success {
+ Fail(t, "Expected not to be nil.", msgAndArgs...)
+ }
+
+ return success
+}
+
+// isNil checks if a specified object is nil or not, without Failing.
+func isNil(object interface{}) bool {
+ if object == nil {
+ return true
+ }
+
+ value := reflect.ValueOf(object)
+ kind := value.Kind()
+ if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
+ return true
+ }
+
+ return false
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(t, err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+ if isNil(object) {
+ return true
+ }
+ return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
+}
+
+var zeros = []interface{}{
+ int(0),
+ int8(0),
+ int16(0),
+ int32(0),
+ int64(0),
+ uint(0),
+ uint8(0),
+ uint16(0),
+ uint32(0),
+ uint64(0),
+ float32(0),
+ float64(0),
+}
+
+// isEmpty gets whether the specified object is considered empty or not.
+func isEmpty(object interface{}) bool {
+
+ if object == nil {
+ return true
+ } else if object == "" {
+ return true
+ } else if object == false {
+ return true
+ }
+
+ for _, v := range zeros {
+ if object == v {
+ return true
+ }
+ }
+
+ objValue := reflect.ValueOf(object)
+
+ switch objValue.Kind() {
+ case reflect.Map:
+ fallthrough
+ case reflect.Slice, reflect.Chan:
+ {
+ return (objValue.Len() == 0)
+ }
+ case reflect.Ptr:
+ {
+ switch object.(type) {
+ case *time.Time:
+ return object.(*time.Time).IsZero()
+ default:
+ return false
+ }
+ }
+ }
+ return false
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Empty(t, obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+
+ pass := isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// if assert.NotEmpty(t, obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
+
+ pass := !isEmpty(object)
+ if !pass {
+ Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...)
+ }
+
+ return pass
+
+}
+
+// getLen try to get length of object.
+// return (false, 0) if impossible.
+func getLen(x interface{}) (ok bool, length int) {
+ v := reflect.ValueOf(x)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ }
+ }()
+ return true, v.Len()
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(t, mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool {
+ ok, l := getLen(object)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...)
+ }
+
+ if l != length {
+ return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...)
+ }
+ return true
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(t, myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+
+ if value != true {
+ return Fail(t, "Should be true", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// False asserts that the specified value is true.
+//
+// assert.False(t, myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
+
+ if value != false {
+ return Fail(t, "Should be false", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
+
+ if ObjectsAreEqual(expected, actual) {
+ return Fail(t, "Should not be equal", msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// containsElement try loop over the list check if the list includes the element.
+// return (false, false) if impossible.
+// return (true, false) if element was not found.
+// return (true, true) if element was found.
+func includeElement(list interface{}, element interface{}) (ok, found bool) {
+
+ listValue := reflect.ValueOf(list)
+ elementValue := reflect.ValueOf(element)
+ defer func() {
+ if e := recover(); e != nil {
+ ok = false
+ found = false
+ }
+ }()
+
+ if reflect.TypeOf(list).Kind() == reflect.String {
+ return true, strings.Contains(listValue.String(), elementValue.String())
+ }
+
+ for i := 0; i < listValue.Len(); i++ {
+ if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
+ return true, true
+ }
+ }
+ return true, false
+
+}
+
+// Contains asserts that the specified string or list(array, slice...) contains the
+// specified substring or element.
+//
+// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
+// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if !found {
+ return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// NotContains asserts that the specified string or list(array, slice...) does NOT contain the
+// specified substring or element.
+//
+// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
+
+ ok, found := includeElement(s, contains)
+ if !ok {
+ return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...)
+ }
+ if found {
+ return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...)
+ }
+
+ return true
+
+}
+
+// Condition uses a Comparison to assert a complex condition.
+func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool {
+ result := comp()
+ if !result {
+ Fail(t, "Condition failed!", msgAndArgs...)
+ }
+ return result
+}
+
+// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics
+// methods, and represents a simple func that takes no arguments, and returns nothing.
+type PanicTestFunc func()
+
+// didPanic returns true if the function passed to it panics. Otherwise, it returns false.
+func didPanic(f PanicTestFunc) (bool, interface{}) {
+
+ didPanic := false
+ var message interface{}
+ func() {
+
+ defer func() {
+ if message = recover(); message != nil {
+ didPanic = true
+ }
+ }()
+
+ // call the target function
+ f()
+
+ }()
+
+ return didPanic, message
+
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(t, func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+
+ if funcDidPanic, panicValue := didPanic(f); !funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(t, func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+
+ if funcDidPanic, panicValue := didPanic(f); funcDidPanic {
+ return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...)
+ }
+
+ return true
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+
+ dt := expected.Sub(actual)
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+func toFloat(x interface{}) (float64, bool) {
+ var xf float64
+ xok := true
+
+ switch xn := x.(type) {
+ case uint8:
+ xf = float64(xn)
+ case uint16:
+ xf = float64(xn)
+ case uint32:
+ xf = float64(xn)
+ case uint64:
+ xf = float64(xn)
+ case int:
+ xf = float64(xn)
+ case int8:
+ xf = float64(xn)
+ case int16:
+ xf = float64(xn)
+ case int32:
+ xf = float64(xn)
+ case int64:
+ xf = float64(xn)
+ case float32:
+ xf = float64(xn)
+ case float64:
+ xf = float64(xn)
+ default:
+ xok = false
+ }
+
+ return xf, xok
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...)
+ }
+
+ dt := af - bf
+ if dt < -delta || dt > delta {
+ return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...)
+ }
+
+ return true
+}
+
+// min(|expected|, |actual|) * epsilon
+func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 {
+ af, aok := toFloat(expected)
+ bf, bok := toFloat(actual)
+
+ if !aok || !bok {
+ // invalid input
+ return 0
+ }
+
+ if af < 0 {
+ af = -af
+ }
+ if bf < 0 {
+ bf = -bf
+ }
+ var delta float64
+ if af < bf {
+ delta = af * epsilon
+ } else {
+ delta = bf * epsilon
+ }
+ return delta
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ delta := calcEpsilonDelta(expected, actual, epsilon)
+
+ return InDelta(t, expected, actual, delta, msgAndArgs...)
+}
+
+/*
+ Errors
+*/
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(t, err) {
+// assert.Equal(t, actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
+ if isNil(err) {
+ return true
+ }
+
+ return Fail(t, fmt.Sprintf("No error is expected but got %v", err), msgAndArgs...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Error(t TestingT, err error, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ return NotNil(t, err, "An error is expected but got nil. %s", message)
+
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(t, err, "An error was expected") {
+// assert.Equal(t, err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool {
+
+ message := messageFromMsgAndArgs(msgAndArgs...)
+ if !NotNil(t, theError, "An error is expected but got nil. %s", message) {
+ return false
+ }
+ s := "An error with value \"%s\" is expected but got \"%s\". %s"
+ return Equal(t, theError.Error(), errString,
+ s, errString, theError.Error(), message)
+}
+
+// matchRegexp return true if a specified regexp matches a string.
+func matchRegexp(rx interface{}, str interface{}) bool {
+
+ var r *regexp.Regexp
+ if rr, ok := rx.(*regexp.Regexp); ok {
+ r = rr
+ } else {
+ r = regexp.MustCompile(fmt.Sprint(rx))
+ }
+
+ return (r.FindStringIndex(fmt.Sprint(str)) != nil)
+
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func Regexp(t TestingT, rx interface{}, str interface{}) bool {
+
+ match := matchRegexp(rx, str)
+
+ if !match {
+ Fail(t, "Expect \"%s\" to match \"%s\"")
+ }
+
+ return match
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func NotRegexp(t TestingT, rx interface{}, str interface{}) bool {
+ match := matchRegexp(rx, str)
+
+ if match {
+ Fail(t, "Expect \"%s\" to NOT match \"%s\"")
+ }
+
+ return !match
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
new file mode 100644
index 0000000000..bb63be2609
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
@@ -0,0 +1,738 @@
+package assert
+
+import (
+ "errors"
+ "regexp"
+ "testing"
+ "time"
+)
+
+// AssertionTesterInterface defines an interface to be used for testing assertion methods
+type AssertionTesterInterface interface {
+ TestMethod()
+}
+
+// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface
+type AssertionTesterConformingObject struct {
+}
+
+func (a *AssertionTesterConformingObject) TestMethod() {
+}
+
+// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface
+type AssertionTesterNonConformingObject struct {
+}
+
+func TestObjectsAreEqual(t *testing.T) {
+
+ if !ObjectsAreEqual("Hello World", "Hello World") {
+ t.Error("objectsAreEqual should return true")
+ }
+ if !ObjectsAreEqual(123, 123) {
+ t.Error("objectsAreEqual should return true")
+ }
+ if !ObjectsAreEqual(123.5, 123.5) {
+ t.Error("objectsAreEqual should return true")
+ }
+ if !ObjectsAreEqual([]byte("Hello World"), []byte("Hello World")) {
+ t.Error("objectsAreEqual should return true")
+ }
+ if !ObjectsAreEqual(nil, nil) {
+ t.Error("objectsAreEqual should return true")
+ }
+
+}
+
+func TestImplements(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
+ t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
+ }
+ if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
+ t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
+ }
+
+}
+
+func TestIsType(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
+ t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
+ }
+ if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
+ t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
+ }
+
+}
+
+func TestEqual(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !Equal(mockT, "Hello World", "Hello World") {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, 123, 123) {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, 123.5, 123.5) {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, []byte("Hello World"), []byte("Hello World")) {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, nil, nil) {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, int32(123), int64(123)) {
+ t.Error("Equal should return true")
+ }
+ if !Equal(mockT, int64(123), uint64(123)) {
+ t.Error("Equal should return true")
+ }
+
+}
+
+func TestNotNil(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !NotNil(mockT, new(AssertionTesterConformingObject)) {
+ t.Error("NotNil should return true: object is not nil")
+ }
+ if NotNil(mockT, nil) {
+ t.Error("NotNil should return false: object is nil")
+ }
+
+}
+
+func TestNil(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !Nil(mockT, nil) {
+ t.Error("Nil should return true: object is nil")
+ }
+ if Nil(mockT, new(AssertionTesterConformingObject)) {
+ t.Error("Nil should return false: object is not nil")
+ }
+
+}
+
+func TestTrue(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !True(mockT, true) {
+ t.Error("True should return true")
+ }
+ if True(mockT, false) {
+ t.Error("True should return false")
+ }
+
+}
+
+func TestFalse(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !False(mockT, false) {
+ t.Error("False should return true")
+ }
+ if False(mockT, true) {
+ t.Error("False should return false")
+ }
+
+}
+
+func TestExactly(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ a := float32(1)
+ b := float64(1)
+ c := float32(1)
+ d := float32(2)
+
+ if Exactly(mockT, a, b) {
+ t.Error("Exactly should return false")
+ }
+ if Exactly(mockT, a, d) {
+ t.Error("Exactly should return false")
+ }
+ if !Exactly(mockT, a, c) {
+ t.Error("Exactly should return true")
+ }
+
+ if Exactly(mockT, nil, a) {
+ t.Error("Exactly should return false")
+ }
+ if Exactly(mockT, a, nil) {
+ t.Error("Exactly should return false")
+ }
+
+}
+
+func TestNotEqual(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !NotEqual(mockT, "Hello World", "Hello World!") {
+ t.Error("NotEqual should return true")
+ }
+ if !NotEqual(mockT, 123, 1234) {
+ t.Error("NotEqual should return true")
+ }
+ if !NotEqual(mockT, 123.5, 123.55) {
+ t.Error("NotEqual should return true")
+ }
+ if !NotEqual(mockT, []byte("Hello World"), []byte("Hello World!")) {
+ t.Error("NotEqual should return true")
+ }
+ if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) {
+ t.Error("NotEqual should return true")
+ }
+
+ if NotEqual(mockT, "Hello World", "Hello World") {
+ t.Error("NotEqual should return false")
+ }
+ if NotEqual(mockT, 123, 123) {
+ t.Error("NotEqual should return false")
+ }
+ if NotEqual(mockT, 123.5, 123.5) {
+ t.Error("NotEqual should return false")
+ }
+ if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) {
+ t.Error("NotEqual should return false")
+ }
+ if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
+ t.Error("NotEqual should return false")
+ }
+}
+
+type A struct {
+ Name, Value string
+}
+
+func TestContains(t *testing.T) {
+
+ mockT := new(testing.T)
+ list := []string{"Foo", "Bar"}
+ complexList := []*A{
+ &A{"b", "c"},
+ &A{"d", "e"},
+ &A{"g", "h"},
+ &A{"j", "k"},
+ }
+
+ if !Contains(mockT, "Hello World", "Hello") {
+ t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
+ }
+ if Contains(mockT, "Hello World", "Salut") {
+ t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
+ }
+
+ if !Contains(mockT, list, "Bar") {
+ t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"")
+ }
+ if Contains(mockT, list, "Salut") {
+ t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
+ }
+ if !Contains(mockT, complexList, &A{"g", "h"}) {
+ t.Error("Contains should return true: complexList contains {\"g\", \"h\"}")
+ }
+ if Contains(mockT, complexList, &A{"g", "e"}) {
+ t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
+ }
+}
+
+func TestNotContains(t *testing.T) {
+
+ mockT := new(testing.T)
+ list := []string{"Foo", "Bar"}
+
+ if !NotContains(mockT, "Hello World", "Hello!") {
+ t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
+ }
+ if NotContains(mockT, "Hello World", "Hello") {
+ t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
+ }
+
+ if !NotContains(mockT, list, "Foo!") {
+ t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
+ }
+ if NotContains(mockT, list, "Foo") {
+ t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
+ }
+
+}
+
+func Test_includeElement(t *testing.T) {
+
+ list1 := []string{"Foo", "Bar"}
+ list2 := []int{1, 2}
+
+ ok, found := includeElement("Hello World", "World")
+ True(t, ok)
+ True(t, found)
+
+ ok, found = includeElement(list1, "Foo")
+ True(t, ok)
+ True(t, found)
+
+ ok, found = includeElement(list1, "Bar")
+ True(t, ok)
+ True(t, found)
+
+ ok, found = includeElement(list2, 1)
+ True(t, ok)
+ True(t, found)
+
+ ok, found = includeElement(list2, 2)
+ True(t, ok)
+ True(t, found)
+
+ ok, found = includeElement(list1, "Foo!")
+ True(t, ok)
+ False(t, found)
+
+ ok, found = includeElement(list2, 3)
+ True(t, ok)
+ False(t, found)
+
+ ok, found = includeElement(list2, "1")
+ True(t, ok)
+ False(t, found)
+
+ ok, found = includeElement(1433, "1")
+ False(t, ok)
+ False(t, found)
+
+}
+
+func TestCondition(t *testing.T) {
+ mockT := new(testing.T)
+
+ if !Condition(mockT, func() bool { return true }, "Truth") {
+ t.Error("Condition should return true")
+ }
+
+ if Condition(mockT, func() bool { return false }, "Lie") {
+ t.Error("Condition should return false")
+ }
+
+}
+
+func TestDidPanic(t *testing.T) {
+
+ if funcDidPanic, _ := didPanic(func() {
+ panic("Panic!")
+ }); !funcDidPanic {
+ t.Error("didPanic should return true")
+ }
+
+ if funcDidPanic, _ := didPanic(func() {
+ }); funcDidPanic {
+ t.Error("didPanic should return false")
+ }
+
+}
+
+func TestPanics(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !Panics(mockT, func() {
+ panic("Panic!")
+ }) {
+ t.Error("Panics should return true")
+ }
+
+ if Panics(mockT, func() {
+ }) {
+ t.Error("Panics should return false")
+ }
+
+}
+
+func TestNotPanics(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ if !NotPanics(mockT, func() {
+ }) {
+ t.Error("NotPanics should return true")
+ }
+
+ if NotPanics(mockT, func() {
+ panic("Panic!")
+ }) {
+ t.Error("NotPanics should return false")
+ }
+
+}
+
+func TestEqual_Funcs(t *testing.T) {
+
+ type f func() int
+ f1 := func() int { return 1 }
+ f2 := func() int { return 2 }
+
+ f1Copy := f1
+
+ Equal(t, f1Copy, f1, "Funcs are the same and should be considered equal")
+ NotEqual(t, f1, f2, "f1 and f2 are different")
+
+}
+
+func TestNoError(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ // start with a nil error
+ var err error
+
+ True(t, NoError(mockT, err), "NoError should return True for nil arg")
+
+ // now set an error
+ err = errors.New("some error")
+
+ False(t, NoError(mockT, err), "NoError with error should return False")
+
+}
+
+func TestError(t *testing.T) {
+
+ mockT := new(testing.T)
+
+ // start with a nil error
+ var err error
+
+ False(t, Error(mockT, err), "Error should return False for nil arg")
+
+ // now set an error
+ err = errors.New("some error")
+
+ True(t, Error(mockT, err), "Error with error should return True")
+
+}
+
+func TestEqualError(t *testing.T) {
+ mockT := new(testing.T)
+
+ // start with a nil error
+ var err error
+ False(t, EqualError(mockT, err, ""),
+ "EqualError should return false for nil arg")
+
+ // now set an error
+ err = errors.New("some error")
+ False(t, EqualError(mockT, err, "Not some error"),
+ "EqualError should return false for different error string")
+ True(t, EqualError(mockT, err, "some error"),
+ "EqualError should return true")
+}
+
+func Test_isEmpty(t *testing.T) {
+
+ chWithValue := make(chan struct{}, 1)
+ chWithValue <- struct{}{}
+
+ True(t, isEmpty(""))
+ True(t, isEmpty(nil))
+ True(t, isEmpty([]string{}))
+ True(t, isEmpty(0))
+ True(t, isEmpty(int32(0)))
+ True(t, isEmpty(int64(0)))
+ True(t, isEmpty(false))
+ True(t, isEmpty(map[string]string{}))
+ True(t, isEmpty(new(time.Time)))
+ True(t, isEmpty(make(chan struct{})))
+ False(t, isEmpty("something"))
+ False(t, isEmpty(errors.New("something")))
+ False(t, isEmpty([]string{"something"}))
+ False(t, isEmpty(1))
+ False(t, isEmpty(true))
+ False(t, isEmpty(map[string]string{"Hello": "World"}))
+ False(t, isEmpty(chWithValue))
+
+}
+
+func TestEmpty(t *testing.T) {
+
+ mockT := new(testing.T)
+ chWithValue := make(chan struct{}, 1)
+ chWithValue <- struct{}{}
+
+ True(t, Empty(mockT, ""), "Empty string is empty")
+ True(t, Empty(mockT, nil), "Nil is empty")
+ True(t, Empty(mockT, []string{}), "Empty string array is empty")
+ True(t, Empty(mockT, 0), "Zero int value is empty")
+ True(t, Empty(mockT, false), "False value is empty")
+ True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty")
+
+ False(t, Empty(mockT, "something"), "Non Empty string is not empty")
+ False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty")
+ False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty")
+ False(t, Empty(mockT, 1), "Non-zero int value is not empty")
+ False(t, Empty(mockT, true), "True value is not empty")
+ False(t, Empty(mockT, chWithValue), "Channel with values is not empty")
+}
+
+func TestNotEmpty(t *testing.T) {
+
+ mockT := new(testing.T)
+ chWithValue := make(chan struct{}, 1)
+ chWithValue <- struct{}{}
+
+ False(t, NotEmpty(mockT, ""), "Empty string is empty")
+ False(t, NotEmpty(mockT, nil), "Nil is empty")
+ False(t, NotEmpty(mockT, []string{}), "Empty string array is empty")
+ False(t, NotEmpty(mockT, 0), "Zero int value is empty")
+ False(t, NotEmpty(mockT, false), "False value is empty")
+ False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty")
+
+ True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty")
+ True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty")
+ True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty")
+ True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty")
+ True(t, NotEmpty(mockT, true), "True value is not empty")
+ True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty")
+}
+
+func Test_getLen(t *testing.T) {
+ falseCases := []interface{}{
+ nil,
+ 0,
+ true,
+ false,
+ 'A',
+ struct{}{},
+ }
+ for _, v := range falseCases {
+ ok, l := getLen(v)
+ False(t, ok, "Expected getLen fail to get length of %#v", v)
+ Equal(t, 0, l, "getLen should return 0 for %#v", v)
+ }
+
+ ch := make(chan int, 5)
+ ch <- 1
+ ch <- 2
+ ch <- 3
+ trueCases := []struct {
+ v interface{}
+ l int
+ }{
+ {[]int{1, 2, 3}, 3},
+ {[...]int{1, 2, 3}, 3},
+ {"ABC", 3},
+ {map[int]int{1: 2, 2: 4, 3: 6}, 3},
+ {ch, 3},
+
+ {[]int{}, 0},
+ {map[int]int{}, 0},
+ {make(chan int), 0},
+
+ {[]int(nil), 0},
+ {map[int]int(nil), 0},
+ {(chan int)(nil), 0},
+ }
+
+ for _, c := range trueCases {
+ ok, l := getLen(c.v)
+ True(t, ok, "Expected getLen success to get length of %#v", c.v)
+ Equal(t, c.l, l)
+ }
+}
+
+func TestLen(t *testing.T) {
+ mockT := new(testing.T)
+
+ False(t, Len(mockT, nil, 0), "nil does not have length")
+ False(t, Len(mockT, 0, 0), "int does not have length")
+ False(t, Len(mockT, true, 0), "true does not have length")
+ False(t, Len(mockT, false, 0), "false does not have length")
+ False(t, Len(mockT, 'A', 0), "Rune does not have length")
+ False(t, Len(mockT, struct{}{}, 0), "Struct does not have length")
+
+ ch := make(chan int, 5)
+ ch <- 1
+ ch <- 2
+ ch <- 3
+
+ cases := []struct {
+ v interface{}
+ l int
+ }{
+ {[]int{1, 2, 3}, 3},
+ {[...]int{1, 2, 3}, 3},
+ {"ABC", 3},
+ {map[int]int{1: 2, 2: 4, 3: 6}, 3},
+ {ch, 3},
+
+ {[]int{}, 0},
+ {map[int]int{}, 0},
+ {make(chan int), 0},
+
+ {[]int(nil), 0},
+ {map[int]int(nil), 0},
+ {(chan int)(nil), 0},
+ }
+
+ for _, c := range cases {
+ True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
+ }
+
+ cases = []struct {
+ v interface{}
+ l int
+ }{
+ {[]int{1, 2, 3}, 4},
+ {[...]int{1, 2, 3}, 2},
+ {"ABC", 2},
+ {map[int]int{1: 2, 2: 4, 3: 6}, 4},
+ {ch, 2},
+
+ {[]int{}, 1},
+ {map[int]int{}, 1},
+ {make(chan int), 1},
+
+ {[]int(nil), 1},
+ {map[int]int(nil), 1},
+ {(chan int)(nil), 1},
+ }
+
+ for _, c := range cases {
+ False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l)
+ }
+}
+
+func TestWithinDuration(t *testing.T) {
+
+ mockT := new(testing.T)
+ a := time.Now()
+ b := a.Add(10 * time.Second)
+
+ True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
+ True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
+
+ False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
+ False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
+
+ False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
+ False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
+
+ False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
+ False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
+}
+
+func TestInDelta(t *testing.T) {
+ mockT := new(testing.T)
+
+ True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
+ True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
+ True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1")
+ False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
+ False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
+ False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail")
+
+ cases := []struct {
+ a, b interface{}
+ delta float64
+ }{
+ {uint8(2), uint8(1), 1},
+ {uint16(2), uint16(1), 1},
+ {uint32(2), uint32(1), 1},
+ {uint64(2), uint64(1), 1},
+
+ {int(2), int(1), 1},
+ {int8(2), int8(1), 1},
+ {int16(2), int16(1), 1},
+ {int32(2), int32(1), 1},
+ {int64(2), int64(1), 1},
+
+ {float32(2), float32(1), 1},
+ {float64(2), float64(1), 1},
+ }
+
+ for _, tc := range cases {
+ True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
+ }
+}
+
+func TestInEpsilon(t *testing.T) {
+ mockT := new(testing.T)
+
+ cases := []struct {
+ a, b interface{}
+ epsilon float64
+ }{
+ {uint8(2), uint16(2), .001},
+ {2.1, 2.2, 0.1},
+ {2.2, 2.1, 0.1},
+ {-2.1, -2.2, 0.1},
+ {-2.2, -2.1, 0.1},
+ {uint64(100), uint8(101), 0.01},
+ {0.1, -0.1, 2},
+ }
+
+ for _, tc := range cases {
+ True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
+ }
+
+ cases = []struct {
+ a, b interface{}
+ epsilon float64
+ }{
+ {uint8(2), int16(-2), .001},
+ {uint64(100), uint8(102), 0.01},
+ {2.1, 2.2, 0.001},
+ {2.2, 2.1, 0.001},
+ {2.1, -2.2, 1},
+ {2.1, "bla-bla", 0},
+ {0.1, -0.1, 1.99},
+ }
+
+ for _, tc := range cases {
+ False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
+ }
+
+}
+
+func TestRegexp(t *testing.T) {
+ mockT := new(testing.T)
+
+ cases := []struct {
+ rx, str string
+ }{
+ {"^start", "start of the line"},
+ {"end$", "in the end"},
+ {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
+ }
+
+ for _, tc := range cases {
+ True(t, Regexp(mockT, tc.rx, tc.str))
+ True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
+ False(t, NotRegexp(mockT, tc.rx, tc.str))
+ False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
+ }
+
+ cases = []struct {
+ rx, str string
+ }{
+ {"^asdfastart", "Not the start of the line"},
+ {"end$", "in the end."},
+ {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
+ }
+
+ for _, tc := range cases {
+ False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
+ False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str))
+ True(t, NotRegexp(mockT, tc.rx, tc.str))
+ True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str))
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
new file mode 100644
index 0000000000..1c6de283d0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
@@ -0,0 +1,150 @@
+// A set of comprehensive testing tools for use with the normal Go testing system.
+//
+// Example Usage
+//
+// The following is a complete example using assert in a standard test function:
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(t, a, b, "The two words should be the same.")
+//
+// }
+//
+// if you assert many times, use the below:
+//
+// import (
+// "testing"
+// "github.com/stretchr/testify/assert"
+// )
+//
+// func TestSomething(t *testing.T) {
+// assert := assert.New(t)
+//
+// var a string = "Hello"
+// var b string = "Hello"
+//
+// assert.Equal(a, b, "The two words should be the same.")
+// }
+//
+// Assertions
+//
+// Assertions allow you to easily write test code, and are global funcs in the `assert` package.
+// All assertion functions take, as the first argument, the `*testing.T` object provided by the
+// testing framework. This allows the assertion funcs to write the failings and other details to
+// the correct place.
+//
+// Every assertion function also takes an optional string message as the final argument,
+// allowing custom error messages to be appended to the message the assertion method outputs.
+//
+// Here is an overview of the assert functions:
+//
+// assert.Equal(t, expected, actual [, message [, format-args])
+//
+// assert.NotEqual(t, notExpected, actual [, message [, format-args]])
+//
+// assert.True(t, actualBool [, message [, format-args]])
+//
+// assert.False(t, actualBool [, message [, format-args]])
+//
+// assert.Nil(t, actualObject [, message [, format-args]])
+//
+// assert.NotNil(t, actualObject [, message [, format-args]])
+//
+// assert.Empty(t, actualObject [, message [, format-args]])
+//
+// assert.NotEmpty(t, actualObject [, message [, format-args]])
+//
+// assert.Len(t, actualObject, expectedLength, [, message [, format-args]])
+//
+// assert.Error(t, errorObject [, message [, format-args]])
+//
+// assert.NoError(t, errorObject [, message [, format-args]])
+//
+// assert.EqualError(t, theError, errString [, message [, format-args]])
+//
+// assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
+//
+// assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
+//
+// assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]])
+//
+// assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]])
+//
+// assert.Panics(t, func(){
+//
+// // call code that should panic
+//
+// } [, message [, format-args]])
+//
+// assert.NotPanics(t, func(){
+//
+// // call code that should not panic
+//
+// } [, message [, format-args]])
+//
+// assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
+//
+// assert.InDelta(t, numA, numB, delta, [, message [, format-args]])
+//
+// assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]])
+//
+// assert package contains Assertions object. it has assertion methods.
+//
+// Here is an overview of the assert functions:
+// assert.Equal(expected, actual [, message [, format-args])
+//
+// assert.NotEqual(notExpected, actual [, message [, format-args]])
+//
+// assert.True(actualBool [, message [, format-args]])
+//
+// assert.False(actualBool [, message [, format-args]])
+//
+// assert.Nil(actualObject [, message [, format-args]])
+//
+// assert.NotNil(actualObject [, message [, format-args]])
+//
+// assert.Empty(actualObject [, message [, format-args]])
+//
+// assert.NotEmpty(actualObject [, message [, format-args]])
+//
+// assert.Len(actualObject, expectedLength, [, message [, format-args]])
+//
+// assert.Error(errorObject [, message [, format-args]])
+//
+// assert.NoError(errorObject [, message [, format-args]])
+//
+// assert.EqualError(theError, errString [, message [, format-args]])
+//
+// assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
+//
+// assert.IsType(expectedObject, actualObject [, message [, format-args]])
+//
+// assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]])
+//
+// assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]])
+//
+// assert.Panics(func(){
+//
+// // call code that should panic
+//
+// } [, message [, format-args]])
+//
+// assert.NotPanics(func(){
+//
+// // call code that should not panic
+//
+// } [, message [, format-args]])
+//
+// assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
+//
+// assert.InDelta(numA, numB, delta, [, message [, format-args]])
+//
+// assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]])
+package assert
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go
new file mode 100644
index 0000000000..ac9dc9d1d6
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go
@@ -0,0 +1,10 @@
+package assert
+
+import (
+ "errors"
+)
+
+// AnError is an error instance useful for testing. If the code does not care
+// about error specifics, and only needs to return the error for example, this
+// error should be used to make the test code more readable.
+var AnError = errors.New("assert.AnError general error for testing")
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
new file mode 100644
index 0000000000..e2866f8be0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
@@ -0,0 +1,252 @@
+package assert
+
+import "time"
+
+type Assertions struct {
+ t TestingT
+}
+
+func New(t TestingT) *Assertions {
+ return &Assertions{
+ t: t,
+ }
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// IsType asserts that the specified objects are of the same type.
+func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ return IsType(a.t, expectedType, object, msgAndArgs...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// assert.Equal(123, 123, "123 and 123 should be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Equal(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactly asserts that two objects are equal is value and type.
+//
+// assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// assert.NotNil(err, "err should be something")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// assert.Nil(err, "err should be nothing")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a
+// slice with len == 0.
+//
+// assert.Empty(obj)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+// Empty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a
+// slice with len == 0.
+//
+// if assert.NotEmpty(obj) {
+// assert.Equal("two", obj[1])
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// assert.Len(mySlice, 3, "The size of slice is not 3")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+// True asserts that the specified value is true.
+//
+// assert.True(myBool, "myBool should be true")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ return True(a.t, value, msgAndArgs...)
+}
+
+// False asserts that the specified value is true.
+//
+// assert.False(myBool, "myBool should be false")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ return False(a.t, value, msgAndArgs...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// Contains asserts that the specified string contains the specified substring.
+//
+// assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContains asserts that the specified string does NOT contain the specified substring.
+//
+// assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// Uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panics(func(){
+// GoCrazy()
+// }, "Calling GoCrazy() should panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanics(func(){
+// RemainCalm()
+// }, "Calling RemainCalm() should NOT panic")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoError(err) {
+// assert.Equal(actualObj, expectedObj)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
+ return NoError(a.t, theError, msgAndArgs...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(err, "An error was expected") {
+// assert.Equal(err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
+ return Error(a.t, theError, msgAndArgs...)
+}
+
+// EqualError asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// if assert.Error(err, "An error was expected") {
+// assert.Equal(err, expectedError)
+// }
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
+// assert.Regexp(t, "start...$", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) Regexp(rx interface{}, str interface{}) bool {
+ return Regexp(a.t, rx, str)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
+// assert.NotRegexp(t, "^start", "it's not starting")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}) bool {
+ return NotRegexp(a.t, rx, str)
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
new file mode 100644
index 0000000000..20cca6e21e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
@@ -0,0 +1,518 @@
+package assert
+
+import (
+ "errors"
+ "regexp"
+ "testing"
+ "time"
+)
+
+func TestImplementsWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) {
+ t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface")
+ }
+ if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) {
+ t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface")
+ }
+}
+
+func TestIsTypeWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) {
+ t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject")
+ }
+ if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) {
+ t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject")
+ }
+
+}
+
+func TestEqualWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.Equal("Hello World", "Hello World") {
+ t.Error("Equal should return true")
+ }
+ if !assert.Equal(123, 123) {
+ t.Error("Equal should return true")
+ }
+ if !assert.Equal(123.5, 123.5) {
+ t.Error("Equal should return true")
+ }
+ if !assert.Equal([]byte("Hello World"), []byte("Hello World")) {
+ t.Error("Equal should return true")
+ }
+ if !assert.Equal(nil, nil) {
+ t.Error("Equal should return true")
+ }
+}
+
+func TestNotNilWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.NotNil(new(AssertionTesterConformingObject)) {
+ t.Error("NotNil should return true: object is not nil")
+ }
+ if assert.NotNil(nil) {
+ t.Error("NotNil should return false: object is nil")
+ }
+
+}
+
+func TestNilWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.Nil(nil) {
+ t.Error("Nil should return true: object is nil")
+ }
+ if assert.Nil(new(AssertionTesterConformingObject)) {
+ t.Error("Nil should return false: object is not nil")
+ }
+
+}
+
+func TestTrueWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.True(true) {
+ t.Error("True should return true")
+ }
+ if assert.True(false) {
+ t.Error("True should return false")
+ }
+
+}
+
+func TestFalseWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ if !assert.False(false) {
+ t.Error("False should return true")
+ }
+ if assert.False(true) {
+ t.Error("False should return false")
+ }
+
+}
+
+func TestExactlyWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ a := float32(1)
+ b := float64(1)
+ c := float32(1)
+ d := float32(2)
+
+ if assert.Exactly(a, b) {
+ t.Error("Exactly should return false")
+ }
+ if assert.Exactly(a, d) {
+ t.Error("Exactly should return false")
+ }
+ if !assert.Exactly(a, c) {
+ t.Error("Exactly should return true")
+ }
+
+ if assert.Exactly(nil, a) {
+ t.Error("Exactly should return false")
+ }
+ if assert.Exactly(a, nil) {
+ t.Error("Exactly should return false")
+ }
+
+}
+
+func TestNotEqualWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+
+ if !assert.NotEqual("Hello World", "Hello World!") {
+ t.Error("NotEqual should return true")
+ }
+ if !assert.NotEqual(123, 1234) {
+ t.Error("NotEqual should return true")
+ }
+ if !assert.NotEqual(123.5, 123.55) {
+ t.Error("NotEqual should return true")
+ }
+ if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) {
+ t.Error("NotEqual should return true")
+ }
+ if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) {
+ t.Error("NotEqual should return true")
+ }
+}
+
+func TestContainsWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+ list := []string{"Foo", "Bar"}
+
+ if !assert.Contains("Hello World", "Hello") {
+ t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
+ }
+ if assert.Contains("Hello World", "Salut") {
+ t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"")
+ }
+
+ if !assert.Contains(list, "Foo") {
+ t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
+ }
+ if assert.Contains(list, "Salut") {
+ t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"")
+ }
+
+}
+
+func TestNotContainsWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+ list := []string{"Foo", "Bar"}
+
+ if !assert.NotContains("Hello World", "Hello!") {
+ t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
+ }
+ if assert.NotContains("Hello World", "Hello") {
+ t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"")
+ }
+
+ if !assert.NotContains(list, "Foo!") {
+ t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"")
+ }
+ if assert.NotContains(list, "Foo") {
+ t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
+ }
+
+}
+
+func TestConditionWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+
+ if !assert.Condition(func() bool { return true }, "Truth") {
+ t.Error("Condition should return true")
+ }
+
+ if assert.Condition(func() bool { return false }, "Lie") {
+ t.Error("Condition should return false")
+ }
+
+}
+
+func TestDidPanicWrapper(t *testing.T) {
+
+ if funcDidPanic, _ := didPanic(func() {
+ panic("Panic!")
+ }); !funcDidPanic {
+ t.Error("didPanic should return true")
+ }
+
+ if funcDidPanic, _ := didPanic(func() {
+ }); funcDidPanic {
+ t.Error("didPanic should return false")
+ }
+
+}
+
+func TestPanicsWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+
+ if !assert.Panics(func() {
+ panic("Panic!")
+ }) {
+ t.Error("Panics should return true")
+ }
+
+ if assert.Panics(func() {
+ }) {
+ t.Error("Panics should return false")
+ }
+
+}
+
+func TestNotPanicsWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+
+ if !assert.NotPanics(func() {
+ }) {
+ t.Error("NotPanics should return true")
+ }
+
+ if assert.NotPanics(func() {
+ panic("Panic!")
+ }) {
+ t.Error("NotPanics should return false")
+ }
+
+}
+
+func TestEqualWrapper_Funcs(t *testing.T) {
+
+ assert := New(t)
+
+ type f func() int
+ var f1 f = func() int { return 1 }
+ var f2 f = func() int { return 2 }
+
+ var f1_copy f = f1
+
+ assert.Equal(f1_copy, f1, "Funcs are the same and should be considered equal")
+ assert.NotEqual(f1, f2, "f1 and f2 are different")
+
+}
+
+func TestNoErrorWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ // start with a nil error
+ var err error = nil
+
+ assert.True(mockAssert.NoError(err), "NoError should return True for nil arg")
+
+ // now set an error
+ err = errors.New("Some error")
+
+ assert.False(mockAssert.NoError(err), "NoError with error should return False")
+
+}
+
+func TestErrorWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ // start with a nil error
+ var err error = nil
+
+ assert.False(mockAssert.Error(err), "Error should return False for nil arg")
+
+ // now set an error
+ err = errors.New("Some error")
+
+ assert.True(mockAssert.Error(err), "Error with error should return True")
+
+}
+
+func TestEqualErrorWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ // start with a nil error
+ var err error
+ assert.False(mockAssert.EqualError(err, ""),
+ "EqualError should return false for nil arg")
+
+ // now set an error
+ err = errors.New("some error")
+ assert.False(mockAssert.EqualError(err, "Not some error"),
+ "EqualError should return false for different error string")
+ assert.True(mockAssert.EqualError(err, "some error"),
+ "EqualError should return true")
+}
+
+func TestEmptyWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ assert.True(mockAssert.Empty(""), "Empty string is empty")
+ assert.True(mockAssert.Empty(nil), "Nil is empty")
+ assert.True(mockAssert.Empty([]string{}), "Empty string array is empty")
+ assert.True(mockAssert.Empty(0), "Zero int value is empty")
+ assert.True(mockAssert.Empty(false), "False value is empty")
+
+ assert.False(mockAssert.Empty("something"), "Non Empty string is not empty")
+ assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty")
+ assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty")
+ assert.False(mockAssert.Empty(1), "Non-zero int value is not empty")
+ assert.False(mockAssert.Empty(true), "True value is not empty")
+
+}
+
+func TestNotEmptyWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ assert.False(mockAssert.NotEmpty(""), "Empty string is empty")
+ assert.False(mockAssert.NotEmpty(nil), "Nil is empty")
+ assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty")
+ assert.False(mockAssert.NotEmpty(0), "Zero int value is empty")
+ assert.False(mockAssert.NotEmpty(false), "False value is empty")
+
+ assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty")
+ assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty")
+ assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty")
+ assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty")
+ assert.True(mockAssert.NotEmpty(true), "True value is not empty")
+
+}
+
+func TestLenWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ assert.False(mockAssert.Len(nil, 0), "nil does not have length")
+ assert.False(mockAssert.Len(0, 0), "int does not have length")
+ assert.False(mockAssert.Len(true, 0), "true does not have length")
+ assert.False(mockAssert.Len(false, 0), "false does not have length")
+ assert.False(mockAssert.Len('A', 0), "Rune does not have length")
+ assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length")
+
+ ch := make(chan int, 5)
+ ch <- 1
+ ch <- 2
+ ch <- 3
+
+ cases := []struct {
+ v interface{}
+ l int
+ }{
+ {[]int{1, 2, 3}, 3},
+ {[...]int{1, 2, 3}, 3},
+ {"ABC", 3},
+ {map[int]int{1: 2, 2: 4, 3: 6}, 3},
+ {ch, 3},
+
+ {[]int{}, 0},
+ {map[int]int{}, 0},
+ {make(chan int), 0},
+
+ {[]int(nil), 0},
+ {map[int]int(nil), 0},
+ {(chan int)(nil), 0},
+ }
+
+ for _, c := range cases {
+ assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l)
+ }
+}
+
+func TestWithinDurationWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+ a := time.Now()
+ b := a.Add(10 * time.Second)
+
+ assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference")
+ assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference")
+
+ assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference")
+ assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference")
+
+ assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference")
+ assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference")
+
+ assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference")
+ assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference")
+}
+
+func TestInDeltaWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01")
+ True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01")
+ True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1")
+ False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail")
+ False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail")
+ False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail")
+
+ cases := []struct {
+ a, b interface{}
+ delta float64
+ }{
+ {uint8(2), uint8(1), 1},
+ {uint16(2), uint16(1), 1},
+ {uint32(2), uint32(1), 1},
+ {uint64(2), uint64(1), 1},
+
+ {int(2), int(1), 1},
+ {int8(2), int8(1), 1},
+ {int16(2), int16(1), 1},
+ {int32(2), int32(1), 1},
+ {int64(2), int64(1), 1},
+
+ {float32(2), float32(1), 1},
+ {float64(2), float64(1), 1},
+ }
+
+ for _, tc := range cases {
+ True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta)
+ }
+}
+
+func TestInEpsilonWrapper(t *testing.T) {
+ assert := New(new(testing.T))
+
+ cases := []struct {
+ a, b interface{}
+ epsilon float64
+ }{
+ {uint8(2), uint16(2), .001},
+ {2.1, 2.2, 0.1},
+ {2.2, 2.1, 0.1},
+ {-2.1, -2.2, 0.1},
+ {-2.2, -2.1, 0.1},
+ {uint64(100), uint8(101), 0.01},
+ {0.1, -0.1, 2},
+ }
+
+ for _, tc := range cases {
+ True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
+ }
+
+ cases = []struct {
+ a, b interface{}
+ epsilon float64
+ }{
+ {uint8(2), int16(-2), .001},
+ {uint64(100), uint8(102), 0.01},
+ {2.1, 2.2, 0.001},
+ {2.2, 2.1, 0.001},
+ {2.1, -2.2, 1},
+ {2.1, "bla-bla", 0},
+ {0.1, -0.1, 1.99},
+ }
+
+ for _, tc := range cases {
+ False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
+ }
+}
+
+func TestRegexpWrapper(t *testing.T) {
+
+ assert := New(new(testing.T))
+
+ cases := []struct {
+ rx, str string
+ }{
+ {"^start", "start of the line"},
+ {"end$", "in the end"},
+ {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"},
+ }
+
+ for _, tc := range cases {
+ True(t, assert.Regexp(tc.rx, tc.str))
+ True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
+ False(t, assert.NotRegexp(tc.rx, tc.str))
+ False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
+ }
+
+ cases = []struct {
+ rx, str string
+ }{
+ {"^asdfastart", "Not the start of the line"},
+ {"end$", "in the end."},
+ {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"},
+ }
+
+ for _, tc := range cases {
+ False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str)
+ False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str))
+ True(t, assert.NotRegexp(tc.rx, tc.str))
+ True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
+ }
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
new file mode 100644
index 0000000000..0bcb6db9b8
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
@@ -0,0 +1,157 @@
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+)
+
+// httpCode is a helper that returns HTTP code of the response. It returns -1
+// if building a new request fails.
+func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return -1
+ }
+ handler(w, req)
+ return w.Code
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(t, myHandler, "POST", http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ code := httpCode(handler, mode, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusOK && code <= http.StatusPartialContent
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ code := httpCode(handler, mode, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ code := httpCode(handler, mode, url, values)
+ if code == -1 {
+ return false
+ }
+ return code >= http.StatusBadRequest
+}
+
+// HttpBody is a helper that returns HTTP body of the response. It returns
+// empty string if building a new request fails.
+func HttpBody(handler http.HandlerFunc, mode, url string, values url.Values) string {
+ w := httptest.NewRecorder()
+ req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
+ if err != nil {
+ return ""
+ }
+ handler(w, req)
+ return w.Body.String()
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
+ body := HttpBody(handler, mode, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if !contains {
+ Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body))
+ }
+
+ return contains
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
+ body := HttpBody(handler, mode, url, values)
+
+ contains := strings.Contains(body, fmt.Sprint(str))
+ if contains {
+ Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)
+ }
+
+ return !contains
+}
+
+//
+// Assertions Wrappers
+//
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccess(myHandler, "POST", http://www.google.com", nil)
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ return HTTPSuccess(a.t, handler, mode, url, values)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ return HTTPRedirect(a.t, handler, mode, url, values)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPError(handler http.HandlerFunc, mode, url string, values url.Values) bool {
+ return HTTPError(a.t, handler, mode, url, values)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyContains(a.t, handler, mode, url, values, str)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
+ return HTTPBodyNotContains(a.t, handler, mode, url, values, str)
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go
new file mode 100644
index 0000000000..684c2d5d1c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go
@@ -0,0 +1,86 @@
+package assert
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "testing"
+)
+
+func httpOK(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+}
+
+func httpRedirect(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusTemporaryRedirect)
+}
+
+func httpError(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusInternalServerError)
+}
+
+func TestHTTPStatuses(t *testing.T) {
+ assert := New(t)
+ mockT := new(testing.T)
+
+ assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true)
+ assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false)
+ assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false)
+
+ assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false)
+ assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true)
+ assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false)
+
+ assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false)
+ assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false)
+ assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true)
+}
+
+func TestHTTPStatusesWrapper(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true)
+ assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false)
+ assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false)
+
+ assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false)
+ assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true)
+ assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false)
+
+ assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false)
+ assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false)
+ assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true)
+}
+
+func httpHelloName(w http.ResponseWriter, r *http.Request) {
+ name := r.FormValue("name")
+ w.Write([]byte(fmt.Sprintf("Hello, %s!", name)))
+}
+
+func TestHttpBody(t *testing.T) {
+ assert := New(t)
+ mockT := new(testing.T)
+
+ assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
+ assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
+ assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
+
+ assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
+ assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
+ assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
+}
+
+func TestHttpBodyWrappers(t *testing.T) {
+ assert := New(t)
+ mockAssert := New(new(testing.T))
+
+ assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
+ assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
+ assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
+
+ assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!"))
+ assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World"))
+ assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world"))
+
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
new file mode 100644
index 0000000000..7d4e7b8d39
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
@@ -0,0 +1,43 @@
+// Provides a system by which it is possible to mock your objects and verify calls are happening as expected.
+//
+// Example Usage
+//
+// The mock package provides an object, Mock, that tracks activity on another object. It is usually
+// embedded into a test object as shown below:
+//
+// type MyTestObject struct {
+// // add a Mock object instance
+// mock.Mock
+//
+// // other fields go here as normal
+// }
+//
+// When implementing the methods of an interface, you wire your functions up
+// to call the Mock.Called(args...) method, and return the appropriate values.
+//
+// For example, to mock a method that saves the name and age of a person and returns
+// the year of their birth or an error, you might write this:
+//
+// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) {
+// args := o.Mock.Called(firstname, lastname, age)
+// return args.Int(0), args.Error(1)
+// }
+//
+// The Int, Error and Bool methods are examples of strongly typed getters that take the argument
+// index position. Given this argument list:
+//
+// (12, true, "Something")
+//
+// You could read them out strongly typed like this:
+//
+// args.Int(0)
+// args.Bool(1)
+// args.String(2)
+//
+// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion:
+//
+// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine)
+//
+// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those
+// cases you should check for nil first.
+package mock
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
new file mode 100644
index 0000000000..f73fa2516b
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
@@ -0,0 +1,510 @@
+package mock
+
+import (
+ "fmt"
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+)
+
+// TestingT is an interface wrapper around *testing.T
+type TestingT interface {
+ Logf(format string, args ...interface{})
+ Errorf(format string, args ...interface{})
+}
+
+/*
+ Call
+*/
+
+// Call represents a method call and is used for setting expectations,
+// as well as recording activity.
+type Call struct {
+
+ // The name of the method that was or will be called.
+ Method string
+
+ // Holds the arguments of the method.
+ Arguments Arguments
+
+ // Holds the arguments that should be returned when
+ // this method is called.
+ ReturnArguments Arguments
+
+ // The number of times to return the return arguments when setting
+ // expectations. 0 means to always return the value.
+ Repeatability int
+}
+
+// Mock is the workhorse used to track activity on another object.
+// For an example of its usage, refer to the "Example Usage" section at the top of this document.
+type Mock struct {
+
+ // The method name that is currently
+ // being referred to by the On method.
+ onMethodName string
+
+ // An array of the arguments that are
+ // currently being referred to by the On method.
+ onMethodArguments Arguments
+
+ // Represents the calls that are expected of
+ // an object.
+ ExpectedCalls []Call
+
+ // Holds the calls that were made to this mocked object.
+ Calls []Call
+
+ // TestData holds any data that might be useful for testing. Testify ignores
+ // this data completely allowing you to do whatever you like with it.
+ testData objx.Map
+
+ mutex sync.Mutex
+}
+
+// TestData holds any data that might be useful for testing. Testify ignores
+// this data completely allowing you to do whatever you like with it.
+func (m *Mock) TestData() objx.Map {
+
+ if m.testData == nil {
+ m.testData = make(objx.Map)
+ }
+
+ return m.testData
+}
+
+/*
+ Setting expectations
+*/
+
+// On starts a description of an expectation of the specified method
+// being called.
+//
+// Mock.On("MyMethod", arg1, arg2)
+func (m *Mock) On(methodName string, arguments ...interface{}) *Mock {
+ m.onMethodName = methodName
+ m.onMethodArguments = arguments
+ return m
+}
+
+// Return finishes a description of an expectation of the method (and arguments)
+// specified in the most recent On method call.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2)
+func (m *Mock) Return(returnArguments ...interface{}) *Mock {
+ m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0})
+ return m
+}
+
+// Once indicates that that the mock should only return the value once.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
+func (m *Mock) Once() {
+ m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 1
+}
+
+// Twice indicates that that the mock should only return the value twice.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
+func (m *Mock) Twice() {
+ m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 2
+}
+
+// Times indicates that that the mock should only return the indicated number
+// of times.
+//
+// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
+func (m *Mock) Times(i int) {
+ m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = i
+}
+
+/*
+ Recording and responding to activity
+*/
+
+func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
+ for i, call := range m.ExpectedCalls {
+ if call.Method == method && call.Repeatability > -1 {
+
+ _, diffCount := call.Arguments.Diff(arguments)
+ if diffCount == 0 {
+ return i, &call
+ }
+
+ }
+ }
+ return -1, nil
+}
+
+func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
+
+ diffCount := 0
+ var closestCall *Call = nil
+
+ for _, call := range m.ExpectedCalls {
+ if call.Method == method {
+
+ _, tempDiffCount := call.Arguments.Diff(arguments)
+ if tempDiffCount < diffCount || diffCount == 0 {
+ diffCount = tempDiffCount
+ closestCall = &call
+ }
+
+ }
+ }
+
+ if closestCall == nil {
+ return false, nil
+ }
+
+ return true, closestCall
+}
+
+func callString(method string, arguments Arguments, includeArgumentValues bool) string {
+
+ var argValsString string = ""
+ if includeArgumentValues {
+ var argVals []string
+ for argIndex, arg := range arguments {
+ argVals = append(argVals, fmt.Sprintf("%d: %v", argIndex, arg))
+ }
+ argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
+ }
+
+ return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString)
+}
+
+// Called tells the mock object that a method has been called, and gets an array
+// of arguments to return. Panics if the call is unexpected (i.e. not preceeded by
+// appropriate .On .Return() calls)
+func (m *Mock) Called(arguments ...interface{}) Arguments {
+ defer m.mutex.Unlock()
+ m.mutex.Lock()
+
+ // get the calling function's name
+ pc, _, _, ok := runtime.Caller(1)
+ if !ok {
+ panic("Couldn't get the caller information")
+ }
+ functionPath := runtime.FuncForPC(pc).Name()
+ parts := strings.Split(functionPath, ".")
+ functionName := parts[len(parts)-1]
+
+ found, call := m.findExpectedCall(functionName, arguments...)
+
+ switch {
+ case found < 0:
+ // we have to fail here - because we don't know what to do
+ // as the return arguments. This is because:
+ //
+ // a) this is a totally unexpected call to this method,
+ // b) the arguments are not what was expected, or
+ // c) the developer has forgotten to add an accompanying On...Return pair.
+
+ closestFound, closestCall := m.findClosestCall(functionName, arguments...)
+
+ if closestFound {
+ panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true)))
+ } else {
+ panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo()))
+ }
+ case call.Repeatability == 1:
+ call.Repeatability = -1
+ m.ExpectedCalls[found] = *call
+ case call.Repeatability > 1:
+ call.Repeatability -= 1
+ m.ExpectedCalls[found] = *call
+ }
+
+ // add the call
+ m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0})
+
+ return call.ReturnArguments
+
+}
+
+/*
+ Assertions
+*/
+
+// AssertExpectationsForObjects asserts that everything specified with On and Return
+// of the specified objects was in fact called as expected.
+//
+// Calls may have occurred in any order.
+func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
+ var success bool = true
+ for _, obj := range testObjects {
+ mockObj := obj.(Mock)
+ success = success && mockObj.AssertExpectations(t)
+ }
+ return success
+}
+
+// AssertExpectations asserts that everything specified with On and Return was
+// in fact called as expected. Calls may have occurred in any order.
+func (m *Mock) AssertExpectations(t TestingT) bool {
+
+ var somethingMissing bool = false
+ var failedExpectations int = 0
+
+ // iterate through each expectation
+ for _, expectedCall := range m.ExpectedCalls {
+ switch {
+ case !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments):
+ somethingMissing = true
+ failedExpectations++
+ t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
+ case expectedCall.Repeatability > 0:
+ somethingMissing = true
+ failedExpectations++
+ default:
+ t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
+ }
+ }
+
+ if somethingMissing {
+ t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(m.ExpectedCalls)-failedExpectations, len(m.ExpectedCalls), failedExpectations, assert.CallerInfo())
+ }
+
+ return !somethingMissing
+}
+
+// AssertNumberOfCalls asserts that the method was called expectedCalls times.
+func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
+ var actualCalls int = 0
+ for _, call := range m.Calls {
+ if call.Method == methodName {
+ actualCalls++
+ }
+ }
+ return assert.Equal(t, actualCalls, expectedCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
+}
+
+// AssertCalled asserts that the method was called.
+func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool {
+ if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) {
+ t.Logf("%s", m.ExpectedCalls)
+ return false
+ }
+ return true
+}
+
+// AssertNotCalled asserts that the method was not called.
+func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool {
+ if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) {
+ t.Logf("%s", m.ExpectedCalls)
+ return false
+ }
+ return true
+}
+
+func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
+ for _, call := range m.Calls {
+ if call.Method == methodName {
+
+ _, differences := Arguments(expected).Diff(call.Arguments)
+
+ if differences == 0 {
+ // found the expected call
+ return true
+ }
+
+ }
+ }
+ // we didn't find the expected call
+ return false
+}
+
+/*
+ Arguments
+*/
+
+// Arguments holds an array of method arguments or return values.
+type Arguments []interface{}
+
+const (
+ // The "any" argument. Used in Diff and Assert when
+ // the argument being tested shouldn't be taken into consideration.
+ Anything string = "mock.Anything"
+)
+
+// AnythingOfTypeArgument is a string that contains the type of an argument
+// for use when type checking. Used in Diff and Assert.
+type AnythingOfTypeArgument string
+
+// AnythingOfType returns an AnythingOfTypeArgument object containing the
+// name of the type to check for. Used in Diff and Assert.
+//
+// For example:
+// Assert(t, AnythingOfType("string"), AnythingOfType("int"))
+func AnythingOfType(t string) AnythingOfTypeArgument {
+ return AnythingOfTypeArgument(t)
+}
+
+// Get Returns the argument at the specified index.
+func (args Arguments) Get(index int) interface{} {
+ if index+1 > len(args) {
+ panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args)))
+ }
+ return args[index]
+}
+
+// Is gets whether the objects match the arguments specified.
+func (args Arguments) Is(objects ...interface{}) bool {
+ for i, obj := range args {
+ if obj != objects[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// Diff gets a string describing the differences between the arguments
+// and the specified objects.
+//
+// Returns the diff string and number of differences found.
+func (args Arguments) Diff(objects []interface{}) (string, int) {
+
+ var output string = "\n"
+ var differences int
+
+ var maxArgCount int = len(args)
+ if len(objects) > maxArgCount {
+ maxArgCount = len(objects)
+ }
+
+ for i := 0; i < maxArgCount; i++ {
+ var actual, expected interface{}
+
+ if len(objects) <= i {
+ actual = "(Missing)"
+ } else {
+ actual = objects[i]
+ }
+
+ if len(args) <= i {
+ expected = "(Missing)"
+ } else {
+ expected = args[i]
+ }
+
+ if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
+
+ // type checking
+ if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
+ // not match
+ differences++
+ output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual)
+ }
+
+ } else {
+
+ // normal checking
+
+ if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) {
+ // match
+ output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected)
+ } else {
+ // not match
+ differences++
+ output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected)
+ }
+ }
+
+ }
+
+ if differences == 0 {
+ return "No differences.", differences
+ }
+
+ return output, differences
+
+}
+
+// Assert compares the arguments with the specified objects and fails if
+// they do not exactly match.
+func (args Arguments) Assert(t TestingT, objects ...interface{}) bool {
+
+ // get the differences
+ diff, diffCount := args.Diff(objects)
+
+ if diffCount == 0 {
+ return true
+ }
+
+ // there are differences... report them...
+ t.Logf(diff)
+ t.Errorf("%sArguments do not match.", assert.CallerInfo())
+
+ return false
+
+}
+
+// String gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+//
+// If no index is provided, String() returns a complete string representation
+// of the arguments.
+func (args Arguments) String(indexOrNil ...int) string {
+
+ if len(indexOrNil) == 0 {
+ // normal String() method - return a string representation of the args
+ var argsStr []string
+ for _, arg := range args {
+ argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg)))
+ }
+ return strings.Join(argsStr, ",")
+ } else if len(indexOrNil) == 1 {
+ // Index has been specified - get the argument at that index
+ var index int = indexOrNil[0]
+ var s string
+ var ok bool
+ if s, ok = args.Get(index).(string); !ok {
+ panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index)))
+ }
+ return s
+ }
+
+ panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil)))
+
+}
+
+// Int gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Int(index int) int {
+ var s int
+ var ok bool
+ if s, ok = args.Get(index).(int); !ok {
+ panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
+
+// Error gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Error(index int) error {
+ obj := args.Get(index)
+ var s error
+ var ok bool
+ if obj == nil {
+ return nil
+ }
+ if s, ok = obj.(error); !ok {
+ panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
+
+// Bool gets the argument at the specified index. Panics if there is no argument, or
+// if the argument is of the wrong type.
+func (args Arguments) Bool(index int) bool {
+ var s bool
+ var ok bool
+ if s, ok = args.Get(index).(bool); !ok {
+ panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index)))
+ }
+ return s
+}
diff --git a/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
new file mode 100644
index 0000000000..353d810483
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
@@ -0,0 +1,669 @@
+package mock
+
+import (
+ "errors"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+/*
+ Test objects
+*/
+
+// ExampleInterface represents an example interface.
+type ExampleInterface interface {
+ TheExampleMethod(a, b, c int) (int, error)
+}
+
+// TestExampleImplementation is a test implementation of ExampleInterface
+type TestExampleImplementation struct {
+ Mock
+}
+
+func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) {
+ args := i.Mock.Called(a, b, c)
+ return args.Int(0), errors.New("Whoops")
+}
+
+func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) {
+ i.Mock.Called(yesorno)
+}
+
+type ExampleType struct{}
+
+func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error {
+ args := i.Mock.Called(et)
+ return args.Error(0)
+}
+
+/*
+ Mock
+*/
+
+func Test_Mock_TestData(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ if assert.NotNil(t, mockedService.TestData()) {
+
+ mockedService.TestData().Set("something", 123)
+ assert.Equal(t, 123, mockedService.TestData().Get("something").Data())
+
+ }
+
+}
+
+func Test_Mock_On(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ assert.Equal(t, mockedService.Mock.On("TheExampleMethod"), &mockedService.Mock)
+ assert.Equal(t, "TheExampleMethod", mockedService.Mock.onMethodName)
+
+}
+
+func Test_Mock_On_WithArgs(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ assert.Equal(t, mockedService.Mock.On("TheExampleMethod", 1, 2, 3), &mockedService.Mock)
+ assert.Equal(t, "TheExampleMethod", mockedService.Mock.onMethodName)
+ assert.Equal(t, 1, mockedService.Mock.onMethodArguments[0])
+ assert.Equal(t, 2, mockedService.Mock.onMethodArguments[1])
+ assert.Equal(t, 3, mockedService.Mock.onMethodArguments[2])
+
+}
+
+func Test_Mock_Return(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true), &mockedService.Mock)
+
+ // ensure the call was created
+ if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 0, call.Repeatability)
+
+ }
+
+}
+
+func Test_Mock_Return_Once(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Once()
+
+ // ensure the call was created
+ if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 1, call.Repeatability)
+
+ }
+
+}
+
+func Test_Mock_Return_Twice(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Twice()
+
+ // ensure the call was created
+ if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 2, call.Repeatability)
+
+ }
+
+}
+
+func Test_Mock_Return_Times(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Times(5)
+
+ // ensure the call was created
+ if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 1, call.ReturnArguments[0])
+ assert.Equal(t, "two", call.ReturnArguments[1])
+ assert.Equal(t, true, call.ReturnArguments[2])
+ assert.Equal(t, 5, call.Repeatability)
+
+ }
+
+}
+
+func Test_Mock_Return_Nothing(t *testing.T) {
+
+ // make a test impl object
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(), &mockedService.Mock)
+
+ // ensure the call was created
+ if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
+ call := mockedService.Mock.ExpectedCalls[0]
+
+ assert.Equal(t, "TheExampleMethod", call.Method)
+ assert.Equal(t, "A", call.Arguments[0])
+ assert.Equal(t, "B", call.Arguments[1])
+ assert.Equal(t, true, call.Arguments[2])
+ assert.Equal(t, 0, len(call.ReturnArguments))
+
+ }
+
+}
+
+func Test_Mock_findExpectedCall(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two")
+ m.On("Two", 3).Return("three")
+
+ f, c := m.findExpectedCall("Two", 3)
+
+ if assert.Equal(t, 2, f) {
+ if assert.NotNil(t, c) {
+ assert.Equal(t, "Two", c.Method)
+ assert.Equal(t, 3, c.Arguments[0])
+ assert.Equal(t, "three", c.ReturnArguments[0])
+ }
+ }
+
+}
+
+func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two")
+ m.On("Two", 3).Return("three")
+
+ f, _ := m.findExpectedCall("Two")
+
+ assert.Equal(t, -1, f)
+
+}
+
+func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) {
+
+ m := new(Mock)
+ m.On("One", 1).Return("one")
+ m.On("Two", 2).Return("two").Once()
+ m.On("Two", 3).Return("three").Twice()
+ m.On("Two", 3).Return("three").Times(8)
+
+ f, c := m.findExpectedCall("Two", 3)
+
+ if assert.Equal(t, 2, f) {
+ if assert.NotNil(t, c) {
+ assert.Equal(t, "Two", c.Method)
+ assert.Equal(t, 3, c.Arguments[0])
+ assert.Equal(t, "three", c.ReturnArguments[0])
+ }
+ }
+
+}
+
+func Test_callString(t *testing.T) {
+
+ assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false))
+
+}
+
+func Test_Mock_Called(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true)
+
+ returnArguments := mockedService.Mock.Called(1, 2, 3)
+
+ if assert.Equal(t, 1, len(mockedService.Mock.Calls)) {
+ assert.Equal(t, "Test_Mock_Called", mockedService.Mock.Calls[0].Method)
+ assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0])
+ assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1])
+ assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments)) {
+ assert.Equal(t, 5, returnArguments[0])
+ assert.Equal(t, "6", returnArguments[1])
+ assert.Equal(t, true, returnArguments[2])
+ }
+
+}
+
+func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(5, "6", true).Once()
+ mockedService.Mock.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(-1, "hi", false)
+
+ returnArguments1 := mockedService.Mock.Called(1, 2, 3)
+ returnArguments2 := mockedService.Mock.Called(1, 2, 3)
+
+ if assert.Equal(t, 2, len(mockedService.Mock.Calls)) {
+ assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Mock.Calls[0].Method)
+ assert.Equal(t, 1, mockedService.Mock.Calls[0].Arguments[0])
+ assert.Equal(t, 2, mockedService.Mock.Calls[0].Arguments[1])
+ assert.Equal(t, 3, mockedService.Mock.Calls[0].Arguments[2])
+
+ assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Mock.Calls[1].Method)
+ assert.Equal(t, 1, mockedService.Mock.Calls[1].Arguments[0])
+ assert.Equal(t, 2, mockedService.Mock.Calls[1].Arguments[1])
+ assert.Equal(t, 3, mockedService.Mock.Calls[1].Arguments[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments1)) {
+ assert.Equal(t, 5, returnArguments1[0])
+ assert.Equal(t, "6", returnArguments1[1])
+ assert.Equal(t, true, returnArguments1[2])
+ }
+
+ if assert.Equal(t, 3, len(returnArguments2)) {
+ assert.Equal(t, -1, returnArguments2[0])
+ assert.Equal(t, "hi", returnArguments2[1])
+ assert.Equal(t, false, returnArguments2[2])
+ }
+
+}
+
+func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4)
+
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ mockedService.TheExampleMethod(1, 2, 3)
+ assert.Panics(t, func() {
+ mockedService.TheExampleMethod(1, 2, 3)
+ })
+
+}
+
+func Test_Mock_Called_Unexpected(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ // make sure it panics if no expectation was made
+ assert.Panics(t, func() {
+ mockedService.Mock.Called(1, 2, 3)
+ }, "Calling unexpected method should panic")
+
+}
+
+func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
+
+ var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
+ var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
+ var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService1.Mock.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
+ mockedService2.Mock.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
+ mockedService3.Mock.On("Test_AssertExpectationsForObjects_Helper", 3).Return()
+
+ mockedService1.Called(1)
+ mockedService2.Called(2)
+ mockedService3.Called(3)
+
+ assert.True(t, AssertExpectationsForObjects(t, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
+
+}
+
+func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
+
+ var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
+ var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
+ var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService1.Mock.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return()
+ mockedService2.Mock.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return()
+ mockedService3.Mock.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return()
+
+ mockedService1.Called(1)
+ mockedService3.Called(3)
+
+ tt := new(testing.T)
+ assert.False(t, AssertExpectationsForObjects(tt, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock))
+
+}
+
+func Test_Mock_AssertExpectations(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7)
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Mock.Called(1, 2, 3)
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once()
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.TheExampleMethod3(&ExampleType{})
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice()
+
+ tt := new(testing.T)
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ // make the call now
+ mockedService.Mock.Called(1, 2, 3)
+
+ assert.False(t, mockedService.AssertExpectations(tt))
+
+ mockedService.Mock.Called(1, 2, 3)
+
+ // now assert expectations
+ assert.True(t, mockedService.AssertExpectations(tt))
+
+}
+
+func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7)
+ mockedService.Mock.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7)
+
+ args1 := mockedService.Mock.Called(1, 2, 3)
+ assert.Equal(t, 5, args1.Int(0))
+ assert.Equal(t, 6, args1.Int(1))
+ assert.Equal(t, 7, args1.Int(2))
+
+ args2 := mockedService.Mock.Called(4, 5, 6)
+ assert.Equal(t, 5, args2.Int(0))
+ assert.Equal(t, 6, args2.Int(1))
+ assert.Equal(t, 7, args2.Int(2))
+
+}
+
+func Test_Mock_AssertNumberOfCalls(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Mock.Called(1, 2, 3)
+ assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1))
+
+ mockedService.Mock.Called(1, 2, 3)
+ assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2))
+
+}
+
+func Test_Mock_AssertCalled(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Mock.Called(1, 2, 3)
+
+ assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3))
+
+}
+
+func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).Return()
+
+ mockedService.Mock.Called(1, "two", []uint8("three"))
+
+ assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8")))
+
+}
+
+func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Mock.Called(1, 2, 3)
+
+ tt := new(testing.T)
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3))
+ assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4))
+
+}
+
+func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once()
+ mockedService.Mock.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once()
+
+ mockedService.Mock.Called(1, 2, 3)
+ mockedService.Mock.Called(2, 3, 4)
+
+ tt := new(testing.T)
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3))
+ assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4))
+ assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5))
+
+}
+
+func Test_Mock_AssertNotCalled(t *testing.T) {
+
+ var mockedService *TestExampleImplementation = new(TestExampleImplementation)
+
+ mockedService.Mock.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7)
+
+ mockedService.Mock.Called(1, 2, 3)
+
+ assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled"))
+
+}
+
+/*
+ Arguments helper methods
+*/
+func Test_Arguments_Get(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+
+ assert.Equal(t, "string", args.Get(0).(string))
+ assert.Equal(t, 123, args.Get(1).(int))
+ assert.Equal(t, true, args.Get(2).(bool))
+
+}
+
+func Test_Arguments_Is(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+
+ assert.True(t, args.Is("string", 123, true))
+ assert.False(t, args.Is("wrong", 456, false))
+
+}
+
+func Test_Arguments_Diff(t *testing.T) {
+
+ var args Arguments = []interface{}{"Hello World", 123, true}
+ var diff string
+ var count int
+ diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
+
+ assert.Equal(t, 2, count)
+ assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`)
+ assert.Contains(t, diff, `false != %!s(bool=true)`)
+
+}
+
+func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ var diff string
+ var count int
+ diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
+
+ assert.Equal(t, 3, count)
+ assert.Contains(t, diff, `extra != (Missing)`)
+
+}
+
+func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ var count int
+ _, count = args.Diff([]interface{}{"string", Anything, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", Anything, true}
+ var count int
+ _, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", AnythingOfType("int"), true}
+ var count int
+ _, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 0, count)
+
+}
+
+func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", AnythingOfType("string"), true}
+ var count int
+ var diff string
+ diff, count = args.Diff([]interface{}{"string", 123, true})
+
+ assert.Equal(t, 1, count)
+ assert.Contains(t, diff, `string != type int - %!s(int=123)`)
+
+}
+
+func Test_Arguments_Assert(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+
+ assert.True(t, args.Assert(t, "string", 123, true))
+
+}
+
+func Test_Arguments_String_Representation(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ assert.Equal(t, `string,int,bool`, args.String())
+
+}
+
+func Test_Arguments_String(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ assert.Equal(t, "string", args.String(0))
+
+}
+
+func Test_Arguments_Error(t *testing.T) {
+
+ var err error = errors.New("An Error")
+ var args Arguments = []interface{}{"string", 123, true, err}
+ assert.Equal(t, err, args.Error(3))
+
+}
+
+func Test_Arguments_Error_Nil(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true, nil}
+ assert.Equal(t, nil, args.Error(3))
+
+}
+
+func Test_Arguments_Int(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ assert.Equal(t, 123, args.Int(1))
+
+}
+
+func Test_Arguments_Bool(t *testing.T) {
+
+ var args Arguments = []interface{}{"string", 123, true}
+ assert.Equal(t, true, args.Bool(2))
+
+}