diff --git a/bootstrap/cmd/bootstrap/app/options/options.go b/bootstrap/cmd/bootstrap/app/options/options.go index a9f2ca26196..0e6f633f351 100644 --- a/bootstrap/cmd/bootstrap/app/options/options.go +++ b/bootstrap/cmd/bootstrap/app/options/options.go @@ -25,6 +25,7 @@ type ServerOption struct { JsonLogFormat bool AppDir string KfVersion string + NameSpace string } // NewServerOption creates a new CMServer with a default config. @@ -39,5 +40,6 @@ func (s *ServerOption) AddFlags(fs *flag.FlagSet) { fs.BoolVar(&s.JsonLogFormat, "json-log-format", true, "Set true to use json style log format. Set false to use plaintext style log format") fs.StringVar(&s.AppDir, "app-dir", "", "The directory for the ksonnet application.") fs.StringVar(&s.KfVersion, "kubeflow-version", "v0.1.0-rc.4", "The Kubeflow version to use.") + fs.StringVar(&s.NameSpace, "namespace", "kubeflow", "The namespace where all resources for kubeflow will be created") fs.BoolVar(&s.Apply, "apply", true, "Whether or not to apply the configuraiton.") } diff --git a/bootstrap/cmd/bootstrap/app/server.go b/bootstrap/cmd/bootstrap/app/server.go index 880a468848b..736bc403f51 100644 --- a/bootstrap/cmd/bootstrap/app/server.go +++ b/bootstrap/cmd/bootstrap/app/server.go @@ -29,6 +29,8 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" clientset "k8s.io/client-go/kubernetes" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + core_v1 "k8s.io/api/core/v1" + type_v1 "k8s.io/client-go/kubernetes/typed/core/v1" "os" "path" @@ -49,8 +51,6 @@ const RecommendedConfigPathEnvVar = "KUBECONFIG" // whether a storage class is the default. const DefaultStorageAnnotation = "storageclass.beta.kubernetes.io/is-default-class" -const DefaultNamespace = "kubeflow" - // Assume gcloud is on the path. const GcloudPath = "gcloud" @@ -98,7 +98,7 @@ func getKubeConfigFile() string { // gGetClusterConfig obtain the config from the Kube configuration used by kubeconfig. // -func getClusterConfig() (*rest.Config, string, error) { +func getClusterConfig() (*rest.Config, error) { configFile := getKubeConfigFile() if len(configFile) > 0 { @@ -113,21 +113,15 @@ func getClusterConfig() (*rest.Config, string, error) { rawConfig, err := clientConfig.RawConfig() if err != nil { - return nil, "", err + return nil, err } if err := modifyGcloudCommand(&rawConfig); err != nil { - return nil, "", err - } - - namespace, _, err := clientConfig.Namespace() - - if err != nil { - return nil, "", err + return nil, err } config, err := clientConfig.ClientConfig() - return config, namespace, err + return config, err } // Work around https://github.com/kubernetes/kubernetes/issues/40973 @@ -138,7 +132,7 @@ func getClusterConfig() (*rest.Config, string, error) { panic(err) } if err := os.Setenv("KUBERNETES_SERVICE_HOST", addrs[0]); err != nil { - return nil, "", err + return nil, err } } if len(os.Getenv("KUBERNETES_SERVICE_PORT")) == 0 { @@ -148,7 +142,7 @@ func getClusterConfig() (*rest.Config, string, error) { } config, err := rest.InClusterConfig() - return config, DefaultNamespace, err + return config, err } func isGke(v *k8sVersion.Info) bool { @@ -183,6 +177,24 @@ func hasDefaultStorage(sClasses *v1.StorageClassList) bool { return false } +func setupNamespace(namespaces type_v1.NamespaceInterface, name_space string) error { + namespace, err := namespaces.Get(name_space, meta_v1.GetOptions{}) + if err == nil { + log.Infof("Using existing namespace: %v", namespace.Name) + } else { + log.Infof("Creating namespace: %v for all kubeflow resources", name_space) + _, err = namespaces.Create( + &core_v1.Namespace{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: name_space, + }, + }, + ) + return err + } + return err +} + // Run the tool. func Run(opt *options.ServerOption) error { // Check if the -version flag was passed and, if so, print the version and exit. @@ -190,8 +202,7 @@ func Run(opt *options.ServerOption) error { version.PrintVersionAndExit() } - config, namespace, err := getClusterConfig() - log.Infof("Using namespace: %v", namespace) + config, err := getClusterConfig() if err != nil { return err } @@ -201,6 +212,11 @@ func Run(opt *options.ServerOption) error { return err } + err = setupNamespace(kubeClient.CoreV1().Namespaces(), opt.NameSpace) + if err != nil { + return err + } + clusterVersion, err := kubeClient.DiscoveryClient.ServerVersion() if err != nil { @@ -237,7 +253,7 @@ func Run(opt *options.ServerOption) error { // TODO(jlewi): What is the proper version to use? It shouldn't be a version like v1.9.0-gke as that // will create an error because ksonnet will be unable to fetch a swagger spec. actions.OptionSpecFlag: "version:v1.7.0", - actions.OptionNamespace: namespace, + actions.OptionNamespace: opt.NameSpace, actions.OptionSkipDefaultRegistries: true, } diff --git a/bootstrap/cmd/bootstrap/app/server_test.go b/bootstrap/cmd/bootstrap/app/server_test.go index aef88fcb0f7..9e44a67bf65 100644 --- a/bootstrap/cmd/bootstrap/app/server_test.go +++ b/bootstrap/cmd/bootstrap/app/server_test.go @@ -20,9 +20,13 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "reflect" - "k8s.io/api/storage/v1" k8sVersion "k8s.io/apimachinery/pkg/version" + "github.com/stretchr/testify/mock" + core_v1 "k8s.io/api/core/v1" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + type_v1 "k8s.io/client-go/kubernetes/typed/core/v1" + "errors" ) func TestModifyGcloudCommand(t *testing.T) { @@ -139,3 +143,47 @@ func TestHasDefaultStorageClass(t *testing.T) { } } } + +type MockedNamespace struct{ + mock.Mock + type_v1.NamespaceInterface +} + +func (n *MockedNamespace) Get(name string, options meta_v1.GetOptions) (*core_v1.Namespace, error) { + if name == "existing" { + return &core_v1.Namespace{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "existing", + }, + }, nil + } + return nil, errors.New("not found") +} + +func (n *MockedNamespace) Create(ns *core_v1.Namespace) (*core_v1.Namespace, error) { + n.Called(ns) + // no consumer of return value, so return nil + return nil, nil +} + +// Make sure setupNamespace will create namespace if and only if the namespace doesn't exist. +func TestSetupNamespace(t *testing.T) { + // create an instance of our test object + mockedNamespace := new(MockedNamespace) + + nsIns := &core_v1.Namespace{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "new", + }, + } + mockedNamespace.On("Create", nsIns).Return( + nsIns, nil) + + // "Create" should be called 0 times when namespace exists already + setupNamespace(mockedNamespace, "existing") + mockedNamespace.AssertNumberOfCalls(t, "Create", 0) + + // "Create" should be called 1 times when namespace doesn't exist + setupNamespace(mockedNamespace, "new") + mockedNamespace.AssertNumberOfCalls(t, "Create", 1) +} diff --git a/bootstrap/glide.lock b/bootstrap/glide.lock index 40162b92afd..d0f387a4cc1 100644 --- a/bootstrap/glide.lock +++ b/bootstrap/glide.lock @@ -1,5 +1,5 @@ -hash: 4d217d52169f8a667803c80293d401e822e0882e88e9339f95e6cf588b7c3d9d -updated: 2018-04-06T09:44:17.779027411-07:00 +hash: f9b98ee92edf64bacb84e736efc13f87ea69ae788161300c7a86d2ddd45ca783 +updated: 2018-04-12T19:11:57.909552-07:00 imports: - name: cloud.google.com/go version: 3b1ae45394a234c385be014e9a488f2bb6eef821 @@ -173,6 +173,11 @@ imports: version: 4dab30cb33e6633c33c787106bafbfbfdde7842d - name: github.com/spf13/pflag version: 1ce0cc6db4029d97571db82f85092fccedb572ce +- name: github.com/stretchr/testify + version: 12b6f73e6084dad08a7c6e575284b177ecafbc71 + subpackages: + - assert + - mock - name: golang.org/x/crypto version: 81e90905daefcd6fd217b62423c0908922eadb30 subpackages: @@ -246,6 +251,7 @@ imports: - certificates/v1beta1 - core/v1 - extensions/v1beta1 + - imagepolicy/v1alpha1 - networking/v1 - policy/v1beta1 - rbac/v1 @@ -352,4 +358,10 @@ imports: version: 868f2f29720b192240e18284659231b440f9cda5 subpackages: - pkg/common -testImports: [] +testImports: +- name: github.com/pmezard/go-difflib + version: d8ed2627bdf02c080bf22230dbb337003b7aba2d + subpackages: + - difflib +- name: github.com/stretchr/objx + version: 8a3f7159479fbc75b30357fbc48f380b7320f08e diff --git a/bootstrap/glide.yaml b/bootstrap/glide.yaml index 0b24e3e5da1..bca7c5c027a 100644 --- a/bootstrap/glide.yaml +++ b/bootstrap/glide.yaml @@ -7,3 +7,5 @@ import: - filename - package: github.com/sirupsen/logrus version: ^1.0.5 +- package: github.com/stretchr/testify + version: ^1.2.0 \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_comp b/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_comp new file mode 100644 index 00000000000..ffbc5a72c93 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_comp @@ -0,0 +1,5 @@ +{ + field: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_mixin_with_string_index b/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_mixin_with_string_index new file mode 100644 index 00000000000..dd470748b9c --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet-lib/ksonnet-gen/printer/testdata/object_mixin_with_string_index @@ -0,0 +1,4 @@ +{ + "id"+: { + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/component/helpers_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/component/helpers_test.go new file mode 100644 index 00000000000..8523ffc040b --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/component/helpers_test.go @@ -0,0 +1,38 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package component + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/ksonnet/ksonnet/metadata/app/mocks" + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/spf13/afero" + "github.com/stretchr/testify/require" +) + +func withAppOsFs(t *testing.T, root string, fn func(*mocks.App, afero.Fs)) { + dir, err := ioutil.TempDir("", "") + require.NoError(t, err) + + defer os.RemoveAll(dir) + + fs := afero.NewBasePathFs(afero.NewOsFs(), dir) + + test.WithAppFs(t, root, fs, fn) +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/delete/env-global.txt b/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/delete/env-global.txt new file mode 100644 index 00000000000..d69c4bc53e8 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/delete/env-global.txt @@ -0,0 +1,10 @@ +COMPONENT INDEX PARAM VALUE +========= ===== ===== ===== +guestbook-ui 0 containerPort 80 +guestbook-ui 0 env-value 2 +guestbook-ui 0 image "gcr.io/heptio-images/ks-guestbook-demo:0.1" +guestbook-ui 0 local-value 1 +guestbook-ui 0 name "guestbook-ui" +guestbook-ui 0 replicas 1 +guestbook-ui 0 servicePort 80 +guestbook-ui 0 type "ClusterIP" diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/set/env-global.txt b/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/set/env-global.txt new file mode 100644 index 00000000000..eeca1080f18 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/e2e/testdata/output/param/set/env-global.txt @@ -0,0 +1,9 @@ +COMPONENT INDEX PARAM VALUE +========= ===== ===== ===== +guestbook-ui 0 containerPort 80 +guestbook-ui 0 department "engineering" +guestbook-ui 0 image "gcr.io/heptio-images/ks-guestbook-demo:0.1" +guestbook-ui 0 name "guestbook-ui" +guestbook-ui 0 replicas 1 +guestbook-ui 0 servicePort 80 +guestbook-ui 0 type "ClusterIP" diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/add-global.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/add-global.libsonnet new file mode 100644 index 00000000000..5f11c2bea4d --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/add-global.libsonnet @@ -0,0 +1,3 @@ +{ + foo: "bar", +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/globals.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/globals.libsonnet new file mode 100644 index 00000000000..5f11c2bea4d --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/globals.libsonnet @@ -0,0 +1,3 @@ +{ + foo: "bar", +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/remove-global.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/remove-global.libsonnet new file mode 100644 index 00000000000..7a73a41bfdf --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/env/testdata/remove-global.libsonnet @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover.go new file mode 100644 index 00000000000..21a1649c524 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover.go @@ -0,0 +1,148 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "bytes" + "fmt" + + "github.com/google/go-jsonnet/ast" + "github.com/ksonnet/ksonnet-lib/ksonnet-gen/astext" + "github.com/ksonnet/ksonnet/pkg/util/jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var ( + errUnsupportedEnvParams = errors.New("unsupported param format. cannot programmatically remove component") +) + +// EnvComponentRemover removes param configuration for components +// from env params libsonnet files. +type EnvComponentRemover struct { +} + +// NewEnvComponentRemover creates an instance of EnvComponentRemover. +func NewEnvComponentRemover() *EnvComponentRemover { + ecr := &EnvComponentRemover{} + + return ecr +} + +// Remove removes component name from the jsonnet snippet. +func (ecr *EnvComponentRemover) Remove(componentName, snippet string) (string, error) { + if componentName == "" { + return "", errors.New("component name was blank") + } + + logger := logrus.WithField("component-name", componentName) + logger.Info("removing environment component") + + n, err := jsonnet.ParseNode("params.libsonnet", snippet) + if err != nil { + return "", err + } + + obj, err := componentParams(n, componentName) + if err != nil { + return "", err + } + + if err = ecr.deleteEntry(obj, componentName); err != nil { + return "", errors.Wrap(err, "delete entry") + } + + var buf bytes.Buffer + if err = jsonnetPrinterFn(&buf, n); err != nil { + return "", errors.Wrap(err, "unable to update snippet") + } + + return buf.String(), nil +} + +func (ecr *EnvComponentRemover) deleteEntry(obj *astext.Object, componentName string) error { + of, err := findField(obj, "components") + if err != nil { + return errors.Wrap(errUnsupportedEnvParams, "unable to find components field") + } + + componentsObj, ok := of.Expr2.(*astext.Object) + if !ok { + return errors.Wrap(errUnsupportedEnvParams, "components field is not an object") + } + + match := -1 + + var id string + for i := range componentsObj.Fields { + id, err = jsonnet.FieldID(componentsObj.Fields[i]) + if err != nil { + return err + } + + if id == componentName { + match = i + } + } + + if match >= 0 { + componentsObj.Fields = append(componentsObj.Fields[:match], + componentsObj.Fields[match+1:]...) + } + + return nil +} + +func findNamedLocal(l *ast.Local, name string) (*ast.Local, error) { + if len(l.Binds) != 1 { + return nil, errors.New("local has multiple binds") + } + + if name == string(l.Binds[0].Variable) { + return l, nil + } + + next, ok := l.Body.(*ast.Local) + if !ok { + return nil, errors.New("unable to find local by name") + } + + return findNamedLocal(next, name) +} + +// TODO: export find field in jsonnet and delete this +func findField(object *astext.Object, id string) (*astext.ObjectField, error) { + for i := range object.Fields { + fieldID, err := jsonnet.FieldID(object.Fields[i]) + if err != nil { + return nil, err + } + + if id == fieldID { + return &object.Fields[i], nil + } + } + + return nil, &unknownField{name: id} +} + +type unknownField struct { + name string +} + +func (e *unknownField) Error() string { + return fmt.Sprintf("unable to find field %q", e.name) +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover_test.go new file mode 100644 index 00000000000..de29e500997 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_component_remover_test.go @@ -0,0 +1,60 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "path/filepath" + "testing" + + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestEnvComponentRemover(t *testing.T) { + componentName := "guestbook" + + cases := []struct { + name string + input string + output string + }{ + { + name: "no globals", + input: filepath.Join("env", "no-globals", "remove-component", "in.libsonnet"), + output: filepath.Join("env", "no-globals", "remove-component", "out.libsonnet"), + }, + { + name: "globals", + input: filepath.Join("env", "globals", "remove-component", "in.libsonnet"), + output: filepath.Join("env", "globals", "remove-component", "out.libsonnet"), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snippet := test.ReadTestData(t, tc.input) + + ecr := NewEnvComponentRemover() + + got, err := ecr.Remove(componentName, snippet) + require.NoError(t, err) + + expected := test.ReadTestData(t, tc.output) + require.Equal(t, expected, got) + }) + } + +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set.go new file mode 100644 index 00000000000..a204be3c884 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set.go @@ -0,0 +1,87 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "bytes" + + "github.com/ksonnet/ksonnet-lib/ksonnet-gen/astext" + nm "github.com/ksonnet/ksonnet-lib/ksonnet-gen/nodemaker" + "github.com/ksonnet/ksonnet/metadata/params" + "github.com/ksonnet/ksonnet/pkg/util/jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// EnvGlobalsSet sets environment globals. +type EnvGlobalsSet struct { +} + +// NewEnvGlobalsSet creates an instance of EnvGlobalsSet. +func NewEnvGlobalsSet() *EnvGlobalsSet { + egs := &EnvGlobalsSet{} + return egs +} + +// Set sets params in environment globals files. +func (egs *EnvGlobalsSet) Set(snippet string, p params.Params) (string, error) { + logger := logrus.WithFields(logrus.Fields{}) + logger.Info("setting environment globals") + + n, err := jsonnet.ParseNode("globals.libsonnet", snippet) + if err != nil { + return "", err + } + + obj, err := componentParams(n, "") + if err != nil { + return "", err + } + + if err = egs.setParams(obj, p); err != nil { + return "", errors.Wrap(err, "delete entry") + } + + // root node should be a local if not, return an error + var buf bytes.Buffer + if err = jsonnetPrinterFn(&buf, n); err != nil { + return "", errors.Wrap(err, "unable to update snippet") + } + + return buf.String(), nil +} + +func (egs *EnvGlobalsSet) setParams(obj *astext.Object, p params.Params) error { + for key := range p { + decoded, err := DecodeValue(p[key]) + if err != nil { + return err + } + + value, err := nm.ValueToNoder(decoded) + if err != nil { + return err + } + + path := []string{key} + if err = jsonnetSetFn(obj, path, value.Node()); err != nil { + return err + } + + } + + return nil +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set_test.go new file mode 100644 index 00000000000..323f1876765 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_set_test.go @@ -0,0 +1,57 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "path/filepath" + "testing" + + "github.com/ksonnet/ksonnet/metadata/params" + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestEnvGlobalsSet(t *testing.T) { + cases := []struct { + name string + input string + output string + params params.Params + }{ + { + name: "in general", + input: filepath.Join("env", "globals", "set-global", "in.libsonnet"), + output: filepath.Join("env", "globals", "set-global", "out.libsonnet"), + params: params.Params{ + "group": "dev", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snippet := test.ReadTestData(t, tc.input) + + egs := NewEnvGlobalsSet() + + got, err := egs.Set(snippet, tc.params) + require.NoError(t, err) + + expected := test.ReadTestData(t, tc.output) + require.Equal(t, expected, got) + }) + } +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset.go new file mode 100644 index 00000000000..3e88a136abe --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset.go @@ -0,0 +1,89 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "bytes" + + "github.com/ksonnet/ksonnet-lib/ksonnet-gen/astext" + "github.com/ksonnet/ksonnet/pkg/util/jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// EnvGlobalsUnset un-sets global environment params. +type EnvGlobalsUnset struct { +} + +// NewEnvGlobalsUnset creates an instance of EnvGlobalsUnset. +func NewEnvGlobalsUnset() *EnvGlobalsUnset { + egu := &EnvGlobalsUnset{} + return egu +} + +// Unset un-sets globals. +func (epu *EnvGlobalsUnset) Unset(paramName, snippet string) (string, error) { + if paramName == "" { + return "", errors.New("global name was blank") + } + + logger := logrus.WithFields(logrus.Fields{}) + logger.WithField("name", paramName).Info("removing environment global") + + n, err := jsonnet.ParseNode("params.libsonnet", snippet) + if err != nil { + return "", err + } + + obj, err := componentParams(n, "") + if err != nil { + return "", err + } + + if err = epu.unsetEntry(obj, paramName); err != nil { + return "", errors.Wrap(err, "delete entry") + } + + var buf bytes.Buffer + if err = jsonnetPrinterFn(&buf, n); err != nil { + return "", errors.Wrap(err, "unable to update snippet") + } + + return buf.String(), nil +} + +func (epu *EnvGlobalsUnset) unsetEntry(obj *astext.Object, paramName string) error { + match := -1 + + var id string + var err error + for i := range obj.Fields { + id, err = jsonnet.FieldID(obj.Fields[i]) + if err != nil { + return err + } + + if id == paramName { + match = i + } + } + + if match >= 0 { + obj.Fields = append(obj.Fields[:match], obj.Fields[match+1:]...) + } + + return nil +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset_test.go new file mode 100644 index 00000000000..379899b1ffc --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_globals_unset_test.go @@ -0,0 +1,54 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "path/filepath" + "testing" + + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestEnvGlobalsUnset(t *testing.T) { + cases := []struct { + name string + input string + output string + paramName string + }{ + { + name: "in general", + input: filepath.Join("env", "globals", "unset-global", "in.libsonnet"), + output: filepath.Join("env", "globals", "unset-global", "out.libsonnet"), + paramName: "group", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snippet := test.ReadTestData(t, tc.input) + + egu := NewEnvGlobalsUnset() + + got, err := egu.Unset(tc.paramName, snippet) + require.NoError(t, err) + + expected := test.ReadTestData(t, tc.output) + require.Equal(t, expected, got) + }) + } +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set.go new file mode 100644 index 00000000000..500ea148eb8 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set.go @@ -0,0 +1,122 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "bytes" + + "github.com/google/go-jsonnet/ast" + "github.com/ksonnet/ksonnet-lib/ksonnet-gen/astext" + nm "github.com/ksonnet/ksonnet-lib/ksonnet-gen/nodemaker" + "github.com/ksonnet/ksonnet/metadata/params" + "github.com/ksonnet/ksonnet/pkg/util/jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// EnvParamSet sets environment params for a component. +type EnvParamSet struct { +} + +// NewEnvParamSet creates an instance of EnvParamSet. +func NewEnvParamSet() *EnvParamSet { + epa := &EnvParamSet{} + return epa +} + +// Set sets params in environment parameter files. +func (epa *EnvParamSet) Set(componentName, snippet string, p params.Params) (string, error) { + if componentName == "" { + return "", errors.New("component name was blank") + } + + logger := logrus.WithField("component-name", componentName) + logger.Info("setting environment component") + + n, err := jsonnet.ParseNode("params.libsonnet", snippet) + if err != nil { + return "", err + } + + obj, err := componentParams(n, componentName) + if err != nil { + return "", err + } + + if err = epa.setParams(obj, componentName, p); err != nil { + return "", errors.Wrap(err, "delete entry") + } + + // root node should be a local if not, return an error + var buf bytes.Buffer + if err = jsonnetPrinterFn(&buf, n); err != nil { + return "", errors.Wrap(err, "unable to update snippet") + } + + return buf.String(), nil +} + +func (epa *EnvParamSet) setParams(obj *astext.Object, componentName string, p params.Params) error { + of, err := findField(obj, "components") + if err != nil { + return errors.Wrap(errUnsupportedEnvParams, "unable to find components field") + } + + componentsObj, ok := of.Expr2.(*astext.Object) + if !ok { + return errors.Wrap(errUnsupportedEnvParams, "components field is not an object") + } + + var componentObj *astext.Object + of, err = findField(componentsObj, componentName) + if err == nil { + of.SuperSugar = true + componentObj, ok = of.Expr2.(*astext.Object) + if !ok { + return errors.Wrapf(errUnsupportedEnvParams, "component field %q is not an object", componentName) + } + } else { + componentObj = &astext.Object{} + of, err := astext.CreateField(componentName) + if err != nil { + return err + } + of.SuperSugar = true + of.Expr2 = componentObj + of.Hide = ast.ObjectFieldInherit + componentsObj.Fields = append(componentsObj.Fields, *of) + } + + for key := range p { + decoded, err := DecodeValue(p[key]) + if err != nil { + return err + } + + value, err := nm.ValueToNoder(decoded) + if err != nil { + return err + } + + path := []string{key} + if err = jsonnetSetFn(componentObj, path, value.Node()); err != nil { + return err + } + + } + + return nil +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set_test.go new file mode 100644 index 00000000000..42b429af44f --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_set_test.go @@ -0,0 +1,77 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "path/filepath" + "testing" + + "github.com/ksonnet/ksonnet/metadata/params" + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestEnvParamSet(t *testing.T) { + cases := []struct { + name string + input string + output string + componentName string + params params.Params + }{ + { + name: "no globals", + input: filepath.Join("env", "no-globals", "set", "in.libsonnet"), + output: filepath.Join("env", "no-globals", "set", "out.libsonnet"), + componentName: "guestbook", + params: params.Params{ + "containerPort": "8080", + }, + }, + { + name: "globals", + input: filepath.Join("env", "globals", "set", "in.libsonnet"), + output: filepath.Join("env", "globals", "set", "out.libsonnet"), + componentName: "guestbook", + params: params.Params{ + "containerPort": "8080", + }, + }, + { + name: "globals new component", + input: filepath.Join("env", "globals", "set", "in.libsonnet"), + output: filepath.Join("env", "globals", "set", "out-new-component.libsonnet"), + componentName: "component", + params: params.Params{ + "name": "new-component", + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snippet := test.ReadTestData(t, tc.input) + + epa := NewEnvParamSet() + + got, err := epa.Set(tc.componentName, snippet, tc.params) + require.NoError(t, err) + + expected := test.ReadTestData(t, tc.output) + require.Equal(t, expected, got) + }) + } +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset.go new file mode 100644 index 00000000000..f676f32d0a3 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset.go @@ -0,0 +1,110 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "bytes" + + "github.com/ksonnet/ksonnet-lib/ksonnet-gen/astext" + "github.com/ksonnet/ksonnet/pkg/util/jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +// EnvParamUnset unset param configuration for components +// from env params libsonnet files. +type EnvParamUnset struct { +} + +// NewEnvParamUnset creates an instance of EnvParamUnset. +func NewEnvParamUnset() *EnvParamUnset { + epu := &EnvParamUnset{} + return epu +} + +// Unset un-sets params. +func (epu *EnvParamUnset) Unset(componentName, paramName, snippet string) (string, error) { + if componentName == "" { + return "", errors.New("component name was blank") + } + + logger := logrus.WithField("component-name", componentName) + logger.Info("removing environment component") + + n, err := jsonnet.ParseNode("params.libsonnet", snippet) + if err != nil { + return "", err + } + + obj, err := componentParams(n, componentName) + if err != nil { + return "", err + } + + if err = epu.unsetEntry(obj, componentName, paramName); err != nil { + return "", errors.Wrap(err, "delete entry") + } + + var buf bytes.Buffer + if err = jsonnetPrinterFn(&buf, n); err != nil { + return "", errors.Wrap(err, "unable to update snippet") + } + + return buf.String(), nil +} + +func (epu *EnvParamUnset) unsetEntry(obj *astext.Object, componentName, paramName string) error { + of, err := findField(obj, "components") + if err != nil { + return errors.Wrap(errUnsupportedEnvParams, "unable to find components field") + } + + componentsObj, ok := of.Expr2.(*astext.Object) + if !ok { + return errors.Wrap(errUnsupportedEnvParams, "components field is not an object") + } + + of, err = findField(componentsObj, componentName) + if err != nil { + return errors.Wrapf(errUnsupportedEnvParams, "unable to find component %q field", componentName) + } + + componentObj, ok := of.Expr2.(*astext.Object) + if !ok { + return errors.Wrapf(errUnsupportedEnvParams, "component field %q is not an object", componentName) + } + + match := -1 + + var id string + for i := range componentObj.Fields { + id, err = jsonnet.FieldID(componentObj.Fields[i]) + if err != nil { + return err + } + + if id == paramName { + match = i + } + } + + if match >= 0 { + componentObj.Fields = append(componentObj.Fields[:match], + componentObj.Fields[match+1:]...) + } + + return nil +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset_test.go new file mode 100644 index 00000000000..b207e525364 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/env_param_unset_test.go @@ -0,0 +1,60 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package params + +import ( + "path/filepath" + "testing" + + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/stretchr/testify/require" +) + +func TestEnvParamRemover(t *testing.T) { + componentName := "guestbook" + paramName := "replicas" + + cases := []struct { + name string + input string + output string + }{ + { + name: "no globals", + input: filepath.Join("env", "no-globals", "unset", "in.libsonnet"), + output: filepath.Join("env", "no-globals", "unset", "out.libsonnet"), + }, + { + name: "globals", + input: filepath.Join("env", "globals", "unset", "in.libsonnet"), + output: filepath.Join("env", "globals", "unset", "out.libsonnet"), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snippet := test.ReadTestData(t, tc.input) + + epu := NewEnvParamUnset() + + got, err := epu.Unset(componentName, paramName, snippet) + require.NoError(t, err) + + expected := test.ReadTestData(t, tc.output) + require.Equal(t, expected, got) + }) + } +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/in.libsonnet new file mode 100644 index 00000000000..8237713c6b5 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/in.libsonnet @@ -0,0 +1,21 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components +: { + // Insert component parameter overrides here. Ex: + // guestbook +: { + // name: "guestbook-dev", + // replicas: params.global.replicas, + // }, + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/out.libsonnet new file mode 100644 index 00000000000..b0adfb45e11 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/remove-component/out.libsonnet @@ -0,0 +1,12 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components+: { + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/in.libsonnet new file mode 100644 index 00000000000..9e26dfeeb6e --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/in.libsonnet @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/out.libsonnet new file mode 100644 index 00000000000..48ec06e3588 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set-global/out.libsonnet @@ -0,0 +1,3 @@ +{ + group: "dev", +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/in.libsonnet new file mode 100644 index 00000000000..3b316c268d8 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/in.libsonnet @@ -0,0 +1,16 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components +: { + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out-new-component.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out-new-component.libsonnet new file mode 100644 index 00000000000..1e038232982 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out-new-component.libsonnet @@ -0,0 +1,19 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components+: { + guestbook+: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + component+: { + name: "new-component", + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out.libsonnet new file mode 100644 index 00000000000..84d61456978 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/set/out.libsonnet @@ -0,0 +1,17 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components+: { + guestbook+: { + name: "guestbook-dev", + replicas: params.global.replicas, + containerPort: 8080, + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/in.libsonnet new file mode 100644 index 00000000000..48ec06e3588 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/in.libsonnet @@ -0,0 +1,3 @@ +{ + group: "dev", +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/out.libsonnet new file mode 100644 index 00000000000..7a73a41bfdf --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset-global/out.libsonnet @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/in.libsonnet new file mode 100644 index 00000000000..3b316c268d8 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/in.libsonnet @@ -0,0 +1,16 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components +: { + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/out.libsonnet new file mode 100644 index 00000000000..5c00d57890d --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/globals/unset/out.libsonnet @@ -0,0 +1,15 @@ +local params = std.extVar("__ksonnet/params"); +local globals = import "globals.libsonnet"; +local envParams = params + { + components+: { + guestbook+: { + name: "guestbook-dev", + }, + }, +}; + +{ + components: { + [x]: envParams.components[x] + globals, for x in std.objectFields(envParams.components) + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/in.libsonnet new file mode 100644 index 00000000000..2025a37bb76 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/in.libsonnet @@ -0,0 +1,14 @@ +local params = import "../../components/params.libsonnet"; +params + { + components +: { + // Insert component parameter overrides here. Ex: + // guestbook +: { + // name: "guestbook-dev", + // replicas: params.global.replicas, + // }, + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/out.libsonnet new file mode 100644 index 00000000000..427df66c5c9 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/remove-component/out.libsonnet @@ -0,0 +1,6 @@ +local params = import "../../components/params.libsonnet"; + +params + { + components+: { + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/in.libsonnet new file mode 100644 index 00000000000..4ef5d3c518f --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/in.libsonnet @@ -0,0 +1,9 @@ +local params = import "../../components/params.libsonnet"; +params + { + components +: { + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/out.libsonnet new file mode 100644 index 00000000000..3c3af0d544d --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/set/out.libsonnet @@ -0,0 +1,11 @@ +local params = import "../../components/params.libsonnet"; + +params + { + components+: { + guestbook+: { + name: "guestbook-dev", + replicas: params.global.replicas, + containerPort: 8080, + }, + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/in.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/in.libsonnet new file mode 100644 index 00000000000..4ef5d3c518f --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/in.libsonnet @@ -0,0 +1,9 @@ +local params = import "../../components/params.libsonnet"; +params + { + components +: { + guestbook +: { + name: "guestbook-dev", + replicas: params.global.replicas, + }, + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/out.libsonnet b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/out.libsonnet new file mode 100644 index 00000000000..2455fa138f7 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/params/testdata/env/no-globals/unset/out.libsonnet @@ -0,0 +1,9 @@ +local params = import "../../components/params.libsonnet"; + +params + { + components+: { + guestbook+: { + name: "guestbook-dev", + }, + }, +} \ No newline at end of file diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm.go new file mode 100644 index 00000000000..752a0210e3e --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm.go @@ -0,0 +1,182 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonnet + +import ( + "fmt" + "path/filepath" + "strings" + "time" + + "github.com/google/go-jsonnet" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/spf13/afero" +) + +type makeVMFn func() *jsonnet.VM +type evaluateSnippetFn func(vm *jsonnet.VM, name, snippet string) (string, error) + +// VMOpt is an option for configuring VM. +type VMOpt func(*VM) + +// VM is a ksonnet wrapper for the jsonnet VM. +type VM struct { + // JPaths are jsonnet library paths + JPaths []string + // UseMemoryImporter forces the vm to use a memory importer rather than the + // file import. + UseMemoryImporter bool + Fs afero.Fs + + extCodes map[string]string + tlaCodes map[string]string + tlaVars map[string]string + + makeVMFn makeVMFn + evaluateSnippetFn evaluateSnippetFn +} + +// NewVM creates an instance of VM. +func NewVM(opts ...VMOpt) *VM { + vm := &VM{ + JPaths: make([]string, 0), + extCodes: make(map[string]string), + tlaCodes: make(map[string]string), + tlaVars: make(map[string]string), + + makeVMFn: jsonnet.MakeVM, + evaluateSnippetFn: evaluateSnippet, + } + + for _, opt := range opts { + opt(vm) + } + + return vm +} + +// ExtCode sets ExtCode for the jsonnet VM. +func (vm *VM) ExtCode(key, value string) { + vm.extCodes[key] = value +} + +// TLACode sets TLACode for the jsonnet VM. +func (vm *VM) TLACode(key, value string) { + vm.tlaCodes[key] = value +} + +// TLAVar sets TLAVar for the jsonnet VM. +func (vm *VM) TLAVar(key, value string) { + vm.tlaVars[key] = value +} + +func evaluateSnippet(vm *jsonnet.VM, name, snippet string) (string, error) { + return vm.EvaluateSnippet(name, snippet) +} + +// EvaluateSnippet evaluates a jsonnet snippet. +func (vm *VM) EvaluateSnippet(name, snippet string) (string, error) { + now := time.Now() + + fields := logrus.Fields{ + "jPaths": strings.Join(vm.JPaths, ", "), + "name": name, + "snippet": snippet, + } + + jvm := jsonnet.MakeVM() + jvm.ErrorFormatter.SetMaxStackTraceSize(40) + importer, err := vm.createImporter() + if err != nil { + return "", errors.Wrap(err, "create jsonnet importer") + } + jvm.Importer(importer) + + for k, v := range vm.extCodes { + jvm.ExtCode(k, v) + key := fmt.Sprintf("extCode#%s", k) + fields[key] = v + } + + for k, v := range vm.tlaCodes { + jvm.TLACode(k, v) + key := fmt.Sprintf("tlaCode#%s", k) + fields[key] = v + } + + for k, v := range vm.tlaVars { + jvm.TLAVar(k, v) + key := fmt.Sprintf("tlaVar#%s", k) + fields[key] = v + } + + defer func() { + fields["elapsed"] = time.Since(now) + logrus.WithFields(fields).Debug("jsonnet evaluate snippet") + }() + + return vm.evaluateSnippetFn(jvm, name, snippet) +} + +func (vm *VM) createImporter() (jsonnet.Importer, error) { + if !vm.UseMemoryImporter { + return &jsonnet.FileImporter{ + JPaths: vm.JPaths, + }, nil + } + + if vm.Fs == nil { + return nil, errors.New("unable to use memory importer without fs") + } + + importer := &jsonnet.MemoryImporter{ + Data: make(map[string]string), + } + + for _, jPath := range vm.JPaths { + fis, err := afero.ReadDir(vm.Fs, jPath) + if err != nil { + return nil, err + } + + for _, fi := range fis { + if fi.IsDir() { + continue + } + + s, err := vm.readString(filepath.Join(jPath, fi.Name())) + if err != nil { + return nil, err + } + + importer.Data[fi.Name()] = s + } + } + + return importer, nil +} + +func (vm *VM) readString(path string) (string, error) { + var b []byte + + b, err := afero.ReadFile(vm.Fs, path) + if err != nil { + return "", err + } + + return string(b), nil +} diff --git a/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm_test.go b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm_test.go new file mode 100644 index 00000000000..5d77a5b5046 --- /dev/null +++ b/bootstrap/vendor/github.com/ksonnet/ksonnet/pkg/util/jsonnet/vm_test.go @@ -0,0 +1,102 @@ +// Copyright 2018 The ksonnet authors +// +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonnet + +import ( + "testing" + + jsonnet "github.com/google/go-jsonnet" + "github.com/ksonnet/ksonnet/pkg/util/test" + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func stubVMOpt() VMOpt { + return func(vm *VM) { + vm.makeVMFn = func() *jsonnet.VM { return &jsonnet.VM{} } + } +} + +func stubVMEvalOpt(fn func(*jsonnet.VM, string, string) (string, error)) VMOpt { + return func(vm *VM) { + vm.evaluateSnippetFn = fn + } +} + +func TestVM_ExtCode(t *testing.T) { + vm := NewVM(stubVMOpt()) + vm.ExtCode("key", "value") + require.Equal(t, "value", vm.extCodes["key"]) +} + +func TestVM_TLACode(t *testing.T) { + vm := NewVM(stubVMOpt()) + vm.TLACode("key", "value") + require.Equal(t, "value", vm.tlaCodes["key"]) +} + +func TestVM_TLAVar(t *testing.T) { + vm := NewVM(stubVMOpt()) + vm.TLAVar("key", "value") + require.Equal(t, "value", vm.tlaVars["key"]) +} + +func TestVM_EvaluateSnippet(t *testing.T) { + + fn := func(vm *jsonnet.VM, name, snippet string) (string, error) { + assert.Equal(t, "snippet", name) + assert.Equal(t, "code", snippet) + + return "evaluated", nil + } + + vm := NewVM(stubVMOpt(), stubVMEvalOpt(fn)) + vm.TLAVar("key", "value") + vm.TLACode("key", "value") + vm.ExtCode("key", "value") + + out, err := vm.EvaluateSnippet("snippet", "code") + require.NoError(t, err) + + require.Equal(t, "evaluated", out) +} + +func TestVM_EvaluateSnippet_memory_importer(t *testing.T) { + fs := afero.NewMemMapFs() + test.StageFile(t, fs, "set-map.jsonnet", "/lib/set-map.jsonnet") + + fn := func(vm *jsonnet.VM, name, snippet string) (string, error) { + assert.Equal(t, "snippet", name) + assert.Equal(t, "code", snippet) + + return "evaluated", nil + } + + vm := NewVM(stubVMOpt(), stubVMEvalOpt(fn)) + vm.UseMemoryImporter = true + vm.Fs = fs + vm.JPaths = []string{"/lib"} + + vm.TLAVar("key", "value") + vm.TLACode("key", "value") + vm.ExtCode("key", "value") + + out, err := vm.EvaluateSnippet("snippet", "code") + require.NoError(t, err) + + require.Equal(t, "evaluated", out) +} diff --git a/bootstrap/vendor/github.com/pmezard/go-difflib/.travis.yml b/bootstrap/vendor/github.com/pmezard/go-difflib/.travis.yml new file mode 100644 index 00000000000..90c9c6f917f --- /dev/null +++ b/bootstrap/vendor/github.com/pmezard/go-difflib/.travis.yml @@ -0,0 +1,5 @@ +language: go +go: + - 1.5 + - tip + diff --git a/bootstrap/vendor/github.com/pmezard/go-difflib/LICENSE b/bootstrap/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 00000000000..c67dad612a3 --- /dev/null +++ b/bootstrap/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bootstrap/vendor/github.com/pmezard/go-difflib/README.md b/bootstrap/vendor/github.com/pmezard/go-difflib/README.md new file mode 100644 index 00000000000..e87f307ed44 --- /dev/null +++ b/bootstrap/vendor/github.com/pmezard/go-difflib/README.md @@ -0,0 +1,50 @@ +go-difflib +========== + +[![Build Status](https://travis-ci.org/pmezard/go-difflib.png?branch=master)](https://travis-ci.org/pmezard/go-difflib) +[![GoDoc](https://godoc.org/github.com/pmezard/go-difflib/difflib?status.svg)](https://godoc.org/github.com/pmezard/go-difflib/difflib) + +Go-difflib is a partial port of python 3 difflib package. Its main goal +was to make unified and context diff available in pure Go, mostly for +testing purposes. + +The following class and functions (and related tests) have be ported: + +* `SequenceMatcher` +* `unified_diff()` +* `context_diff()` + +## Installation + +```bash +$ go get github.com/pmezard/go-difflib/difflib +``` + +### Quick Start + +Diffs are configured with Unified (or ContextDiff) structures, and can +be output to an io.Writer or returned as a string. + +```Go +diff := UnifiedDiff{ + A: difflib.SplitLines("foo\nbar\n"), + B: difflib.SplitLines("foo\nbaz\n"), + FromFile: "Original", + ToFile: "Current", + Context: 3, +} +text, _ := GetUnifiedDiffString(diff) +fmt.Printf(text) +``` + +would output: + +``` +--- Original ++++ Current +@@ -1,3 +1,3 @@ + foo +-bar ++baz +``` + diff --git a/bootstrap/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/bootstrap/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 00000000000..64cc40fe1da --- /dev/null +++ b/bootstrap/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,758 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "
" lines in HTML files). That may be
+// because this is the only method of the 3 that has a *concept* of
+// "junk"
+ Use
+ One block per line
+
+ Template
+
+ {x}
as a placeholder for each argument.
+
+ Arguments (comma separated)
+
+
+ Output
+
+
+
+
+
+
+
+
+
diff --git a/bootstrap/vendor/github.com/stretchr/objx/codegen/template.txt b/bootstrap/vendor/github.com/stretchr/objx/codegen/template.txt
new file mode 100644
index 00000000000..047bfc13f14
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/codegen/template.txt
@@ -0,0 +1,124 @@
+/*
+ {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 {
+ 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 {
+ 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}
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/codegen/template_test.txt b/bootstrap/vendor/github.com/stretchr/objx/codegen/template_test.txt
new file mode 100644
index 00000000000..6490cb2df8e
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/codegen/template_test.txt
@@ -0,0 +1,120 @@
+/*
+ Tests for {4} ({1} and []{1})
+*/
+func Test{4}(t *testing.T) {
+ val := {1}({2})
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").{4}())
+ assert.Equal(t, val, m.Get("value").Must{4}())
+ assert.Equal(t, {1}({3}), m.Get("nothing").{4}())
+ assert.Equal(t, val, m.Get("nothing").{4}({2}))
+ assert.Panics(t, func() {
+ m.Get("age").Must{4}()
+ })
+}
+
+func Test{4}Slice(t *testing.T) {
+ val := {1}({2})
+ m := objx.Map{"value": []{1}{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").{4}Slice()[0])
+ assert.Equal(t, val, m.Get("value").Must{4}Slice()[0])
+ assert.Equal(t, []{1}(nil), m.Get("nothing").{4}Slice())
+ assert.Equal(t, val, m.Get("nothing").{4}Slice([]{1}{{1}({2})})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").Must{4}Slice()
+ })
+}
+
+func TestIs{4}(t *testing.T) {
+ m := objx.Map{"data": {1}({2})}
+
+ assert.True(t, m.Get("data").Is{4}())
+}
+
+func TestIs{4}Slice(t *testing.T) {
+ m := objx.Map{"data": []{1}{{1}({2})}}
+
+ assert.True(t, m.Get("data").Is{4}Slice())
+}
+
+func TestEach{4}(t *testing.T) {
+ m := objx.Map{"data": []{1}{{1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2})}}
+ count := 0
+ replacedVals := make([]{1}, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").Each{4}(func(i int, val {1}) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").Must{4}Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").Must{4}Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").Must{4}Slice()[2])
+}
+
+func TestWhere{4}(t *testing.T) {
+ m := objx.Map{"data": []{1}{{1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2})}}
+
+ selected := m.Get("data").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) {
+ m := objx.Map{"data": []{1}{{1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2})}}
+
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []{1}{{1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2})}}
+ rawArr := m.Get("data").Must{4}Slice()
+
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []{1}{{1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2})}}
+
+ collected := m.Get("data").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/bootstrap/vendor/github.com/stretchr/objx/codegen/types_list.txt b/bootstrap/vendor/github.com/stretchr/objx/codegen/types_list.txt
new file mode 100644
index 00000000000..932139d57b4
--- /dev/null
+++ b/bootstrap/vendor/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,(objx.Map),objx.New(1),objx.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/bootstrap/vendor/github.com/stretchr/objx/conversions.go b/bootstrap/vendor/github.com/stretchr/objx/conversions.go
new file mode 100644
index 00000000000..ca1c2dec67e
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/conversions.go
@@ -0,0 +1,109 @@
+package objx
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/url"
+)
+
+// SignatureSeparator is the character that is used to
+// separate the Base64 string from the security signature.
+const SignatureSeparator = "_"
+
+// 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/bootstrap/vendor/github.com/stretchr/objx/conversions_test.go b/bootstrap/vendor/github.com/stretchr/objx/conversions_test.go
new file mode 100644
index 00000000000..4584208d845
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/conversions_test.go
@@ -0,0 +1,96 @@
+package objx_test
+
+import (
+ "net/url"
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestConversionJSON(t *testing.T) {
+ jsonString := `{"name":"Mat"}`
+ o := objx.MustFromJSON(jsonString)
+
+ result, err := o.JSON()
+
+ require.NoError(t, err)
+ assert.Equal(t, jsonString, result)
+ assert.Equal(t, jsonString, o.MustJSON())
+}
+
+func TestConversionJSONWithError(t *testing.T) {
+ o := objx.MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustJSON()
+ })
+
+ _, err := o.JSON()
+
+ assert.Error(t, err)
+}
+
+func TestConversionBase64(t *testing.T) {
+ o := objx.Map{"name": "Mat"}
+
+ result, err := o.Base64()
+
+ require.NoError(t, err)
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", result)
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", o.MustBase64())
+}
+
+func TestConversionBase64WithError(t *testing.T) {
+ o := objx.MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustBase64()
+ })
+
+ _, err := o.Base64()
+
+ assert.Error(t, err)
+}
+
+func TestConversionSignedBase64(t *testing.T) {
+ o := objx.Map{"name": "Mat"}
+
+ result, err := o.SignedBase64("key")
+
+ require.NoError(t, err)
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", result)
+ assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", o.MustSignedBase64("key"))
+}
+
+func TestConversionSignedBase64WithError(t *testing.T) {
+ o := objx.MSI()
+ o["test"] = func() {}
+
+ assert.Panics(t, func() {
+ o.MustSignedBase64("key")
+ })
+
+ _, err := o.SignedBase64("key")
+
+ assert.Error(t, err)
+}
+
+func TestConversionURLValues(t *testing.T) {
+ m := objx.Map{"abc": 123, "name": "Mat"}
+ u := m.URLValues()
+
+ assert.Equal(t, url.Values{"abc": []string{"123"}, "name": []string{"Mat"}}, u)
+}
+
+func TestConversionURLQuery(t *testing.T) {
+ m := objx.Map{"abc": 123, "name": "Mat"}
+ u, err := m.URLQuery()
+
+ assert.Nil(t, err)
+ require.NotNil(t, u)
+ assert.Equal(t, "abc=123&name=Mat", u)
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/doc.go b/bootstrap/vendor/github.com/stretchr/objx/doc.go
new file mode 100644
index 00000000000..6d6af1a83ab
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/doc.go
@@ -0,0 +1,66 @@
+/*
+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{}` 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 sought the `Value` you're interested in, you can use the `Is*` methods to determine its type.
+
+ if m.Get("code").IsStr() { // Your code... }
+
+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 {
+ // Your code...
+ }
+*/
+package objx
diff --git a/bootstrap/vendor/github.com/stretchr/objx/fixture_test.go b/bootstrap/vendor/github.com/stretchr/objx/fixture_test.go
new file mode 100644
index 00000000000..cefe8cdc697
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/fixture_test.go
@@ -0,0 +1,96 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+)
+
+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 := objx.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/bootstrap/vendor/github.com/stretchr/objx/map.go b/bootstrap/vendor/github.com/stretchr/objx/map.go
new file mode 100644
index 00000000000..95149c06a6d
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/map.go
@@ -0,0 +1,228 @@
+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 = 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.
+//
+//
+// Returns nil if any key argument 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.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}}
+func MSI(keyAndValuePairs ...interface{}) Map {
+ newMap := Map{}
+ keyAndValuePairsLen := len(keyAndValuePairs)
+ if keyAndValuePairsLen%2 != 0 {
+ return nil
+ }
+ 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 {
+ return nil
+ }
+ newMap[keyString] = value
+ }
+ return 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 m Map
+ err := json.Unmarshal([]byte(jsonString), &m)
+ if err != nil {
+ return Nil, err
+ }
+ m.tryConvertFloat64()
+ return m, nil
+}
+
+func (m Map) tryConvertFloat64() {
+ for k, v := range m {
+ switch v.(type) {
+ case float64:
+ f := v.(float64)
+ if float64(int(f)) == f {
+ m[k] = int(f)
+ }
+ case map[string]interface{}:
+ t := New(v)
+ t.tryConvertFloat64()
+ m[k] = t
+ case []interface{}:
+ m[k] = tryConvertFloat64InSlice(v.([]interface{}))
+ }
+ }
+}
+
+func tryConvertFloat64InSlice(s []interface{}) []interface{} {
+ for k, v := range s {
+ switch v.(type) {
+ case float64:
+ f := v.(float64)
+ if float64(int(f)) == f {
+ s[k] = int(f)
+ }
+ case map[string]interface{}:
+ t := New(v)
+ t.tryConvertFloat64()
+ s[k] = t
+ case []interface{}:
+ s[k] = tryConvertFloat64InSlice(v.([]interface{}))
+ }
+ }
+ return s
+}
+
+// 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 := Map{}
+ for k, vals := range vals {
+ m[k] = vals[0]
+ }
+ return 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/bootstrap/vendor/github.com/stretchr/objx/map_test.go b/bootstrap/vendor/github.com/stretchr/objx/map_test.go
new file mode 100644
index 00000000000..5cda629dd93
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/map_test.go
@@ -0,0 +1,227 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+var TestMap = objx.Map{
+ "name": "Tyler",
+ "address": objx.Map{
+ "city": "Salt Lake City",
+ "state": "UT",
+ },
+ "numbers": []interface{}{"one", "two", "three", "four", "five"},
+}
+
+type Convertable struct {
+ name string
+}
+
+type Unconvertable struct {
+ name string
+}
+
+func (c *Convertable) MSI() map[string]interface{} {
+ return objx.Map{"name": c.name}
+}
+
+func TestMapCreation(t *testing.T) {
+ o := objx.New(nil)
+ assert.Nil(t, o)
+
+ o = objx.New("Tyler")
+ assert.Nil(t, o)
+
+ unconvertable := &Unconvertable{name: "Tyler"}
+ o = objx.New(unconvertable)
+ assert.Nil(t, o)
+
+ convertable := &Convertable{name: "Tyler"}
+ o = objx.New(convertable)
+ require.NotNil(t, convertable)
+ assert.Equal(t, "Tyler", o["name"])
+
+ o = objx.MSI()
+ assert.NotNil(t, o)
+
+ o = objx.MSI("name", "Tyler")
+ require.NotNil(t, o)
+ assert.Equal(t, o["name"], "Tyler")
+
+ o = objx.MSI(1, "a")
+ assert.Nil(t, o)
+
+ o = objx.MSI("a")
+ assert.Nil(t, o)
+
+ o = objx.MSI("a", "b", "c")
+ assert.Nil(t, o)
+}
+
+func TestMapValure(t *testing.T) {
+ m := objx.Map{
+ "a": 1,
+ }
+ v := m.Value()
+
+ assert.Equal(t, m, v.ObjxMap())
+}
+
+func TestMapMustFromJSONWithError(t *testing.T) {
+ _, err := objx.FromJSON(`"name":"Mat"}`)
+ assert.Error(t, err)
+}
+
+func TestMapFromJSON(t *testing.T) {
+ o := objx.MustFromJSON(`{"name":"Mat"}`)
+
+ require.NotNil(t, o)
+ assert.Equal(t, "Mat", o["name"])
+}
+
+func TestMapFromJSONWithError(t *testing.T) {
+ var m objx.Map
+
+ assert.Panics(t, func() {
+ m = objx.MustFromJSON(`"name":"Mat"}`)
+ })
+ assert.Nil(t, m)
+}
+
+func TestConversionJSONInt(t *testing.T) {
+ jsonString :=
+ `{
+ "a": 1,
+ "b": {
+ "data": 1
+ },
+ "c": [1],
+ "d": [[1]]
+ }`
+ m, err := objx.FromJSON(jsonString)
+
+ assert.Nil(t, err)
+ require.NotNil(t, m)
+ assert.Equal(t, 1, m.Get("a").Int())
+ assert.Equal(t, 1, m.Get("b.data").Int())
+
+ assert.True(t, m.Get("c").IsInterSlice())
+ assert.Equal(t, 1, m.Get("c").InterSlice()[0])
+
+ assert.True(t, m.Get("d").IsInterSlice())
+ assert.Equal(t, []interface{}{1}, m.Get("d").InterSlice()[0])
+}
+
+func TestJSONSliceInt(t *testing.T) {
+ jsonString :=
+ `{
+ "a": [
+ {"b": 1},
+ {"c": 2}
+ ]
+ }`
+ m, err := objx.FromJSON(jsonString)
+
+ assert.Nil(t, err)
+ require.NotNil(t, m)
+ assert.Equal(t, []objx.Map{objx.Map{"b": 1}, objx.Map{"c": 2}}, m.Get("a").ObjxMapSlice())
+}
+
+func TestJSONSliceMixed(t *testing.T) {
+ jsonString :=
+ `{
+ "a": [
+ {"b": 1},
+ "a"
+ ]
+ }`
+ m, err := objx.FromJSON(jsonString)
+
+ assert.Nil(t, err)
+ require.NotNil(t, m)
+
+ assert.Nil(t, m.Get("a").ObjxMapSlice())
+}
+
+func TestMapFromBase64String(t *testing.T) {
+ base64String := "eyJuYW1lIjoiTWF0In0="
+ o, err := objx.FromBase64(base64String)
+
+ require.NoError(t, err)
+ assert.Equal(t, o.Get("name").Str(), "Mat")
+ assert.Equal(t, objx.MustFromBase64(base64String).Get("name").Str(), "Mat")
+}
+
+func TestMapFromBase64StringWithError(t *testing.T) {
+ base64String := "eyJuYW1lIjoiTWFasd0In0="
+ _, err := objx.FromBase64(base64String)
+
+ assert.Error(t, err)
+ assert.Panics(t, func() {
+ objx.MustFromBase64(base64String)
+ })
+}
+
+func TestMapFromSignedBase64String(t *testing.T) {
+ base64String := "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
+
+ o, err := objx.FromSignedBase64(base64String, "key")
+
+ require.NoError(t, err)
+ assert.Equal(t, o.Get("name").Str(), "Mat")
+ assert.Equal(t, objx.MustFromSignedBase64(base64String, "key").Get("name").Str(), "Mat")
+}
+
+func TestMapFromSignedBase64StringWithError(t *testing.T) {
+ base64String := "eyJuYW1lasdIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
+ _, err := objx.FromSignedBase64(base64String, "key")
+ assert.Error(t, err)
+ assert.Panics(t, func() {
+ objx.MustFromSignedBase64(base64String, "key")
+ })
+
+ base64String = "eyJuYW1lasdIjoiTWF0In0=67ee82916f90b2c0d68c903266e8998c9ef0c3d6"
+ _, err = objx.FromSignedBase64(base64String, "key")
+ assert.Error(t, err)
+ assert.Panics(t, func() {
+ objx.MustFromSignedBase64(base64String, "key")
+ })
+
+ base64String = "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6_junk"
+ _, err = objx.FromSignedBase64(base64String, "key")
+ assert.Error(t, err)
+ assert.Panics(t, func() {
+ objx.MustFromSignedBase64(base64String, "key")
+ })
+}
+
+func TestMapFromURLQuery(t *testing.T) {
+ m, err := objx.FromURLQuery("name=tyler&state=UT")
+
+ assert.NoError(t, err)
+ require.NotNil(t, m)
+ assert.Equal(t, "tyler", m.Get("name").Str())
+ assert.Equal(t, "UT", m.Get("state").Str())
+}
+
+func TestMapMustFromURLQuery(t *testing.T) {
+ m := objx.MustFromURLQuery("name=tyler&state=UT")
+
+ require.NotNil(t, m)
+ assert.Equal(t, "tyler", m.Get("name").Str())
+ assert.Equal(t, "UT", m.Get("state").Str())
+}
+
+func TestMapFromURLQueryWithError(t *testing.T) {
+ m, err := objx.FromURLQuery("%")
+
+ assert.Error(t, err)
+ assert.Nil(t, m)
+ assert.Panics(t, func() {
+ objx.MustFromURLQuery("%")
+ })
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/mutations.go b/bootstrap/vendor/github.com/stretchr/objx/mutations.go
new file mode 100644
index 00000000000..c3400a3f709
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/mutations.go
@@ -0,0 +1,77 @@
+package objx
+
+// Exclude returns a new Map with the keys in the specified []string
+// excluded.
+func (m Map) Exclude(exclude []string) Map {
+ excluded := make(Map)
+ for k, v := range m {
+ if !contains(exclude, k) {
+ excluded[k] = v
+ }
+ }
+ return excluded
+}
+
+// Copy creates a shallow copy of the Obj.
+func (m Map) Copy() Map {
+ copied := Map{}
+ for k, v := range m {
+ copied[k] = v
+ }
+ return 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)
+}
+
+// MergeHere 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 := Map{}
+ for k, v := range m {
+ modifiedKey, modifiedVal := transformer(k, v)
+ newMap[modifiedKey] = modifiedVal
+ }
+ return 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
+ })
+}
+
+// Checks if a string slice contains a string
+func contains(s []string, e string) bool {
+ for _, a := range s {
+ if a == e {
+ return true
+ }
+ }
+ return false
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/mutations_test.go b/bootstrap/vendor/github.com/stretchr/objx/mutations_test.go
new file mode 100644
index 00000000000..40901ceba3a
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/mutations_test.go
@@ -0,0 +1,106 @@
+package objx_test
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestExclude(t *testing.T) {
+ m := objx.Map{
+ "name": "Mat",
+ "age": 29,
+ "secret": "ABC",
+ }
+
+ excluded := m.Exclude([]string{"secret"})
+
+ assert.Equal(t, m["name"], excluded["name"])
+ assert.Equal(t, m["age"], excluded["age"])
+ assert.False(t, excluded.Has("secret"), "secret should be excluded")
+}
+
+func TestCopy(t *testing.T) {
+ m1 := objx.Map{
+ "name": "Tyler",
+ "location": "UT",
+ }
+
+ m2 := m1.Copy()
+ require.NotNil(t, m2)
+ m2["name"] = "Mat"
+
+ assert.Equal(t, m1.Get("name").Str(), "Tyler")
+ assert.Equal(t, m2.Get("name").Str(), "Mat")
+
+}
+
+func TestMerge(t *testing.T) {
+ m1 := objx.Map{
+ "name": "Mat",
+ }
+ m2 := objx.Map{
+ "name": "Tyler",
+ "location": "UT",
+ }
+
+ merged := m1.Merge(m2)
+
+ assert.Equal(t, merged.Get("name").Str(), m2.Get("name").Str())
+ assert.Equal(t, merged.Get("location").Str(), m2.Get("location").Str())
+ assert.Empty(t, m1.Get("location").Str())
+}
+
+func TestMergeHere(t *testing.T) {
+ m1 := objx.Map{
+ "name": "Mat",
+ }
+ m2 := objx.Map{
+ "name": "Tyler",
+ "location": "UT",
+ }
+
+ merged := m1.MergeHere(m2)
+
+ assert.Equal(t, m1, merged, "With MergeHere, it should return the first modified map")
+ assert.Equal(t, merged.Get("name").Str(), m2.Get("name").Str())
+ assert.Equal(t, merged.Get("location").Str(), m2.Get("location").Str())
+ assert.Equal(t, merged.Get("location").Str(), m1.Get("location").Str())
+}
+
+func TestTransform(t *testing.T) {
+ m := objx.Map{
+ "name": "Mat",
+ "location": "UK",
+ }
+ r := m.Transform(keyToUpper)
+ assert.Equal(t, objx.Map{
+ "NAME": "Mat",
+ "LOCATION": "UK",
+ }, r)
+}
+
+func TestTransformKeys(t *testing.T) {
+ m := objx.Map{
+ "a": "1",
+ "b": "2",
+ "c": "3",
+ }
+ mapping := map[string]string{
+ "a": "d",
+ "b": "e",
+ }
+ r := m.TransformKeys(mapping)
+ assert.Equal(t, objx.Map{
+ "c": "3",
+ "d": "1",
+ "e": "2",
+ }, r)
+}
+
+func keyToUpper(s string, v interface{}) (string, interface{}) {
+ return strings.ToUpper(s), v
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/security.go b/bootstrap/vendor/github.com/stretchr/objx/security.go
new file mode 100644
index 00000000000..692be8e2a9f
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/security.go
@@ -0,0 +1,12 @@
+package objx
+
+import (
+ "crypto/sha1"
+ "encoding/hex"
+)
+
+// HashWithKey hashes the specified string using the security key
+func HashWithKey(data, key string) string {
+ d := sha1.Sum([]byte(data + ":" + key))
+ return hex.EncodeToString(d[:])
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/security_test.go b/bootstrap/vendor/github.com/stretchr/objx/security_test.go
new file mode 100644
index 00000000000..8c623db91da
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/security_test.go
@@ -0,0 +1,12 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestHashWithKey(t *testing.T) {
+ assert.Equal(t, "0ce84d8d01f2c7b6e0882b784429c54d280ea2d9", objx.HashWithKey("abc", "def"))
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/simple_example_test.go b/bootstrap/vendor/github.com/stretchr/objx/simple_example_test.go
new file mode 100644
index 00000000000..403753d6525
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/simple_example_test.go
@@ -0,0 +1,42 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestSimpleExample(t *testing.T) {
+ // build a map from a JSON object
+ o := objx.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")
+ require.NotNil(t, v)
+
+ // 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/bootstrap/vendor/github.com/stretchr/objx/tests.go b/bootstrap/vendor/github.com/stretchr/objx/tests.go
new file mode 100644
index 00000000000..d9e0b479a4c
--- /dev/null
+++ b/bootstrap/vendor/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/bootstrap/vendor/github.com/stretchr/objx/tests_test.go b/bootstrap/vendor/github.com/stretchr/objx/tests_test.go
new file mode 100644
index 00000000000..94a8adaf69a
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/tests_test.go
@@ -0,0 +1,25 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestHas(t *testing.T) {
+ m := objx.Map(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/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen.go b/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen.go
new file mode 100644
index 00000000000..de42409559f
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen.go
@@ -0,0 +1,2516 @@
+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 {
+ 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 {
+ 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 {
+ 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 {
+ 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
+ }
+ s, ok := v.data.([]interface{})
+ if !ok {
+ if len(optionalDefault) == 1 {
+ return optionalDefault[0]
+ } else {
+ return nil
+ }
+ }
+
+ result := make([]Map, len(s))
+ for i := range s {
+ switch s[i].(type) {
+ case Map:
+ result[i] = s[i].(Map)
+ default:
+ return nil
+ }
+ }
+ return result
+}
+
+// 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen_test.go b/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen_test.go
new file mode 100644
index 00000000000..4b75146020b
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/type_specific_codegen_test.go
@@ -0,0 +1,2350 @@
+package objx_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+)
+
+/*
+ Tests for Inter (interface{} and []interface{})
+*/
+func TestInter(t *testing.T) {
+ val := interface{}("something")
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Inter())
+ assert.Equal(t, val, m.Get("value").MustInter())
+ assert.Equal(t, interface{}(nil), m.Get("nothing").Inter())
+ assert.Equal(t, val, m.Get("nothing").Inter("something"))
+ assert.Panics(t, func() {
+ m.Get("age").MustInter()
+ })
+}
+
+func TestInterSlice(t *testing.T) {
+ val := interface{}("something")
+ m := objx.Map{"value": []interface{}{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").InterSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustInterSlice()[0])
+ assert.Equal(t, []interface{}(nil), m.Get("nothing").InterSlice())
+ assert.Equal(t, val, m.Get("nothing").InterSlice([]interface{}{interface{}("something")})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustInterSlice()
+ })
+}
+
+func TestIsInter(t *testing.T) {
+ m := objx.Map{"data": interface{}("something")}
+
+ assert.True(t, m.Get("data").IsInter())
+}
+
+func TestIsInterSlice(t *testing.T) {
+ m := objx.Map{"data": []interface{}{interface{}("something")}}
+
+ assert.True(t, m.Get("data").IsInterSlice())
+}
+
+func TestEachInter(t *testing.T) {
+ m := objx.Map{"data": []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ count := 0
+ replacedVals := make([]interface{}, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInter(func(i int, val interface{}) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustInterSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustInterSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustInterSlice()[2])
+}
+
+func TestWhereInter(t *testing.T) {
+ m := objx.Map{"data": []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ selected := m.Get("data").WhereInter(func(i int, val interface{}) bool {
+ return i%2 == 0
+ }).MustInterSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInter(t *testing.T) {
+ m := objx.Map{"data": []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ rawArr := m.Get("data").MustInterSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}}
+ collected := m.Get("data").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 for MSI (map[string]interface{} and []map[string]interface{})
+*/
+func TestMSI(t *testing.T) {
+ val := map[string]interface{}(map[string]interface{}{"name":"Tyler"})
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").MSI())
+ assert.Equal(t, val, m.Get("value").MustMSI())
+ assert.Equal(t, map[string]interface{}(nil), m.Get("nothing").MSI())
+ assert.Equal(t, val, m.Get("nothing").MSI(map[string]interface{}{"name":"Tyler"}))
+ assert.Panics(t, func() {
+ m.Get("age").MustMSI()
+ })
+}
+
+func TestMSISlice(t *testing.T) {
+ val := map[string]interface{}(map[string]interface{}{"name":"Tyler"})
+ m := objx.Map{"value": []map[string]interface{}{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").MSISlice()[0])
+ assert.Equal(t, val, m.Get("value").MustMSISlice()[0])
+ assert.Equal(t, []map[string]interface{}(nil), m.Get("nothing").MSISlice())
+ assert.Equal(t, val, m.Get("nothing").MSISlice([]map[string]interface{}{map[string]interface{}(map[string]interface{}{"name":"Tyler"})})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustMSISlice()
+ })
+}
+
+func TestIsMSI(t *testing.T) {
+ m := objx.Map{"data": map[string]interface{}(map[string]interface{}{"name":"Tyler"})}
+
+ assert.True(t, m.Get("data").IsMSI())
+}
+
+func TestIsMSISlice(t *testing.T) {
+ m := objx.Map{"data": []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name":"Tyler"})}}
+
+ assert.True(t, m.Get("data").IsMSISlice())
+}
+
+func TestEachMSI(t *testing.T) {
+ m := objx.Map{"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, m.Get("data"), m.Get("data").EachMSI(func(i int, val map[string]interface{}) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustMSISlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustMSISlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustMSISlice()[2])
+}
+
+func TestWhereMSI(t *testing.T) {
+ m := objx.Map{"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 := m.Get("data").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) {
+ m := objx.Map{"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 := m.Get("data").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) {
+ m := objx.Map{"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 := m.Get("data").MustMSISlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"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 := m.Get("data").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 for ObjxMap ((objx.Map) and [](objx.Map))
+*/
+func TestObjxMap(t *testing.T) {
+ val := (objx.Map)(objx.New(1))
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").ObjxMap())
+ assert.Equal(t, val, m.Get("value").MustObjxMap())
+ assert.Equal(t, (objx.Map)(objx.New(nil)), m.Get("nothing").ObjxMap())
+ assert.Equal(t, val, m.Get("nothing").ObjxMap(objx.New(1)))
+ assert.Panics(t, func() {
+ m.Get("age").MustObjxMap()
+ })
+}
+
+func TestObjxMapSlice(t *testing.T) {
+ val := (objx.Map)(objx.New(1))
+ m := objx.Map{"value": [](objx.Map){ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").ObjxMapSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustObjxMapSlice()[0])
+ assert.Equal(t, [](objx.Map)(nil), m.Get("nothing").ObjxMapSlice())
+ assert.Equal(t, val, m.Get("nothing").ObjxMapSlice([](objx.Map){(objx.Map)(objx.New(1))})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustObjxMapSlice()
+ })
+}
+
+func TestIsObjxMap(t *testing.T) {
+ m := objx.Map{"data": (objx.Map)(objx.New(1))}
+
+ assert.True(t, m.Get("data").IsObjxMap())
+}
+
+func TestIsObjxMapSlice(t *testing.T) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1))}}
+
+ assert.True(t, m.Get("data").IsObjxMapSlice())
+}
+
+func TestEachObjxMap(t *testing.T) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1))}}
+ count := 0
+ replacedVals := make([](objx.Map), 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachObjxMap(func(i int, val (objx.Map)) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustObjxMapSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustObjxMapSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustObjxMapSlice()[2])
+}
+
+func TestWhereObjxMap(t *testing.T) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1))}}
+ selected := m.Get("data").WhereObjxMap(func(i int, val (objx.Map)) bool {
+ return i%2 == 0
+ }).MustObjxMapSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupObjxMap(t *testing.T) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1))}}
+ grouped := m.Get("data").GroupObjxMap(func(i int, val (objx.Map)) string {
+ return fmt.Sprintf("%v", i%2==0)
+ }).Data().(map[string][](objx.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) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1))}}
+ rawArr := m.Get("data").MustObjxMapSlice()
+ replaced := m.Get("data").ReplaceObjxMap(func(index int, val (objx.Map)) (objx.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) {
+ m := objx.Map{"data": [](objx.Map){(objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1)), (objx.Map)(objx.New(1))}}
+ collected := m.Get("data").CollectObjxMap(func(index int, val (objx.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 for Bool (bool and []bool)
+*/
+func TestBool(t *testing.T) {
+ val := bool(true)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Bool())
+ assert.Equal(t, val, m.Get("value").MustBool())
+ assert.Equal(t, bool(false), m.Get("nothing").Bool())
+ assert.Equal(t, val, m.Get("nothing").Bool(true))
+ assert.Panics(t, func() {
+ m.Get("age").MustBool()
+ })
+}
+
+func TestBoolSlice(t *testing.T) {
+ val := bool(true)
+ m := objx.Map{"value": []bool{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").BoolSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustBoolSlice()[0])
+ assert.Equal(t, []bool(nil), m.Get("nothing").BoolSlice())
+ assert.Equal(t, val, m.Get("nothing").BoolSlice([]bool{bool(true)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustBoolSlice()
+ })
+}
+
+func TestIsBool(t *testing.T) {
+ m := objx.Map{"data": bool(true)}
+
+ assert.True(t, m.Get("data").IsBool())
+}
+
+func TestIsBoolSlice(t *testing.T) {
+ m := objx.Map{"data": []bool{bool(true)}}
+
+ assert.True(t, m.Get("data").IsBoolSlice())
+}
+
+func TestEachBool(t *testing.T) {
+ m := objx.Map{"data": []bool{bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ count := 0
+ replacedVals := make([]bool, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachBool(func(i int, val bool) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustBoolSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustBoolSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustBoolSlice()[2])
+}
+
+func TestWhereBool(t *testing.T) {
+ m := objx.Map{"data": []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ selected := m.Get("data").WhereBool(func(i int, val bool) bool {
+ return i%2 == 0
+ }).MustBoolSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupBool(t *testing.T) {
+ m := objx.Map{"data": []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ rawArr := m.Get("data").MustBoolSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}}
+ collected := m.Get("data").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 for Str (string and []string)
+*/
+func TestStr(t *testing.T) {
+ val := string("hello")
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Str())
+ assert.Equal(t, val, m.Get("value").MustStr())
+ assert.Equal(t, string(""), m.Get("nothing").Str())
+ assert.Equal(t, val, m.Get("nothing").Str("hello"))
+ assert.Panics(t, func() {
+ m.Get("age").MustStr()
+ })
+}
+
+func TestStrSlice(t *testing.T) {
+ val := string("hello")
+ m := objx.Map{"value": []string{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").StrSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustStrSlice()[0])
+ assert.Equal(t, []string(nil), m.Get("nothing").StrSlice())
+ assert.Equal(t, val, m.Get("nothing").StrSlice([]string{string("hello")})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustStrSlice()
+ })
+}
+
+func TestIsStr(t *testing.T) {
+ m := objx.Map{"data": string("hello")}
+
+ assert.True(t, m.Get("data").IsStr())
+}
+
+func TestIsStrSlice(t *testing.T) {
+ m := objx.Map{"data": []string{string("hello")}}
+
+ assert.True(t, m.Get("data").IsStrSlice())
+}
+
+func TestEachStr(t *testing.T) {
+ m := objx.Map{"data": []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ count := 0
+ replacedVals := make([]string, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachStr(func(i int, val string) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustStrSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustStrSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustStrSlice()[2])
+}
+
+func TestWhereStr(t *testing.T) {
+ m := objx.Map{"data": []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ selected := m.Get("data").WhereStr(func(i int, val string) bool {
+ return i%2 == 0
+ }).MustStrSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupStr(t *testing.T) {
+ m := objx.Map{"data": []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ rawArr := m.Get("data").MustStrSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}}
+ collected := m.Get("data").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 for Int (int and []int)
+*/
+func TestInt(t *testing.T) {
+ val := int(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int())
+ assert.Equal(t, val, m.Get("value").MustInt())
+ assert.Equal(t, int(0), m.Get("nothing").Int())
+ assert.Equal(t, val, m.Get("nothing").Int(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustInt()
+ })
+}
+
+func TestIntSlice(t *testing.T) {
+ val := int(1)
+ m := objx.Map{"value": []int{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").IntSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustIntSlice()[0])
+ assert.Equal(t, []int(nil), m.Get("nothing").IntSlice())
+ assert.Equal(t, val, m.Get("nothing").IntSlice([]int{int(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustIntSlice()
+ })
+}
+
+func TestIsInt(t *testing.T) {
+ m := objx.Map{"data": int(1)}
+
+ assert.True(t, m.Get("data").IsInt())
+}
+
+func TestIsIntSlice(t *testing.T) {
+ m := objx.Map{"data": []int{int(1)}}
+
+ assert.True(t, m.Get("data").IsIntSlice())
+}
+
+func TestEachInt(t *testing.T) {
+ m := objx.Map{"data": []int{int(1), int(1), int(1), int(1), int(1)}}
+ count := 0
+ replacedVals := make([]int, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInt(func(i int, val int) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustIntSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustIntSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustIntSlice()[2])
+}
+
+func TestWhereInt(t *testing.T) {
+ m := objx.Map{"data": []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+ selected := m.Get("data").WhereInt(func(i int, val int) bool {
+ return i%2 == 0
+ }).MustIntSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInt(t *testing.T) {
+ m := objx.Map{"data": []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+ rawArr := m.Get("data").MustIntSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []int{int(1), int(1), int(1), int(1), int(1), int(1)}}
+ collected := m.Get("data").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 for Int8 (int8 and []int8)
+*/
+func TestInt8(t *testing.T) {
+ val := int8(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int8())
+ assert.Equal(t, val, m.Get("value").MustInt8())
+ assert.Equal(t, int8(0), m.Get("nothing").Int8())
+ assert.Equal(t, val, m.Get("nothing").Int8(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustInt8()
+ })
+}
+
+func TestInt8Slice(t *testing.T) {
+ val := int8(1)
+ m := objx.Map{"value": []int8{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int8Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustInt8Slice()[0])
+ assert.Equal(t, []int8(nil), m.Get("nothing").Int8Slice())
+ assert.Equal(t, val, m.Get("nothing").Int8Slice([]int8{int8(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustInt8Slice()
+ })
+}
+
+func TestIsInt8(t *testing.T) {
+ m := objx.Map{"data": int8(1)}
+
+ assert.True(t, m.Get("data").IsInt8())
+}
+
+func TestIsInt8Slice(t *testing.T) {
+ m := objx.Map{"data": []int8{int8(1)}}
+
+ assert.True(t, m.Get("data").IsInt8Slice())
+}
+
+func TestEachInt8(t *testing.T) {
+ m := objx.Map{"data": []int8{int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ count := 0
+ replacedVals := make([]int8, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInt8(func(i int, val int8) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustInt8Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustInt8Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustInt8Slice()[2])
+}
+
+func TestWhereInt8(t *testing.T) {
+ m := objx.Map{"data": []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ selected := m.Get("data").WhereInt8(func(i int, val int8) bool {
+ return i%2 == 0
+ }).MustInt8Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInt8(t *testing.T) {
+ m := objx.Map{"data": []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ rawArr := m.Get("data").MustInt8Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}}
+ collected := m.Get("data").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 for Int16 (int16 and []int16)
+*/
+func TestInt16(t *testing.T) {
+ val := int16(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int16())
+ assert.Equal(t, val, m.Get("value").MustInt16())
+ assert.Equal(t, int16(0), m.Get("nothing").Int16())
+ assert.Equal(t, val, m.Get("nothing").Int16(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustInt16()
+ })
+}
+
+func TestInt16Slice(t *testing.T) {
+ val := int16(1)
+ m := objx.Map{"value": []int16{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int16Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustInt16Slice()[0])
+ assert.Equal(t, []int16(nil), m.Get("nothing").Int16Slice())
+ assert.Equal(t, val, m.Get("nothing").Int16Slice([]int16{int16(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustInt16Slice()
+ })
+}
+
+func TestIsInt16(t *testing.T) {
+ m := objx.Map{"data": int16(1)}
+
+ assert.True(t, m.Get("data").IsInt16())
+}
+
+func TestIsInt16Slice(t *testing.T) {
+ m := objx.Map{"data": []int16{int16(1)}}
+
+ assert.True(t, m.Get("data").IsInt16Slice())
+}
+
+func TestEachInt16(t *testing.T) {
+ m := objx.Map{"data": []int16{int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ count := 0
+ replacedVals := make([]int16, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInt16(func(i int, val int16) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustInt16Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustInt16Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustInt16Slice()[2])
+}
+
+func TestWhereInt16(t *testing.T) {
+ m := objx.Map{"data": []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ selected := m.Get("data").WhereInt16(func(i int, val int16) bool {
+ return i%2 == 0
+ }).MustInt16Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInt16(t *testing.T) {
+ m := objx.Map{"data": []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ rawArr := m.Get("data").MustInt16Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}}
+ collected := m.Get("data").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 for Int32 (int32 and []int32)
+*/
+func TestInt32(t *testing.T) {
+ val := int32(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int32())
+ assert.Equal(t, val, m.Get("value").MustInt32())
+ assert.Equal(t, int32(0), m.Get("nothing").Int32())
+ assert.Equal(t, val, m.Get("nothing").Int32(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustInt32()
+ })
+}
+
+func TestInt32Slice(t *testing.T) {
+ val := int32(1)
+ m := objx.Map{"value": []int32{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int32Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustInt32Slice()[0])
+ assert.Equal(t, []int32(nil), m.Get("nothing").Int32Slice())
+ assert.Equal(t, val, m.Get("nothing").Int32Slice([]int32{int32(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustInt32Slice()
+ })
+}
+
+func TestIsInt32(t *testing.T) {
+ m := objx.Map{"data": int32(1)}
+
+ assert.True(t, m.Get("data").IsInt32())
+}
+
+func TestIsInt32Slice(t *testing.T) {
+ m := objx.Map{"data": []int32{int32(1)}}
+
+ assert.True(t, m.Get("data").IsInt32Slice())
+}
+
+func TestEachInt32(t *testing.T) {
+ m := objx.Map{"data": []int32{int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ count := 0
+ replacedVals := make([]int32, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInt32(func(i int, val int32) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustInt32Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustInt32Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustInt32Slice()[2])
+}
+
+func TestWhereInt32(t *testing.T) {
+ m := objx.Map{"data": []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ selected := m.Get("data").WhereInt32(func(i int, val int32) bool {
+ return i%2 == 0
+ }).MustInt32Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInt32(t *testing.T) {
+ m := objx.Map{"data": []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ rawArr := m.Get("data").MustInt32Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}}
+ collected := m.Get("data").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 for Int64 (int64 and []int64)
+*/
+func TestInt64(t *testing.T) {
+ val := int64(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int64())
+ assert.Equal(t, val, m.Get("value").MustInt64())
+ assert.Equal(t, int64(0), m.Get("nothing").Int64())
+ assert.Equal(t, val, m.Get("nothing").Int64(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustInt64()
+ })
+}
+
+func TestInt64Slice(t *testing.T) {
+ val := int64(1)
+ m := objx.Map{"value": []int64{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Int64Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustInt64Slice()[0])
+ assert.Equal(t, []int64(nil), m.Get("nothing").Int64Slice())
+ assert.Equal(t, val, m.Get("nothing").Int64Slice([]int64{int64(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustInt64Slice()
+ })
+}
+
+func TestIsInt64(t *testing.T) {
+ m := objx.Map{"data": int64(1)}
+
+ assert.True(t, m.Get("data").IsInt64())
+}
+
+func TestIsInt64Slice(t *testing.T) {
+ m := objx.Map{"data": []int64{int64(1)}}
+
+ assert.True(t, m.Get("data").IsInt64Slice())
+}
+
+func TestEachInt64(t *testing.T) {
+ m := objx.Map{"data": []int64{int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ count := 0
+ replacedVals := make([]int64, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachInt64(func(i int, val int64) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustInt64Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustInt64Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustInt64Slice()[2])
+}
+
+func TestWhereInt64(t *testing.T) {
+ m := objx.Map{"data": []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ selected := m.Get("data").WhereInt64(func(i int, val int64) bool {
+ return i%2 == 0
+ }).MustInt64Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupInt64(t *testing.T) {
+ m := objx.Map{"data": []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ rawArr := m.Get("data").MustInt64Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}}
+ collected := m.Get("data").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 for Uint (uint and []uint)
+*/
+func TestUint(t *testing.T) {
+ val := uint(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint())
+ assert.Equal(t, val, m.Get("value").MustUint())
+ assert.Equal(t, uint(0), m.Get("nothing").Uint())
+ assert.Equal(t, val, m.Get("nothing").Uint(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUint()
+ })
+}
+
+func TestUintSlice(t *testing.T) {
+ val := uint(1)
+ m := objx.Map{"value": []uint{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").UintSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustUintSlice()[0])
+ assert.Equal(t, []uint(nil), m.Get("nothing").UintSlice())
+ assert.Equal(t, val, m.Get("nothing").UintSlice([]uint{uint(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUintSlice()
+ })
+}
+
+func TestIsUint(t *testing.T) {
+ m := objx.Map{"data": uint(1)}
+
+ assert.True(t, m.Get("data").IsUint())
+}
+
+func TestIsUintSlice(t *testing.T) {
+ m := objx.Map{"data": []uint{uint(1)}}
+
+ assert.True(t, m.Get("data").IsUintSlice())
+}
+
+func TestEachUint(t *testing.T) {
+ m := objx.Map{"data": []uint{uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ count := 0
+ replacedVals := make([]uint, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUint(func(i int, val uint) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUintSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUintSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUintSlice()[2])
+}
+
+func TestWhereUint(t *testing.T) {
+ m := objx.Map{"data": []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ selected := m.Get("data").WhereUint(func(i int, val uint) bool {
+ return i%2 == 0
+ }).MustUintSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUint(t *testing.T) {
+ m := objx.Map{"data": []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ rawArr := m.Get("data").MustUintSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}}
+ collected := m.Get("data").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 for Uint8 (uint8 and []uint8)
+*/
+func TestUint8(t *testing.T) {
+ val := uint8(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint8())
+ assert.Equal(t, val, m.Get("value").MustUint8())
+ assert.Equal(t, uint8(0), m.Get("nothing").Uint8())
+ assert.Equal(t, val, m.Get("nothing").Uint8(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUint8()
+ })
+}
+
+func TestUint8Slice(t *testing.T) {
+ val := uint8(1)
+ m := objx.Map{"value": []uint8{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint8Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustUint8Slice()[0])
+ assert.Equal(t, []uint8(nil), m.Get("nothing").Uint8Slice())
+ assert.Equal(t, val, m.Get("nothing").Uint8Slice([]uint8{uint8(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUint8Slice()
+ })
+}
+
+func TestIsUint8(t *testing.T) {
+ m := objx.Map{"data": uint8(1)}
+
+ assert.True(t, m.Get("data").IsUint8())
+}
+
+func TestIsUint8Slice(t *testing.T) {
+ m := objx.Map{"data": []uint8{uint8(1)}}
+
+ assert.True(t, m.Get("data").IsUint8Slice())
+}
+
+func TestEachUint8(t *testing.T) {
+ m := objx.Map{"data": []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ count := 0
+ replacedVals := make([]uint8, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUint8(func(i int, val uint8) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUint8Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUint8Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUint8Slice()[2])
+}
+
+func TestWhereUint8(t *testing.T) {
+ m := objx.Map{"data": []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ selected := m.Get("data").WhereUint8(func(i int, val uint8) bool {
+ return i%2 == 0
+ }).MustUint8Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUint8(t *testing.T) {
+ m := objx.Map{"data": []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ rawArr := m.Get("data").MustUint8Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}}
+ collected := m.Get("data").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 for Uint16 (uint16 and []uint16)
+*/
+func TestUint16(t *testing.T) {
+ val := uint16(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint16())
+ assert.Equal(t, val, m.Get("value").MustUint16())
+ assert.Equal(t, uint16(0), m.Get("nothing").Uint16())
+ assert.Equal(t, val, m.Get("nothing").Uint16(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUint16()
+ })
+}
+
+func TestUint16Slice(t *testing.T) {
+ val := uint16(1)
+ m := objx.Map{"value": []uint16{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint16Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustUint16Slice()[0])
+ assert.Equal(t, []uint16(nil), m.Get("nothing").Uint16Slice())
+ assert.Equal(t, val, m.Get("nothing").Uint16Slice([]uint16{uint16(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUint16Slice()
+ })
+}
+
+func TestIsUint16(t *testing.T) {
+ m := objx.Map{"data": uint16(1)}
+
+ assert.True(t, m.Get("data").IsUint16())
+}
+
+func TestIsUint16Slice(t *testing.T) {
+ m := objx.Map{"data": []uint16{uint16(1)}}
+
+ assert.True(t, m.Get("data").IsUint16Slice())
+}
+
+func TestEachUint16(t *testing.T) {
+ m := objx.Map{"data": []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ count := 0
+ replacedVals := make([]uint16, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUint16(func(i int, val uint16) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUint16Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUint16Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUint16Slice()[2])
+}
+
+func TestWhereUint16(t *testing.T) {
+ m := objx.Map{"data": []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ selected := m.Get("data").WhereUint16(func(i int, val uint16) bool {
+ return i%2 == 0
+ }).MustUint16Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUint16(t *testing.T) {
+ m := objx.Map{"data": []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ rawArr := m.Get("data").MustUint16Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}}
+ collected := m.Get("data").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 for Uint32 (uint32 and []uint32)
+*/
+func TestUint32(t *testing.T) {
+ val := uint32(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint32())
+ assert.Equal(t, val, m.Get("value").MustUint32())
+ assert.Equal(t, uint32(0), m.Get("nothing").Uint32())
+ assert.Equal(t, val, m.Get("nothing").Uint32(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUint32()
+ })
+}
+
+func TestUint32Slice(t *testing.T) {
+ val := uint32(1)
+ m := objx.Map{"value": []uint32{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint32Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustUint32Slice()[0])
+ assert.Equal(t, []uint32(nil), m.Get("nothing").Uint32Slice())
+ assert.Equal(t, val, m.Get("nothing").Uint32Slice([]uint32{uint32(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUint32Slice()
+ })
+}
+
+func TestIsUint32(t *testing.T) {
+ m := objx.Map{"data": uint32(1)}
+
+ assert.True(t, m.Get("data").IsUint32())
+}
+
+func TestIsUint32Slice(t *testing.T) {
+ m := objx.Map{"data": []uint32{uint32(1)}}
+
+ assert.True(t, m.Get("data").IsUint32Slice())
+}
+
+func TestEachUint32(t *testing.T) {
+ m := objx.Map{"data": []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ count := 0
+ replacedVals := make([]uint32, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUint32(func(i int, val uint32) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUint32Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUint32Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUint32Slice()[2])
+}
+
+func TestWhereUint32(t *testing.T) {
+ m := objx.Map{"data": []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ selected := m.Get("data").WhereUint32(func(i int, val uint32) bool {
+ return i%2 == 0
+ }).MustUint32Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUint32(t *testing.T) {
+ m := objx.Map{"data": []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ rawArr := m.Get("data").MustUint32Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}}
+ collected := m.Get("data").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 for Uint64 (uint64 and []uint64)
+*/
+func TestUint64(t *testing.T) {
+ val := uint64(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint64())
+ assert.Equal(t, val, m.Get("value").MustUint64())
+ assert.Equal(t, uint64(0), m.Get("nothing").Uint64())
+ assert.Equal(t, val, m.Get("nothing").Uint64(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUint64()
+ })
+}
+
+func TestUint64Slice(t *testing.T) {
+ val := uint64(1)
+ m := objx.Map{"value": []uint64{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uint64Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustUint64Slice()[0])
+ assert.Equal(t, []uint64(nil), m.Get("nothing").Uint64Slice())
+ assert.Equal(t, val, m.Get("nothing").Uint64Slice([]uint64{uint64(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUint64Slice()
+ })
+}
+
+func TestIsUint64(t *testing.T) {
+ m := objx.Map{"data": uint64(1)}
+
+ assert.True(t, m.Get("data").IsUint64())
+}
+
+func TestIsUint64Slice(t *testing.T) {
+ m := objx.Map{"data": []uint64{uint64(1)}}
+
+ assert.True(t, m.Get("data").IsUint64Slice())
+}
+
+func TestEachUint64(t *testing.T) {
+ m := objx.Map{"data": []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ count := 0
+ replacedVals := make([]uint64, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUint64(func(i int, val uint64) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUint64Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUint64Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUint64Slice()[2])
+}
+
+func TestWhereUint64(t *testing.T) {
+ m := objx.Map{"data": []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ selected := m.Get("data").WhereUint64(func(i int, val uint64) bool {
+ return i%2 == 0
+ }).MustUint64Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUint64(t *testing.T) {
+ m := objx.Map{"data": []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ rawArr := m.Get("data").MustUint64Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}}
+ collected := m.Get("data").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 for Uintptr (uintptr and []uintptr)
+*/
+func TestUintptr(t *testing.T) {
+ val := uintptr(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Uintptr())
+ assert.Equal(t, val, m.Get("value").MustUintptr())
+ assert.Equal(t, uintptr(0), m.Get("nothing").Uintptr())
+ assert.Equal(t, val, m.Get("nothing").Uintptr(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustUintptr()
+ })
+}
+
+func TestUintptrSlice(t *testing.T) {
+ val := uintptr(1)
+ m := objx.Map{"value": []uintptr{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").UintptrSlice()[0])
+ assert.Equal(t, val, m.Get("value").MustUintptrSlice()[0])
+ assert.Equal(t, []uintptr(nil), m.Get("nothing").UintptrSlice())
+ assert.Equal(t, val, m.Get("nothing").UintptrSlice([]uintptr{uintptr(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustUintptrSlice()
+ })
+}
+
+func TestIsUintptr(t *testing.T) {
+ m := objx.Map{"data": uintptr(1)}
+
+ assert.True(t, m.Get("data").IsUintptr())
+}
+
+func TestIsUintptrSlice(t *testing.T) {
+ m := objx.Map{"data": []uintptr{uintptr(1)}}
+
+ assert.True(t, m.Get("data").IsUintptrSlice())
+}
+
+func TestEachUintptr(t *testing.T) {
+ m := objx.Map{"data": []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ count := 0
+ replacedVals := make([]uintptr, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachUintptr(func(i int, val uintptr) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustUintptrSlice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustUintptrSlice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustUintptrSlice()[2])
+}
+
+func TestWhereUintptr(t *testing.T) {
+ m := objx.Map{"data": []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ selected := m.Get("data").WhereUintptr(func(i int, val uintptr) bool {
+ return i%2 == 0
+ }).MustUintptrSlice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupUintptr(t *testing.T) {
+ m := objx.Map{"data": []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ rawArr := m.Get("data").MustUintptrSlice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}}
+ collected := m.Get("data").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 for Float32 (float32 and []float32)
+*/
+func TestFloat32(t *testing.T) {
+ val := float32(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Float32())
+ assert.Equal(t, val, m.Get("value").MustFloat32())
+ assert.Equal(t, float32(0), m.Get("nothing").Float32())
+ assert.Equal(t, val, m.Get("nothing").Float32(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustFloat32()
+ })
+}
+
+func TestFloat32Slice(t *testing.T) {
+ val := float32(1)
+ m := objx.Map{"value": []float32{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Float32Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustFloat32Slice()[0])
+ assert.Equal(t, []float32(nil), m.Get("nothing").Float32Slice())
+ assert.Equal(t, val, m.Get("nothing").Float32Slice([]float32{float32(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustFloat32Slice()
+ })
+}
+
+func TestIsFloat32(t *testing.T) {
+ m := objx.Map{"data": float32(1)}
+
+ assert.True(t, m.Get("data").IsFloat32())
+}
+
+func TestIsFloat32Slice(t *testing.T) {
+ m := objx.Map{"data": []float32{float32(1)}}
+
+ assert.True(t, m.Get("data").IsFloat32Slice())
+}
+
+func TestEachFloat32(t *testing.T) {
+ m := objx.Map{"data": []float32{float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ count := 0
+ replacedVals := make([]float32, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachFloat32(func(i int, val float32) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustFloat32Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustFloat32Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustFloat32Slice()[2])
+}
+
+func TestWhereFloat32(t *testing.T) {
+ m := objx.Map{"data": []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ selected := m.Get("data").WhereFloat32(func(i int, val float32) bool {
+ return i%2 == 0
+ }).MustFloat32Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupFloat32(t *testing.T) {
+ m := objx.Map{"data": []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ rawArr := m.Get("data").MustFloat32Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}}
+ collected := m.Get("data").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 for Float64 (float64 and []float64)
+*/
+func TestFloat64(t *testing.T) {
+ val := float64(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Float64())
+ assert.Equal(t, val, m.Get("value").MustFloat64())
+ assert.Equal(t, float64(0), m.Get("nothing").Float64())
+ assert.Equal(t, val, m.Get("nothing").Float64(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustFloat64()
+ })
+}
+
+func TestFloat64Slice(t *testing.T) {
+ val := float64(1)
+ m := objx.Map{"value": []float64{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Float64Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustFloat64Slice()[0])
+ assert.Equal(t, []float64(nil), m.Get("nothing").Float64Slice())
+ assert.Equal(t, val, m.Get("nothing").Float64Slice([]float64{float64(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustFloat64Slice()
+ })
+}
+
+func TestIsFloat64(t *testing.T) {
+ m := objx.Map{"data": float64(1)}
+
+ assert.True(t, m.Get("data").IsFloat64())
+}
+
+func TestIsFloat64Slice(t *testing.T) {
+ m := objx.Map{"data": []float64{float64(1)}}
+
+ assert.True(t, m.Get("data").IsFloat64Slice())
+}
+
+func TestEachFloat64(t *testing.T) {
+ m := objx.Map{"data": []float64{float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ count := 0
+ replacedVals := make([]float64, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachFloat64(func(i int, val float64) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustFloat64Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustFloat64Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustFloat64Slice()[2])
+}
+
+func TestWhereFloat64(t *testing.T) {
+ m := objx.Map{"data": []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ selected := m.Get("data").WhereFloat64(func(i int, val float64) bool {
+ return i%2 == 0
+ }).MustFloat64Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupFloat64(t *testing.T) {
+ m := objx.Map{"data": []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ rawArr := m.Get("data").MustFloat64Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}}
+ collected := m.Get("data").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 for Complex64 (complex64 and []complex64)
+*/
+func TestComplex64(t *testing.T) {
+ val := complex64(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Complex64())
+ assert.Equal(t, val, m.Get("value").MustComplex64())
+ assert.Equal(t, complex64(0), m.Get("nothing").Complex64())
+ assert.Equal(t, val, m.Get("nothing").Complex64(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustComplex64()
+ })
+}
+
+func TestComplex64Slice(t *testing.T) {
+ val := complex64(1)
+ m := objx.Map{"value": []complex64{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Complex64Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustComplex64Slice()[0])
+ assert.Equal(t, []complex64(nil), m.Get("nothing").Complex64Slice())
+ assert.Equal(t, val, m.Get("nothing").Complex64Slice([]complex64{complex64(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustComplex64Slice()
+ })
+}
+
+func TestIsComplex64(t *testing.T) {
+ m := objx.Map{"data": complex64(1)}
+
+ assert.True(t, m.Get("data").IsComplex64())
+}
+
+func TestIsComplex64Slice(t *testing.T) {
+ m := objx.Map{"data": []complex64{complex64(1)}}
+
+ assert.True(t, m.Get("data").IsComplex64Slice())
+}
+
+func TestEachComplex64(t *testing.T) {
+ m := objx.Map{"data": []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ count := 0
+ replacedVals := make([]complex64, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachComplex64(func(i int, val complex64) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustComplex64Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustComplex64Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustComplex64Slice()[2])
+}
+
+func TestWhereComplex64(t *testing.T) {
+ m := objx.Map{"data": []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ selected := m.Get("data").WhereComplex64(func(i int, val complex64) bool {
+ return i%2 == 0
+ }).MustComplex64Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupComplex64(t *testing.T) {
+ m := objx.Map{"data": []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ rawArr := m.Get("data").MustComplex64Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}}
+ collected := m.Get("data").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 for Complex128 (complex128 and []complex128)
+*/
+func TestComplex128(t *testing.T) {
+ val := complex128(1)
+ m := objx.Map{"value": val, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Complex128())
+ assert.Equal(t, val, m.Get("value").MustComplex128())
+ assert.Equal(t, complex128(0), m.Get("nothing").Complex128())
+ assert.Equal(t, val, m.Get("nothing").Complex128(1))
+ assert.Panics(t, func() {
+ m.Get("age").MustComplex128()
+ })
+}
+
+func TestComplex128Slice(t *testing.T) {
+ val := complex128(1)
+ m := objx.Map{"value": []complex128{ val }, "nothing": nil}
+
+ assert.Equal(t, val, m.Get("value").Complex128Slice()[0])
+ assert.Equal(t, val, m.Get("value").MustComplex128Slice()[0])
+ assert.Equal(t, []complex128(nil), m.Get("nothing").Complex128Slice())
+ assert.Equal(t, val, m.Get("nothing").Complex128Slice([]complex128{complex128(1)})[0])
+ assert.Panics(t, func() {
+ m.Get("nothing").MustComplex128Slice()
+ })
+}
+
+func TestIsComplex128(t *testing.T) {
+ m := objx.Map{"data": complex128(1)}
+
+ assert.True(t, m.Get("data").IsComplex128())
+}
+
+func TestIsComplex128Slice(t *testing.T) {
+ m := objx.Map{"data": []complex128{complex128(1)}}
+
+ assert.True(t, m.Get("data").IsComplex128Slice())
+}
+
+func TestEachComplex128(t *testing.T) {
+ m := objx.Map{"data": []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ count := 0
+ replacedVals := make([]complex128, 0)
+ assert.Equal(t, m.Get("data"), m.Get("data").EachComplex128(func(i int, val complex128) bool {
+ count++
+ replacedVals = append(replacedVals, val)
+
+ // abort early
+ return i != 2
+ }))
+
+ assert.Equal(t, count, 3)
+ assert.Equal(t, replacedVals[0], m.Get("data").MustComplex128Slice()[0])
+ assert.Equal(t, replacedVals[1], m.Get("data").MustComplex128Slice()[1])
+ assert.Equal(t, replacedVals[2], m.Get("data").MustComplex128Slice()[2])
+}
+
+func TestWhereComplex128(t *testing.T) {
+ m := objx.Map{"data": []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ selected := m.Get("data").WhereComplex128(func(i int, val complex128) bool {
+ return i%2 == 0
+ }).MustComplex128Slice()
+
+ assert.Equal(t, 3, len(selected))
+}
+
+func TestGroupComplex128(t *testing.T) {
+ m := objx.Map{"data": []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ grouped := m.Get("data").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) {
+ m := objx.Map{"data": []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ rawArr := m.Get("data").MustComplex128Slice()
+ replaced := m.Get("data").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) {
+ m := objx.Map{"data": []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}}
+ collected := m.Get("data").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/bootstrap/vendor/github.com/stretchr/objx/value.go b/bootstrap/vendor/github.com/stretchr/objx/value.go
new file mode 100644
index 00000000000..e4b4a14335d
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/value.go
@@ -0,0 +1,53 @@
+package objx
+
+import (
+ "fmt"
+ "strconv"
+)
+
+// 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
+}
+
+// String returns the value always as a string
+func (v *Value) String() string {
+ switch {
+ case v.IsStr():
+ return v.Str()
+ case v.IsBool():
+ return strconv.FormatBool(v.Bool())
+ case v.IsFloat32():
+ return strconv.FormatFloat(float64(v.Float32()), 'f', -1, 32)
+ case v.IsFloat64():
+ return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
+ case v.IsInt():
+ return strconv.FormatInt(int64(v.Int()), 10)
+ case v.IsInt8():
+ return strconv.FormatInt(int64(v.Int8()), 10)
+ case v.IsInt16():
+ return strconv.FormatInt(int64(v.Int16()), 10)
+ case v.IsInt32():
+ return strconv.FormatInt(int64(v.Int32()), 10)
+ case v.IsInt64():
+ return strconv.FormatInt(v.Int64(), 10)
+ case v.IsUint():
+ return strconv.FormatUint(uint64(v.Uint()), 10)
+ case v.IsUint8():
+ return strconv.FormatUint(uint64(v.Uint8()), 10)
+ case v.IsUint16():
+ return strconv.FormatUint(uint64(v.Uint16()), 10)
+ case v.IsUint32():
+ return strconv.FormatUint(uint64(v.Uint32()), 10)
+ case v.IsUint64():
+ return strconv.FormatUint(v.Uint64(), 10)
+ }
+ return fmt.Sprintf("%#v", v.Data())
+}
diff --git a/bootstrap/vendor/github.com/stretchr/objx/value_test.go b/bootstrap/vendor/github.com/stretchr/objx/value_test.go
new file mode 100644
index 00000000000..1b1e3091f62
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/objx/value_test.go
@@ -0,0 +1,74 @@
+package objx_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/objx"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestStringTypeString(t *testing.T) {
+ m := objx.Map{
+ "string": "foo",
+ }
+
+ assert.Equal(t, "foo", m.Get("string").String())
+}
+
+func TestStringTypeBool(t *testing.T) {
+ m := objx.Map{
+ "bool": true,
+ }
+
+ assert.Equal(t, "true", m.Get("bool").String())
+}
+
+func TestStringTypeInt(t *testing.T) {
+ m := objx.Map{
+ "int": int(1),
+ "int8": int8(8),
+ "int16": int16(16),
+ "int32": int32(32),
+ "int64": int64(64),
+ }
+
+ assert.Equal(t, "1", m.Get("int").String())
+ assert.Equal(t, "8", m.Get("int8").String())
+ assert.Equal(t, "16", m.Get("int16").String())
+ assert.Equal(t, "32", m.Get("int32").String())
+ assert.Equal(t, "64", m.Get("int64").String())
+}
+
+func TestStringTypeUint(t *testing.T) {
+ m := objx.Map{
+ "uint": uint(1),
+ "uint8": uint8(8),
+ "uint16": uint16(16),
+ "uint32": uint32(32),
+ "uint64": uint64(64),
+ }
+
+ assert.Equal(t, "1", m.Get("uint").String())
+ assert.Equal(t, "8", m.Get("uint8").String())
+ assert.Equal(t, "16", m.Get("uint16").String())
+ assert.Equal(t, "32", m.Get("uint32").String())
+ assert.Equal(t, "64", m.Get("uint64").String())
+}
+
+func TestStringTypeFloat(t *testing.T) {
+ m := objx.Map{
+ "float32": float32(32.32),
+ "float64": float64(64.64),
+ }
+
+ assert.Equal(t, "32.32", m.Get("float32").String())
+ assert.Equal(t, "64.64", m.Get("float64").String())
+}
+
+func TestStringTypeOther(t *testing.T) {
+ m := objx.Map{
+ "other": []string{"foo", "bar"},
+ }
+
+ assert.Equal(t, "[]string{\"foo\", \"bar\"}", m.Get("other").String())
+}
diff --git a/bootstrap/vendor/github.com/stretchr/testify/.gitignore b/bootstrap/vendor/github.com/stretchr/testify/.gitignore
new file mode 100644
index 00000000000..5aacdb7cca6
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/.gitignore
@@ -0,0 +1,24 @@
+# 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
+
+.DS_Store
diff --git a/bootstrap/vendor/github.com/stretchr/testify/.travis.gofmt.sh b/bootstrap/vendor/github.com/stretchr/testify/.travis.gofmt.sh
new file mode 100755
index 00000000000..bfffdca8bca
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/.travis.gofmt.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+if [ -n "$(gofmt -l .)" ]; then
+ echo "Go code is not formatted:"
+ gofmt -d .
+ exit 1
+fi
diff --git a/bootstrap/vendor/github.com/stretchr/testify/.travis.gogenerate.sh b/bootstrap/vendor/github.com/stretchr/testify/.travis.gogenerate.sh
new file mode 100755
index 00000000000..161b449cd8d
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/.travis.gogenerate.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+if [[ "$TRAVIS_GO_VERSION" =~ ^1\.[45](\..*)?$ ]]; then
+ exit 0
+fi
+
+go get github.com/ernesto-jimenez/gogen/imports
+go generate ./...
+if [ -n "$(git diff)" ]; then
+ echo "Go generate had not been run"
+ git diff
+ exit 1
+fi
diff --git a/bootstrap/vendor/github.com/stretchr/testify/.travis.govet.sh b/bootstrap/vendor/github.com/stretchr/testify/.travis.govet.sh
new file mode 100755
index 00000000000..f8fbba7a1be
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/.travis.govet.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+cd "$(dirname $0)"
+DIRS=". assert require mock _codegen"
+set -e
+for subdir in $DIRS; do
+ pushd $subdir
+ go vet
+ popd
+done
diff --git a/bootstrap/vendor/github.com/stretchr/testify/.travis.yml b/bootstrap/vendor/github.com/stretchr/testify/.travis.yml
new file mode 100644
index 00000000000..6e51e63c2f2
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/.travis.yml
@@ -0,0 +1,15 @@
+language: go
+
+sudo: false
+
+go:
+ - 1.7
+ - 1.8
+ - 1.9
+ - tip
+
+script:
+ - ./.travis.gogenerate.sh
+ - ./.travis.gofmt.sh
+ - ./.travis.govet.sh
+ - go test -v -race $(go list ./... | grep -v vendor)
diff --git a/bootstrap/vendor/github.com/stretchr/testify/Gopkg.lock b/bootstrap/vendor/github.com/stretchr/testify/Gopkg.lock
new file mode 100644
index 00000000000..294cda0930d
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/Gopkg.lock
@@ -0,0 +1,27 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ name = "github.com/davecgh/go-spew"
+ packages = ["spew"]
+ revision = "346938d642f2ec3594ed81d874461961cd0faa76"
+ version = "v1.1.0"
+
+[[projects]]
+ name = "github.com/pmezard/go-difflib"
+ packages = ["difflib"]
+ revision = "792786c7400a136282c1664665ae0a8db921c6c2"
+ version = "v1.0.0"
+
+[[projects]]
+ name = "github.com/stretchr/objx"
+ packages = ["."]
+ revision = "facf9a85c22f48d2f52f2380e4efce1768749a89"
+ version = "v0.1"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "448ddae4702c6aded2555faafd390c537789bb1c483f70b0431e6634f73f2090"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/bootstrap/vendor/github.com/stretchr/testify/Gopkg.toml b/bootstrap/vendor/github.com/stretchr/testify/Gopkg.toml
new file mode 100644
index 00000000000..a16374c8b44
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/Gopkg.toml
@@ -0,0 +1,16 @@
+[prune]
+ unused-packages = true
+ non-go = true
+ go-tests = true
+
+[[constraint]]
+ name = "github.com/davecgh/go-spew"
+ version = "~1.1.0"
+
+[[constraint]]
+ name = "github.com/pmezard/go-difflib"
+ version = "~1.0.0"
+
+[[constraint]]
+ name = "github.com/stretchr/objx"
+ version = "~0.1.0"
diff --git a/bootstrap/vendor/github.com/stretchr/testify/LICENSE b/bootstrap/vendor/github.com/stretchr/testify/LICENSE
new file mode 100644
index 00000000000..473b670a7c6
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
+
+Please consider promoting this project if you find it useful.
+
+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/bootstrap/vendor/github.com/stretchr/testify/README.md b/bootstrap/vendor/github.com/stretchr/testify/README.md
new file mode 100644
index 00000000000..d3b942b7f33
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/README.md
@@ -0,0 +1,301 @@
+Testify - Thou Shalt Write Tests
+================================
+
+[![Build Status](https://travis-ci.org/stretchr/testify.svg)](https://travis-ci.org/stretchr/testify) [![Go Report Card](https://goreportcard.com/badge/github.com/stretchr/testify)](https://goreportcard.com/report/github.com/stretchr/testify) [![GoDoc](https://godoc.org/github.com/stretchr/testify?status.svg)](https://godoc.org/github.com/stretchr/testify)
+
+Go code (golang) set of packages that provide many tools for testifying that your code will behave as you intend.
+
+Features include:
+
+ * [Easy assertions](#assert-package)
+ * [Mocking](#mock-package)
+ * [Testing suite interfaces and functions](#suite-package)
+
+Get started:
+
+ * Install testify with [one line of code](#installation), or [update it with another](#staying-up-to-date)
+ * For an introduction to writing test code in Go, see http://golang.org/doc/code.html#Testing
+ * Check out the API Documentation http://godoc.org/github.com/stretchr/testify
+ * To make your testing life easier, check out our other project, [gorc](http://github.com/stretchr/gorc)
+ * A little about [Test-Driven Development (TDD)](http://en.wikipedia.org/wiki/Test-driven_development)
+
+
+
+[`assert`](http://godoc.org/github.com/stretchr/testify/assert "API documentation") package
+-------------------------------------------------------------------------------------------
+
+The `assert` package provides some helpful methods that allow you to write better test code in Go.
+
+ * Prints friendly, easy to read failure descriptions
+ * Allows for very readable code
+ * Optionally annotate each assertion with a message
+
+See it in action:
+
+```go
+package yours
+
+import (
+ "testing"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSomething(t *testing.T) {
+
+ // assert equality
+ assert.Equal(t, 123, 123, "they should be equal")
+
+ // assert inequality
+ assert.NotEqual(t, 123, 456, "they should not be equal")
+
+ // assert for nil (good for errors)
+ assert.Nil(t, object)
+
+ // assert for not nil (good when you expect something)
+ if assert.NotNil(t, object) {
+
+ // now we know that object isn't nil, we are safe to make
+ // further assertions without causing any errors
+ assert.Equal(t, "Something", object.Value)
+
+ }
+
+}
+```
+
+ * Every assert func takes the `testing.T` object as the first argument. This is how it writes the errors out through the normal `go test` capabilities.
+ * Every assert func returns a bool indicating whether the assertion was successful or not, this is useful for if you want to go on making further assertions under certain conditions.
+
+if you assert many times, use the below:
+
+```go
+package yours
+
+import (
+ "testing"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSomething(t *testing.T) {
+ assert := assert.New(t)
+
+ // assert equality
+ assert.Equal(123, 123, "they should be equal")
+
+ // assert inequality
+ assert.NotEqual(123, 456, "they should not be equal")
+
+ // assert for nil (good for errors)
+ assert.Nil(object)
+
+ // assert for not nil (good when you expect something)
+ if assert.NotNil(object) {
+
+ // now we know that object isn't nil, we are safe to make
+ // further assertions without causing any errors
+ assert.Equal("Something", object.Value)
+ }
+}
+```
+
+[`require`](http://godoc.org/github.com/stretchr/testify/require "API documentation") package
+---------------------------------------------------------------------------------------------
+
+The `require` package provides same global functions as the `assert` package, but instead of returning a boolean result they terminate current test.
+
+See [t.FailNow](http://golang.org/pkg/testing/#T.FailNow) for details.
+
+[`mock`](http://godoc.org/github.com/stretchr/testify/mock "API documentation") package
+----------------------------------------------------------------------------------------
+
+The `mock` package provides a mechanism for easily writing mock objects that can be used in place of real objects when writing test code.
+
+An example test function that tests a piece of code that relies on an external object `testObj`, can setup expectations (testify) and assert that they indeed happened:
+
+```go
+package yours
+
+import (
+ "testing"
+ "github.com/stretchr/testify/mock"
+)
+
+/*
+ Test objects
+*/
+
+// MyMockedObject is a mocked object that implements an interface
+// that describes an object that the code I am testing relies on.
+type MyMockedObject struct{
+ mock.Mock
+}
+
+// DoSomething is a method on MyMockedObject that implements some interface
+// and just records the activity, and returns what the Mock object tells it to.
+//
+// In the real object, this method would do something useful, but since this
+// is a mocked object - we're just going to stub it out.
+//
+// NOTE: This method is not being tested here, code that uses this object is.
+func (m *MyMockedObject) DoSomething(number int) (bool, error) {
+
+ args := m.Called(number)
+ return args.Bool(0), args.Error(1)
+
+}
+
+/*
+ Actual test functions
+*/
+
+// TestSomething is an example of how to use our test object to
+// make assertions about some target code we are testing.
+func TestSomething(t *testing.T) {
+
+ // create an instance of our test object
+ testObj := new(MyMockedObject)
+
+ // setup expectations
+ testObj.On("DoSomething", 123).Return(true, nil)
+
+ // call the code we are testing
+ targetFuncThatDoesSomethingWithObj(testObj)
+
+ // assert that the expectations were met
+ testObj.AssertExpectations(t)
+
+}
+```
+
+For more information on how to write mock code, check out the [API documentation for the `mock` package](http://godoc.org/github.com/stretchr/testify/mock).
+
+You can use the [mockery tool](http://github.com/vektra/mockery) to autogenerate the mock code against an interface as well, making using mocks much quicker.
+
+[`suite`](http://godoc.org/github.com/stretchr/testify/suite "API documentation") package
+-----------------------------------------------------------------------------------------
+
+The `suite` package provides functionality that you might be used to from more common object oriented languages. With it, you can build a testing suite as a struct, build setup/teardown methods and testing methods on your struct, and run them with 'go test' as per normal.
+
+An example suite is shown below:
+
+```go
+// Basic imports
+import (
+ "testing"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/suite"
+)
+
+// Define the suite, and absorb the built-in basic suite
+// functionality from testify - including a T() method which
+// returns the current testing context
+type ExampleTestSuite struct {
+ suite.Suite
+ VariableThatShouldStartAtFive int
+}
+
+// Make sure that VariableThatShouldStartAtFive is set to five
+// before each test
+func (suite *ExampleTestSuite) SetupTest() {
+ suite.VariableThatShouldStartAtFive = 5
+}
+
+// All methods that begin with "Test" are run as tests within a
+// suite.
+func (suite *ExampleTestSuite) TestExample() {
+ assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
+}
+
+// In order for 'go test' to run this suite, we need to create
+// a normal test function and pass our suite to suite.Run
+func TestExampleTestSuite(t *testing.T) {
+ suite.Run(t, new(ExampleTestSuite))
+}
+```
+
+For a more complete example, using all of the functionality provided by the suite package, look at our [example testing suite](https://github.com/stretchr/testify/blob/master/suite/suite_test.go)
+
+For more information on writing suites, check out the [API documentation for the `suite` package](http://godoc.org/github.com/stretchr/testify/suite).
+
+`Suite` object has assertion methods:
+
+```go
+// Basic imports
+import (
+ "testing"
+ "github.com/stretchr/testify/suite"
+)
+
+// Define the suite, and absorb the built-in basic suite
+// functionality from testify - including assertion methods.
+type ExampleTestSuite struct {
+ suite.Suite
+ VariableThatShouldStartAtFive int
+}
+
+// Make sure that VariableThatShouldStartAtFive is set to five
+// before each test
+func (suite *ExampleTestSuite) SetupTest() {
+ suite.VariableThatShouldStartAtFive = 5
+}
+
+// All methods that begin with "Test" are run as tests within a
+// suite.
+func (suite *ExampleTestSuite) TestExample() {
+ suite.Equal(suite.VariableThatShouldStartAtFive, 5)
+}
+
+// In order for 'go test' to run this suite, we need to create
+// a normal test function and pass our suite to suite.Run
+func TestExampleTestSuite(t *testing.T) {
+ suite.Run(t, new(ExampleTestSuite))
+}
+```
+
+------
+
+Installation
+============
+
+To install Testify, use `go get`:
+
+ go get github.com/stretchr/testify
+
+This will then make the following packages available to you:
+
+ github.com/stretchr/testify/assert
+ github.com/stretchr/testify/mock
+ github.com/stretchr/testify/http
+
+Import the `testify/assert` package into your code using this template:
+
+```go
+package yours
+
+import (
+ "testing"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestSomething(t *testing.T) {
+
+ assert.True(t, true, "True is true!")
+
+}
+```
+
+------
+
+Staying up to date
+==================
+
+To update Testify to the latest version, use `go get -u github.com/stretchr/testify`.
+
+------
+
+Contributing
+============
+
+Please feel free to submit issues, fork the repository and send pull requests!
+
+When submitting an issue, we ask that you please include a complete test function that demonstrates the issue. Extra credit for those using Testify to write the test code that demonstrates it.
diff --git a/bootstrap/vendor/github.com/stretchr/testify/_codegen/main.go b/bootstrap/vendor/github.com/stretchr/testify/_codegen/main.go
new file mode 100644
index 00000000000..2e5e8124ff1
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/_codegen/main.go
@@ -0,0 +1,316 @@
+// This program reads all assertion functions from the assert package and
+// automatically generates the corresponding requires and forwarded assertions
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/build"
+ "go/doc"
+ "go/format"
+ "go/importer"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path"
+ "regexp"
+ "strings"
+ "text/template"
+
+ "github.com/ernesto-jimenez/gogen/imports"
+)
+
+var (
+ pkg = flag.String("assert-path", "github.com/stretchr/testify/assert", "Path to the assert package")
+ includeF = flag.Bool("include-format-funcs", false, "include format functions such as Errorf and Equalf")
+ outputPkg = flag.String("output-package", "", "package for the resulting code")
+ tmplFile = flag.String("template", "", "What file to load the function template from")
+ out = flag.String("out", "", "What file to write the source code to")
+)
+
+func main() {
+ flag.Parse()
+
+ scope, docs, err := parsePackageSource(*pkg)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ importer, funcs, err := analyzeCode(scope, docs)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := generateCode(importer, funcs); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func generateCode(importer imports.Importer, funcs []testFunc) error {
+ buff := bytes.NewBuffer(nil)
+
+ tmplHead, tmplFunc, err := parseTemplates()
+ if err != nil {
+ return err
+ }
+
+ // Generate header
+ if err := tmplHead.Execute(buff, struct {
+ Name string
+ Imports map[string]string
+ }{
+ *outputPkg,
+ importer.Imports(),
+ }); err != nil {
+ return err
+ }
+
+ // Generate funcs
+ for _, fn := range funcs {
+ buff.Write([]byte("\n\n"))
+ if err := tmplFunc.Execute(buff, &fn); err != nil {
+ return err
+ }
+ }
+
+ code, err := format.Source(buff.Bytes())
+ if err != nil {
+ return err
+ }
+
+ // Write file
+ output, err := outputFile()
+ if err != nil {
+ return err
+ }
+ defer output.Close()
+ _, err = io.Copy(output, bytes.NewReader(code))
+ return err
+}
+
+func parseTemplates() (*template.Template, *template.Template, error) {
+ tmplHead, err := template.New("header").Parse(headerTemplate)
+ if err != nil {
+ return nil, nil, err
+ }
+ if *tmplFile != "" {
+ f, err := ioutil.ReadFile(*tmplFile)
+ if err != nil {
+ return nil, nil, err
+ }
+ funcTemplate = string(f)
+ }
+ tmpl, err := template.New("function").Parse(funcTemplate)
+ if err != nil {
+ return nil, nil, err
+ }
+ return tmplHead, tmpl, nil
+}
+
+func outputFile() (*os.File, error) {
+ filename := *out
+ if filename == "-" || (filename == "" && *tmplFile == "") {
+ return os.Stdout, nil
+ }
+ if filename == "" {
+ filename = strings.TrimSuffix(strings.TrimSuffix(*tmplFile, ".tmpl"), ".go") + ".go"
+ }
+ return os.Create(filename)
+}
+
+// analyzeCode takes the types scope and the docs and returns the import
+// information and information about all the assertion functions.
+func analyzeCode(scope *types.Scope, docs *doc.Package) (imports.Importer, []testFunc, error) {
+ testingT := scope.Lookup("TestingT").Type().Underlying().(*types.Interface)
+
+ importer := imports.New(*outputPkg)
+ var funcs []testFunc
+ // Go through all the top level functions
+ for _, fdocs := range docs.Funcs {
+ // Find the function
+ obj := scope.Lookup(fdocs.Name)
+
+ fn, ok := obj.(*types.Func)
+ if !ok {
+ continue
+ }
+ // Check function signature has at least two arguments
+ sig := fn.Type().(*types.Signature)
+ if sig.Params().Len() < 2 {
+ continue
+ }
+ // Check first argument is of type testingT
+ first, ok := sig.Params().At(0).Type().(*types.Named)
+ if !ok {
+ continue
+ }
+ firstType, ok := first.Underlying().(*types.Interface)
+ if !ok {
+ continue
+ }
+ if !types.Implements(firstType, testingT) {
+ continue
+ }
+
+ // Skip functions ending with f
+ if strings.HasSuffix(fdocs.Name, "f") && !*includeF {
+ continue
+ }
+
+ funcs = append(funcs, testFunc{*outputPkg, fdocs, fn})
+ importer.AddImportsFrom(sig.Params())
+ }
+ return importer, funcs, nil
+}
+
+// parsePackageSource returns the types scope and the package documentation from the package
+func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) {
+ pd, err := build.Import(pkg, ".", 0)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ fset := token.NewFileSet()
+ files := make(map[string]*ast.File)
+ fileList := make([]*ast.File, len(pd.GoFiles))
+ for i, fname := range pd.GoFiles {
+ src, err := ioutil.ReadFile(path.Join(pd.SrcRoot, pd.ImportPath, fname))
+ if err != nil {
+ return nil, nil, err
+ }
+ f, err := parser.ParseFile(fset, fname, src, parser.ParseComments|parser.AllErrors)
+ if err != nil {
+ return nil, nil, err
+ }
+ files[fname] = f
+ fileList[i] = f
+ }
+
+ cfg := types.Config{
+ Importer: importer.Default(),
+ }
+ info := types.Info{
+ Defs: make(map[*ast.Ident]types.Object),
+ }
+ tp, err := cfg.Check(pkg, fset, fileList, &info)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ scope := tp.Scope()
+
+ ap, _ := ast.NewPackage(fset, files, nil, nil)
+ docs := doc.New(ap, pkg, 0)
+
+ return scope, docs, nil
+}
+
+type testFunc struct {
+ CurrentPkg string
+ DocInfo *doc.Func
+ TypeInfo *types.Func
+}
+
+func (f *testFunc) Qualifier(p *types.Package) string {
+ if p == nil || p.Name() == f.CurrentPkg {
+ return ""
+ }
+ return p.Name()
+}
+
+func (f *testFunc) Params() string {
+ sig := f.TypeInfo.Type().(*types.Signature)
+ params := sig.Params()
+ p := ""
+ comma := ""
+ to := params.Len()
+ var i int
+
+ if sig.Variadic() {
+ to--
+ }
+ for i = 1; i < to; i++ {
+ param := params.At(i)
+ p += fmt.Sprintf("%s%s %s", comma, param.Name(), types.TypeString(param.Type(), f.Qualifier))
+ comma = ", "
+ }
+ if sig.Variadic() {
+ param := params.At(params.Len() - 1)
+ p += fmt.Sprintf("%s%s ...%s", comma, param.Name(), types.TypeString(param.Type().(*types.Slice).Elem(), f.Qualifier))
+ }
+ return p
+}
+
+func (f *testFunc) ForwardedParams() string {
+ sig := f.TypeInfo.Type().(*types.Signature)
+ params := sig.Params()
+ p := ""
+ comma := ""
+ to := params.Len()
+ var i int
+
+ if sig.Variadic() {
+ to--
+ }
+ for i = 1; i < to; i++ {
+ param := params.At(i)
+ p += fmt.Sprintf("%s%s", comma, param.Name())
+ comma = ", "
+ }
+ if sig.Variadic() {
+ param := params.At(params.Len() - 1)
+ p += fmt.Sprintf("%s%s...", comma, param.Name())
+ }
+ return p
+}
+
+func (f *testFunc) ParamsFormat() string {
+ return strings.Replace(f.Params(), "msgAndArgs", "msg string, args", 1)
+}
+
+func (f *testFunc) ForwardedParamsFormat() string {
+ return strings.Replace(f.ForwardedParams(), "msgAndArgs", "append([]interface{}{msg}, args...)", 1)
+}
+
+func (f *testFunc) Comment() string {
+ return "// " + strings.Replace(strings.TrimSpace(f.DocInfo.Doc), "\n", "\n// ", -1)
+}
+
+func (f *testFunc) CommentFormat() string {
+ search := fmt.Sprintf("%s", f.DocInfo.Name)
+ replace := fmt.Sprintf("%sf", f.DocInfo.Name)
+ comment := strings.Replace(f.Comment(), search, replace, -1)
+ exp := regexp.MustCompile(replace + `\(((\(\)|[^)])+)\)`)
+ return exp.ReplaceAllString(comment, replace+`($1, "error message %s", "formatted")`)
+}
+
+func (f *testFunc) CommentWithoutT(receiver string) string {
+ search := fmt.Sprintf("assert.%s(t, ", f.DocInfo.Name)
+ replace := fmt.Sprintf("%s.%s(", receiver, f.DocInfo.Name)
+ return strings.Replace(f.Comment(), search, replace, -1)
+}
+
+var headerTemplate = `/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+*/
+
+package {{.Name}}
+
+import (
+{{range $path, $name := .Imports}}
+ {{$name}} "{{$path}}"{{end}}
+)
+`
+
+var funcTemplate = `{{.Comment}}
+func (fwd *AssertionsForwarder) {{.DocInfo.Name}}({{.Params}}) bool {
+ return assert.{{.DocInfo.Name}}({{.ForwardedParams}})
+}`
diff --git a/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go
new file mode 100644
index 00000000000..ae06a54e20a
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go
@@ -0,0 +1,349 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Conditionf uses a Comparison to assert a complex condition.
+func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool {
+ return Condition(t, comp, append([]interface{}{msg}, args...)...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted")
+// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted")
+// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted")
+func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return Contains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ return DirExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// assert.Emptyf(t, obj, "error message %s", "formatted")
+func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return Empty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// assert.Equalf(t, 123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Equal(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted")
+func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool {
+ return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123))
+func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.Errorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func Errorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ return Error(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123))
+func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Failf reports a failure through
+func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ return Fail(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// FailNowf fails test
+func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool {
+ return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// assert.Falsef(t, myBool, "error message %s", "formatted")
+func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ return False(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool {
+ return FileExists(t, path, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool {
+ return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// assert.Lenf(t, mySlice, 3, "error message %s", "formatted")
+func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool {
+ return Len(t, object, length, append([]interface{}{msg}, args...)...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// assert.Nilf(t, err, "error message %s", "formatted")
+func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return Nil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if assert.NoErrorf(t, err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool {
+ return NoError(t, err, append([]interface{}{msg}, args...)...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted")
+// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted")
+func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return NotContains(t, s, contains, append([]interface{}{msg}, args...)...)
+}
+
+// NotEmptyf 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.NotEmptyf(t, obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return NotEmpty(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// assert.NotNilf(t, err, "error message %s", "formatted")
+func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool {
+ return NotNil(t, object, append([]interface{}{msg}, args...)...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted")
+func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return NotPanics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
+// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted")
+func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ return NotZero(t, i, append([]interface{}{msg}, args...)...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted")
+func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return Panics(t, f, append([]interface{}{msg}, args...)...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
+// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted")
+func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return Regexp(t, rx, str, append([]interface{}{msg}, args...)...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return Subset(t, list, subset, append([]interface{}{msg}, args...)...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// assert.Truef(t, myBool, "error message %s", "formatted")
+func Truef(t TestingT, value bool, msg string, args ...interface{}) bool {
+ return True(t, value, append([]interface{}{msg}, args...)...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool {
+ return Zero(t, i, append([]interface{}{msg}, args...)...)
+}
diff --git a/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
new file mode 100644
index 00000000000..c5cc66f4305
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
@@ -0,0 +1,4 @@
+{{.CommentFormat}}
+func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool {
+ return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}})
+}
diff --git a/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go
new file mode 100644
index 00000000000..ffa5428f34d
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go
@@ -0,0 +1,686 @@
+/*
+* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
+* THIS FILE MUST NOT BE EDITED BY HAND
+ */
+
+package assert
+
+import (
+ http "net/http"
+ url "net/url"
+ time "time"
+)
+
+// Condition uses a Comparison to assert a complex condition.
+func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
+ return Condition(a.t, comp, msgAndArgs...)
+}
+
+// Conditionf uses a Comparison to assert a complex condition.
+func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool {
+ return Conditionf(a.t, comp, msg, args...)
+}
+
+// Contains asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Contains("Hello World", "World")
+// a.Contains(["Hello", "World"], "World")
+// a.Contains({"Hello": "World"}, "Hello")
+func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ return Contains(a.t, s, contains, msgAndArgs...)
+}
+
+// Containsf asserts that the specified string, list(array, slice...) or map contains the
+// specified substring or element.
+//
+// a.Containsf("Hello World", "World", "error message %s", "formatted")
+// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted")
+// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted")
+func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return Containsf(a.t, s, contains, msg, args...)
+}
+
+// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool {
+ return DirExists(a.t, path, msgAndArgs...)
+}
+
+// DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists.
+func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool {
+ return DirExistsf(a.t, path, msg, args...)
+}
+
+// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])
+func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool {
+ return ElementsMatch(a.t, listA, listB, msgAndArgs...)
+}
+
+// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified
+// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
+// the number of appearances of each of them in both lists should match.
+//
+// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")
+func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool {
+ return ElementsMatchf(a.t, listA, listB, msg, args...)
+}
+
+// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Empty(obj)
+func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
+ return Empty(a.t, object, msgAndArgs...)
+}
+
+// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either
+// a slice or a channel with len == 0.
+//
+// a.Emptyf(obj, "error message %s", "formatted")
+func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool {
+ return Emptyf(a.t, object, msg, args...)
+}
+
+// Equal asserts that two objects are equal.
+//
+// a.Equal(123, 123)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Equal(a.t, expected, actual, 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()
+// a.EqualError(err, expectedErrorString)
+func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
+ return EqualError(a.t, theError, errString, msgAndArgs...)
+}
+
+// EqualErrorf asserts that a function returned an error (i.e. not `nil`)
+// and that it is equal to the provided error.
+//
+// actualObj, err := SomeFunction()
+// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted")
+func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool {
+ return EqualErrorf(a.t, theError, errString, msg, args...)
+}
+
+// EqualValues asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValues(uint32(123), int32(123))
+func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return EqualValues(a.t, expected, actual, msgAndArgs...)
+}
+
+// EqualValuesf asserts that two objects are equal or convertable to the same types
+// and equal.
+//
+// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123))
+func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return EqualValuesf(a.t, expected, actual, msg, args...)
+}
+
+// Equalf asserts that two objects are equal.
+//
+// a.Equalf(123, 123, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses). Function equality
+// cannot be determined and will always fail.
+func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Equalf(a.t, expected, actual, msg, args...)
+}
+
+// Error asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Error(err) {
+// assert.Equal(t, expectedError, err)
+// }
+func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
+ return Error(a.t, err, msgAndArgs...)
+}
+
+// Errorf asserts that a function returned an error (i.e. not `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.Errorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedErrorf, err)
+// }
+func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool {
+ return Errorf(a.t, err, msg, args...)
+}
+
+// Exactly asserts that two objects are equal in value and type.
+//
+// a.Exactly(int32(123), int64(123))
+func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return Exactly(a.t, expected, actual, msgAndArgs...)
+}
+
+// Exactlyf asserts that two objects are equal in value and type.
+//
+// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123))
+func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return Exactlyf(a.t, expected, actual, msg, args...)
+}
+
+// Fail reports a failure through
+func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
+ return Fail(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNow fails test
+func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
+ return FailNow(a.t, failureMessage, msgAndArgs...)
+}
+
+// FailNowf fails test
+func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool {
+ return FailNowf(a.t, failureMessage, msg, args...)
+}
+
+// Failf reports a failure through
+func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool {
+ return Failf(a.t, failureMessage, msg, args...)
+}
+
+// False asserts that the specified value is false.
+//
+// a.False(myBool)
+func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
+ return False(a.t, value, msgAndArgs...)
+}
+
+// Falsef asserts that the specified value is false.
+//
+// a.Falsef(myBool, "error message %s", "formatted")
+func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool {
+ return Falsef(a.t, value, msg, args...)
+}
+
+// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool {
+ return FileExists(a.t, path, msgAndArgs...)
+}
+
+// FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file.
+func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool {
+ return FileExistsf(a.t, path, msg, args...)
+}
+
+// HTTPBodyContains asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContains(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, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyContainsf asserts that a specified handler returns a
+// body that contains a string.
+//
+// a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPBodyNotContains asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContains(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, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool {
+ return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...)
+}
+
+// HTTPBodyNotContainsf asserts that a specified handler returns a
+// body that does not contain a string.
+//
+// a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool {
+ return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...)
+}
+
+// HTTPError asserts that a specified handler returns an error status code.
+//
+// a.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, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ return HTTPError(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPErrorf asserts that a specified handler returns an error status code.
+//
+// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPErrorf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPRedirect asserts that a specified handler returns a redirect status code.
+//
+// a.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, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPRedirectf asserts that a specified handler returns a redirect status code.
+//
+// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
+//
+// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false).
+func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPRedirectf(a.t, handler, method, url, values, msg, args...)
+}
+
+// HTTPSuccess asserts that a specified handler returns a success status code.
+//
+// a.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, method string, url string, values url.Values, msgAndArgs ...interface{}) bool {
+ return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...)
+}
+
+// HTTPSuccessf asserts that a specified handler returns a success status code.
+//
+// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted")
+//
+// Returns whether the assertion was successful (true) or not (false).
+func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool {
+ return HTTPSuccessf(a.t, handler, method, url, values, msg, args...)
+}
+
+// Implements asserts that an object is implemented by the specified interface.
+//
+// a.Implements((*MyInterface)(nil), new(MyObject))
+func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
+ return Implements(a.t, interfaceObject, object, msgAndArgs...)
+}
+
+// Implementsf asserts that an object is implemented by the specified interface.
+//
+// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject))
+func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return Implementsf(a.t, interfaceObject, object, msg, args...)
+}
+
+// InDelta asserts that the two numerals are within delta of each other.
+//
+// a.InDelta(math.Pi, (22 / 7.0), 0.01)
+func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDelta(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys.
+func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaSlice is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
+ return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// InDeltaSlicef is the same as InDelta, except it compares two slices.
+func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaSlicef(a.t, expected, actual, delta, msg, args...)
+}
+
+// InDeltaf asserts that the two numerals are within delta of each other.
+//
+// a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01)
+func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool {
+ return InDeltaf(a.t, expected, actual, delta, msg, args...)
+}
+
+// InEpsilon asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
+ return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...)
+}
+
+// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices.
+func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// InEpsilonf asserts that expected and actual have a relative error less than epsilon
+func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool {
+ return InEpsilonf(a.t, expected, actual, epsilon, msg, args...)
+}
+
+// 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...)
+}
+
+// IsTypef asserts that the specified objects are of the same type.
+func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool {
+ return IsTypef(a.t, expectedType, object, msg, args...)
+}
+
+// JSONEq asserts that two JSON strings are equivalent.
+//
+// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
+func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
+ return JSONEq(a.t, expected, actual, msgAndArgs...)
+}
+
+// JSONEqf asserts that two JSON strings are equivalent.
+//
+// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted")
+func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool {
+ return JSONEqf(a.t, expected, actual, msg, args...)
+}
+
+// Len asserts that the specified object has specific length.
+// Len also fails if the object has a type that len() not accept.
+//
+// a.Len(mySlice, 3)
+func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
+ return Len(a.t, object, length, msgAndArgs...)
+}
+
+// Lenf asserts that the specified object has specific length.
+// Lenf also fails if the object has a type that len() not accept.
+//
+// a.Lenf(mySlice, 3, "error message %s", "formatted")
+func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool {
+ return Lenf(a.t, object, length, msg, args...)
+}
+
+// Nil asserts that the specified object is nil.
+//
+// a.Nil(err)
+func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
+ return Nil(a.t, object, msgAndArgs...)
+}
+
+// Nilf asserts that the specified object is nil.
+//
+// a.Nilf(err, "error message %s", "formatted")
+func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool {
+ return Nilf(a.t, object, msg, args...)
+}
+
+// NoError asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoError(err) {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
+ return NoError(a.t, err, msgAndArgs...)
+}
+
+// NoErrorf asserts that a function returned no error (i.e. `nil`).
+//
+// actualObj, err := SomeFunction()
+// if a.NoErrorf(err, "error message %s", "formatted") {
+// assert.Equal(t, expectedObj, actualObj)
+// }
+func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool {
+ return NoErrorf(a.t, err, msg, args...)
+}
+
+// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContains("Hello World", "Earth")
+// a.NotContains(["Hello", "World"], "Earth")
+// a.NotContains({"Hello": "World"}, "Earth")
+func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
+ return NotContains(a.t, s, contains, msgAndArgs...)
+}
+
+// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the
+// specified substring or element.
+//
+// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted")
+// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted")
+// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted")
+func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool {
+ return NotContainsf(a.t, s, contains, msg, args...)
+}
+
+// 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 a.NotEmpty(obj) {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotEmpty(a.t, object, msgAndArgs...)
+}
+
+// NotEmptyf 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 a.NotEmptyf(obj, "error message %s", "formatted") {
+// assert.Equal(t, "two", obj[1])
+// }
+func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool {
+ return NotEmptyf(a.t, object, msg, args...)
+}
+
+// NotEqual asserts that the specified values are NOT equal.
+//
+// a.NotEqual(obj1, obj2)
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
+ return NotEqual(a.t, expected, actual, msgAndArgs...)
+}
+
+// NotEqualf asserts that the specified values are NOT equal.
+//
+// a.NotEqualf(obj1, obj2, "error message %s", "formatted")
+//
+// Pointer variable equality is determined based on the equality of the
+// referenced values (as opposed to the memory addresses).
+func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool {
+ return NotEqualf(a.t, expected, actual, msg, args...)
+}
+
+// NotNil asserts that the specified object is not nil.
+//
+// a.NotNil(err)
+func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
+ return NotNil(a.t, object, msgAndArgs...)
+}
+
+// NotNilf asserts that the specified object is not nil.
+//
+// a.NotNilf(err, "error message %s", "formatted")
+func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool {
+ return NotNilf(a.t, object, msg, args...)
+}
+
+// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanics(func(){ RemainCalm() })
+func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return NotPanics(a.t, f, msgAndArgs...)
+}
+
+// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic.
+//
+// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted")
+func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ return NotPanicsf(a.t, f, msg, args...)
+}
+
+// NotRegexp asserts that a specified regexp does not match a string.
+//
+// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
+// a.NotRegexp("^start", "it's not starting")
+func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ return NotRegexp(a.t, rx, str, msgAndArgs...)
+}
+
+// NotRegexpf asserts that a specified regexp does not match a string.
+//
+// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting")
+// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return NotRegexpf(a.t, rx, str, msg, args...)
+}
+
+// NotSubset asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]")
+func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ return NotSubset(a.t, list, subset, msgAndArgs...)
+}
+
+// NotSubsetf asserts that the specified list(array, slice...) contains not all
+// elements given in the specified subset(array, slice...).
+//
+// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return NotSubsetf(a.t, list, subset, msg, args...)
+}
+
+// NotZero asserts that i is not the zero value for its type.
+func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
+ return NotZero(a.t, i, msgAndArgs...)
+}
+
+// NotZerof asserts that i is not the zero value for its type.
+func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool {
+ return NotZerof(a.t, i, msg, args...)
+}
+
+// Panics asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panics(func(){ GoCrazy() })
+func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return Panics(a.t, f, msgAndArgs...)
+}
+
+// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValue("crazy error", func(){ GoCrazy() })
+func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool {
+ return PanicsWithValue(a.t, expected, f, msgAndArgs...)
+}
+
+// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that
+// the recovered panic value equals the expected panic value.
+//
+// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool {
+ return PanicsWithValuef(a.t, expected, f, msg, args...)
+}
+
+// Panicsf asserts that the code inside the specified PanicTestFunc panics.
+//
+// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted")
+func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool {
+ return Panicsf(a.t, f, msg, args...)
+}
+
+// Regexp asserts that a specified regexp matches a string.
+//
+// a.Regexp(regexp.MustCompile("start"), "it's starting")
+// a.Regexp("start...$", "it's not starting")
+func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
+ return Regexp(a.t, rx, str, msgAndArgs...)
+}
+
+// Regexpf asserts that a specified regexp matches a string.
+//
+// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting")
+// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted")
+func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool {
+ return Regexpf(a.t, rx, str, msg, args...)
+}
+
+// Subset asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]")
+func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool {
+ return Subset(a.t, list, subset, msgAndArgs...)
+}
+
+// Subsetf asserts that the specified list(array, slice...) contains all
+// elements given in the specified subset(array, slice...).
+//
+// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted")
+func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool {
+ return Subsetf(a.t, list, subset, msg, args...)
+}
+
+// True asserts that the specified value is true.
+//
+// a.True(myBool)
+func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
+ return True(a.t, value, msgAndArgs...)
+}
+
+// Truef asserts that the specified value is true.
+//
+// a.Truef(myBool, "error message %s", "formatted")
+func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool {
+ return Truef(a.t, value, msg, args...)
+}
+
+// WithinDuration asserts that the two times are within duration delta of each other.
+//
+// a.WithinDuration(time.Now(), time.Now(), 10*time.Second)
+func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
+ return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
+}
+
+// WithinDurationf asserts that the two times are within duration delta of each other.
+//
+// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted")
+func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool {
+ return WithinDurationf(a.t, expected, actual, delta, msg, args...)
+}
+
+// Zero asserts that i is the zero value for its type.
+func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
+ return Zero(a.t, i, msgAndArgs...)
+}
+
+// Zerof asserts that i is the zero value for its type.
+func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool {
+ return Zerof(a.t, i, msg, args...)
+}
diff --git a/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
new file mode 100644
index 00000000000..99f9acfbba5
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
@@ -0,0 +1,4 @@
+{{.CommentWithoutT "a"}}
+func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
+ return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
+}
diff --git a/bootstrap/vendor/github.com/stretchr/testify/assert/assertions.go b/bootstrap/vendor/github.com/stretchr/testify/assert/assertions.go
new file mode 100644
index 00000000000..47bda778666
--- /dev/null
+++ b/bootstrap/vendor/github.com/stretchr/testify/assert/assertions.go
@@ -0,0 +1,1256 @@
+package assert
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "os"
+ "reflect"
+ "regexp"
+ "runtime"
+ "strings"
+ "time"
+ "unicode"
+ "unicode/utf8"
+
+ "github.com/davecgh/go-spew/spew"
+ "github.com/pmezard/go-difflib/difflib"
+)
+
+//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl
+
+// 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 exp, ok := expected.([]byte); ok {
+ act, ok := actual.([]byte)
+ if !ok {
+ return false
+ } else if exp == nil || act == nil {
+ return exp == nil && act == nil
+ }
+ return bytes.Equal(exp, act)
+ }
+ return reflect.DeepEqual(expected, actual)
+
+}
+
+// ObjectsAreEqualValues gets whether two objects are equal, or if their
+// values are equal.
+func ObjectsAreEqualValues(expected, actual interface{}) bool {
+ if ObjectsAreEqual(expected, actual) {
+ return true
+ }
+
+ actualType := reflect.TypeOf(actual)
+ if actualType == nil {
+ return false
+ }
+ expectedValue := reflect.ValueOf(expected)
+ if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
+ // Attempt comparison after type conversion
+ return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
+ }
+
+ 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 occurred in calling code.*/
+
+// CallerInfo returns an array of strings containing the file and line number
+// of each stack frame leading from the current test to the assert call that
+// failed.
+func CallerInfo() []string {
+
+ pc := uintptr(0)
+ file := ""
+ line := 0
+ ok := false
+ name := ""
+
+ callers := []string{}
+ for i := 0; ; i++ {
+ pc, file, line, ok = runtime.Caller(i)
+ if !ok {
+ // The breaks below failed to terminate the loop, and we ran off the
+ // end of the call stack.
+ break
+ }
+
+ // This is a huge edge case, but it will panic if this is the case, see #180
+ if file == "