From 0dd4b19e4bc812723932c65a9c69cb8e3432341c Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Thu, 13 Aug 2015 18:56:59 +0200 Subject: [PATCH 01/10] Added 'make convey' --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index d9b43fd413..30b24dc0a8 100644 --- a/Makefile +++ b/Makefile @@ -146,3 +146,9 @@ golint: party: party -c -d=vendor + + +.PHONY: convey +convey: + go get github.com/smartystreets/goconvey + goconvey -cover -port=9042 -workDir="$(realpath .)/pkg" -depth=-1 From ba880ba422ec58a4d8686474bfda4474183190bb Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 12:50:02 +0200 Subject: [PATCH 02/10] Added more tests on sshcommand --- pkg/sshcommand/sshcommand_test.go | 78 ++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/pkg/sshcommand/sshcommand_test.go b/pkg/sshcommand/sshcommand_test.go index 0a1f868bdc..3818548648 100644 --- a/pkg/sshcommand/sshcommand_test.go +++ b/pkg/sshcommand/sshcommand_test.go @@ -1,6 +1,11 @@ package sshcommand -import "fmt" +import ( + "fmt" + "testing" + + . "github.com/smartystreets/goconvey/convey" +) func ExampleCommand() *Command { return &Command{ @@ -145,3 +150,74 @@ func ExampleCommand_Slice_complex() { // Output: // ["ssh" "-q" "-o" "UserKnownHostsFile=/dev/null" "-o" "StrictHostKeyChecking=no" "-o" "ProxyCommand=ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -W %h:%p -l toor 5.6.7.8 -t -t" "1.2.3.4" "-t" "-t" "--" "/bin/sh" "-e" "-c" "\"echo hello world\""] } + +func TestCommand_defaults(t *testing.T) { + Convey("Testing Command{} default values", t, func() { + command := Command{} + So(command.Host, ShouldEqual, "") + So(command.Port, ShouldEqual, 0) + So(command.User, ShouldEqual, "") + So(command.SkipHostKeyChecking, ShouldEqual, false) + So(command.Quiet, ShouldEqual, false) + So(len(command.SSHOptions), ShouldEqual, 0) + So(command.Gateway, ShouldEqual, nil) + So(command.AllocateTTY, ShouldEqual, false) + So(len(command.Command), ShouldEqual, 0) + So(command.Debug, ShouldEqual, false) + So(command.NoEscapeCommand, ShouldEqual, false) + So(command.isGateway, ShouldEqual, false) + }) +} + +func TestCommand_applyDefaults(t *testing.T) { + Convey("Testing Command.applyDefaults()", t, func() { + Convey("On a Command{}", func() { + command := Command{} + command.applyDefaults() + So(command.Host, ShouldEqual, "") + So(command.Port, ShouldEqual, 22) + So(command.User, ShouldEqual, "") + So(command.SkipHostKeyChecking, ShouldEqual, false) + So(command.Quiet, ShouldEqual, false) + So(len(command.SSHOptions), ShouldEqual, 0) + So(command.Gateway, ShouldEqual, nil) + So(command.AllocateTTY, ShouldEqual, false) + So(len(command.Command), ShouldEqual, 0) + So(command.Debug, ShouldEqual, false) + So(command.NoEscapeCommand, ShouldEqual, false) + So(command.isGateway, ShouldEqual, false) + }) + Convey("On a New(\"example.com\")", func() { + command := New("example.com") + command.applyDefaults() + So(command.Host, ShouldEqual, "example.com") + So(command.Port, ShouldEqual, 22) + So(command.User, ShouldEqual, "") + So(command.SkipHostKeyChecking, ShouldEqual, false) + So(command.Quiet, ShouldEqual, false) + So(len(command.SSHOptions), ShouldEqual, 0) + So(command.Gateway, ShouldEqual, nil) + So(command.AllocateTTY, ShouldEqual, false) + So(len(command.Command), ShouldEqual, 0) + So(command.Debug, ShouldEqual, false) + So(command.NoEscapeCommand, ShouldEqual, false) + So(command.isGateway, ShouldEqual, false) + }) + Convey("On a New(\"toto@example.com\")", func() { + command := New("toto@example.com") + command.applyDefaults() + So(command.Host, ShouldEqual, "example.com") + So(command.Port, ShouldEqual, 22) + So(command.User, ShouldEqual, "toto") + So(command.SkipHostKeyChecking, ShouldEqual, false) + So(command.Quiet, ShouldEqual, false) + So(len(command.SSHOptions), ShouldEqual, 0) + So(command.Gateway, ShouldEqual, nil) + So(command.AllocateTTY, ShouldEqual, false) + So(len(command.Command), ShouldEqual, 0) + So(command.Debug, ShouldEqual, false) + So(command.NoEscapeCommand, ShouldEqual, false) + So(command.isGateway, ShouldEqual, false) + }) + }) +} From 83c241de2019b766b80aea0ff71f9b0215cd918c Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 13:00:23 +0200 Subject: [PATCH 03/10] Converted utils tests to convey --- pkg/utils/utils_test.go | 82 +++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 49 deletions(-) diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index ba62e086fa..dfdb644ca8 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -1,60 +1,44 @@ package utils -import "testing" +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) func TestWordify(t *testing.T) { - actual := Wordify("Hello World 42 !!") - expected := "Hello_World_42" - if actual != expected { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } + Convey("Testing Wordify()", t, func() { + So(Wordify("Hello World 42 !!"), ShouldEqual, "Hello_World_42") + So(Wordify(" Hello World 42 !! "), ShouldEqual, "Hello_World_42") + So(Wordify("Hello_World_42"), ShouldEqual, "Hello_World_42") + So(Wordify(""), ShouldEqual, "") + }) } func TestTruncIf(t *testing.T) { - actual := TruncIf("Hello World", 5, false) - expected := "Hello World" - if actual != expected { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } - - actual = TruncIf("Hello World", 5, true) - expected = "Hello" - if actual != expected { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } - - actual = TruncIf("Hello World", 50, false) - expected = "Hello World" - if actual != expected { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } - - actual = TruncIf("Hello World", 50, true) - expected = "Hello World" - if actual != expected { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } + Convey("Testing TruncIf()", t, func() { + So(TruncIf("Hello World", 5, false), ShouldEqual, "Hello World") + So(TruncIf("Hello World", 5, true), ShouldEqual, "Hello") + So(TruncIf("Hello World", 50, false), ShouldEqual, "Hello World") + So(TruncIf("Hello World", 50, true), ShouldEqual, "Hello World") + }) } func TestPathToTARPathparts(t *testing.T) { - dir, base := PathToTARPathparts("/etc/passwd") - expected := []string{"/etc", "passwd"} - actual := []string{dir, base} - if actual[0] != expected[0] || actual[1] != expected[1] { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } - - dir, base = PathToTARPathparts("/etc") - expected = []string{"/", "etc"} - actual = []string{dir, base} - if actual[0] != expected[0] || actual[1] != expected[1] { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } - - dir, base = PathToTARPathparts("/etc/") - expected = []string{"/", "etc"} - actual = []string{dir, base} - if actual[0] != expected[0] || actual[1] != expected[1] { - t.Errorf("returned value is invalid [actual: %s][expected: %s]", actual, expected) - } + Convey("Testing PathToTARPathparts()", t, func() { + dir, base := PathToTARPathparts("/etc/passwd") + So([]string{"/etc", "passwd"}, ShouldResemble, []string{dir, base}) + + dir, base = PathToTARPathparts("/etc") + So([]string{"/", "etc"}, ShouldResemble, []string{dir, base}) + + dir, base = PathToTARPathparts("/etc/") + So([]string{"/", "etc"}, ShouldResemble, []string{dir, base}) + + dir, base = PathToTARPathparts("/long/path/to/file") + So([]string{"/long/path/to", "file"}, ShouldResemble, []string{dir, base}) + + dir, base = PathToTARPathparts("/long/path/to/dir/") + So([]string{"/long/path/to", "dir"}, ShouldResemble, []string{dir, base}) + }) } From d899df4c36c20638b026ecc91aba9e94d5054a19 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 13:05:15 +0200 Subject: [PATCH 04/10] Added test for scwversoin --- pkg/scwversion/version_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 pkg/scwversion/version_test.go diff --git a/pkg/scwversion/version_test.go b/pkg/scwversion/version_test.go new file mode 100644 index 0000000000..d5a1649867 --- /dev/null +++ b/pkg/scwversion/version_test.go @@ -0,0 +1,14 @@ +package scwversion + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestInit(t *testing.T) { + Convey("Testing init()", t, func() { + So(VERSION, ShouldNotEqual, "") + So(GITCOMMIT, ShouldNotEqual, "") + }) +} From 6ff26a9cdb2f54954b340da758a0b9eb05002e98 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 14:08:14 +0200 Subject: [PATCH 05/10] Added more tests --- pkg/api/config.go | 3 ++- pkg/utils/utils_test.go | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pkg/api/config.go b/pkg/api/config.go index 55a35db9f6..2e60a577e5 100644 --- a/pkg/api/config.go +++ b/pkg/api/config.go @@ -7,8 +7,9 @@ package api import ( "encoding/json" "fmt" - "github.com/scaleway/scaleway-cli/pkg/utils" "os" + + "github.com/scaleway/scaleway-cli/pkg/utils" ) // Config is a Scaleway CLI configuration file diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index dfdb644ca8..240cab81ae 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -1,6 +1,8 @@ package utils import ( + "sort" + "strings" "testing" . "github.com/smartystreets/goconvey/convey" @@ -42,3 +44,43 @@ func TestPathToTARPathparts(t *testing.T) { So([]string{"/long/path/to", "dir"}, ShouldResemble, []string{dir, base}) }) } + +func TestRemoveDuplicates(t *testing.T) { + Convey("Testing RemoveDuplicates()", t, func() { + slice := RemoveDuplicates([]string{"a", "b", "c", "a"}) + sort.Strings(slice) + So(slice, ShouldResemble, []string{"a", "b", "c"}) + + slice = RemoveDuplicates([]string{"a", "b", "c", "a"}) + sort.Strings(slice) + So(slice, ShouldResemble, []string{"a", "b", "c"}) + + slice = RemoveDuplicates([]string{"a", "b", "c", "a", "a", "b", "d"}) + sort.Strings(slice) + So(slice, ShouldResemble, []string{"a", "b", "c", "d"}) + + slice = RemoveDuplicates([]string{"a", "b", "c", "a", ""}) + sort.Strings(slice) + So(slice, ShouldResemble, []string{"", "a", "b", "c"}) + }) +} + +func TestGetHomeDir(t *testing.T) { + Convey("Testing GetHomeDir()", t, func() { + homedir, err := GetHomeDir() + So(err, ShouldBeNil) + So(homedir, ShouldNotEqual, "") + }) +} + +func TestGetConfigFilePath(t *testing.T) { + Convey("Testing GetConfigFilePath()", t, func() { + configPath, err := GetConfigFilePath() + So(err, ShouldBeNil) + So(configPath, ShouldNotEqual, "") + + homedir, err := GetHomeDir() + So(err, ShouldBeNil) + So(strings.Contains(configPath, homedir), ShouldBeTrue) + }) +} From 610eda2d2c7201b4734ecef2b2034b0616608860 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 14:25:54 +0200 Subject: [PATCH 06/10] Added test files withing package without any tests --- pkg/api/api_test.go | 22 ++++++++++++++++++++++ pkg/cli/command_test.go | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 pkg/api/api_test.go create mode 100644 pkg/cli/command_test.go diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go new file mode 100644 index 0000000000..26bac3fc56 --- /dev/null +++ b/pkg/api/api_test.go @@ -0,0 +1,22 @@ +package api + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestNewScalewayAPI(t *testing.T) { + Convey("Testing NewScalewayAPI()", t, func() { + api, err := NewScalewayAPI("http://api-endpoint.com", "http://account-endpoint.com", "my-organization", "my-token") + So(err, ShouldBeNil) + So(api, ShouldNotBeNil) + So(api.ComputeAPI, ShouldEqual, "http://api-endpoint.com") + So(api.AccountAPI, ShouldEqual, "http://account-endpoint.com") + So(api.Token, ShouldEqual, "my-token") + So(api.Organization, ShouldEqual, "my-organization") + So(api.Cache, ShouldNotBeNil) + So(api.client, ShouldNotBeNil) + So(api.anonuuid, ShouldNotBeNil) + }) +} diff --git a/pkg/cli/command_test.go b/pkg/cli/command_test.go new file mode 100644 index 0000000000..e7c97d898a --- /dev/null +++ b/pkg/cli/command_test.go @@ -0,0 +1,21 @@ +package cli + +import ( + "testing" + + . "github.com/smartystreets/goconvey/convey" +) + +func TestCommand_Name(t *testing.T) { + Convey("Testing Command.Name()", t, func() { + command := Command{ + UsageLine: "top [OPTIONS] SERVER", + } + So(command.Name(), ShouldEqual, "top") + + command = Command{ + UsageLine: "top", + } + So(command.Name(), ShouldEqual, "top") + }) +} From a48579b0f6b30b2fec3bfadaf5d0ece0af1b56dd Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 14:11:37 +0200 Subject: [PATCH 07/10] party -c -t -d=vendor --- pkg/api/api_test.go | 2 +- pkg/cli/command_test.go | 2 +- pkg/scwversion/version_test.go | 2 +- pkg/sshcommand/sshcommand_test.go | 2 +- pkg/utils/utils_test.go | 2 +- vendor/github.com/jtolds/gls/LICENSE | 18 + vendor/github.com/jtolds/gls/README.md | 89 + vendor/github.com/jtolds/gls/context.go | 150 + vendor/github.com/jtolds/gls/context_test.go | 139 + vendor/github.com/jtolds/gls/gen_sym.go | 13 + vendor/github.com/jtolds/gls/id_pool.go | 34 + vendor/github.com/jtolds/gls/stack_tags.go | 93 + .../smartystreets/assertions/LICENSE.md | 23 + .../smartystreets/assertions/README.md | 528 +++ .../assertions/assertions.goconvey | 3 + .../smartystreets/assertions/collections.go | 195 + .../assertions/collections_test.go | 125 + .../smartystreets/assertions/doc.go | 99 + .../smartystreets/assertions/doc_test.go | 57 + .../smartystreets/assertions/equality.go | 279 ++ .../smartystreets/assertions/equality_test.go | 267 ++ .../smartystreets/assertions/filter.go | 23 + .../assertions/internal/oglematchers/LICENSE | 202 + .../internal/oglematchers/README.md | 58 + .../internal/oglematchers/all_of.go | 70 + .../internal/oglematchers/all_of_test.go | 110 + .../assertions/internal/oglematchers/any.go | 32 + .../internal/oglematchers/any_of.go | 94 + .../internal/oglematchers/any_of_test.go | 139 + .../internal/oglematchers/any_test.go | 53 + .../internal/oglematchers/contains.go | 61 + .../internal/oglematchers/contains_test.go | 234 + .../internal/oglematchers/deep_equals.go | 88 + .../internal/oglematchers/deep_equals_test.go | 344 ++ .../internal/oglematchers/elements_are.go | 91 + .../oglematchers/elements_are_test.go | 208 + .../internal/oglematchers/equals.go | 541 +++ .../internal/oglematchers/equals_test.go | 3864 +++++++++++++++++ .../assertions/internal/oglematchers/error.go | 51 + .../internal/oglematchers/error_test.go | 92 + .../internal/oglematchers/greater_or_equal.go | 39 + .../oglematchers/greater_or_equal_test.go | 1101 +++++ .../internal/oglematchers/greater_than.go | 39 + .../oglematchers/greater_than_test.go | 1077 +++++ .../internal/oglematchers/has_same_type_as.go | 37 + .../oglematchers/has_same_type_as_test.go | 181 + .../internal/oglematchers/has_substr.go | 46 + .../internal/oglematchers/has_substr_test.go | 92 + .../internal/oglematchers/identical_to.go | 134 + .../oglematchers/identical_to_test.go | 849 ++++ .../internal/oglematchers/less_or_equal.go | 41 + .../oglematchers/less_or_equal_test.go | 1077 +++++ .../internal/oglematchers/less_than.go | 152 + .../internal/oglematchers/less_than_test.go | 1057 +++++ .../internal/oglematchers/matcher.go | 86 + .../internal/oglematchers/matches_regexp.go | 69 + .../oglematchers/matches_regexp_test.go | 92 + .../internal/oglematchers/new_matcher.go | 43 + .../assertions/internal/oglematchers/not.go | 53 + .../internal/oglematchers/not_test.go | 107 + .../internal/oglematchers/panics.go | 74 + .../internal/oglematchers/panics_test.go | 141 + .../internal/oglematchers/pointee.go | 65 + .../internal/oglematchers/pointee_test.go | 153 + .../oglematchers/transform_description.go | 36 + .../assertions/internal/oglemock/LICENSE | 202 + .../assertions/internal/oglemock/README.md | 103 + .../assertions/internal/oglemock/action.go | 36 + .../internal/oglemock/controller.go | 480 ++ .../internal/oglemock/controller_test.go | 1249 ++++++ .../assertions/internal/oglemock/do_all.go | 53 + .../internal/oglemock/do_all_test.go | 90 + .../internal/oglemock/error_reporter.go | 29 + .../internal/oglemock/expectation.go | 59 + .../internal/oglemock/integration_test.go | 129 + .../internal/oglemock/internal_expectation.go | 180 + .../oglemock/internal_expectation_test.go | 265 ++ .../assertions/internal/oglemock/invoke.go | 73 + .../internal/oglemock/invoke_test.go | 110 + .../internal/oglemock/mock_object.go | 30 + .../assertions/internal/oglemock/return.go | 251 ++ .../internal/oglemock/return_test.go | 978 +++++ .../oglemock/sample/mock_io/mock_io.go | 71 + .../assertions/internal/oglemock/save_arg.go | 83 + .../internal/oglemock/save_arg_test.go | 132 + .../assertions/internal/ogletest/LICENSE | 202 + .../assertions/internal/ogletest/README.md | 151 + .../internal/ogletest/assert_aliases.go | 70 + .../internal/ogletest/assert_that.go | 46 + .../assertions/internal/ogletest/doc.go | 51 + .../internal/ogletest/expect_aliases.go | 64 + .../internal/ogletest/expect_call.go | 59 + .../internal/ogletest/expect_that.go | 100 + .../internal/ogletest/expect_that_test.go | 168 + .../assertions/internal/ogletest/failure.go | 90 + .../internal/ogletest/integration_test.go | 265 ++ .../assertions/internal/ogletest/register.go | 86 + .../internal/ogletest/register_test_suite.go | 193 + .../assertions/internal/ogletest/run_tests.go | 354 ++ .../internal/ogletest/srcutil/docs.go | 5 + .../internal/ogletest/srcutil/methods.go | 65 + .../internal/ogletest/srcutil/methods_test.go | 107 + .../assertions/internal/ogletest/test_info.go | 91 + .../assertions/internal/reqtrace/LICENSE | 202 + .../assertions/internal/reqtrace/README.md | 53 + .../assertions/internal/reqtrace/reqtrace.go | 132 + .../internal/reqtrace/trace_state.go | 175 + .../smartystreets/assertions/messages.go | 89 + .../smartystreets/assertions/panic.go | 115 + .../smartystreets/assertions/panic_test.go | 53 + .../smartystreets/assertions/quantity.go | 141 + .../smartystreets/assertions/quantity_test.go | 145 + .../smartystreets/assertions/serializer.go | 59 + .../assertions/serializer_test.go | 38 + .../smartystreets/assertions/strings.go | 183 + .../smartystreets/assertions/strings_test.go | 102 + .../smartystreets/assertions/time.go | 202 + .../smartystreets/assertions/time_test.go | 159 + .../smartystreets/assertions/type.go | 112 + .../smartystreets/assertions/type_test.go | 76 + .../assertions/utilities_for_test.go | 75 + .../goconvey/convey/assertions.go | 67 + .../smartystreets/goconvey/convey/context.go | 272 ++ .../goconvey/convey/convey.goconvey | 4 + .../goconvey/convey/discovery.go | 103 + .../smartystreets/goconvey/convey/doc.go | 218 + .../goconvey/convey/focused_execution_test.go | 72 + .../goconvey/convey/gotest/doc_test.go | 1 + .../goconvey/convey/gotest/utils.go | 37 + .../smartystreets/goconvey/convey/init.go | 76 + .../convey/isolated_execution_test.go | 774 ++++ .../goconvey/convey/nilReporter.go | 15 + .../goconvey/convey/reporting/console.go | 16 + .../goconvey/convey/reporting/doc.go | 5 + .../goconvey/convey/reporting/dot.go | 40 + .../goconvey/convey/reporting/dot_test.go | 40 + .../goconvey/convey/reporting/gotest.go | 33 + .../goconvey/convey/reporting/gotest_test.go | 66 + .../goconvey/convey/reporting/init.go | 97 + .../goconvey/convey/reporting/json.go | 88 + .../goconvey/convey/reporting/printer.go | 57 + .../goconvey/convey/reporting/printer_test.go | 181 + .../goconvey/convey/reporting/problems.go | 68 + .../convey/reporting/problems_test.go | 51 + .../goconvey/convey/reporting/reporter.go | 39 + .../convey/reporting/reporter_test.go | 94 + .../convey/reporting/reporting.goconvey | 2 + .../goconvey/convey/reporting/reports.go | 177 + .../goconvey/convey/reporting/statistics.go | 89 + .../goconvey/convey/reporting/story.go | 73 + .../goconvey/convey/reporting_hooks_test.go | 317 ++ .../goconvey/convey/story_conventions_test.go | 184 + vendor/golang.org/x/net/context/context.go | 447 ++ .../golang.org/x/net/context/context_test.go | 575 +++ .../x/net/context/withtimeout_test.go | 26 + 155 files changed, 28598 insertions(+), 5 deletions(-) create mode 100644 vendor/github.com/jtolds/gls/LICENSE create mode 100644 vendor/github.com/jtolds/gls/README.md create mode 100644 vendor/github.com/jtolds/gls/context.go create mode 100644 vendor/github.com/jtolds/gls/context_test.go create mode 100644 vendor/github.com/jtolds/gls/gen_sym.go create mode 100644 vendor/github.com/jtolds/gls/id_pool.go create mode 100644 vendor/github.com/jtolds/gls/stack_tags.go create mode 100644 vendor/github.com/smartystreets/assertions/LICENSE.md create mode 100644 vendor/github.com/smartystreets/assertions/README.md create mode 100644 vendor/github.com/smartystreets/assertions/assertions.goconvey create mode 100644 vendor/github.com/smartystreets/assertions/collections.go create mode 100644 vendor/github.com/smartystreets/assertions/collections_test.go create mode 100644 vendor/github.com/smartystreets/assertions/doc.go create mode 100644 vendor/github.com/smartystreets/assertions/doc_test.go create mode 100644 vendor/github.com/smartystreets/assertions/equality.go create mode 100644 vendor/github.com/smartystreets/assertions/equality_test.go create mode 100644 vendor/github.com/smartystreets/assertions/filter.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/LICENSE create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/README.md create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/any.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/any_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/contains.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/contains_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/equals.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/equals_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/error.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/error_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/matcher.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/new_matcher.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/not.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/not_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/panics.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/panics_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglematchers/transform_description.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/LICENSE create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/README.md create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/action.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/controller.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/controller_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/do_all.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/do_all_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/error_reporter.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/expectation.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/integration_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/invoke.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/invoke_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/mock_object.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/return.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/return_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/sample/mock_io/mock_io.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/LICENSE create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/README.md create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/assert_aliases.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/assert_that.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/doc.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/expect_aliases.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/expect_call.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/failure.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/integration_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/register.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/register_test_suite.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/run_tests.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/docs.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods_test.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/ogletest/test_info.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/reqtrace/LICENSE create mode 100644 vendor/github.com/smartystreets/assertions/internal/reqtrace/README.md create mode 100644 vendor/github.com/smartystreets/assertions/internal/reqtrace/reqtrace.go create mode 100644 vendor/github.com/smartystreets/assertions/internal/reqtrace/trace_state.go create mode 100644 vendor/github.com/smartystreets/assertions/messages.go create mode 100644 vendor/github.com/smartystreets/assertions/panic.go create mode 100644 vendor/github.com/smartystreets/assertions/panic_test.go create mode 100644 vendor/github.com/smartystreets/assertions/quantity.go create mode 100644 vendor/github.com/smartystreets/assertions/quantity_test.go create mode 100644 vendor/github.com/smartystreets/assertions/serializer.go create mode 100644 vendor/github.com/smartystreets/assertions/serializer_test.go create mode 100644 vendor/github.com/smartystreets/assertions/strings.go create mode 100644 vendor/github.com/smartystreets/assertions/strings_test.go create mode 100644 vendor/github.com/smartystreets/assertions/time.go create mode 100644 vendor/github.com/smartystreets/assertions/time_test.go create mode 100644 vendor/github.com/smartystreets/assertions/type.go create mode 100644 vendor/github.com/smartystreets/assertions/type_test.go create mode 100644 vendor/github.com/smartystreets/assertions/utilities_for_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/assertions.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/context.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/convey.goconvey create mode 100644 vendor/github.com/smartystreets/goconvey/convey/discovery.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/doc.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/focused_execution_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/gotest/doc_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/gotest/utils.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/init.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/isolated_execution_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/nilReporter.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/console.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/dot_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/init.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/json.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/printer_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/problems_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting/story.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go create mode 100644 vendor/github.com/smartystreets/goconvey/convey/story_conventions_test.go create mode 100644 vendor/golang.org/x/net/context/context.go create mode 100644 vendor/golang.org/x/net/context/context_test.go create mode 100644 vendor/golang.org/x/net/context/withtimeout_test.go diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 26bac3fc56..184c22f3d9 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -3,7 +3,7 @@ package api import ( "testing" - . "github.com/smartystreets/goconvey/convey" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" ) func TestNewScalewayAPI(t *testing.T) { diff --git a/pkg/cli/command_test.go b/pkg/cli/command_test.go index e7c97d898a..ccf9342e06 100644 --- a/pkg/cli/command_test.go +++ b/pkg/cli/command_test.go @@ -3,7 +3,7 @@ package cli import ( "testing" - . "github.com/smartystreets/goconvey/convey" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" ) func TestCommand_Name(t *testing.T) { diff --git a/pkg/scwversion/version_test.go b/pkg/scwversion/version_test.go index d5a1649867..66bda27beb 100644 --- a/pkg/scwversion/version_test.go +++ b/pkg/scwversion/version_test.go @@ -3,7 +3,7 @@ package scwversion import ( "testing" - . "github.com/smartystreets/goconvey/convey" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" ) func TestInit(t *testing.T) { diff --git a/pkg/sshcommand/sshcommand_test.go b/pkg/sshcommand/sshcommand_test.go index 3818548648..aecc3526d0 100644 --- a/pkg/sshcommand/sshcommand_test.go +++ b/pkg/sshcommand/sshcommand_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - . "github.com/smartystreets/goconvey/convey" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" ) func ExampleCommand() *Command { diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index 240cab81ae..4cc5acb6ea 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - . "github.com/smartystreets/goconvey/convey" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" ) func TestWordify(t *testing.T) { diff --git a/vendor/github.com/jtolds/gls/LICENSE b/vendor/github.com/jtolds/gls/LICENSE new file mode 100644 index 0000000000..9b4a822d92 --- /dev/null +++ b/vendor/github.com/jtolds/gls/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2013, Space Monkey, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/jtolds/gls/README.md b/vendor/github.com/jtolds/gls/README.md new file mode 100644 index 0000000000..4ebb692fb1 --- /dev/null +++ b/vendor/github.com/jtolds/gls/README.md @@ -0,0 +1,89 @@ +gls +=== + +Goroutine local storage + +### IMPORTANT NOTE ### + +It is my duty to point you to https://blog.golang.org/context, which is how +Google solves all of the problems you'd perhaps consider using this package +for at scale. + +One downside to Google's approach is that *all* of your functions must have +a new first argument, but after clearing that hurdle everything else is much +better. + +If you aren't interested in this warning, read on. + +### Huhwaht? Why? ### + +Every so often, a thread shows up on the +[golang-nuts](https://groups.google.com/d/forum/golang-nuts) asking for some +form of goroutine-local-storage, or some kind of goroutine id, or some kind of +context. There are a few valid use cases for goroutine-local-storage, one of +the most prominent being log line context. One poster was interested in being +able to log an HTTP request context id in every log line in the same goroutine +as the incoming HTTP request, without having to change every library and +function call he was interested in logging. + +This would be pretty useful. Provided that you could get some kind of +goroutine-local-storage, you could call +[log.SetOutput](http://golang.org/pkg/log/#SetOutput) with your own logging +writer that checks goroutine-local-storage for some context information and +adds that context to your log lines. + +But alas, Andrew Gerrand's typically diplomatic answer to the question of +goroutine-local variables was: + +> We wouldn't even be having this discussion if thread local storage wasn't +> useful. But every feature comes at a cost, and in my opinion the cost of +> threadlocals far outweighs their benefits. They're just not a good fit for +> Go. + +So, yeah, that makes sense. That's a pretty good reason for why the language +won't support a specific and (relatively) unuseful feature that requires some +runtime changes, just for the sake of a little bit of log improvement. + +But does Go require runtime changes? + +### How it works ### + +Go has pretty fantastic introspective and reflective features, but one thing Go +doesn't give you is any kind of access to the stack pointer, or frame pointer, +or goroutine id, or anything contextual about your current stack. It gives you +access to your list of callers, but only along with program counters, which are +fixed at compile time. + +But it does give you the stack. + +So, we define 16 special functions and embed base-16 tags into the stack using +the call order of those 16 functions. Then, we can read our tags back out of +the stack looking at the callers list. + +We then use these tags as an index into a traditional map for implementing +this library. + +### What are people saying? ### + +"Wow, that's horrifying." + +"This is the most terrible thing I have seen in a very long time." + +"Where is it getting a context from? Is this serializing all the requests? +What the heck is the client being bound to? What are these tags? Why does he +need callers? Oh god no. No no no." + +### Docs ### + +Please see the docs at http://godoc.org/github.com/jtolds/gls + +### Related ### + +If you're okay relying on the string format of the current runtime stacktrace +including a unique goroutine id (not guaranteed by the spec or anything, but +very unlikely to change within a Go release), you might be able to squeeze +out a bit more performance by using this similar library, inspired by some +code Brad Fitzpatrick wrote for debugging his HTTP/2 library: +https://github.com/tylerb/gls (in contrast, jtolds/gls doesn't require +any knowledge of the string format of the runtime stacktrace, which +probably adds unnecessary overhead). diff --git a/vendor/github.com/jtolds/gls/context.go b/vendor/github.com/jtolds/gls/context.go new file mode 100644 index 0000000000..94d7fbb7f2 --- /dev/null +++ b/vendor/github.com/jtolds/gls/context.go @@ -0,0 +1,150 @@ +// Package gls implements goroutine-local storage. +package gls + +import ( + "runtime" + "sync" +) + +const ( + maxCallers = 64 +) + +var ( + stackTagPool = &idPool{} + mgrRegistry = make(map[*ContextManager]bool) + mgrRegistryMtx sync.RWMutex +) + +// Values is simply a map of key types to value types. Used by SetValues to +// set multiple values at once. +type Values map[interface{}]interface{} + +func currentStack(skip int) []uintptr { + stack := make([]uintptr, maxCallers) + return stack[:runtime.Callers(2+skip, stack)] +} + +// ContextManager is the main entrypoint for interacting with +// Goroutine-local-storage. You can have multiple independent ContextManagers +// at any given time. ContextManagers are usually declared globally for a given +// class of context variables. You should use NewContextManager for +// construction. +type ContextManager struct { + mtx sync.RWMutex + values map[uint]Values +} + +// NewContextManager returns a brand new ContextManager. It also registers the +// new ContextManager in the ContextManager registry which is used by the Go +// method. ContextManagers are typically defined globally at package scope. +func NewContextManager() *ContextManager { + mgr := &ContextManager{values: make(map[uint]Values)} + mgrRegistryMtx.Lock() + defer mgrRegistryMtx.Unlock() + mgrRegistry[mgr] = true + return mgr +} + +// Unregister removes a ContextManager from the global registry, used by the +// Go method. Only intended for use when you're completely done with a +// ContextManager. Use of Unregister at all is rare. +func (m *ContextManager) Unregister() { + mgrRegistryMtx.Lock() + defer mgrRegistryMtx.Unlock() + delete(mgrRegistry, m) +} + +// SetValues takes a collection of values and a function to call for those +// values to be set in. Anything further down the stack will have the set +// values available through GetValue. SetValues will add new values or replace +// existing values of the same key and will not mutate or change values for +// previous stack frames. +// SetValues is slow (makes a copy of all current and new values for the new +// gls-context) in order to reduce the amount of lookups GetValue requires. +func (m *ContextManager) SetValues(new_values Values, context_call func()) { + if len(new_values) == 0 { + context_call() + return + } + + tags := readStackTags(currentStack(1)) + + m.mtx.Lock() + values := new_values + for _, tag := range tags { + if existing_values, ok := m.values[tag]; ok { + // oh, we found existing values, let's make a copy + values = make(Values, len(existing_values)+len(new_values)) + for key, val := range existing_values { + values[key] = val + } + for key, val := range new_values { + values[key] = val + } + break + } + } + new_tag := stackTagPool.Acquire() + m.values[new_tag] = values + m.mtx.Unlock() + defer func() { + m.mtx.Lock() + delete(m.values, new_tag) + m.mtx.Unlock() + stackTagPool.Release(new_tag) + }() + + addStackTag(new_tag, context_call) +} + +// GetValue will return a previously set value, provided that the value was set +// by SetValues somewhere higher up the stack. If the value is not found, ok +// will be false. +func (m *ContextManager) GetValue(key interface{}) (value interface{}, ok bool) { + + tags := readStackTags(currentStack(1)) + m.mtx.RLock() + defer m.mtx.RUnlock() + for _, tag := range tags { + if values, ok := m.values[tag]; ok { + value, ok := values[key] + return value, ok + } + } + return "", false +} + +func (m *ContextManager) getValues() Values { + tags := readStackTags(currentStack(2)) + m.mtx.RLock() + defer m.mtx.RUnlock() + for _, tag := range tags { + if values, ok := m.values[tag]; ok { + return values + } + } + return nil +} + +// Go preserves ContextManager values and Goroutine-local-storage across new +// goroutine invocations. The Go method makes a copy of all existing values on +// all registered context managers and makes sure they are still set after +// kicking off the provided function in a new goroutine. If you don't use this +// Go method instead of the standard 'go' keyword, you will lose values in +// ContextManagers, as goroutines have brand new stacks. +func Go(cb func()) { + mgrRegistryMtx.RLock() + defer mgrRegistryMtx.RUnlock() + + for mgr, _ := range mgrRegistry { + values := mgr.getValues() + if len(values) > 0 { + mgr_copy := mgr + cb_copy := cb + cb = func() { mgr_copy.SetValues(values, cb_copy) } + } + } + + go cb() +} diff --git a/vendor/github.com/jtolds/gls/context_test.go b/vendor/github.com/jtolds/gls/context_test.go new file mode 100644 index 0000000000..ae5bde4aed --- /dev/null +++ b/vendor/github.com/jtolds/gls/context_test.go @@ -0,0 +1,139 @@ +package gls + +import ( + "fmt" + "sync" + "testing" +) + +func TestContexts(t *testing.T) { + mgr1 := NewContextManager() + mgr2 := NewContextManager() + + CheckVal := func(mgr *ContextManager, key, exp_val string) { + val, ok := mgr.GetValue(key) + if len(exp_val) == 0 { + if ok { + t.Fatalf("expected no value for key %s, got %s", key, val) + } + return + } + if !ok { + t.Fatalf("expected value %s for key %s, got no value", + exp_val, key) + } + if exp_val != val { + t.Fatalf("expected value %s for key %s, got %s", exp_val, key, + val) + } + + } + + Check := func(exp_m1v1, exp_m1v2, exp_m2v1, exp_m2v2 string) { + CheckVal(mgr1, "key1", exp_m1v1) + CheckVal(mgr1, "key2", exp_m1v2) + CheckVal(mgr2, "key1", exp_m2v1) + CheckVal(mgr2, "key2", exp_m2v2) + } + + Check("", "", "", "") + mgr2.SetValues(Values{"key1": "val1c"}, func() { + Check("", "", "val1c", "") + mgr1.SetValues(Values{"key1": "val1a"}, func() { + Check("val1a", "", "val1c", "") + mgr1.SetValues(Values{"key2": "val1b"}, func() { + Check("val1a", "val1b", "val1c", "") + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + Check("", "", "", "") + }() + Go(func() { + defer wg.Done() + Check("val1a", "val1b", "val1c", "") + }) + wg.Wait() + }) + }) + }) +} + +func ExampleContextManager_SetValues() { + var ( + mgr = NewContextManager() + request_id_key = GenSym() + ) + + MyLog := func() { + if request_id, ok := mgr.GetValue(request_id_key); ok { + fmt.Println("My request id is:", request_id) + } else { + fmt.Println("No request id found") + } + } + + mgr.SetValues(Values{request_id_key: "12345"}, func() { + MyLog() + }) + MyLog() + + // Output: My request id is: 12345 + // No request id found +} + +func ExampleGo() { + var ( + mgr = NewContextManager() + request_id_key = GenSym() + ) + + MyLog := func() { + if request_id, ok := mgr.GetValue(request_id_key); ok { + fmt.Println("My request id is:", request_id) + } else { + fmt.Println("No request id found") + } + } + + mgr.SetValues(Values{request_id_key: "12345"}, func() { + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + MyLog() + }() + wg.Wait() + wg.Add(1) + Go(func() { + defer wg.Done() + MyLog() + }) + wg.Wait() + }) + + // Output: No request id found + // My request id is: 12345 +} + +func BenchmarkGetValue(b *testing.B) { + mgr := NewContextManager() + mgr.SetValues(Values{"test_key": "test_val"}, func() { + b.ResetTimer() + for i := 0; i < b.N; i++ { + val, ok := mgr.GetValue("test_key") + if !ok || val != "test_val" { + b.FailNow() + } + } + }) +} + +func BenchmarkSetValues(b *testing.B) { + mgr := NewContextManager() + for i := 0; i < b.N/2; i++ { + mgr.SetValues(Values{"test_key": "test_val"}, func() { + mgr.SetValues(Values{"test_key2": "test_val2"}, func() {}) + }) + } +} diff --git a/vendor/github.com/jtolds/gls/gen_sym.go b/vendor/github.com/jtolds/gls/gen_sym.go new file mode 100644 index 0000000000..8d5fc24d4a --- /dev/null +++ b/vendor/github.com/jtolds/gls/gen_sym.go @@ -0,0 +1,13 @@ +package gls + +var ( + symPool = &idPool{} +) + +// ContextKey is a throwaway value you can use as a key to a ContextManager +type ContextKey struct{ id uint } + +// GenSym will return a brand new, never-before-used ContextKey +func GenSym() ContextKey { + return ContextKey{id: symPool.Acquire()} +} diff --git a/vendor/github.com/jtolds/gls/id_pool.go b/vendor/github.com/jtolds/gls/id_pool.go new file mode 100644 index 0000000000..b7974ae002 --- /dev/null +++ b/vendor/github.com/jtolds/gls/id_pool.go @@ -0,0 +1,34 @@ +package gls + +// though this could probably be better at keeping ids smaller, the goal of +// this class is to keep a registry of the smallest unique integer ids +// per-process possible + +import ( + "sync" +) + +type idPool struct { + mtx sync.Mutex + released []uint + max_id uint +} + +func (p *idPool) Acquire() (id uint) { + p.mtx.Lock() + defer p.mtx.Unlock() + if len(p.released) > 0 { + id = p.released[len(p.released)-1] + p.released = p.released[:len(p.released)-1] + return id + } + id = p.max_id + p.max_id++ + return id +} + +func (p *idPool) Release(id uint) { + p.mtx.Lock() + defer p.mtx.Unlock() + p.released = append(p.released, id) +} diff --git a/vendor/github.com/jtolds/gls/stack_tags.go b/vendor/github.com/jtolds/gls/stack_tags.go new file mode 100644 index 0000000000..562a2fab79 --- /dev/null +++ b/vendor/github.com/jtolds/gls/stack_tags.go @@ -0,0 +1,93 @@ +package gls + +// so, basically, we're going to encode integer tags in base-16 on the stack + +import ( + "reflect" + "runtime" +) + +const ( + bitWidth = 4 +) + +func addStackTag(tag uint, context_call func()) { + if context_call == nil { + return + } + markS(tag, context_call) +} + +func markS(tag uint, cb func()) { _m(tag, cb) } +func mark0(tag uint, cb func()) { _m(tag, cb) } +func mark1(tag uint, cb func()) { _m(tag, cb) } +func mark2(tag uint, cb func()) { _m(tag, cb) } +func mark3(tag uint, cb func()) { _m(tag, cb) } +func mark4(tag uint, cb func()) { _m(tag, cb) } +func mark5(tag uint, cb func()) { _m(tag, cb) } +func mark6(tag uint, cb func()) { _m(tag, cb) } +func mark7(tag uint, cb func()) { _m(tag, cb) } +func mark8(tag uint, cb func()) { _m(tag, cb) } +func mark9(tag uint, cb func()) { _m(tag, cb) } +func markA(tag uint, cb func()) { _m(tag, cb) } +func markB(tag uint, cb func()) { _m(tag, cb) } +func markC(tag uint, cb func()) { _m(tag, cb) } +func markD(tag uint, cb func()) { _m(tag, cb) } +func markE(tag uint, cb func()) { _m(tag, cb) } +func markF(tag uint, cb func()) { _m(tag, cb) } + +var pc_lookup = make(map[uintptr]int8, 17) +var mark_lookup [16]func(uint, func()) + +func init() { + setEntries := func(f func(uint, func()), v int8) { + pc_lookup[reflect.ValueOf(f).Pointer()] = v + if v >= 0 { + mark_lookup[v] = f + } + } + setEntries(markS, -0x1) + setEntries(mark0, 0x0) + setEntries(mark1, 0x1) + setEntries(mark2, 0x2) + setEntries(mark3, 0x3) + setEntries(mark4, 0x4) + setEntries(mark5, 0x5) + setEntries(mark6, 0x6) + setEntries(mark7, 0x7) + setEntries(mark8, 0x8) + setEntries(mark9, 0x9) + setEntries(markA, 0xa) + setEntries(markB, 0xb) + setEntries(markC, 0xc) + setEntries(markD, 0xd) + setEntries(markE, 0xe) + setEntries(markF, 0xf) +} + +func _m(tag_remainder uint, cb func()) { + if tag_remainder == 0 { + cb() + } else { + mark_lookup[tag_remainder&0xf](tag_remainder>>bitWidth, cb) + } +} + +func readStackTags(stack []uintptr) (tags []uint) { + var current_tag uint + for _, pc := range stack { + pc = runtime.FuncForPC(pc).Entry() + val, ok := pc_lookup[pc] + if !ok { + continue + } + if val < 0 { + tags = append(tags, current_tag) + current_tag = 0 + continue + } + current_tag <<= bitWidth + current_tag += uint(val) + } + return +} diff --git a/vendor/github.com/smartystreets/assertions/LICENSE.md b/vendor/github.com/smartystreets/assertions/LICENSE.md new file mode 100644 index 0000000000..48a3731c01 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/LICENSE.md @@ -0,0 +1,23 @@ +Copyright (c) 2015 SmartyStreets, LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +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. + +NOTE: Various optional and subordinate components carry their own licensing +requirements and restrictions. Use of those components is subject to the terms +and conditions outlined the respective license of each component. diff --git a/vendor/github.com/smartystreets/assertions/README.md b/vendor/github.com/smartystreets/assertions/README.md new file mode 100644 index 0000000000..fdbd63238f --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/README.md @@ -0,0 +1,528 @@ +# assertions +-- + import "github.com/smartystreets/assertions" + +Package assertions contains the implementations for all assertions which are +referenced in goconvey's `convey` package +(github.com/smartystreets/goconvey/convey) for use with the So(...) method. They +can also be used in traditional Go test functions and even in applicaitons. + +## Usage + +#### func GoConveyMode + +```go +func GoConveyMode(yes bool) +``` +GoConveyMode provides control over JSON serialization of failures. When using +the assertions in this package from the convey package JSON results are very +helpful and can be rendered in a DIFF view. In that case, this function will be +called with a true value to enable the JSON serialization. By default, the +assertions in this package will not serializer a JSON result, making standalone +ussage more convenient. + +#### func ShouldAlmostEqual + +```go +func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string +``` +ShouldAlmostEqual makes sure that two parameters are close enough to being +equal. The acceptable delta may be specified with a third argument, or a very +small default delta will be used. + +#### func ShouldBeBetween + +```go +func ShouldBeBetween(actual interface{}, expected ...interface{}) string +``` +ShouldBeBetween receives exactly three parameters: an actual value, a lower +bound, and an upper bound. It ensures that the actual value is between both +bounds (but not equal to either of them). + +#### func ShouldBeBetweenOrEqual + +```go +func ShouldBeBetweenOrEqual(actual interface{}, expected ...interface{}) string +``` +ShouldBeBetweenOrEqual receives exactly three parameters: an actual value, a +lower bound, and an upper bound. It ensures that the actual value is between +both bounds or equal to one of them. + +#### func ShouldBeBlank + +```go +func ShouldBeBlank(actual interface{}, expected ...interface{}) string +``` +ShouldBeBlank receives exactly 1 string parameter and ensures that it is equal +to "". + +#### func ShouldBeChronological + +```go +func ShouldBeChronological(actual interface{}, expected ...interface{}) string +``` +ShouldBeChronological receives a []time.Time slice and asserts that the are in +chronological order starting with the first time.Time as the earliest. + +#### func ShouldBeEmpty + +```go +func ShouldBeEmpty(actual interface{}, expected ...interface{}) string +``` +ShouldBeEmpty receives a single parameter (actual) and determines whether or not +calling len(actual) would return `0`. It obeys the rules specified by the len +function for determining length: http://golang.org/pkg/builtin/#len + +#### func ShouldBeFalse + +```go +func ShouldBeFalse(actual interface{}, expected ...interface{}) string +``` +ShouldBeFalse receives a single parameter and ensures that it is false. + +#### func ShouldBeGreaterThan + +```go +func ShouldBeGreaterThan(actual interface{}, expected ...interface{}) string +``` +ShouldBeGreaterThan receives exactly two parameters and ensures that the first +is greater than the second. + +#### func ShouldBeGreaterThanOrEqualTo + +```go +func ShouldBeGreaterThanOrEqualTo(actual interface{}, expected ...interface{}) string +``` +ShouldBeGreaterThanOrEqualTo receives exactly two parameters and ensures that +the first is greater than or equal to the second. + +#### func ShouldBeIn + +```go +func ShouldBeIn(actual interface{}, expected ...interface{}) string +``` +ShouldBeIn receives at least 2 parameters. The first is a proposed member of the +collection that is passed in either as the second parameter, or of the +collection that is comprised of all the remaining parameters. This assertion +ensures that the proposed member is in the collection (using ShouldEqual). + +#### func ShouldBeLessThan + +```go +func ShouldBeLessThan(actual interface{}, expected ...interface{}) string +``` +ShouldBeLessThan receives exactly two parameters and ensures that the first is +less than the second. + +#### func ShouldBeLessThanOrEqualTo + +```go +func ShouldBeLessThanOrEqualTo(actual interface{}, expected ...interface{}) string +``` +ShouldBeLessThan receives exactly two parameters and ensures that the first is +less than or equal to the second. + +#### func ShouldBeNil + +```go +func ShouldBeNil(actual interface{}, expected ...interface{}) string +``` +ShouldBeNil receives a single parameter and ensures that it is nil. + +#### func ShouldBeTrue + +```go +func ShouldBeTrue(actual interface{}, expected ...interface{}) string +``` +ShouldBeTrue receives a single parameter and ensures that it is true. + +#### func ShouldBeZeroValue + +```go +func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string +``` +ShouldBeZeroValue receives a single parameter and ensures that it is the Go +equivalent of the default value, or "zero" value. + +#### func ShouldContain + +```go +func ShouldContain(actual interface{}, expected ...interface{}) string +``` +ShouldContain receives exactly two parameters. The first is a slice and the +second is a proposed member. Membership is determined using ShouldEqual. + +#### func ShouldContainKey + +```go +func ShouldContainKey(actual interface{}, expected ...interface{}) string +``` +ShouldContainKey receives exactly two parameters. The first is a map and the +second is a proposed key. Keys are compared with a simple '=='. + +#### func ShouldContainSubstring + +```go +func ShouldContainSubstring(actual interface{}, expected ...interface{}) string +``` +ShouldContainSubstring receives exactly 2 string parameters and ensures that the +first contains the second as a substring. + +#### func ShouldEndWith + +```go +func ShouldEndWith(actual interface{}, expected ...interface{}) string +``` +ShouldEndWith receives exactly 2 string parameters and ensures that the first +ends with the second. + +#### func ShouldEqual + +```go +func ShouldEqual(actual interface{}, expected ...interface{}) string +``` +ShouldEqual receives exactly two parameters and does an equality check. + +#### func ShouldHappenAfter + +```go +func ShouldHappenAfter(actual interface{}, expected ...interface{}) string +``` +ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the +first happens after the second. + +#### func ShouldHappenBefore + +```go +func ShouldHappenBefore(actual interface{}, expected ...interface{}) string +``` +ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the +first happens before the second. + +#### func ShouldHappenBetween + +```go +func ShouldHappenBetween(actual interface{}, expected ...interface{}) string +``` +ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the +first happens between (not on) the second and third. + +#### func ShouldHappenOnOrAfter + +```go +func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) string +``` +ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that +the first happens on or after the second. + +#### func ShouldHappenOnOrBefore + +```go +func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) string +``` +ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that +the first happens on or before the second. + +#### func ShouldHappenOnOrBetween + +```go +func ShouldHappenOnOrBetween(actual interface{}, expected ...interface{}) string +``` +ShouldHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that +the first happens between or on the second and third. + +#### func ShouldHappenWithin + +```go +func ShouldHappenWithin(actual interface{}, expected ...interface{}) string +``` +ShouldHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 +arguments) and asserts that the first time.Time happens within or on the +duration specified relative to the other time.Time. + +#### func ShouldHaveSameTypeAs + +```go +func ShouldHaveSameTypeAs(actual interface{}, expected ...interface{}) string +``` +ShouldHaveSameTypeAs receives exactly two parameters and compares their +underlying types for equality. + +#### func ShouldImplement + +```go +func ShouldImplement(actual interface{}, expectedList ...interface{}) string +``` +ShouldImplement receives exactly two parameters and ensures that the first +implements the interface type of the second. + +#### func ShouldNotAlmostEqual + +```go +func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string +``` +ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual + +#### func ShouldNotBeBetween + +```go +func ShouldNotBeBetween(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeBetween receives exactly three parameters: an actual value, a lower +bound, and an upper bound. It ensures that the actual value is NOT between both +bounds. + +#### func ShouldNotBeBetweenOrEqual + +```go +func ShouldNotBeBetweenOrEqual(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeBetweenOrEqual receives exactly three parameters: an actual value, a +lower bound, and an upper bound. It ensures that the actual value is nopt +between the bounds nor equal to either of them. + +#### func ShouldNotBeBlank + +```go +func ShouldNotBeBlank(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeBlank receives exactly 1 string parameter and ensures that it is +equal to "". + +#### func ShouldNotBeEmpty + +```go +func ShouldNotBeEmpty(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeEmpty receives a single parameter (actual) and determines whether or +not calling len(actual) would return a value greater than zero. It obeys the +rules specified by the `len` function for determining length: +http://golang.org/pkg/builtin/#len + +#### func ShouldNotBeIn + +```go +func ShouldNotBeIn(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeIn receives at least 2 parameters. The first is a proposed member of +the collection that is passed in either as the second parameter, or of the +collection that is comprised of all the remaining parameters. This assertion +ensures that the proposed member is NOT in the collection (using ShouldEqual). + +#### func ShouldNotBeNil + +```go +func ShouldNotBeNil(actual interface{}, expected ...interface{}) string +``` +ShouldNotBeNil receives a single parameter and ensures that it is not nil. + +#### func ShouldNotContain + +```go +func ShouldNotContain(actual interface{}, expected ...interface{}) string +``` +ShouldNotContain receives exactly two parameters. The first is a slice and the +second is a proposed member. Membership is determinied using ShouldEqual. + +#### func ShouldNotContainKey + +```go +func ShouldNotContainKey(actual interface{}, expected ...interface{}) string +``` +ShouldNotContainKey receives exactly two parameters. The first is a map and the +second is a proposed absent key. Keys are compared with a simple '=='. + +#### func ShouldNotContainSubstring + +```go +func ShouldNotContainSubstring(actual interface{}, expected ...interface{}) string +``` +ShouldNotContainSubstring receives exactly 2 string parameters and ensures that +the first does NOT contain the second as a substring. + +#### func ShouldNotEndWith + +```go +func ShouldNotEndWith(actual interface{}, expected ...interface{}) string +``` +ShouldEndWith receives exactly 2 string parameters and ensures that the first +does not end with the second. + +#### func ShouldNotEqual + +```go +func ShouldNotEqual(actual interface{}, expected ...interface{}) string +``` +ShouldNotEqual receives exactly two parameters and does an inequality check. + +#### func ShouldNotHappenOnOrBetween + +```go +func ShouldNotHappenOnOrBetween(actual interface{}, expected ...interface{}) string +``` +ShouldNotHappenOnOrBetween receives exactly 3 time.Time arguments and asserts +that the first does NOT happen between or on the second or third. + +#### func ShouldNotHappenWithin + +```go +func ShouldNotHappenWithin(actual interface{}, expected ...interface{}) string +``` +ShouldNotHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 +arguments) and asserts that the first time.Time does NOT happen within or on the +duration specified relative to the other time.Time. + +#### func ShouldNotHaveSameTypeAs + +```go +func ShouldNotHaveSameTypeAs(actual interface{}, expected ...interface{}) string +``` +ShouldNotHaveSameTypeAs receives exactly two parameters and compares their +underlying types for inequality. + +#### func ShouldNotImplement + +```go +func ShouldNotImplement(actual interface{}, expectedList ...interface{}) string +``` +ShouldNotImplement receives exactly two parameters and ensures that the first +does NOT implement the interface type of the second. + +#### func ShouldNotPanic + +```go +func ShouldNotPanic(actual interface{}, expected ...interface{}) (message string) +``` +ShouldNotPanic receives a void, niladic function and expects to execute the +function without any panic. + +#### func ShouldNotPanicWith + +```go +func ShouldNotPanicWith(actual interface{}, expected ...interface{}) (message string) +``` +ShouldNotPanicWith receives a void, niladic function and expects to recover a +panic whose content differs from the second argument. + +#### func ShouldNotPointTo + +```go +func ShouldNotPointTo(actual interface{}, expected ...interface{}) string +``` +ShouldNotPointTo receives exactly two parameters and checks to see that they +point to different addresess. + +#### func ShouldNotResemble + +```go +func ShouldNotResemble(actual interface{}, expected ...interface{}) string +``` +ShouldNotResemble receives exactly two parameters and does an inverse deep equal +check (see reflect.DeepEqual) + +#### func ShouldNotStartWith + +```go +func ShouldNotStartWith(actual interface{}, expected ...interface{}) string +``` +ShouldNotStartWith receives exactly 2 string parameters and ensures that the +first does not start with the second. + +#### func ShouldPanic + +```go +func ShouldPanic(actual interface{}, expected ...interface{}) (message string) +``` +ShouldPanic receives a void, niladic function and expects to recover a panic. + +#### func ShouldPanicWith + +```go +func ShouldPanicWith(actual interface{}, expected ...interface{}) (message string) +``` +ShouldPanicWith receives a void, niladic function and expects to recover a panic +with the second argument as the content. + +#### func ShouldPointTo + +```go +func ShouldPointTo(actual interface{}, expected ...interface{}) string +``` +ShouldPointTo receives exactly two parameters and checks to see that they point +to the same address. + +#### func ShouldResemble + +```go +func ShouldResemble(actual interface{}, expected ...interface{}) string +``` +ShouldResemble receives exactly two parameters and does a deep equal check (see +reflect.DeepEqual) + +#### func ShouldStartWith + +```go +func ShouldStartWith(actual interface{}, expected ...interface{}) string +``` +ShouldStartWith receives exactly 2 string parameters and ensures that the first +starts with the second. + +#### func So + +```go +func So(actual interface{}, assert assertion, expected ...interface{}) (bool, string) +``` +So is a convenience function (as opposed to an inconvenience function?) for +running assertions on arbitrary arguments in any context, be it for testing or +even application logging. It allows you to perform assertion-like behavior (and +get nicely formatted messages detailing discrepancies) but without the program +blowing up or panicking. All that is required is to import this package and call +`So` with one of the assertions exported by this package as the second +parameter. The first return parameter is a boolean indicating if the assertion +was true. The second return parameter is the well-formatted message showing why +an assertion was incorrect, or blank if the assertion was correct. + +Example: + + if ok, message := So(x, ShouldBeGreaterThan, y); !ok { + log.Println(message) + } + +#### type Assertion + +```go +type Assertion struct { +} +``` + + +#### func New + +```go +func New(t testingT) *Assertion +``` +New swallows the *testing.T struct and prints failed assertions using t.Error. +Example: assertions.New(t).So(1, should.Equal, 1) + +#### func (*Assertion) Failed + +```go +func (this *Assertion) Failed() bool +``` +Failed reports whether any calls to So (on this Assertion instance) have failed. + +#### func (*Assertion) So + +```go +func (this *Assertion) So(actual interface{}, assert assertion, expected ...interface{}) bool +``` +So calls the standalone So function and additionally, calls t.Error in failure +scenarios. + +#### type Serializer + +```go +type Serializer interface { + // contains filtered or unexported methods +} +``` diff --git a/vendor/github.com/smartystreets/assertions/assertions.goconvey b/vendor/github.com/smartystreets/assertions/assertions.goconvey new file mode 100644 index 0000000000..e76cf275d4 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/assertions.goconvey @@ -0,0 +1,3 @@ +#ignore +-timeout=1s +-coverpkg=github.com/smartystreets/assertions,github.com/smartystreets/assertions/internal/oglematchers \ No newline at end of file diff --git a/vendor/github.com/smartystreets/assertions/collections.go b/vendor/github.com/smartystreets/assertions/collections.go new file mode 100644 index 0000000000..b06ac65326 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/collections.go @@ -0,0 +1,195 @@ +package assertions + +import ( + "fmt" + "reflect" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +// ShouldContain receives exactly two parameters. The first is a slice and the +// second is a proposed member. Membership is determined using ShouldEqual. +func ShouldContain(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil { + typeName := reflect.TypeOf(actual) + + if fmt.Sprintf("%v", matchError) == "which is not a slice or array" { + return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName) + } + return fmt.Sprintf(shouldHaveContained, typeName, expected[0]) + } + return success +} + +// ShouldNotContain receives exactly two parameters. The first is a slice and the +// second is a proposed member. Membership is determinied using ShouldEqual. +func ShouldNotContain(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + typeName := reflect.TypeOf(actual) + + if matchError := oglematchers.Contains(expected[0]).Matches(actual); matchError != nil { + if fmt.Sprintf("%v", matchError) == "which is not a slice or array" { + return fmt.Sprintf(shouldHaveBeenAValidCollection, typeName) + } + return success + } + return fmt.Sprintf(shouldNotHaveContained, typeName, expected[0]) +} + +// ShouldContainKey receives exactly two parameters. The first is a map and the +// second is a proposed key. Keys are compared with a simple '=='. +func ShouldContainKey(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + keys, isMap := mapKeys(actual) + if !isMap { + return fmt.Sprintf(shouldHaveBeenAValidMap, reflect.TypeOf(actual)) + } + + if !keyFound(keys, expected[0]) { + return fmt.Sprintf(shouldHaveContainedKey, reflect.TypeOf(actual), expected) + } + + return "" +} + +// ShouldNotContainKey receives exactly two parameters. The first is a map and the +// second is a proposed absent key. Keys are compared with a simple '=='. +func ShouldNotContainKey(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + keys, isMap := mapKeys(actual) + if !isMap { + return fmt.Sprintf(shouldHaveBeenAValidMap, reflect.TypeOf(actual)) + } + + if keyFound(keys, expected[0]) { + return fmt.Sprintf(shouldNotHaveContainedKey, reflect.TypeOf(actual), expected) + } + + return "" +} + +func mapKeys(m interface{}) ([]reflect.Value, bool) { + value := reflect.ValueOf(m) + if value.Kind() != reflect.Map { + return nil, false + } + return value.MapKeys(), true +} +func keyFound(keys []reflect.Value, expectedKey interface{}) bool { + found := false + for _, key := range keys { + if key.Interface() == expectedKey { + found = true + } + } + return found +} + +// ShouldBeIn receives at least 2 parameters. The first is a proposed member of the collection +// that is passed in either as the second parameter, or of the collection that is comprised +// of all the remaining parameters. This assertion ensures that the proposed member is in +// the collection (using ShouldEqual). +func ShouldBeIn(actual interface{}, expected ...interface{}) string { + if fail := atLeast(1, expected); fail != success { + return fail + } + + if len(expected) == 1 { + return shouldBeIn(actual, expected[0]) + } + return shouldBeIn(actual, expected) +} +func shouldBeIn(actual interface{}, expected interface{}) string { + if matchError := oglematchers.Contains(actual).Matches(expected); matchError != nil { + return fmt.Sprintf(shouldHaveBeenIn, actual, reflect.TypeOf(expected)) + } + return success +} + +// ShouldNotBeIn receives at least 2 parameters. The first is a proposed member of the collection +// that is passed in either as the second parameter, or of the collection that is comprised +// of all the remaining parameters. This assertion ensures that the proposed member is NOT in +// the collection (using ShouldEqual). +func ShouldNotBeIn(actual interface{}, expected ...interface{}) string { + if fail := atLeast(1, expected); fail != success { + return fail + } + + if len(expected) == 1 { + return shouldNotBeIn(actual, expected[0]) + } + return shouldNotBeIn(actual, expected) +} +func shouldNotBeIn(actual interface{}, expected interface{}) string { + if matchError := oglematchers.Contains(actual).Matches(expected); matchError == nil { + return fmt.Sprintf(shouldNotHaveBeenIn, actual, reflect.TypeOf(expected)) + } + return success +} + +// ShouldBeEmpty receives a single parameter (actual) and determines whether or not +// calling len(actual) would return `0`. It obeys the rules specified by the len +// function for determining length: http://golang.org/pkg/builtin/#len +func ShouldBeEmpty(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + + if actual == nil { + return success + } + + value := reflect.ValueOf(actual) + switch value.Kind() { + case reflect.Slice: + if value.Len() == 0 { + return success + } + case reflect.Chan: + if value.Len() == 0 { + return success + } + case reflect.Map: + if value.Len() == 0 { + return success + } + case reflect.String: + if value.Len() == 0 { + return success + } + case reflect.Ptr: + elem := value.Elem() + kind := elem.Kind() + if (kind == reflect.Slice || kind == reflect.Array) && elem.Len() == 0 { + return success + } + } + + return fmt.Sprintf(shouldHaveBeenEmpty, actual) +} + +// ShouldNotBeEmpty receives a single parameter (actual) and determines whether or not +// calling len(actual) would return a value greater than zero. It obeys the rules +// specified by the `len` function for determining length: http://golang.org/pkg/builtin/#len +func ShouldNotBeEmpty(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + + if empty := ShouldBeEmpty(actual, expected...); empty != success { + return success + } + return fmt.Sprintf(shouldNotHaveBeenEmpty, actual) +} diff --git a/vendor/github.com/smartystreets/assertions/collections_test.go b/vendor/github.com/smartystreets/assertions/collections_test.go new file mode 100644 index 0000000000..ba4afb4055 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/collections_test.go @@ -0,0 +1,125 @@ +package assertions + +import ( + "fmt" + "testing" + "time" +) + +func TestShouldContainKey(t *testing.T) { + fail(t, so(map[int]int{}, ShouldContainKey), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(map[int]int{}, ShouldContainKey, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(Thing1{}, ShouldContainKey, 1), "You must provide a valid map type (was assertions.Thing1)!") + fail(t, so(nil, ShouldContainKey, 1), "You must provide a valid map type (was )!") + fail(t, so(map[int]int{1: 41}, ShouldContainKey, 2), "Expected the map[int]int to contain the key: [2] (but it didn't)!") + + pass(t, so(map[int]int{1: 41}, ShouldContainKey, 1)) + pass(t, so(map[int]int{1: 41, 2: 42, 3: 43}, ShouldContainKey, 2)) +} + +func TestShouldNotContainKey(t *testing.T) { + fail(t, so(map[int]int{}, ShouldNotContainKey), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(map[int]int{}, ShouldNotContainKey, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(Thing1{}, ShouldNotContainKey, 1), "You must provide a valid map type (was assertions.Thing1)!") + fail(t, so(nil, ShouldNotContainKey, 1), "You must provide a valid map type (was )!") + fail(t, so(map[int]int{1: 41}, ShouldNotContainKey, 1), "Expected the map[int]int NOT to contain the key: [1] (but it did)!") + pass(t, so(map[int]int{1: 41}, ShouldNotContainKey, 2)) +} + +func TestShouldContain(t *testing.T) { + fail(t, so([]int{}, ShouldContain), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so([]int{}, ShouldContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(Thing1{}, ShouldContain, 1), "You must provide a valid container (was assertions.Thing1)!") + fail(t, so(nil, ShouldContain, 1), "You must provide a valid container (was )!") + fail(t, so([]int{1}, ShouldContain, 2), "Expected the container ([]int) to contain: '2' (but it didn't)!") + + pass(t, so([]int{1}, ShouldContain, 1)) + pass(t, so([]int{1, 2, 3}, ShouldContain, 2)) +} + +func TestShouldNotContain(t *testing.T) { + fail(t, so([]int{}, ShouldNotContain), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so([]int{}, ShouldNotContain, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(Thing1{}, ShouldNotContain, 1), "You must provide a valid container (was assertions.Thing1)!") + fail(t, so(nil, ShouldNotContain, 1), "You must provide a valid container (was )!") + + fail(t, so([]int{1}, ShouldNotContain, 1), "Expected the container ([]int) NOT to contain: '1' (but it did)!") + fail(t, so([]int{1, 2, 3}, ShouldNotContain, 2), "Expected the container ([]int) NOT to contain: '2' (but it did)!") + + pass(t, so([]int{1}, ShouldNotContain, 2)) +} + +func TestShouldBeIn(t *testing.T) { + fail(t, so(4, ShouldBeIn), needNonEmptyCollection) + + container := []int{1, 2, 3, 4} + pass(t, so(4, ShouldBeIn, container)) + pass(t, so(4, ShouldBeIn, 1, 2, 3, 4)) + + fail(t, so(4, ShouldBeIn, 1, 2, 3), "Expected '4' to be in the container ([]interface {}), but it wasn't!") + fail(t, so(4, ShouldBeIn, []int{1, 2, 3}), "Expected '4' to be in the container ([]int), but it wasn't!") +} + +func TestShouldNotBeIn(t *testing.T) { + fail(t, so(4, ShouldNotBeIn), needNonEmptyCollection) + + container := []int{1, 2, 3, 4} + pass(t, so(42, ShouldNotBeIn, container)) + pass(t, so(42, ShouldNotBeIn, 1, 2, 3, 4)) + + fail(t, so(2, ShouldNotBeIn, 1, 2, 3), "Expected '2' NOT to be in the container ([]interface {}), but it was!") + fail(t, so(2, ShouldNotBeIn, []int{1, 2, 3}), "Expected '2' NOT to be in the container ([]int), but it was!") +} + +func TestShouldBeEmpty(t *testing.T) { + fail(t, so(1, ShouldBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).") + + pass(t, so([]int{}, ShouldBeEmpty)) // empty slice + pass(t, so([]interface{}{}, ShouldBeEmpty)) // empty slice + pass(t, so(map[string]int{}, ShouldBeEmpty)) // empty map + pass(t, so("", ShouldBeEmpty)) // empty string + pass(t, so(&[]int{}, ShouldBeEmpty)) // pointer to empty slice + pass(t, so(&[0]int{}, ShouldBeEmpty)) // pointer to empty array + pass(t, so(nil, ShouldBeEmpty)) // nil + pass(t, so(make(chan string), ShouldBeEmpty)) // empty channel + + fail(t, so([]int{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!") // non-empty slice + fail(t, so([]interface{}{1}, ShouldBeEmpty), "Expected [1] to be empty (but it wasn't)!") // non-empty slice + fail(t, so(map[string]int{"hi": 0}, ShouldBeEmpty), "Expected map[hi:0] to be empty (but it wasn't)!") // non-empty map + fail(t, so("hi", ShouldBeEmpty), "Expected hi to be empty (but it wasn't)!") // non-empty string + fail(t, so(&[]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!") // pointer to non-empty slice + fail(t, so(&[1]int{1}, ShouldBeEmpty), "Expected &[1] to be empty (but it wasn't)!") // pointer to non-empty array + c := make(chan int, 1) // non-empty channel + go func() { c <- 1 }() + time.Sleep(time.Millisecond) + fail(t, so(c, ShouldBeEmpty), fmt.Sprintf("Expected %+v to be empty (but it wasn't)!", c)) +} + +func TestShouldNotBeEmpty(t *testing.T) { + fail(t, so(1, ShouldNotBeEmpty, 2, 3), "This assertion requires exactly 0 comparison values (you provided 2).") + + fail(t, so([]int{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!") // empty slice + fail(t, so([]interface{}{}, ShouldNotBeEmpty), "Expected [] to NOT be empty (but it was)!") // empty slice + fail(t, so(map[string]int{}, ShouldNotBeEmpty), "Expected map[] to NOT be empty (but it was)!") // empty map + fail(t, so("", ShouldNotBeEmpty), "Expected to NOT be empty (but it was)!") // empty string + fail(t, so(&[]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!") // pointer to empty slice + fail(t, so(&[0]int{}, ShouldNotBeEmpty), "Expected &[] to NOT be empty (but it was)!") // pointer to empty array + fail(t, so(nil, ShouldNotBeEmpty), "Expected to NOT be empty (but it was)!") // nil + c := make(chan int, 0) // non-empty channel + fail(t, so(c, ShouldNotBeEmpty), fmt.Sprintf("Expected %+v to NOT be empty (but it was)!", c)) // empty channel + + pass(t, so([]int{1}, ShouldNotBeEmpty)) // non-empty slice + pass(t, so([]interface{}{1}, ShouldNotBeEmpty)) // non-empty slice + pass(t, so(map[string]int{"hi": 0}, ShouldNotBeEmpty)) // non-empty map + pass(t, so("hi", ShouldNotBeEmpty)) // non-empty string + pass(t, so(&[]int{1}, ShouldNotBeEmpty)) // pointer to non-empty slice + pass(t, so(&[1]int{1}, ShouldNotBeEmpty)) // pointer to non-empty array + c = make(chan int, 1) + go func() { c <- 1 }() + time.Sleep(time.Millisecond) + pass(t, so(c, ShouldNotBeEmpty)) +} diff --git a/vendor/github.com/smartystreets/assertions/doc.go b/vendor/github.com/smartystreets/assertions/doc.go new file mode 100644 index 0000000000..d3d116c418 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/doc.go @@ -0,0 +1,99 @@ +// Package assertions contains the implementations for all assertions which +// are referenced in goconvey's `convey` package +// (github.com/smartystreets/goconvey/convey) for use with the So(...) method. +// They can also be used in traditional Go test functions and even in +// applicaitons. +package assertions + +import ( + "fmt" + "runtime" +) + +// By default we use a no-op serializer. The actual Serializer provides a JSON +// representation of failure results on selected assertions so the goconvey +// web UI can display a convenient diff. +var serializer Serializer = new(noopSerializer) + +// GoConveyMode provides control over JSON serialization of failures. When +// using the assertions in this package from the convey package JSON results +// are very helpful and can be rendered in a DIFF view. In that case, this function +// will be called with a true value to enable the JSON serialization. By default, +// the assertions in this package will not serializer a JSON result, making +// standalone ussage more convenient. +func GoConveyMode(yes bool) { + if yes { + serializer = newSerializer() + } else { + serializer = new(noopSerializer) + } +} + +type testingT interface { + Error(args ...interface{}) +} + +type Assertion struct { + t testingT + failed bool +} + +// New swallows the *testing.T struct and prints failed assertions using t.Error. +// Example: assertions.New(t).So(1, should.Equal, 1) +func New(t testingT) *Assertion { + return &Assertion{t: t} +} + +// Failed reports whether any calls to So (on this Assertion instance) have failed. +func (this *Assertion) Failed() bool { + return this.failed +} + +// So calls the standalone So function and additionally, calls t.Error in failure scenarios. +func (this *Assertion) So(actual interface{}, assert assertion, expected ...interface{}) bool { + ok, result := So(actual, assert, expected...) + if !ok { + this.failed = true + _, file, line, _ := runtime.Caller(1) + this.t.Error(fmt.Sprintf("\n%s:%d\n%s", file, line, result)) + } + return ok +} + +// So is a convenience function (as opposed to an inconvenience function?) +// for running assertions on arbitrary arguments in any context, be it for testing or even +// application logging. It allows you to perform assertion-like behavior (and get nicely +// formatted messages detailing discrepancies) but without the program blowing up or panicking. +// All that is required is to import this package and call `So` with one of the assertions +// exported by this package as the second parameter. +// The first return parameter is a boolean indicating if the assertion was true. The second +// return parameter is the well-formatted message showing why an assertion was incorrect, or +// blank if the assertion was correct. +// +// Example: +// +// if ok, message := So(x, ShouldBeGreaterThan, y); !ok { +// log.Println(message) +// } +// +func So(actual interface{}, assert assertion, expected ...interface{}) (bool, string) { + if result := so(actual, assert, expected...); len(result) == 0 { + return true, result + } else { + return false, result + } +} + +// so is like So, except that it only returns the string message, which is blank if the +// assertion passed. Used to facilitate testing. +func so(actual interface{}, assert func(interface{}, ...interface{}) string, expected ...interface{}) string { + return assert(actual, expected...) +} + +// assertion is an alias for a function with a signature that the So() +// function can handle. Any future or custom assertions should conform to this +// method signature. The return value should be an empty string if the assertion +// passes and a well-formed failure message if not. +type assertion func(actual interface{}, expected ...interface{}) string + +//////////////////////////////////////////////////////////////////////////// diff --git a/vendor/github.com/smartystreets/assertions/doc_test.go b/vendor/github.com/smartystreets/assertions/doc_test.go new file mode 100644 index 0000000000..041faaffcb --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/doc_test.go @@ -0,0 +1,57 @@ +package assertions + +import ( + "bytes" + "fmt" + "testing" +) + +func TestPassingAssertion(t *testing.T) { + fake := &FakeT{buffer: new(bytes.Buffer)} + assertion := New(fake) + passed := assertion.So(1, ShouldEqual, 1) + + if !passed { + t.Error("Assertion failed when it should have passed.") + } + if fake.buffer.Len() > 0 { + t.Error("Unexpected error message was printed.") + } +} + +func TestFailingAssertion(t *testing.T) { + fake := &FakeT{buffer: new(bytes.Buffer)} + assertion := New(fake) + passed := assertion.So(1, ShouldEqual, 2) + + if passed { + t.Error("Assertion passed when it should have failed.") + } + if fake.buffer.Len() == 0 { + t.Error("Expected error message not printed.") + } +} + +func TestFailingGroupsOfAssertions(t *testing.T) { + fake := &FakeT{buffer: new(bytes.Buffer)} + assertion1 := New(fake) + assertion2 := New(fake) + + assertion1.So(1, ShouldEqual, 2) // fail + assertion2.So(1, ShouldEqual, 1) // pass + + if !assertion1.Failed() { + t.Error("Expected the first assertion to have been marked as failed.") + } + if assertion2.Failed() { + t.Error("Expected the second assertion to NOT have been marked as failed.") + } +} + +type FakeT struct { + buffer *bytes.Buffer +} + +func (this *FakeT) Error(args ...interface{}) { + fmt.Fprint(this.buffer, args...) +} diff --git a/vendor/github.com/smartystreets/assertions/equality.go b/vendor/github.com/smartystreets/assertions/equality.go new file mode 100644 index 0000000000..636aa918e4 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/equality.go @@ -0,0 +1,279 @@ +package assertions + +import ( + "errors" + "fmt" + "math" + "reflect" + "strings" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +// default acceptable delta for ShouldAlmostEqual +const defaultDelta = 0.0000000001 + +// ShouldEqual receives exactly two parameters and does an equality check. +func ShouldEqual(actual interface{}, expected ...interface{}) string { + if message := need(1, expected); message != success { + return message + } + return shouldEqual(actual, expected[0]) +} +func shouldEqual(actual, expected interface{}) (message string) { + defer func() { + if r := recover(); r != nil { + message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual)) + return + } + }() + + if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil { + message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual)) + return + } + + return success +} + +// ShouldNotEqual receives exactly two parameters and does an inequality check. +func ShouldNotEqual(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } else if ShouldEqual(actual, expected[0]) == success { + return fmt.Sprintf(shouldNotHaveBeenEqual, actual, expected[0]) + } + return success +} + +// ShouldAlmostEqual makes sure that two parameters are close enough to being equal. +// The acceptable delta may be specified with a third argument, +// or a very small default delta will be used. +func ShouldAlmostEqual(actual interface{}, expected ...interface{}) string { + actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...) + + if err != "" { + return err + } + + if math.Abs(actualFloat-expectedFloat) <= deltaFloat { + return success + } else { + return fmt.Sprintf(shouldHaveBeenAlmostEqual, actualFloat, expectedFloat) + } +} + +// ShouldNotAlmostEqual is the inverse of ShouldAlmostEqual +func ShouldNotAlmostEqual(actual interface{}, expected ...interface{}) string { + actualFloat, expectedFloat, deltaFloat, err := cleanAlmostEqualInput(actual, expected...) + + if err != "" { + return err + } + + if math.Abs(actualFloat-expectedFloat) > deltaFloat { + return success + } else { + return fmt.Sprintf(shouldHaveNotBeenAlmostEqual, actualFloat, expectedFloat) + } +} + +func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64, float64, float64, string) { + deltaFloat := 0.0000000001 + + if len(expected) == 0 { + return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided neither)" + } else if len(expected) == 2 { + delta, err := getFloat(expected[1]) + + if err != nil { + return 0.0, 0.0, 0.0, "delta must be a numerical type" + } + + deltaFloat = delta + } else if len(expected) > 2 { + return 0.0, 0.0, 0.0, "This assertion requires exactly one comparison value and an optional delta (you provided more values)" + } + + actualFloat, err := getFloat(actual) + + if err != nil { + return 0.0, 0.0, 0.0, err.Error() + } + + expectedFloat, err := getFloat(expected[0]) + + if err != nil { + return 0.0, 0.0, 0.0, err.Error() + } + + return actualFloat, expectedFloat, deltaFloat, "" +} + +// returns the float value of any real number, or error if it is not a numerical type +func getFloat(num interface{}) (float64, error) { + numValue := reflect.ValueOf(num) + numKind := numValue.Kind() + + if numKind == reflect.Int || + numKind == reflect.Int8 || + numKind == reflect.Int16 || + numKind == reflect.Int32 || + numKind == reflect.Int64 { + return float64(numValue.Int()), nil + } else if numKind == reflect.Uint || + numKind == reflect.Uint8 || + numKind == reflect.Uint16 || + numKind == reflect.Uint32 || + numKind == reflect.Uint64 { + return float64(numValue.Uint()), nil + } else if numKind == reflect.Float32 || + numKind == reflect.Float64 { + return numValue.Float(), nil + } else { + return 0.0, errors.New("must be a numerical type, but was " + numKind.String()) + } +} + +// ShouldResemble receives exactly two parameters and does a deep equal check (see reflect.DeepEqual) +func ShouldResemble(actual interface{}, expected ...interface{}) string { + if message := need(1, expected); message != success { + return message + } + + if matchError := oglematchers.DeepEquals(expected[0]).Matches(actual); matchError != nil { + expectedSyntax := fmt.Sprintf("%#v", expected[0]) + actualSyntax := fmt.Sprintf("%#v", actual) + var message string + if expectedSyntax == actualSyntax { + message = fmt.Sprintf(shouldHaveResembledTypeMismatch, expected[0], actual, expected[0], actual) + } else { + message = fmt.Sprintf(shouldHaveResembled, expected[0], actual) + } + return serializer.serializeDetailed(expected[0], actual, message) + } + + return success +} + +// ShouldNotResemble receives exactly two parameters and does an inverse deep equal check (see reflect.DeepEqual) +func ShouldNotResemble(actual interface{}, expected ...interface{}) string { + if message := need(1, expected); message != success { + return message + } else if ShouldResemble(actual, expected[0]) == success { + return fmt.Sprintf(shouldNotHaveResembled, actual, expected[0]) + } + return success +} + +// ShouldPointTo receives exactly two parameters and checks to see that they point to the same address. +func ShouldPointTo(actual interface{}, expected ...interface{}) string { + if message := need(1, expected); message != success { + return message + } + return shouldPointTo(actual, expected[0]) + +} +func shouldPointTo(actual, expected interface{}) string { + actualValue := reflect.ValueOf(actual) + expectedValue := reflect.ValueOf(expected) + + if ShouldNotBeNil(actual) != success { + return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "nil") + } else if ShouldNotBeNil(expected) != success { + return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "nil") + } else if actualValue.Kind() != reflect.Ptr { + return fmt.Sprintf(shouldHaveBeenNonNilPointer, "first", "not") + } else if expectedValue.Kind() != reflect.Ptr { + return fmt.Sprintf(shouldHaveBeenNonNilPointer, "second", "not") + } else if ShouldEqual(actualValue.Pointer(), expectedValue.Pointer()) != success { + actualAddress := reflect.ValueOf(actual).Pointer() + expectedAddress := reflect.ValueOf(expected).Pointer() + return serializer.serialize(expectedAddress, actualAddress, fmt.Sprintf(shouldHavePointedTo, + actual, actualAddress, + expected, expectedAddress)) + } + return success +} + +// ShouldNotPointTo receives exactly two parameters and checks to see that they point to different addresess. +func ShouldNotPointTo(actual interface{}, expected ...interface{}) string { + if message := need(1, expected); message != success { + return message + } + compare := ShouldPointTo(actual, expected[0]) + if strings.HasPrefix(compare, shouldBePointers) { + return compare + } else if compare == success { + return fmt.Sprintf(shouldNotHavePointedTo, actual, expected[0], reflect.ValueOf(actual).Pointer()) + } + return success +} + +// ShouldBeNil receives a single parameter and ensures that it is nil. +func ShouldBeNil(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } else if actual == nil { + return success + } else if interfaceHasNilValue(actual) { + return success + } + return fmt.Sprintf(shouldHaveBeenNil, actual) +} +func interfaceHasNilValue(actual interface{}) bool { + value := reflect.ValueOf(actual) + kind := value.Kind() + nilable := kind == reflect.Slice || + kind == reflect.Chan || + kind == reflect.Func || + kind == reflect.Ptr || + kind == reflect.Map + + // Careful: reflect.Value.IsNil() will panic unless it's an interface, chan, map, func, slice, or ptr + // Reference: http://golang.org/pkg/reflect/#Value.IsNil + return nilable && value.IsNil() +} + +// ShouldNotBeNil receives a single parameter and ensures that it is not nil. +func ShouldNotBeNil(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } else if ShouldBeNil(actual) == success { + return fmt.Sprintf(shouldNotHaveBeenNil, actual) + } + return success +} + +// ShouldBeTrue receives a single parameter and ensures that it is true. +func ShouldBeTrue(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } else if actual != true { + return fmt.Sprintf(shouldHaveBeenTrue, actual) + } + return success +} + +// ShouldBeFalse receives a single parameter and ensures that it is false. +func ShouldBeFalse(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } else if actual != false { + return fmt.Sprintf(shouldHaveBeenFalse, actual) + } + return success +} + +// ShouldBeZeroValue receives a single parameter and ensures that it is +// the Go equivalent of the default value, or "zero" value. +func ShouldBeZeroValue(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + zeroVal := reflect.Zero(reflect.TypeOf(actual)).Interface() + if !reflect.DeepEqual(zeroVal, actual) { + return serializer.serialize(zeroVal, actual, fmt.Sprintf(shouldHaveBeenZeroValue, actual)) + } + return success +} diff --git a/vendor/github.com/smartystreets/assertions/equality_test.go b/vendor/github.com/smartystreets/assertions/equality_test.go new file mode 100644 index 0000000000..ee3939712f --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/equality_test.go @@ -0,0 +1,267 @@ +package assertions + +import ( + "fmt" + "reflect" + "testing" +) + +func TestShouldEqual(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so(1, ShouldEqual), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") + fail(t, so(1, ShouldEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + pass(t, so(1, ShouldEqual, 1)) + fail(t, so(1, ShouldEqual, 2), "2|1|Expected: '2' Actual: '1' (Should be equal)") + + pass(t, so(true, ShouldEqual, true)) + fail(t, so(true, ShouldEqual, false), "false|true|Expected: 'false' Actual: 'true' (Should be equal)") + + pass(t, so("hi", ShouldEqual, "hi")) + fail(t, so("hi", ShouldEqual, "bye"), "bye|hi|Expected: 'bye' Actual: 'hi' (Should be equal)") + + pass(t, so(42, ShouldEqual, uint(42))) + + fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{}), "{}|{hi}|Expected: '{}' Actual: '{hi}' (Should be equal)") + fail(t, so(Thing1{"hi"}, ShouldEqual, Thing1{"hi"}), "{hi}|{hi}|Expected: '{hi}' Actual: '{hi}' (Should be equal)") + fail(t, so(&Thing1{"hi"}, ShouldEqual, &Thing1{"hi"}), "&{hi}|&{hi}|Expected: '&{hi}' Actual: '&{hi}' (Should be equal)") + + fail(t, so(Thing1{}, ShouldEqual, Thing2{}), "{}|{}|Expected: '{}' Actual: '{}' (Should be equal)") +} + +func TestShouldNotEqual(t *testing.T) { + fail(t, so(1, ShouldNotEqual), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldNotEqual, 1, 2), "This assertion requires exactly 1 comparison values (you provided 2).") + fail(t, so(1, ShouldNotEqual, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + pass(t, so(1, ShouldNotEqual, 2)) + fail(t, so(1, ShouldNotEqual, 1), "Expected '1' to NOT equal '1' (but it did)!") + + pass(t, so(true, ShouldNotEqual, false)) + fail(t, so(true, ShouldNotEqual, true), "Expected 'true' to NOT equal 'true' (but it did)!") + + pass(t, so("hi", ShouldNotEqual, "bye")) + fail(t, so("hi", ShouldNotEqual, "hi"), "Expected 'hi' to NOT equal 'hi' (but it did)!") + + pass(t, so(&Thing1{"hi"}, ShouldNotEqual, &Thing1{"hi"})) + pass(t, so(Thing1{"hi"}, ShouldNotEqual, Thing1{"hi"})) + pass(t, so(Thing1{}, ShouldNotEqual, Thing1{})) + pass(t, so(Thing1{}, ShouldNotEqual, Thing2{})) +} + +func TestShouldAlmostEqual(t *testing.T) { + fail(t, so(1, ShouldAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") + fail(t, so(1, ShouldAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") + + // with the default delta + pass(t, so(1, ShouldAlmostEqual, .99999999999999)) + pass(t, so(1.3612499999999996, ShouldAlmostEqual, 1.36125)) + pass(t, so(0.7285312499999999, ShouldAlmostEqual, 0.72853125)) + fail(t, so(1, ShouldAlmostEqual, .99), "Expected '1' to almost equal '0.99' (but it didn't)!") + + // with a different delta + pass(t, so(100.0, ShouldAlmostEqual, 110.0, 10.0)) + fail(t, so(100.0, ShouldAlmostEqual, 111.0, 10.5), "Expected '100' to almost equal '111' (but it didn't)!") + + // ints should work + pass(t, so(100, ShouldAlmostEqual, 100.0)) + fail(t, so(100, ShouldAlmostEqual, 99.0), "Expected '100' to almost equal '99' (but it didn't)!") + + // float32 should work + pass(t, so(float64(100.0), ShouldAlmostEqual, float32(100.0))) + fail(t, so(float32(100.0), ShouldAlmostEqual, 99.0, float32(0.1)), "Expected '100' to almost equal '99' (but it didn't)!") +} + +func TestShouldNotAlmostEqual(t *testing.T) { + fail(t, so(1, ShouldNotAlmostEqual), "This assertion requires exactly one comparison value and an optional delta (you provided neither)") + fail(t, so(1, ShouldNotAlmostEqual, 1, 2, 3), "This assertion requires exactly one comparison value and an optional delta (you provided more values)") + + // with the default delta + fail(t, so(1, ShouldNotAlmostEqual, .99999999999999), "Expected '1' to NOT almost equal '0.99999999999999' (but it did)!") + fail(t, so(1.3612499999999996, ShouldNotAlmostEqual, 1.36125), "Expected '1.3612499999999996' to NOT almost equal '1.36125' (but it did)!") + pass(t, so(1, ShouldNotAlmostEqual, .99)) + + // with a different delta + fail(t, so(100.0, ShouldNotAlmostEqual, 110.0, 10.0), "Expected '100' to NOT almost equal '110' (but it did)!") + pass(t, so(100.0, ShouldNotAlmostEqual, 111.0, 10.5)) + + // ints should work + fail(t, so(100, ShouldNotAlmostEqual, 100.0), "Expected '100' to NOT almost equal '100' (but it did)!") + pass(t, so(100, ShouldNotAlmostEqual, 99.0)) + + // float32 should work + fail(t, so(float64(100.0), ShouldNotAlmostEqual, float32(100.0)), "Expected '100' to NOT almost equal '100' (but it did)!") + pass(t, so(float32(100.0), ShouldNotAlmostEqual, 99.0, float32(0.1))) +} + +func TestShouldResemble(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so(Thing1{"hi"}, ShouldResemble), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"hi"})) + fail(t, so(Thing1{"hi"}, ShouldResemble, Thing1{"bye"}), "{bye}|{hi}|Expected: 'assertions.Thing1{a:\"bye\"}' Actual: 'assertions.Thing1{a:\"hi\"}' (Should resemble)!") + + var ( + a []int + b []int = []int{} + ) + + fail(t, so(a, ShouldResemble, b), "[]|[]|Expected: '[]int{}' Actual: '[]int(nil)' (Should resemble)!") + fail(t, so(2, ShouldResemble, 1), "1|2|Expected: '1' Actual: '2' (Should resemble)!") + + fail(t, so(StringStringMapAlias{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"}), + "map[hi:bye]|map[hi:bye]|Expected: 'map[string]string{\"hi\":\"bye\"}' Actual: 'assertions.StringStringMapAlias{\"hi\":\"bye\"}' (Should resemble)!") + fail(t, so(StringSliceAlias{"hi", "bye"}, ShouldResemble, []string{"hi", "bye"}), + "[hi bye]|[hi bye]|Expected: '[]string{\"hi\", \"bye\"}' Actual: 'assertions.StringSliceAlias{\"hi\", \"bye\"}' (Should resemble)!") + + // some types come out looking the same when represented with "%#v" so we show type mismatch info: + fail(t, so(StringAlias("hi"), ShouldResemble, "hi"), "hi|hi|Expected: '\"hi\"' Actual: '\"hi\"' (Type mismatch: 'string' vs 'assertions.StringAlias')!") + fail(t, so(IntAlias(42), ShouldResemble, 42), "42|42|Expected: '42' Actual: '42' (Type mismatch: 'int' vs 'assertions.IntAlias')!") +} + +func TestShouldNotResemble(t *testing.T) { + fail(t, so(Thing1{"hi"}, ShouldNotResemble), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}, Thing1{"hi"}), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"bye"})) + fail(t, so(Thing1{"hi"}, ShouldNotResemble, Thing1{"hi"}), + "Expected 'assertions.Thing1{a:\"hi\"}' to NOT resemble 'assertions.Thing1{a:\"hi\"}' (but it did)!") + + pass(t, so(map[string]string{"hi": "bye"}, ShouldResemble, map[string]string{"hi": "bye"})) + pass(t, so(IntAlias(42), ShouldNotResemble, 42)) + + pass(t, so(StringSliceAlias{"hi", "bye"}, ShouldNotResemble, []string{"hi", "bye"})) +} + +func TestShouldPointTo(t *testing.T) { + serializer = newFakeSerializer() + + t1 := &Thing1{} + t2 := t1 + t3 := &Thing1{} + + pointer1 := reflect.ValueOf(t1).Pointer() + pointer3 := reflect.ValueOf(t3).Pointer() + + fail(t, so(t1, ShouldPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(t1, ShouldPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(t1, ShouldPointTo, t2)) + fail(t, so(t1, ShouldPointTo, t3), fmt.Sprintf( + "%v|%v|Expected '&{a:}' (address: '%v') and '&{a:}' (address: '%v') to be the same address (but their weren't)!", + pointer3, pointer1, pointer1, pointer3)) + + t4 := Thing1{} + t5 := t4 + + fail(t, so(t4, ShouldPointTo, t5), "Both arguments should be pointers (the first was not)!") + fail(t, so(&t4, ShouldPointTo, t5), "Both arguments should be pointers (the second was not)!") + fail(t, so(nil, ShouldPointTo, nil), "Both arguments should be pointers (the first was nil)!") + fail(t, so(&t4, ShouldPointTo, nil), "Both arguments should be pointers (the second was nil)!") +} + +func TestShouldNotPointTo(t *testing.T) { + t1 := &Thing1{} + t2 := t1 + t3 := &Thing1{} + + pointer1 := reflect.ValueOf(t1).Pointer() + + fail(t, so(t1, ShouldNotPointTo), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(t1, ShouldNotPointTo, t2, t3), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(t1, ShouldNotPointTo, t3)) + fail(t, so(t1, ShouldNotPointTo, t2), fmt.Sprintf("Expected '&{a:}' and '&{a:}' to be different references (but they matched: '%v')!", pointer1)) + + t4 := Thing1{} + t5 := t4 + + fail(t, so(t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the first was not)!") + fail(t, so(&t4, ShouldNotPointTo, t5), "Both arguments should be pointers (the second was not)!") + fail(t, so(nil, ShouldNotPointTo, nil), "Both arguments should be pointers (the first was nil)!") + fail(t, so(&t4, ShouldNotPointTo, nil), "Both arguments should be pointers (the second was nil)!") +} + +func TestShouldBeNil(t *testing.T) { + fail(t, so(nil, ShouldBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(nil, ShouldBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") + + pass(t, so(nil, ShouldBeNil)) + fail(t, so(1, ShouldBeNil), "Expected: nil Actual: '1'") + + var thing Thinger + pass(t, so(thing, ShouldBeNil)) + thing = &Thing{} + fail(t, so(thing, ShouldBeNil), "Expected: nil Actual: '&{}'") + + var thingOne *Thing1 + pass(t, so(thingOne, ShouldBeNil)) + + var nilSlice []int = nil + pass(t, so(nilSlice, ShouldBeNil)) + + var nilMap map[string]string = nil + pass(t, so(nilMap, ShouldBeNil)) + + var nilChannel chan int = nil + pass(t, so(nilChannel, ShouldBeNil)) + + var nilFunc func() = nil + pass(t, so(nilFunc, ShouldBeNil)) + + var nilInterface interface{} = nil + pass(t, so(nilInterface, ShouldBeNil)) +} + +func TestShouldNotBeNil(t *testing.T) { + fail(t, so(nil, ShouldNotBeNil, nil, nil, nil), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(nil, ShouldNotBeNil, nil), "This assertion requires exactly 0 comparison values (you provided 1).") + + fail(t, so(nil, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") + pass(t, so(1, ShouldNotBeNil)) + + var thing Thinger + fail(t, so(thing, ShouldNotBeNil), "Expected '' to NOT be nil (but it was)!") + thing = &Thing{} + pass(t, so(thing, ShouldNotBeNil)) +} + +func TestShouldBeTrue(t *testing.T) { + fail(t, so(true, ShouldBeTrue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(true, ShouldBeTrue, 1), "This assertion requires exactly 0 comparison values (you provided 1).") + + fail(t, so(false, ShouldBeTrue), "Expected: true Actual: false") + fail(t, so(1, ShouldBeTrue), "Expected: true Actual: 1") + pass(t, so(true, ShouldBeTrue)) +} + +func TestShouldBeFalse(t *testing.T) { + fail(t, so(false, ShouldBeFalse, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(false, ShouldBeFalse, 1), "This assertion requires exactly 0 comparison values (you provided 1).") + + fail(t, so(true, ShouldBeFalse), "Expected: false Actual: true") + fail(t, so(1, ShouldBeFalse), "Expected: false Actual: 1") + pass(t, so(false, ShouldBeFalse)) +} + +func TestShouldBeZeroValue(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so(0, ShouldBeZeroValue, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(false, ShouldBeZeroValue, true), "This assertion requires exactly 0 comparison values (you provided 1).") + + fail(t, so(1, ShouldBeZeroValue), "0|1|'1' should have been the zero value") //"Expected: (zero value) Actual: 1") + fail(t, so(true, ShouldBeZeroValue), "false|true|'true' should have been the zero value") //"Expected: (zero value) Actual: true") + fail(t, so("123", ShouldBeZeroValue), "|123|'123' should have been the zero value") //"Expected: (zero value) Actual: 123") + fail(t, so(" ", ShouldBeZeroValue), "| |' ' should have been the zero value") //"Expected: (zero value) Actual: ") + fail(t, so([]string{"Nonempty"}, ShouldBeZeroValue), "[]|[Nonempty]|'[Nonempty]' should have been the zero value") //"Expected: (zero value) Actual: [Nonempty]") + fail(t, so(struct{ a string }{a: "asdf"}, ShouldBeZeroValue), "{}|{asdf}|'{a:asdf}' should have been the zero value") + pass(t, so(0, ShouldBeZeroValue)) + pass(t, so(false, ShouldBeZeroValue)) + pass(t, so("", ShouldBeZeroValue)) + pass(t, so(struct{}{}, ShouldBeZeroValue)) +} diff --git a/vendor/github.com/smartystreets/assertions/filter.go b/vendor/github.com/smartystreets/assertions/filter.go new file mode 100644 index 0000000000..ee368a97ed --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/filter.go @@ -0,0 +1,23 @@ +package assertions + +import "fmt" + +const ( + success = "" + needExactValues = "This assertion requires exactly %d comparison values (you provided %d)." + needNonEmptyCollection = "This assertion requires at least 1 comparison value (you provided 0)." +) + +func need(needed int, expected []interface{}) string { + if len(expected) != needed { + return fmt.Sprintf(needExactValues, needed, len(expected)) + } + return success +} + +func atLeast(minimum int, expected []interface{}) string { + if len(expected) < 1 { + return needNonEmptyCollection + } + return success +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/LICENSE b/vendor/github.com/smartystreets/assertions/internal/oglematchers/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/README.md b/vendor/github.com/smartystreets/assertions/internal/oglematchers/README.md new file mode 100644 index 0000000000..215a2bb7a8 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/README.md @@ -0,0 +1,58 @@ +[![GoDoc](https://godoc.org/github.com/smartystreets/assertions/internal/oglematchers?status.svg)](https://godoc.org/github.com/smartystreets/assertions/internal/oglematchers) + +`oglematchers` is a package for the Go programming language containing a set of +matchers, useful in a testing or mocking framework, inspired by and mostly +compatible with [Google Test][googletest] for C++ and +[Google JS Test][google-js-test]. The package is used by the +[ogletest][ogletest] testing framework and [oglemock][oglemock] mocking +framework, which may be more directly useful to you, but can be generically used +elsewhere as well. + +A "matcher" is simply an object with a `Matches` method defining a set of golang +values matched by the matcher, and a `Description` method describing that set. +For example, here are some matchers: + +```go +// Numbers +Equals(17.13) +LessThan(19) + +// Strings +Equals("taco") +HasSubstr("burrito") +MatchesRegex("t.*o") + +// Combining matchers +AnyOf(LessThan(17), GreaterThan(19)) +``` + +There are lots more; see [here][reference] for a reference. You can also add +your own simply by implementing the `oglematchers.Matcher` interface. + + +Installation +------------ + +First, make sure you have installed Go 1.0.2 or newer. See +[here][golang-install] for instructions. + +Use the following command to install `oglematchers` and keep it up to date: + + go get -u github.com/smartystreets/assertions/internal/oglematchers + + +Documentation +------------- + +See [here][reference] for documentation. Alternatively, you can install the +package and then use `godoc`: + + godoc github.com/smartystreets/assertions/internal/oglematchers + + +[reference]: http://godoc.org/github.com/smartystreets/assertions/internal/oglematchers +[golang-install]: http://golang.org/doc/install.html +[googletest]: http://code.google.com/p/googletest/ +[google-js-test]: http://code.google.com/p/google-js-test/ +[ogletest]: http://github.com/smartystreets/assertions/internal/ogletest +[oglemock]: http://github.com/smartystreets/assertions/internal/oglemock diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of.go new file mode 100644 index 0000000000..d93a974044 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of.go @@ -0,0 +1,70 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "strings" +) + +// AllOf accepts a set of matchers S and returns a matcher that follows the +// algorithm below when considering a candidate c: +// +// 1. Return true if for every Matcher m in S, m matches c. +// +// 2. Otherwise, if there is a matcher m in S such that m returns a fatal +// error for c, return that matcher's error message. +// +// 3. Otherwise, return false with the error from some wrapped matcher. +// +// This is akin to a logical AND operation for matchers. +func AllOf(matchers ...Matcher) Matcher { + return &allOfMatcher{matchers} +} + +type allOfMatcher struct { + wrappedMatchers []Matcher +} + +func (m *allOfMatcher) Description() string { + // Special case: the empty set. + if len(m.wrappedMatchers) == 0 { + return "is anything" + } + + // Join the descriptions for the wrapped matchers. + wrappedDescs := make([]string, len(m.wrappedMatchers)) + for i, wrappedMatcher := range m.wrappedMatchers { + wrappedDescs[i] = wrappedMatcher.Description() + } + + return strings.Join(wrappedDescs, ", and ") +} + +func (m *allOfMatcher) Matches(c interface{}) (err error) { + for _, wrappedMatcher := range m.wrappedMatchers { + if wrappedErr := wrappedMatcher.Matches(c); wrappedErr != nil { + err = wrappedErr + + // If the error is fatal, return immediately with this error. + _, ok := wrappedErr.(*FatalError) + if ok { + return + } + } + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of_test.go new file mode 100644 index 0000000000..fd6453104e --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/all_of_test.go @@ -0,0 +1,110 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type allOfFakeMatcher struct { + desc string + err error +} + +func (m *allOfFakeMatcher) Matches(c interface{}) error { + return m.err +} + +func (m *allOfFakeMatcher) Description() string { + return m.desc +} + +type AllOfTest struct { +} + +func init() { RegisterTestSuite(&AllOfTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *AllOfTest) DescriptionWithEmptySet() { + m := AllOf() + ExpectEq("is anything", m.Description()) +} + +func (t *AllOfTest) DescriptionWithOneMatcher() { + m := AllOf(&allOfFakeMatcher{"taco", errors.New("")}) + ExpectEq("taco", m.Description()) +} + +func (t *AllOfTest) DescriptionWithMultipleMatchers() { + m := AllOf( + &allOfFakeMatcher{"taco", errors.New("")}, + &allOfFakeMatcher{"burrito", errors.New("")}, + &allOfFakeMatcher{"enchilada", errors.New("")}) + + ExpectEq("taco, and burrito, and enchilada", m.Description()) +} + +func (t *AllOfTest) EmptySet() { + m := AllOf() + err := m.Matches(17) + + ExpectEq(nil, err) +} + +func (t *AllOfTest) OneMatcherReturnsFatalErrorAndSomeOthersFail() { + m := AllOf( + &allOfFakeMatcher{"", errors.New("")}, + &allOfFakeMatcher{"", NewFatalError("taco")}, + &allOfFakeMatcher{"", errors.New("")}, + &allOfFakeMatcher{"", nil}) + + err := m.Matches(17) + + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *AllOfTest) OneMatcherReturnsNonFatalAndOthersSayTrue() { + m := AllOf( + &allOfFakeMatcher{"", nil}, + &allOfFakeMatcher{"", errors.New("taco")}, + &allOfFakeMatcher{"", nil}) + + err := m.Matches(17) + + ExpectFalse(isFatal(err)) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *AllOfTest) AllMatchersSayTrue() { + m := AllOf( + &allOfFakeMatcher{"", nil}, + &allOfFakeMatcher{"", nil}, + &allOfFakeMatcher{"", nil}) + + err := m.Matches(17) + + ExpectEq(nil, err) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/any.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any.go new file mode 100644 index 0000000000..f6991ec102 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any.go @@ -0,0 +1,32 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +// Any returns a matcher that matches any value. +func Any() Matcher { + return &anyMatcher{} +} + +type anyMatcher struct { +} + +func (m *anyMatcher) Description() string { + return "is anything" +} + +func (m *anyMatcher) Matches(c interface{}) error { + return nil +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of.go new file mode 100644 index 0000000000..2918b51f21 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of.go @@ -0,0 +1,94 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" + "strings" +) + +// AnyOf accepts a set of values S and returns a matcher that follows the +// algorithm below when considering a candidate c: +// +// 1. If there exists a value m in S such that m implements the Matcher +// interface and m matches c, return true. +// +// 2. Otherwise, if there exists a value v in S such that v does not implement +// the Matcher interface and the matcher Equals(v) matches c, return true. +// +// 3. Otherwise, if there is a value m in S such that m implements the Matcher +// interface and m returns a fatal error for c, return that fatal error. +// +// 4. Otherwise, return false. +// +// This is akin to a logical OR operation for matchers, with non-matchers x +// being treated as Equals(x). +func AnyOf(vals ...interface{}) Matcher { + // Get ahold of a type variable for the Matcher interface. + var dummy *Matcher + matcherType := reflect.TypeOf(dummy).Elem() + + // Create a matcher for each value, or use the value itself if it's already a + // matcher. + wrapped := make([]Matcher, len(vals)) + for i, v := range vals { + t := reflect.TypeOf(v) + if t != nil && t.Implements(matcherType) { + wrapped[i] = v.(Matcher) + } else { + wrapped[i] = Equals(v) + } + } + + return &anyOfMatcher{wrapped} +} + +type anyOfMatcher struct { + wrapped []Matcher +} + +func (m *anyOfMatcher) Description() string { + wrappedDescs := make([]string, len(m.wrapped)) + for i, matcher := range m.wrapped { + wrappedDescs[i] = matcher.Description() + } + + return fmt.Sprintf("or(%s)", strings.Join(wrappedDescs, ", ")) +} + +func (m *anyOfMatcher) Matches(c interface{}) (err error) { + err = errors.New("") + + // Try each matcher in turn. + for _, matcher := range m.wrapped { + wrappedErr := matcher.Matches(c) + + // Return immediately if there's a match. + if wrappedErr == nil { + err = nil + return + } + + // Note the fatal error, if any. + if _, isFatal := wrappedErr.(*FatalError); isFatal { + err = wrappedErr + } + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of_test.go new file mode 100644 index 0000000000..5a7ed46a67 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_of_test.go @@ -0,0 +1,139 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type fakeAnyOfMatcher struct { + desc string + err error +} + +func (m *fakeAnyOfMatcher) Matches(c interface{}) error { + return m.err +} + +func (m *fakeAnyOfMatcher) Description() string { + return m.desc +} + +type AnyOfTest struct { +} + +func init() { RegisterTestSuite(&AnyOfTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *AnyOfTest) EmptySet() { + matcher := AnyOf() + + err := matcher.Matches(0) + ExpectThat(err, Error(Equals(""))) +} + +func (t *AnyOfTest) OneTrue() { + matcher := AnyOf( + &fakeAnyOfMatcher{"", NewFatalError("foo")}, + 17, + &fakeAnyOfMatcher{"", errors.New("foo")}, + &fakeAnyOfMatcher{"", nil}, + &fakeAnyOfMatcher{"", errors.New("foo")}, + ) + + err := matcher.Matches(0) + ExpectEq(nil, err) +} + +func (t *AnyOfTest) OneEqual() { + matcher := AnyOf( + &fakeAnyOfMatcher{"", NewFatalError("foo")}, + &fakeAnyOfMatcher{"", errors.New("foo")}, + 13, + "taco", + 19, + &fakeAnyOfMatcher{"", errors.New("foo")}, + ) + + err := matcher.Matches("taco") + ExpectEq(nil, err) +} + +func (t *AnyOfTest) OneFatal() { + matcher := AnyOf( + &fakeAnyOfMatcher{"", errors.New("foo")}, + 17, + &fakeAnyOfMatcher{"", NewFatalError("taco")}, + &fakeAnyOfMatcher{"", errors.New("foo")}, + ) + + err := matcher.Matches(0) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *AnyOfTest) OneNil() { + var err error + matcher := AnyOf( + 13, + nil, + 19, + ) + + // No match + err = matcher.Matches(14) + ExpectNe(nil, err) + + // Match + err = matcher.Matches(nil) + ExpectEq(nil, err) +} + +func (t *AnyOfTest) AllFalseAndNotEqual() { + matcher := AnyOf( + &fakeAnyOfMatcher{"", errors.New("foo")}, + 17, + &fakeAnyOfMatcher{"", errors.New("foo")}, + 19, + ) + + err := matcher.Matches(0) + ExpectThat(err, Error(Equals(""))) +} + +func (t *AnyOfTest) DescriptionForEmptySet() { + matcher := AnyOf() + ExpectEq("or()", matcher.Description()) +} + +func (t *AnyOfTest) DescriptionForNonEmptySet() { + matcher := AnyOf( + &fakeAnyOfMatcher{"taco", nil}, + "burrito", + &fakeAnyOfMatcher{"enchilada", nil}, + ) + + ExpectEq("or(taco, burrito, enchilada)", matcher.Description()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_test.go new file mode 100644 index 0000000000..c7d6de3f4e --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/any_test.go @@ -0,0 +1,53 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type AnyTest struct { +} + +func init() { RegisterTestSuite(&AnyTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *AnyTest) Description() { + m := Any() + ExpectEq("is anything", m.Description()) +} + +func (t *AnyTest) Matches() { + var err error + m := Any() + + err = m.Matches(nil) + ExpectEq(nil, err) + + err = m.Matches(17) + ExpectEq(nil, err) + + err = m.Matches("taco") + ExpectEq(nil, err) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains.go new file mode 100644 index 0000000000..2f326dbc5d --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains.go @@ -0,0 +1,61 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "fmt" + "reflect" +) + +// Return a matcher that matches arrays slices with at least one element that +// matches the supplied argument. If the argument x is not itself a Matcher, +// this is equivalent to Contains(Equals(x)). +func Contains(x interface{}) Matcher { + var result containsMatcher + var ok bool + + if result.elementMatcher, ok = x.(Matcher); !ok { + result.elementMatcher = Equals(x) + } + + return &result +} + +type containsMatcher struct { + elementMatcher Matcher +} + +func (m *containsMatcher) Description() string { + return fmt.Sprintf("contains: %s", m.elementMatcher.Description()) +} + +func (m *containsMatcher) Matches(candidate interface{}) error { + // The candidate must be a slice or an array. + v := reflect.ValueOf(candidate) + if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { + return NewFatalError("which is not a slice or array") + } + + // Check each element. + for i := 0; i < v.Len(); i++ { + elem := v.Index(i) + if matchErr := m.elementMatcher.Matches(elem.Interface()); matchErr == nil { + return nil + } + } + + return fmt.Errorf("") +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains_test.go new file mode 100644 index 0000000000..0d41c68cf7 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/contains_test.go @@ -0,0 +1,234 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type ContainsTest struct{} + +func init() { RegisterTestSuite(&ContainsTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *ContainsTest) WrongTypeCandidates() { + m := Contains("") + ExpectEq("contains: ", m.Description()) + + var err error + + // Nil candidate + err = m.Matches(nil) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) + + // String candidate + err = m.Matches("") + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) + + // Map candidate + err = m.Matches(make(map[string]string)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) +} + +func (t *ContainsTest) NilArgument() { + m := Contains(nil) + ExpectEq("contains: is nil", m.Description()) + + var c interface{} + var err error + + // Empty array of pointers + c = [...]*int{} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Empty slice of pointers + c = []*int{} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-empty array of integers + c = [...]int{17, 0, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-empty slice of integers + c = []int{17, 0, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching array of pointers + c = [...]*int{new(int), new(int)} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching slice of pointers + c = []*int{new(int), new(int)} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Matching array of pointers + c = [...]*int{new(int), nil, new(int)} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching slice of pointers + c = []*int{new(int), nil, new(int)} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching slice of pointers from matching array + someArray := [...]*int{new(int), nil, new(int)} + c = someArray[0:1] + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *ContainsTest) StringArgument() { + m := Contains("taco") + ExpectEq("contains: taco", m.Description()) + + var c interface{} + var err error + + // Non-matching array of strings + c = [...]string{"burrito", "enchilada"} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching slice of strings + c = []string{"burrito", "enchilada"} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Matching array of strings + c = [...]string{"burrito", "taco", "enchilada"} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching slice of strings + c = []string{"burrito", "taco", "enchilada"} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching slice of strings from matching array + someArray := [...]string{"burrito", "taco", "enchilada"} + c = someArray[0:1] + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *ContainsTest) IntegerArgument() { + m := Contains(int(17)) + ExpectEq("contains: 17", m.Description()) + + var c interface{} + var err error + + // Non-matching array of integers + c = [...]int{13, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching slice of integers + c = []int{13, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Matching array of integers + c = [...]int{13, 17, 19} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching slice of integers + c = []int{13, 17, 19} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching slice of integers from matching array + someArray := [...]int{13, 17, 19} + c = someArray[0:1] + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching array of floats + c = [...]float32{13, 17.5, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching slice of floats + c = []float32{13, 17.5, 19} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Matching array of floats + c = [...]float32{13, 17, 19} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching slice of floats + c = []float32{13, 17, 19} + err = m.Matches(c) + ExpectEq(nil, err) +} + +func (t *ContainsTest) MatcherArgument() { + m := Contains(HasSubstr("ac")) + ExpectEq("contains: has substring \"ac\"", m.Description()) + + var c interface{} + var err error + + // Non-matching array of strings + c = [...]string{"burrito", "enchilada"} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Non-matching slice of strings + c = []string{"burrito", "enchilada"} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Matching array of strings + c = [...]string{"burrito", "taco", "enchilada"} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching slice of strings + c = []string{"burrito", "taco", "enchilada"} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching slice of strings from matching array + someArray := [...]string{"burrito", "taco", "enchilada"} + c = someArray[0:1] + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals.go new file mode 100644 index 0000000000..1d91baef32 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals.go @@ -0,0 +1,88 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "bytes" + "errors" + "fmt" + "reflect" +) + +var byteSliceType reflect.Type = reflect.TypeOf([]byte{}) + +// DeepEquals returns a matcher that matches based on 'deep equality', as +// defined by the reflect package. This matcher requires that values have +// identical types to x. +func DeepEquals(x interface{}) Matcher { + return &deepEqualsMatcher{x} +} + +type deepEqualsMatcher struct { + x interface{} +} + +func (m *deepEqualsMatcher) Description() string { + xDesc := fmt.Sprintf("%v", m.x) + xValue := reflect.ValueOf(m.x) + + // Special case: fmt.Sprintf presents nil slices as "[]", but + // reflect.DeepEqual makes a distinction between nil and empty slices. Make + // this less confusing. + if xValue.Kind() == reflect.Slice && xValue.IsNil() { + xDesc = "" + } + + return fmt.Sprintf("deep equals: %s", xDesc) +} + +func (m *deepEqualsMatcher) Matches(c interface{}) error { + // Make sure the types match. + ct := reflect.TypeOf(c) + xt := reflect.TypeOf(m.x) + + if ct != xt { + return NewFatalError(fmt.Sprintf("which is of type %v", ct)) + } + + // Special case: handle byte slices more efficiently. + cValue := reflect.ValueOf(c) + xValue := reflect.ValueOf(m.x) + + if ct == byteSliceType && !cValue.IsNil() && !xValue.IsNil() { + xBytes := m.x.([]byte) + cBytes := c.([]byte) + + if bytes.Equal(cBytes, xBytes) { + return nil + } + + return errors.New("") + } + + // Defer to the reflect package. + if reflect.DeepEqual(m.x, c) { + return nil + } + + // Special case: if the comparison failed because c is the nil slice, given + // an indication of this (since its value is printed as "[]"). + if cValue.Kind() == reflect.Slice && cValue.IsNil() { + return errors.New("which is nil") + } + + return errors.New("") +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals_test.go new file mode 100644 index 0000000000..5b5d26487b --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/deep_equals_test.go @@ -0,0 +1,344 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "bytes" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "testing" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type DeepEqualsTest struct{} + +func init() { RegisterTestSuite(&DeepEqualsTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *DeepEqualsTest) WrongTypeCandidateWithScalarValue() { + var x int = 17 + m := DeepEquals(x) + + var err error + + // Nil candidate. + err = m.Matches(nil) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr(""))) + + // Int alias candidate. + type intAlias int + err = m.Matches(intAlias(x)) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("intAlias"))) + + // String candidate. + err = m.Matches("taco") + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("string"))) + + // Byte slice candidate. + err = m.Matches([]byte{}) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint8"))) + + // Other slice candidate. + err = m.Matches([]uint16{}) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint16"))) + + // Unsigned int candidate. + err = m.Matches(uint(17)) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("uint"))) +} + +func (t *DeepEqualsTest) WrongTypeCandidateWithByteSliceValue() { + x := []byte{} + m := DeepEquals(x) + + var err error + + // Nil candidate. + err = m.Matches(nil) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr(""))) + + // String candidate. + err = m.Matches("taco") + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("string"))) + + // Slice candidate with wrong value type. + err = m.Matches([]uint16{}) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint16"))) +} + +func (t *DeepEqualsTest) WrongTypeCandidateWithOtherSliceValue() { + x := []uint16{} + m := DeepEquals(x) + + var err error + + // Nil candidate. + err = m.Matches(nil) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr(""))) + + // String candidate. + err = m.Matches("taco") + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("string"))) + + // Byte slice candidate with wrong value type. + err = m.Matches([]byte{}) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint8"))) + + // Other slice candidate with wrong value type. + err = m.Matches([]uint32{}) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint32"))) +} + +func (t *DeepEqualsTest) WrongTypeCandidateWithNilLiteralValue() { + m := DeepEquals(nil) + + var err error + + // String candidate. + err = m.Matches("taco") + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("string"))) + + // Nil byte slice candidate. + err = m.Matches([]byte(nil)) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint8"))) + + // Nil other slice candidate. + err = m.Matches([]uint16(nil)) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("type"))) + ExpectThat(err, Error(HasSubstr("[]uint16"))) +} + +func (t *DeepEqualsTest) NilLiteralValue() { + m := DeepEquals(nil) + ExpectEq("deep equals: ", m.Description()) + + var c interface{} + var err error + + // Nil literal candidate. + c = nil + err = m.Matches(c) + ExpectEq(nil, err) +} + +func (t *DeepEqualsTest) IntValue() { + m := DeepEquals(int(17)) + ExpectEq("deep equals: 17", m.Description()) + + var c interface{} + var err error + + // Matching int. + c = int(17) + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching int. + c = int(18) + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *DeepEqualsTest) ByteSliceValue() { + x := []byte{17, 19} + m := DeepEquals(x) + ExpectEq("deep equals: [17 19]", m.Description()) + + var c []byte + var err error + + // Matching. + c = make([]byte, len(x)) + AssertEq(len(x), copy(c, x)) + + err = m.Matches(c) + ExpectEq(nil, err) + + // Nil slice. + c = []byte(nil) + err = m.Matches(c) + ExpectThat(err, Error(Equals("which is nil"))) + + // Prefix. + AssertGt(len(x), 1) + c = make([]byte, len(x)-1) + AssertEq(len(x)-1, copy(c, x)) + + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Suffix. + c = make([]byte, len(x)+1) + AssertEq(len(x), copy(c, x)) + + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *DeepEqualsTest) OtherSliceValue() { + x := []uint16{17, 19} + m := DeepEquals(x) + ExpectEq("deep equals: [17 19]", m.Description()) + + var c []uint16 + var err error + + // Matching. + c = make([]uint16, len(x)) + AssertEq(len(x), copy(c, x)) + + err = m.Matches(c) + ExpectEq(nil, err) + + // Nil slice. + c = []uint16(nil) + err = m.Matches(c) + ExpectThat(err, Error(Equals("which is nil"))) + + // Prefix. + AssertGt(len(x), 1) + c = make([]uint16, len(x)-1) + AssertEq(len(x)-1, copy(c, x)) + + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) + + // Suffix. + c = make([]uint16, len(x)+1) + AssertEq(len(x), copy(c, x)) + + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *DeepEqualsTest) NilByteSliceValue() { + x := []byte(nil) + m := DeepEquals(x) + ExpectEq("deep equals: ", m.Description()) + + var c []byte + var err error + + // Nil slice. + c = []byte(nil) + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-nil slice. + c = []byte{} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +func (t *DeepEqualsTest) NilOtherSliceValue() { + x := []uint16(nil) + m := DeepEquals(x) + ExpectEq("deep equals: ", m.Description()) + + var c []uint16 + var err error + + // Nil slice. + c = []uint16(nil) + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-nil slice. + c = []uint16{} + err = m.Matches(c) + ExpectThat(err, Error(Equals(""))) +} + +//////////////////////////////////////////////////////////////////////// +// Benchmarks +//////////////////////////////////////////////////////////////////////// + +func benchmarkWithSize(b *testing.B, size int) { + b.StopTimer() + buf := bytes.Repeat([]byte{0x01}, size) + bufCopy := make([]byte, size) + copy(bufCopy, buf) + + matcher := DeepEquals(buf) + b.StartTimer() + + for i := 0; i < b.N; i++ { + matcher.Matches(bufCopy) + } + + b.SetBytes(int64(size)) +} + +func BenchmarkShortByteSlice(b *testing.B) { + benchmarkWithSize(b, 256) +} + +func BenchmarkLongByteSlice(b *testing.B) { + benchmarkWithSize(b, 1<<24) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are.go new file mode 100644 index 0000000000..2941847c70 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are.go @@ -0,0 +1,91 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" + "strings" +) + +// Given a list of arguments M, ElementsAre returns a matcher that matches +// arrays and slices A where all of the following hold: +// +// * A is the same length as M. +// +// * For each i < len(A) where M[i] is a matcher, A[i] matches M[i]. +// +// * For each i < len(A) where M[i] is not a matcher, A[i] matches +// Equals(M[i]). +// +func ElementsAre(M ...interface{}) Matcher { + // Copy over matchers, or convert to Equals(x) for non-matcher x. + subMatchers := make([]Matcher, len(M)) + for i, x := range M { + if matcher, ok := x.(Matcher); ok { + subMatchers[i] = matcher + continue + } + + subMatchers[i] = Equals(x) + } + + return &elementsAreMatcher{subMatchers} +} + +type elementsAreMatcher struct { + subMatchers []Matcher +} + +func (m *elementsAreMatcher) Description() string { + subDescs := make([]string, len(m.subMatchers)) + for i, sm := range m.subMatchers { + subDescs[i] = sm.Description() + } + + return fmt.Sprintf("elements are: [%s]", strings.Join(subDescs, ", ")) +} + +func (m *elementsAreMatcher) Matches(candidates interface{}) error { + // The candidate must be a slice or an array. + v := reflect.ValueOf(candidates) + if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { + return NewFatalError("which is not a slice or array") + } + + // The length must be correct. + if v.Len() != len(m.subMatchers) { + return errors.New(fmt.Sprintf("which is of length %d", v.Len())) + } + + // Check each element. + for i, subMatcher := range m.subMatchers { + c := v.Index(i) + if matchErr := subMatcher.Matches(c.Interface()); matchErr != nil { + // Return an errors indicating which element doesn't match. If the + // matcher error was fatal, make this one fatal too. + err := errors.New(fmt.Sprintf("whose element %d doesn't match", i)) + if _, isFatal := matchErr.(*FatalError); isFatal { + err = NewFatalError(err.Error()) + } + + return err + } + } + + return nil +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are_test.go new file mode 100644 index 0000000000..5b45a8068b --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/elements_are_test.go @@ -0,0 +1,208 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type ElementsAreTest struct { +} + +func init() { RegisterTestSuite(&ElementsAreTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *ElementsAreTest) EmptySet() { + m := ElementsAre() + ExpectEq("elements are: []", m.Description()) + + var c []interface{} + var err error + + // No candidates. + c = []interface{}{} + err = m.Matches(c) + ExpectEq(nil, err) + + // One candidate. + c = []interface{}{17} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 1"))) +} + +func (t *ElementsAreTest) OneMatcher() { + m := ElementsAre(LessThan(17)) + ExpectEq("elements are: [less than 17]", m.Description()) + + var c []interface{} + var err error + + // No candidates. + c = []interface{}{} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 0"))) + + // Matching candidate. + c = []interface{}{16} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching candidate. + c = []interface{}{19} + err = m.Matches(c) + ExpectNe(nil, err) + + // Two candidates. + c = []interface{}{17, 19} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 2"))) +} + +func (t *ElementsAreTest) OneValue() { + m := ElementsAre(17) + ExpectEq("elements are: [17]", m.Description()) + + var c []interface{} + var err error + + // No candidates. + c = []interface{}{} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 0"))) + + // Matching int. + c = []interface{}{int(17)} + err = m.Matches(c) + ExpectEq(nil, err) + + // Matching float. + c = []interface{}{float32(17)} + err = m.Matches(c) + ExpectEq(nil, err) + + // Non-matching candidate. + c = []interface{}{19} + err = m.Matches(c) + ExpectNe(nil, err) + + // Two candidates. + c = []interface{}{17, 19} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 2"))) +} + +func (t *ElementsAreTest) MultipleElements() { + m := ElementsAre("taco", LessThan(17)) + ExpectEq("elements are: [taco, less than 17]", m.Description()) + + var c []interface{} + var err error + + // One candidate. + c = []interface{}{17} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 1"))) + + // Both matching. + c = []interface{}{"taco", 16} + err = m.Matches(c) + ExpectEq(nil, err) + + // First non-matching. + c = []interface{}{"burrito", 16} + err = m.Matches(c) + ExpectThat(err, Error(Equals("whose element 0 doesn't match"))) + + // Second non-matching. + c = []interface{}{"taco", 17} + err = m.Matches(c) + ExpectThat(err, Error(Equals("whose element 1 doesn't match"))) + + // Three candidates. + c = []interface{}{"taco", 17, 19} + err = m.Matches(c) + ExpectThat(err, Error(HasSubstr("length 3"))) +} + +func (t *ElementsAreTest) ArrayCandidates() { + m := ElementsAre("taco", LessThan(17)) + + var err error + + // One candidate. + err = m.Matches([1]interface{}{"taco"}) + ExpectThat(err, Error(HasSubstr("length 1"))) + + // Both matching. + err = m.Matches([2]interface{}{"taco", 16}) + ExpectEq(nil, err) + + // First non-matching. + err = m.Matches([2]interface{}{"burrito", 16}) + ExpectThat(err, Error(Equals("whose element 0 doesn't match"))) +} + +func (t *ElementsAreTest) WrongTypeCandidate() { + m := ElementsAre("taco") + + var err error + + // String candidate. + err = m.Matches("taco") + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) + + // Map candidate. + err = m.Matches(map[string]string{}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) + + // Nil candidate. + err = m.Matches(nil) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("array"))) + ExpectThat(err, Error(HasSubstr("slice"))) +} + +func (t *ElementsAreTest) PropagatesFatality() { + m := ElementsAre(LessThan(17)) + ExpectEq("elements are: [less than 17]", m.Description()) + + var c []interface{} + var err error + + // Non-fatal error. + c = []interface{}{19} + err = m.Matches(c) + AssertNe(nil, err) + ExpectFalse(isFatal(err)) + + // Fatal error. + c = []interface{}{"taco"} + err = m.Matches(c) + AssertNe(nil, err) + ExpectTrue(isFatal(err)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals.go new file mode 100644 index 0000000000..a510707b3c --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals.go @@ -0,0 +1,541 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +// Equals(x) returns a matcher that matches values v such that v and x are +// equivalent. This includes the case when the comparison v == x using Go's +// built-in comparison operator is legal (except for structs, which this +// matcher does not support), but for convenience the following rules also +// apply: +// +// * Type checking is done based on underlying types rather than actual +// types, so that e.g. two aliases for string can be compared: +// +// type stringAlias1 string +// type stringAlias2 string +// +// a := "taco" +// b := stringAlias1("taco") +// c := stringAlias2("taco") +// +// ExpectTrue(a == b) // Legal, passes +// ExpectTrue(b == c) // Illegal, doesn't compile +// +// ExpectThat(a, Equals(b)) // Passes +// ExpectThat(b, Equals(c)) // Passes +// +// * Values of numeric type are treated as if they were abstract numbers, and +// compared accordingly. Therefore Equals(17) will match int(17), +// int16(17), uint(17), float32(17), complex64(17), and so on. +// +// If you want a stricter matcher that contains no such cleverness, see +// IdenticalTo instead. +// +// Arrays are supported by this matcher, but do not participate in the +// exceptions above. Two arrays compared with this matcher must have identical +// types, and their element type must itself be comparable according to Go's == +// operator. +func Equals(x interface{}) Matcher { + v := reflect.ValueOf(x) + + // This matcher doesn't support structs. + if v.Kind() == reflect.Struct { + panic(fmt.Sprintf("oglematchers.Equals: unsupported kind %v", v.Kind())) + } + + // The == operator is not defined for non-nil slices. + if v.Kind() == reflect.Slice && v.Pointer() != uintptr(0) { + panic(fmt.Sprintf("oglematchers.Equals: non-nil slice")) + } + + return &equalsMatcher{v} +} + +type equalsMatcher struct { + expectedValue reflect.Value +} + +//////////////////////////////////////////////////////////////////////// +// Numeric types +//////////////////////////////////////////////////////////////////////// + +func isSignedInteger(v reflect.Value) bool { + k := v.Kind() + return k >= reflect.Int && k <= reflect.Int64 +} + +func isUnsignedInteger(v reflect.Value) bool { + k := v.Kind() + return k >= reflect.Uint && k <= reflect.Uintptr +} + +func isInteger(v reflect.Value) bool { + return isSignedInteger(v) || isUnsignedInteger(v) +} + +func isFloat(v reflect.Value) bool { + k := v.Kind() + return k == reflect.Float32 || k == reflect.Float64 +} + +func isComplex(v reflect.Value) bool { + k := v.Kind() + return k == reflect.Complex64 || k == reflect.Complex128 +} + +func checkAgainstInt64(e int64, c reflect.Value) (err error) { + err = errors.New("") + + switch { + case isSignedInteger(c): + if c.Int() == e { + err = nil + } + + case isUnsignedInteger(c): + u := c.Uint() + if u <= math.MaxInt64 && int64(u) == e { + err = nil + } + + // Turn around the various floating point types so that the checkAgainst* + // functions for them can deal with precision issues. + case isFloat(c), isComplex(c): + return Equals(c.Interface()).Matches(e) + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +func checkAgainstUint64(e uint64, c reflect.Value) (err error) { + err = errors.New("") + + switch { + case isSignedInteger(c): + i := c.Int() + if i >= 0 && uint64(i) == e { + err = nil + } + + case isUnsignedInteger(c): + if c.Uint() == e { + err = nil + } + + // Turn around the various floating point types so that the checkAgainst* + // functions for them can deal with precision issues. + case isFloat(c), isComplex(c): + return Equals(c.Interface()).Matches(e) + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +func checkAgainstFloat32(e float32, c reflect.Value) (err error) { + err = errors.New("") + + switch { + case isSignedInteger(c): + if float32(c.Int()) == e { + err = nil + } + + case isUnsignedInteger(c): + if float32(c.Uint()) == e { + err = nil + } + + case isFloat(c): + // Compare using float32 to avoid a false sense of precision; otherwise + // e.g. Equals(float32(0.1)) won't match float32(0.1). + if float32(c.Float()) == e { + err = nil + } + + case isComplex(c): + comp := c.Complex() + rl := real(comp) + im := imag(comp) + + // Compare using float32 to avoid a false sense of precision; otherwise + // e.g. Equals(float32(0.1)) won't match (0.1 + 0i). + if im == 0 && float32(rl) == e { + err = nil + } + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +func checkAgainstFloat64(e float64, c reflect.Value) (err error) { + err = errors.New("") + + ck := c.Kind() + + switch { + case isSignedInteger(c): + if float64(c.Int()) == e { + err = nil + } + + case isUnsignedInteger(c): + if float64(c.Uint()) == e { + err = nil + } + + // If the actual value is lower precision, turn the comparison around so we + // apply the low-precision rules. Otherwise, e.g. Equals(0.1) may not match + // float32(0.1). + case ck == reflect.Float32 || ck == reflect.Complex64: + return Equals(c.Interface()).Matches(e) + + // Otherwise, compare with double precision. + case isFloat(c): + if c.Float() == e { + err = nil + } + + case isComplex(c): + comp := c.Complex() + rl := real(comp) + im := imag(comp) + + if im == 0 && rl == e { + err = nil + } + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +func checkAgainstComplex64(e complex64, c reflect.Value) (err error) { + err = errors.New("") + realPart := real(e) + imaginaryPart := imag(e) + + switch { + case isInteger(c) || isFloat(c): + // If we have no imaginary part, then we should just compare against the + // real part. Otherwise, we can't be equal. + if imaginaryPart != 0 { + return + } + + return checkAgainstFloat32(realPart, c) + + case isComplex(c): + // Compare using complex64 to avoid a false sense of precision; otherwise + // e.g. Equals(0.1 + 0i) won't match float32(0.1). + if complex64(c.Complex()) == e { + err = nil + } + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +func checkAgainstComplex128(e complex128, c reflect.Value) (err error) { + err = errors.New("") + realPart := real(e) + imaginaryPart := imag(e) + + switch { + case isInteger(c) || isFloat(c): + // If we have no imaginary part, then we should just compare against the + // real part. Otherwise, we can't be equal. + if imaginaryPart != 0 { + return + } + + return checkAgainstFloat64(realPart, c) + + case isComplex(c): + if c.Complex() == e { + err = nil + } + + default: + err = NewFatalError("which is not numeric") + } + + return +} + +//////////////////////////////////////////////////////////////////////// +// Other types +//////////////////////////////////////////////////////////////////////// + +func checkAgainstBool(e bool, c reflect.Value) (err error) { + if c.Kind() != reflect.Bool { + err = NewFatalError("which is not a bool") + return + } + + err = errors.New("") + if c.Bool() == e { + err = nil + } + return +} + +func checkAgainstChan(e reflect.Value, c reflect.Value) (err error) { + // Create a description of e's type, e.g. "chan int". + typeStr := fmt.Sprintf("%s %s", e.Type().ChanDir(), e.Type().Elem()) + + // Make sure c is a chan of the correct type. + if c.Kind() != reflect.Chan || + c.Type().ChanDir() != e.Type().ChanDir() || + c.Type().Elem() != e.Type().Elem() { + err = NewFatalError(fmt.Sprintf("which is not a %s", typeStr)) + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkAgainstFunc(e reflect.Value, c reflect.Value) (err error) { + // Make sure c is a function. + if c.Kind() != reflect.Func { + err = NewFatalError("which is not a function") + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkAgainstMap(e reflect.Value, c reflect.Value) (err error) { + // Make sure c is a map. + if c.Kind() != reflect.Map { + err = NewFatalError("which is not a map") + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkAgainstPtr(e reflect.Value, c reflect.Value) (err error) { + // Create a description of e's type, e.g. "*int". + typeStr := fmt.Sprintf("*%v", e.Type().Elem()) + + // Make sure c is a pointer of the correct type. + if c.Kind() != reflect.Ptr || + c.Type().Elem() != e.Type().Elem() { + err = NewFatalError(fmt.Sprintf("which is not a %s", typeStr)) + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkAgainstSlice(e reflect.Value, c reflect.Value) (err error) { + // Create a description of e's type, e.g. "[]int". + typeStr := fmt.Sprintf("[]%v", e.Type().Elem()) + + // Make sure c is a slice of the correct type. + if c.Kind() != reflect.Slice || + c.Type().Elem() != e.Type().Elem() { + err = NewFatalError(fmt.Sprintf("which is not a %s", typeStr)) + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkAgainstString(e reflect.Value, c reflect.Value) (err error) { + // Make sure c is a string. + if c.Kind() != reflect.String { + err = NewFatalError("which is not a string") + return + } + + err = errors.New("") + if c.String() == e.String() { + err = nil + } + return +} + +func checkAgainstArray(e reflect.Value, c reflect.Value) (err error) { + // Create a description of e's type, e.g. "[2]int". + typeStr := fmt.Sprintf("%v", e.Type()) + + // Make sure c is the correct type. + if c.Type() != e.Type() { + err = NewFatalError(fmt.Sprintf("which is not %s", typeStr)) + return + } + + // Check for equality. + if e.Interface() != c.Interface() { + err = errors.New("") + return + } + + return +} + +func checkAgainstUnsafePointer(e reflect.Value, c reflect.Value) (err error) { + // Make sure c is a pointer. + if c.Kind() != reflect.UnsafePointer { + err = NewFatalError("which is not a unsafe.Pointer") + return + } + + err = errors.New("") + if c.Pointer() == e.Pointer() { + err = nil + } + return +} + +func checkForNil(c reflect.Value) (err error) { + err = errors.New("") + + // Make sure it is legal to call IsNil. + switch c.Kind() { + case reflect.Invalid: + case reflect.Chan: + case reflect.Func: + case reflect.Interface: + case reflect.Map: + case reflect.Ptr: + case reflect.Slice: + + default: + err = NewFatalError("which cannot be compared to nil") + return + } + + // Ask whether the value is nil. Handle a nil literal (kind Invalid) + // specially, since it's not legal to call IsNil there. + if c.Kind() == reflect.Invalid || c.IsNil() { + err = nil + } + return +} + +//////////////////////////////////////////////////////////////////////// +// Public implementation +//////////////////////////////////////////////////////////////////////// + +func (m *equalsMatcher) Matches(candidate interface{}) error { + e := m.expectedValue + c := reflect.ValueOf(candidate) + ek := e.Kind() + + switch { + case ek == reflect.Bool: + return checkAgainstBool(e.Bool(), c) + + case isSignedInteger(e): + return checkAgainstInt64(e.Int(), c) + + case isUnsignedInteger(e): + return checkAgainstUint64(e.Uint(), c) + + case ek == reflect.Float32: + return checkAgainstFloat32(float32(e.Float()), c) + + case ek == reflect.Float64: + return checkAgainstFloat64(e.Float(), c) + + case ek == reflect.Complex64: + return checkAgainstComplex64(complex64(e.Complex()), c) + + case ek == reflect.Complex128: + return checkAgainstComplex128(complex128(e.Complex()), c) + + case ek == reflect.Chan: + return checkAgainstChan(e, c) + + case ek == reflect.Func: + return checkAgainstFunc(e, c) + + case ek == reflect.Map: + return checkAgainstMap(e, c) + + case ek == reflect.Ptr: + return checkAgainstPtr(e, c) + + case ek == reflect.Slice: + return checkAgainstSlice(e, c) + + case ek == reflect.String: + return checkAgainstString(e, c) + + case ek == reflect.Array: + return checkAgainstArray(e, c) + + case ek == reflect.UnsafePointer: + return checkAgainstUnsafePointer(e, c) + + case ek == reflect.Invalid: + return checkForNil(c) + } + + panic(fmt.Sprintf("equalsMatcher.Matches: unexpected kind: %v", ek)) +} + +func (m *equalsMatcher) Description() string { + // Special case: handle nil. + if !m.expectedValue.IsValid() { + return "is nil" + } + + return fmt.Sprintf("%v", m.expectedValue.Interface()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals_test.go new file mode 100644 index 0000000000..78716a82e3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/equals_test.go @@ -0,0 +1,3864 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "fmt" + "math" + "unsafe" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +var someInt int = -17 + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type EqualsTest struct { +} + +func init() { RegisterTestSuite(&EqualsTest{}) } + +type equalsTestCase struct { + candidate interface{} + expectedResult bool + shouldBeFatal bool + expectedError string +} + +func (t *EqualsTest) checkTestCases(matcher Matcher, cases []equalsTestCase) { + for i, c := range cases { + err := matcher.Matches(c.candidate) + ExpectEq( + c.expectedResult, + (err == nil), + "Result for case %d: %v (Error: %v)", i, c, err) + + if err == nil { + continue + } + + _, isFatal := err.(*FatalError) + ExpectEq(c.shouldBeFatal, isFatal, "Fatality for case %d: %v", i, c) + + ExpectThat(err, Error(Equals(c.expectedError)), "Case %d: %v", i, c) + } +} + +//////////////////////////////////////////////////////////////////////// +// nil +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) EqualsNil() { + matcher := Equals(nil) + ExpectEq("is nil", matcher.Description()) + + cases := []equalsTestCase{ + // Legal types + equalsTestCase{nil, true, false, ""}, + equalsTestCase{chan int(nil), true, false, ""}, + equalsTestCase{(func())(nil), true, false, ""}, + equalsTestCase{interface{}(nil), true, false, ""}, + equalsTestCase{map[int]int(nil), true, false, ""}, + equalsTestCase{(*int)(nil), true, false, ""}, + equalsTestCase{[]int(nil), true, false, ""}, + + equalsTestCase{make(chan int), false, false, ""}, + equalsTestCase{func() {}, false, false, ""}, + equalsTestCase{map[int]int{}, false, false, ""}, + equalsTestCase{&someInt, false, false, ""}, + equalsTestCase{[]int{}, false, false, ""}, + + // Illegal types + equalsTestCase{17, false, true, "which cannot be compared to nil"}, + equalsTestCase{int8(17), false, true, "which cannot be compared to nil"}, + equalsTestCase{uintptr(17), false, true, "which cannot be compared to nil"}, + equalsTestCase{[...]int{}, false, true, "which cannot be compared to nil"}, + equalsTestCase{"taco", false, true, "which cannot be compared to nil"}, + equalsTestCase{equalsTestCase{}, false, true, "which cannot be compared to nil"}, + equalsTestCase{unsafe.Pointer(&someInt), false, true, "which cannot be compared to nil"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegerLiteral() { + // -2^30 + matcher := Equals(-1073741824) + ExpectEq("-1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -1073741824. + equalsTestCase{-1073741824, true, false, ""}, + equalsTestCase{-1073741824.0, true, false, ""}, + equalsTestCase{-1073741824 + 0i, true, false, ""}, + equalsTestCase{int(-1073741824), true, false, ""}, + equalsTestCase{int32(-1073741824), true, false, ""}, + equalsTestCase{int64(-1073741824), true, false, ""}, + equalsTestCase{float32(-1073741824), true, false, ""}, + equalsTestCase{float64(-1073741824), true, false, ""}, + equalsTestCase{complex64(-1073741824), true, false, ""}, + equalsTestCase{complex128(-1073741824), true, false, ""}, + equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, + + // Values that would be -1073741824 in two's complement. + equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 1073741824), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-1073741823), false, false, ""}, + equalsTestCase{int32(-1073741823), false, false, ""}, + equalsTestCase{int64(-1073741823), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float64(-1073741824.1), false, false, ""}, + equalsTestCase{float64(-1073741823.9), false, false, ""}, + equalsTestCase{complex128(-1073741823), false, false, ""}, + equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegerLiteral() { + // 2^30 + matcher := Equals(1073741824) + ExpectEq("1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 1073741824. + equalsTestCase{1073741824, true, false, ""}, + equalsTestCase{1073741824.0, true, false, ""}, + equalsTestCase{1073741824 + 0i, true, false, ""}, + equalsTestCase{int(1073741824), true, false, ""}, + equalsTestCase{uint(1073741824), true, false, ""}, + equalsTestCase{int32(1073741824), true, false, ""}, + equalsTestCase{int64(1073741824), true, false, ""}, + equalsTestCase{uint32(1073741824), true, false, ""}, + equalsTestCase{uint64(1073741824), true, false, ""}, + equalsTestCase{uintptr(1073741824), true, false, ""}, + equalsTestCase{float32(1073741824), true, false, ""}, + equalsTestCase{float64(1073741824), true, false, ""}, + equalsTestCase{complex64(1073741824), true, false, ""}, + equalsTestCase{complex128(1073741824), true, false, ""}, + equalsTestCase{interface{}(int(1073741824)), true, false, ""}, + equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1073741823), false, false, ""}, + equalsTestCase{int32(1073741823), false, false, ""}, + equalsTestCase{int64(1073741823), false, false, ""}, + equalsTestCase{float64(1073741824.1), false, false, ""}, + equalsTestCase{float64(1073741823.9), false, false, ""}, + equalsTestCase{complex128(1073741823), false, false, ""}, + equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Floating point literals +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegralFloatingPointLiteral() { + // -2^30 + matcher := Equals(-1073741824.0) + ExpectEq("-1.073741824e+09", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -1073741824. + equalsTestCase{-1073741824, true, false, ""}, + equalsTestCase{-1073741824.0, true, false, ""}, + equalsTestCase{-1073741824 + 0i, true, false, ""}, + equalsTestCase{int(-1073741824), true, false, ""}, + equalsTestCase{int32(-1073741824), true, false, ""}, + equalsTestCase{int64(-1073741824), true, false, ""}, + equalsTestCase{float32(-1073741824), true, false, ""}, + equalsTestCase{float64(-1073741824), true, false, ""}, + equalsTestCase{complex64(-1073741824), true, false, ""}, + equalsTestCase{complex128(-1073741824), true, false, ""}, + equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, + equalsTestCase{interface{}(float64(-1073741824)), true, false, ""}, + + // Values that would be -1073741824 in two's complement. + equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 1073741824), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-1073741823), false, false, ""}, + equalsTestCase{int32(-1073741823), false, false, ""}, + equalsTestCase{int64(-1073741823), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float64(-1073741824.1), false, false, ""}, + equalsTestCase{float64(-1073741823.9), false, false, ""}, + equalsTestCase{complex128(-1073741823), false, false, ""}, + equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegralFloatingPointLiteral() { + // 2^30 + matcher := Equals(1073741824.0) + ExpectEq("1.073741824e+09", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 1073741824. + equalsTestCase{1073741824, true, false, ""}, + equalsTestCase{1073741824.0, true, false, ""}, + equalsTestCase{1073741824 + 0i, true, false, ""}, + equalsTestCase{int(1073741824), true, false, ""}, + equalsTestCase{int32(1073741824), true, false, ""}, + equalsTestCase{int64(1073741824), true, false, ""}, + equalsTestCase{uint(1073741824), true, false, ""}, + equalsTestCase{uint32(1073741824), true, false, ""}, + equalsTestCase{uint64(1073741824), true, false, ""}, + equalsTestCase{float32(1073741824), true, false, ""}, + equalsTestCase{float64(1073741824), true, false, ""}, + equalsTestCase{complex64(1073741824), true, false, ""}, + equalsTestCase{complex128(1073741824), true, false, ""}, + equalsTestCase{interface{}(int(1073741824)), true, false, ""}, + equalsTestCase{interface{}(float64(1073741824)), true, false, ""}, + + // Values that would be 1073741824 in two's complement. + equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 1073741824), false, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1073741823), false, false, ""}, + equalsTestCase{int32(1073741823), false, false, ""}, + equalsTestCase{int64(1073741823), false, false, ""}, + equalsTestCase{uint(1073741823), false, false, ""}, + equalsTestCase{uint32(1073741823), false, false, ""}, + equalsTestCase{uint64(1073741823), false, false, ""}, + equalsTestCase{float64(1073741824.1), false, false, ""}, + equalsTestCase{float64(1073741823.9), false, false, ""}, + equalsTestCase{complex128(1073741823), false, false, ""}, + equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonIntegralFloatingPointLiteral() { + matcher := Equals(17.1) + ExpectEq("17.1", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 17.1. + equalsTestCase{17.1, true, false, ""}, + equalsTestCase{17.1, true, false, ""}, + equalsTestCase{17.1 + 0i, true, false, ""}, + equalsTestCase{float32(17.1), true, false, ""}, + equalsTestCase{float64(17.1), true, false, ""}, + equalsTestCase{complex64(17.1), true, false, ""}, + equalsTestCase{complex128(17.1), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{17, false, false, ""}, + equalsTestCase{17.2, false, false, ""}, + equalsTestCase{18, false, false, ""}, + equalsTestCase{int(17), false, false, ""}, + equalsTestCase{int(18), false, false, ""}, + equalsTestCase{int32(17), false, false, ""}, + equalsTestCase{int64(17), false, false, ""}, + equalsTestCase{uint(17), false, false, ""}, + equalsTestCase{uint32(17), false, false, ""}, + equalsTestCase{uint64(17), false, false, ""}, + equalsTestCase{uintptr(17), false, false, ""}, + equalsTestCase{complex128(17.1 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// bool +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) False() { + matcher := Equals(false) + ExpectEq("false", matcher.Description()) + + cases := []equalsTestCase{ + // bools + equalsTestCase{false, true, false, ""}, + equalsTestCase{bool(false), true, false, ""}, + + equalsTestCase{true, false, false, ""}, + equalsTestCase{bool(true), false, false, ""}, + + // Other types. + equalsTestCase{int(0), false, true, "which is not a bool"}, + equalsTestCase{int8(0), false, true, "which is not a bool"}, + equalsTestCase{int16(0), false, true, "which is not a bool"}, + equalsTestCase{int32(0), false, true, "which is not a bool"}, + equalsTestCase{int64(0), false, true, "which is not a bool"}, + equalsTestCase{uint(0), false, true, "which is not a bool"}, + equalsTestCase{uint8(0), false, true, "which is not a bool"}, + equalsTestCase{uint16(0), false, true, "which is not a bool"}, + equalsTestCase{uint32(0), false, true, "which is not a bool"}, + equalsTestCase{uint64(0), false, true, "which is not a bool"}, + equalsTestCase{uintptr(0), false, true, "which is not a bool"}, + equalsTestCase{[...]int{}, false, true, "which is not a bool"}, + equalsTestCase{make(chan int), false, true, "which is not a bool"}, + equalsTestCase{func() {}, false, true, "which is not a bool"}, + equalsTestCase{map[int]int{}, false, true, "which is not a bool"}, + equalsTestCase{&someInt, false, true, "which is not a bool"}, + equalsTestCase{[]int{}, false, true, "which is not a bool"}, + equalsTestCase{"taco", false, true, "which is not a bool"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a bool"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) True() { + matcher := Equals(true) + ExpectEq("true", matcher.Description()) + + cases := []equalsTestCase{ + // bools + equalsTestCase{true, true, false, ""}, + equalsTestCase{bool(true), true, false, ""}, + + equalsTestCase{false, false, false, ""}, + equalsTestCase{bool(false), false, false, ""}, + + // Other types. + equalsTestCase{int(1), false, true, "which is not a bool"}, + equalsTestCase{int8(1), false, true, "which is not a bool"}, + equalsTestCase{int16(1), false, true, "which is not a bool"}, + equalsTestCase{int32(1), false, true, "which is not a bool"}, + equalsTestCase{int64(1), false, true, "which is not a bool"}, + equalsTestCase{uint(1), false, true, "which is not a bool"}, + equalsTestCase{uint8(1), false, true, "which is not a bool"}, + equalsTestCase{uint16(1), false, true, "which is not a bool"}, + equalsTestCase{uint32(1), false, true, "which is not a bool"}, + equalsTestCase{uint64(1), false, true, "which is not a bool"}, + equalsTestCase{uintptr(1), false, true, "which is not a bool"}, + equalsTestCase{[...]int{}, false, true, "which is not a bool"}, + equalsTestCase{make(chan int), false, true, "which is not a bool"}, + equalsTestCase{func() {}, false, true, "which is not a bool"}, + equalsTestCase{map[int]int{}, false, true, "which is not a bool"}, + equalsTestCase{&someInt, false, true, "which is not a bool"}, + equalsTestCase{[]int{}, false, true, "which is not a bool"}, + equalsTestCase{"taco", false, true, "which is not a bool"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a bool"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// int +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeInt() { + // -2^30 + matcher := Equals(int(-1073741824)) + ExpectEq("-1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -1073741824. + equalsTestCase{-1073741824, true, false, ""}, + equalsTestCase{-1073741824.0, true, false, ""}, + equalsTestCase{-1073741824 + 0i, true, false, ""}, + equalsTestCase{int(-1073741824), true, false, ""}, + equalsTestCase{int32(-1073741824), true, false, ""}, + equalsTestCase{int64(-1073741824), true, false, ""}, + equalsTestCase{float32(-1073741824), true, false, ""}, + equalsTestCase{float64(-1073741824), true, false, ""}, + equalsTestCase{complex64(-1073741824), true, false, ""}, + equalsTestCase{complex128(-1073741824), true, false, ""}, + equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, + + // Values that would be -1073741824 in two's complement. + equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 1073741824), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-1073741823), false, false, ""}, + equalsTestCase{int32(-1073741823), false, false, ""}, + equalsTestCase{int64(-1073741823), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float64(-1073741824.1), false, false, ""}, + equalsTestCase{float64(-1073741823.9), false, false, ""}, + equalsTestCase{complex128(-1073741823), false, false, ""}, + equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveInt() { + // 2^30 + matcher := Equals(int(1073741824)) + ExpectEq("1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 1073741824. + equalsTestCase{1073741824, true, false, ""}, + equalsTestCase{1073741824.0, true, false, ""}, + equalsTestCase{1073741824 + 0i, true, false, ""}, + equalsTestCase{int(1073741824), true, false, ""}, + equalsTestCase{uint(1073741824), true, false, ""}, + equalsTestCase{int32(1073741824), true, false, ""}, + equalsTestCase{int64(1073741824), true, false, ""}, + equalsTestCase{uint32(1073741824), true, false, ""}, + equalsTestCase{uint64(1073741824), true, false, ""}, + equalsTestCase{uintptr(1073741824), true, false, ""}, + equalsTestCase{float32(1073741824), true, false, ""}, + equalsTestCase{float64(1073741824), true, false, ""}, + equalsTestCase{complex64(1073741824), true, false, ""}, + equalsTestCase{complex128(1073741824), true, false, ""}, + equalsTestCase{interface{}(int(1073741824)), true, false, ""}, + equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1073741823), false, false, ""}, + equalsTestCase{int32(1073741823), false, false, ""}, + equalsTestCase{int64(1073741823), false, false, ""}, + equalsTestCase{float64(1073741824.1), false, false, ""}, + equalsTestCase{float64(1073741823.9), false, false, ""}, + equalsTestCase{complex128(1073741823), false, false, ""}, + equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// int8 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeInt8() { + matcher := Equals(int8(-17)) + ExpectEq("-17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -17. + equalsTestCase{-17, true, false, ""}, + equalsTestCase{-17.0, true, false, ""}, + equalsTestCase{-17 + 0i, true, false, ""}, + equalsTestCase{int(-17), true, false, ""}, + equalsTestCase{int8(-17), true, false, ""}, + equalsTestCase{int16(-17), true, false, ""}, + equalsTestCase{int32(-17), true, false, ""}, + equalsTestCase{int64(-17), true, false, ""}, + equalsTestCase{float32(-17), true, false, ""}, + equalsTestCase{float64(-17), true, false, ""}, + equalsTestCase{complex64(-17), true, false, ""}, + equalsTestCase{complex128(-17), true, false, ""}, + equalsTestCase{interface{}(int(-17)), true, false, ""}, + + // Values that would be -17 in two's complement. + equalsTestCase{uint((1 << 32) - 17), false, false, ""}, + equalsTestCase{uint8((1 << 8) - 17), false, false, ""}, + equalsTestCase{uint16((1 << 16) - 17), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 17), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 17), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 17), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-16), false, false, ""}, + equalsTestCase{int8(-16), false, false, ""}, + equalsTestCase{int16(-16), false, false, ""}, + equalsTestCase{int32(-16), false, false, ""}, + equalsTestCase{int64(-16), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float32(-17.1), false, false, ""}, + equalsTestCase{float32(-16.9), false, false, ""}, + equalsTestCase{complex64(-16), false, false, ""}, + equalsTestCase{complex64(-17 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{-17}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{-17}, false, true, "which is not numeric"}, + equalsTestCase{"-17", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroInt8() { + matcher := Equals(int8(0)) + ExpectEq("0", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 0. + equalsTestCase{0, true, false, ""}, + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(int(0)), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1), false, false, ""}, + equalsTestCase{int8(1), false, false, ""}, + equalsTestCase{int16(1), false, false, ""}, + equalsTestCase{int32(1), false, false, ""}, + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{float32(-0.1), false, false, ""}, + equalsTestCase{float32(0.1), false, false, ""}, + equalsTestCase{complex64(1), false, false, ""}, + equalsTestCase{complex64(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{0}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{0}, false, true, "which is not numeric"}, + equalsTestCase{"0", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveInt8() { + matcher := Equals(int8(17)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 17. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(17), true, false, ""}, + equalsTestCase{int8(17), true, false, ""}, + equalsTestCase{int16(17), true, false, ""}, + equalsTestCase{int32(17), true, false, ""}, + equalsTestCase{int64(17), true, false, ""}, + equalsTestCase{float32(17), true, false, ""}, + equalsTestCase{float64(17), true, false, ""}, + equalsTestCase{complex64(17), true, false, ""}, + equalsTestCase{complex128(17), true, false, ""}, + equalsTestCase{interface{}(int(17)), true, false, ""}, + equalsTestCase{uint(17), true, false, ""}, + equalsTestCase{uint8(17), true, false, ""}, + equalsTestCase{uint16(17), true, false, ""}, + equalsTestCase{uint32(17), true, false, ""}, + equalsTestCase{uint64(17), true, false, ""}, + equalsTestCase{uintptr(17), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(16), false, false, ""}, + equalsTestCase{int8(16), false, false, ""}, + equalsTestCase{int16(16), false, false, ""}, + equalsTestCase{int32(16), false, false, ""}, + equalsTestCase{int64(16), false, false, ""}, + equalsTestCase{float32(16.9), false, false, ""}, + equalsTestCase{float32(17.1), false, false, ""}, + equalsTestCase{complex64(16), false, false, ""}, + equalsTestCase{complex64(17 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{17}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{17}, false, true, "which is not numeric"}, + equalsTestCase{"17", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// int16 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeInt16() { + matcher := Equals(int16(-32766)) + ExpectEq("-32766", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -32766. + equalsTestCase{-32766, true, false, ""}, + equalsTestCase{-32766.0, true, false, ""}, + equalsTestCase{-32766 + 0i, true, false, ""}, + equalsTestCase{int(-32766), true, false, ""}, + equalsTestCase{int16(-32766), true, false, ""}, + equalsTestCase{int32(-32766), true, false, ""}, + equalsTestCase{int64(-32766), true, false, ""}, + equalsTestCase{float32(-32766), true, false, ""}, + equalsTestCase{float64(-32766), true, false, ""}, + equalsTestCase{complex64(-32766), true, false, ""}, + equalsTestCase{complex128(-32766), true, false, ""}, + equalsTestCase{interface{}(int(-32766)), true, false, ""}, + + // Values that would be -32766 in two's complement. + equalsTestCase{uint((1 << 32) - 32766), false, false, ""}, + equalsTestCase{uint16((1 << 16) - 32766), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 32766), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 32766), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 32766), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-16), false, false, ""}, + equalsTestCase{int8(-16), false, false, ""}, + equalsTestCase{int16(-16), false, false, ""}, + equalsTestCase{int32(-16), false, false, ""}, + equalsTestCase{int64(-16), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float32(-32766.1), false, false, ""}, + equalsTestCase{float32(-32765.9), false, false, ""}, + equalsTestCase{complex64(-32766.1), false, false, ""}, + equalsTestCase{complex64(-32766 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{-32766}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{-32766}, false, true, "which is not numeric"}, + equalsTestCase{"-32766", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroInt16() { + matcher := Equals(int16(0)) + ExpectEq("0", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 0. + equalsTestCase{0, true, false, ""}, + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(int(0)), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1), false, false, ""}, + equalsTestCase{int8(1), false, false, ""}, + equalsTestCase{int16(1), false, false, ""}, + equalsTestCase{int32(1), false, false, ""}, + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{float32(-0.1), false, false, ""}, + equalsTestCase{float32(0.1), false, false, ""}, + equalsTestCase{complex64(1), false, false, ""}, + equalsTestCase{complex64(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{0}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{0}, false, true, "which is not numeric"}, + equalsTestCase{"0", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveInt16() { + matcher := Equals(int16(32765)) + ExpectEq("32765", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32765. + equalsTestCase{32765, true, false, ""}, + equalsTestCase{32765.0, true, false, ""}, + equalsTestCase{32765 + 0i, true, false, ""}, + equalsTestCase{int(32765), true, false, ""}, + equalsTestCase{int16(32765), true, false, ""}, + equalsTestCase{int32(32765), true, false, ""}, + equalsTestCase{int64(32765), true, false, ""}, + equalsTestCase{float32(32765), true, false, ""}, + equalsTestCase{float64(32765), true, false, ""}, + equalsTestCase{complex64(32765), true, false, ""}, + equalsTestCase{complex128(32765), true, false, ""}, + equalsTestCase{interface{}(int(32765)), true, false, ""}, + equalsTestCase{uint(32765), true, false, ""}, + equalsTestCase{uint16(32765), true, false, ""}, + equalsTestCase{uint32(32765), true, false, ""}, + equalsTestCase{uint64(32765), true, false, ""}, + equalsTestCase{uintptr(32765), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(32764), false, false, ""}, + equalsTestCase{int16(32764), false, false, ""}, + equalsTestCase{int32(32764), false, false, ""}, + equalsTestCase{int64(32764), false, false, ""}, + equalsTestCase{float32(32764.9), false, false, ""}, + equalsTestCase{float32(32765.1), false, false, ""}, + equalsTestCase{complex64(32765.9), false, false, ""}, + equalsTestCase{complex64(32765 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{32765}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{32765}, false, true, "which is not numeric"}, + equalsTestCase{"32765", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// int32 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeInt32() { + // -2^30 + matcher := Equals(int32(-1073741824)) + ExpectEq("-1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -1073741824. + equalsTestCase{-1073741824, true, false, ""}, + equalsTestCase{-1073741824.0, true, false, ""}, + equalsTestCase{-1073741824 + 0i, true, false, ""}, + equalsTestCase{int(-1073741824), true, false, ""}, + equalsTestCase{int32(-1073741824), true, false, ""}, + equalsTestCase{int64(-1073741824), true, false, ""}, + equalsTestCase{float32(-1073741824), true, false, ""}, + equalsTestCase{float64(-1073741824), true, false, ""}, + equalsTestCase{complex64(-1073741824), true, false, ""}, + equalsTestCase{complex128(-1073741824), true, false, ""}, + equalsTestCase{interface{}(int(-1073741824)), true, false, ""}, + + // Values that would be -1073741824 in two's complement. + equalsTestCase{uint((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint32((1 << 32) - 1073741824), false, false, ""}, + equalsTestCase{uint64((1 << 64) - 1073741824), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 1073741824), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int(-1073741823), false, false, ""}, + equalsTestCase{int32(-1073741823), false, false, ""}, + equalsTestCase{int64(-1073741823), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float64(-1073741824.1), false, false, ""}, + equalsTestCase{float64(-1073741823.9), false, false, ""}, + equalsTestCase{complex128(-1073741823), false, false, ""}, + equalsTestCase{complex128(-1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveInt32() { + // 2^30 + matcher := Equals(int32(1073741824)) + ExpectEq("1073741824", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 1073741824. + equalsTestCase{1073741824, true, false, ""}, + equalsTestCase{1073741824.0, true, false, ""}, + equalsTestCase{1073741824 + 0i, true, false, ""}, + equalsTestCase{int(1073741824), true, false, ""}, + equalsTestCase{uint(1073741824), true, false, ""}, + equalsTestCase{int32(1073741824), true, false, ""}, + equalsTestCase{int64(1073741824), true, false, ""}, + equalsTestCase{uint32(1073741824), true, false, ""}, + equalsTestCase{uint64(1073741824), true, false, ""}, + equalsTestCase{uintptr(1073741824), true, false, ""}, + equalsTestCase{float32(1073741824), true, false, ""}, + equalsTestCase{float64(1073741824), true, false, ""}, + equalsTestCase{complex64(1073741824), true, false, ""}, + equalsTestCase{complex128(1073741824), true, false, ""}, + equalsTestCase{interface{}(int(1073741824)), true, false, ""}, + equalsTestCase{interface{}(uint(1073741824)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(1073741823), false, false, ""}, + equalsTestCase{int32(1073741823), false, false, ""}, + equalsTestCase{int64(1073741823), false, false, ""}, + equalsTestCase{float64(1073741824.1), false, false, ""}, + equalsTestCase{float64(1073741823.9), false, false, ""}, + equalsTestCase{complex128(1073741823), false, false, ""}, + equalsTestCase{complex128(1073741824 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// int64 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeInt64() { + // -2^40 + matcher := Equals(int64(-1099511627776)) + ExpectEq("-1099511627776", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -1099511627776. + equalsTestCase{-1099511627776.0, true, false, ""}, + equalsTestCase{-1099511627776 + 0i, true, false, ""}, + equalsTestCase{int64(-1099511627776), true, false, ""}, + equalsTestCase{float32(-1099511627776), true, false, ""}, + equalsTestCase{float64(-1099511627776), true, false, ""}, + equalsTestCase{complex64(-1099511627776), true, false, ""}, + equalsTestCase{complex128(-1099511627776), true, false, ""}, + equalsTestCase{interface{}(int64(-1099511627776)), true, false, ""}, + + // Values that would be -1099511627776 in two's complement. + equalsTestCase{uint64((1 << 64) - 1099511627776), false, false, ""}, + + // Non-equal values of signed integer type. + equalsTestCase{int64(-1099511627775), false, false, ""}, + + // Non-equal values of other numeric types. + equalsTestCase{float64(-1099511627776.1), false, false, ""}, + equalsTestCase{float64(-1099511627775.9), false, false, ""}, + equalsTestCase{complex128(-1099511627775), false, false, ""}, + equalsTestCase{complex128(-1099511627776 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveInt64() { + // 2^40 + matcher := Equals(int64(1099511627776)) + ExpectEq("1099511627776", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 1099511627776. + equalsTestCase{1099511627776.0, true, false, ""}, + equalsTestCase{1099511627776 + 0i, true, false, ""}, + equalsTestCase{int64(1099511627776), true, false, ""}, + equalsTestCase{uint64(1099511627776), true, false, ""}, + equalsTestCase{uintptr(1099511627776), true, false, ""}, + equalsTestCase{float32(1099511627776), true, false, ""}, + equalsTestCase{float64(1099511627776), true, false, ""}, + equalsTestCase{complex64(1099511627776), true, false, ""}, + equalsTestCase{complex128(1099511627776), true, false, ""}, + equalsTestCase{interface{}(int64(1099511627776)), true, false, ""}, + equalsTestCase{interface{}(uint64(1099511627776)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(1099511627775), false, false, ""}, + equalsTestCase{uint64(1099511627775), false, false, ""}, + equalsTestCase{float64(1099511627776.1), false, false, ""}, + equalsTestCase{float64(1099511627775.9), false, false, ""}, + equalsTestCase{complex128(1099511627775), false, false, ""}, + equalsTestCase{complex128(1099511627776 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Int64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(int64(kTwoTo25 + 1)) + ExpectEq("33554433", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Int64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := Equals(int64(kTwoTo54 + 1)) + ExpectEq("18014398509481985", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo54 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uint +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUint() { + const kExpected = 17 + matcher := Equals(uint(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeUint() { + const kExpected = (1 << 16) + 17 + matcher := Equals(uint(kExpected)) + ExpectEq("65553", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{65553, true, false, ""}, + equalsTestCase{65553.0, true, false, ""}, + equalsTestCase{65553 + 0i, true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{int16(17), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(17), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) UintNotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(uint(kTwoTo25 + 1)) + ExpectEq("33554433", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uint8 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUint8() { + const kExpected = 17 + matcher := Equals(uint8(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uint16 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUint16() { + const kExpected = 17 + matcher := Equals(uint16(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeUint16() { + const kExpected = (1 << 8) + 17 + matcher := Equals(uint16(kExpected)) + ExpectEq("273", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{273, true, false, ""}, + equalsTestCase{273.0, true, false, ""}, + equalsTestCase{273 + 0i, true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{int8(17), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(17), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uint32 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUint32() { + const kExpected = 17 + matcher := Equals(uint32(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeUint32() { + const kExpected = (1 << 16) + 17 + matcher := Equals(uint32(kExpected)) + ExpectEq("65553", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{65553, true, false, ""}, + equalsTestCase{65553.0, true, false, ""}, + equalsTestCase{65553 + 0i, true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{int16(17), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(17), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Uint32NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(uint32(kTwoTo25 + 1)) + ExpectEq("33554433", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uint64 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUint64() { + const kExpected = 17 + matcher := Equals(uint64(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeUint64() { + const kExpected = (1 << 32) + 17 + matcher := Equals(uint64(kExpected)) + ExpectEq("4294967313", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{4294967313.0, true, false, ""}, + equalsTestCase{4294967313 + 0i, true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{int(17), false, false, ""}, + equalsTestCase{int32(17), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(17), false, false, ""}, + equalsTestCase{uint32(17), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Uint64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(uint64(kTwoTo25 + 1)) + ExpectEq("33554433", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 + 0), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Uint64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := Equals(uint64(kTwoTo54 + 1)) + ExpectEq("18014398509481985", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo54 + 0), false, false, ""}, + equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + equalsTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// uintptr +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) SmallUintptr() { + const kExpected = 17 + matcher := Equals(uintptr(kExpected)) + ExpectEq("17", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{17, true, false, ""}, + equalsTestCase{17.0, true, false, ""}, + equalsTestCase{17 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int8(kExpected), true, false, ""}, + equalsTestCase{int16(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint8(kExpected), true, false, ""}, + equalsTestCase{uint16(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{kExpected + 1, false, false, ""}, + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int8(kExpected + 1), false, false, ""}, + equalsTestCase{int16(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint8(kExpected + 1), false, false, ""}, + equalsTestCase{uint16(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeUintptr() { + const kExpected = (1 << 32) + 17 + matcher := Equals(uintptr(kExpected)) + ExpectEq("4294967313", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{4294967313.0, true, false, ""}, + equalsTestCase{4294967313 + 0i, true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric types. + equalsTestCase{int(17), false, false, ""}, + equalsTestCase{int32(17), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(17), false, false, ""}, + equalsTestCase{uint32(17), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected + 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 1), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// float32 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegralFloat32() { + matcher := Equals(float32(-32769)) + ExpectEq("-32769", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -32769. + equalsTestCase{-32769.0, true, false, ""}, + equalsTestCase{-32769 + 0i, true, false, ""}, + equalsTestCase{int32(-32769), true, false, ""}, + equalsTestCase{int64(-32769), true, false, ""}, + equalsTestCase{float32(-32769), true, false, ""}, + equalsTestCase{float64(-32769), true, false, ""}, + equalsTestCase{complex64(-32769), true, false, ""}, + equalsTestCase{complex128(-32769), true, false, ""}, + equalsTestCase{interface{}(float32(-32769)), true, false, ""}, + equalsTestCase{interface{}(int64(-32769)), true, false, ""}, + + // Values that would be -32769 in two's complement. + equalsTestCase{uint64((1 << 64) - 32769), false, false, ""}, + equalsTestCase{uintptr((1 << 64) - 32769), false, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(-32770), false, false, ""}, + equalsTestCase{float32(-32769.1), false, false, ""}, + equalsTestCase{float32(-32768.9), false, false, ""}, + equalsTestCase{float64(-32769.1), false, false, ""}, + equalsTestCase{float64(-32768.9), false, false, ""}, + equalsTestCase{complex128(-32768), false, false, ""}, + equalsTestCase{complex128(-32769 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NegativeNonIntegralFloat32() { + matcher := Equals(float32(-32769.1)) + ExpectEq("-32769.1", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of -32769.1. + equalsTestCase{-32769.1, true, false, ""}, + equalsTestCase{-32769.1 + 0i, true, false, ""}, + equalsTestCase{float32(-32769.1), true, false, ""}, + equalsTestCase{float64(-32769.1), true, false, ""}, + equalsTestCase{complex64(-32769.1), true, false, ""}, + equalsTestCase{complex128(-32769.1), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int32(-32769), false, false, ""}, + equalsTestCase{int32(-32770), false, false, ""}, + equalsTestCase{int64(-32769), false, false, ""}, + equalsTestCase{int64(-32770), false, false, ""}, + equalsTestCase{float32(-32769.2), false, false, ""}, + equalsTestCase{float32(-32769.0), false, false, ""}, + equalsTestCase{float64(-32769.2), false, false, ""}, + equalsTestCase{complex128(-32769.1 + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeNegativeFloat32() { + const kExpected = -1 * (1 << 65) + matcher := Equals(float32(kExpected)) + ExpectEq("-3.689349e+19", matcher.Description()) + + floatExpected := float32(kExpected) + castedInt := int64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroFloat32() { + matcher := Equals(float32(0)) + ExpectEq("0", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of zero. + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(float32(0)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{int64(-1), false, false, ""}, + equalsTestCase{float32(1), false, false, ""}, + equalsTestCase{float32(-1), false, false, ""}, + equalsTestCase{complex128(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegralFloat32() { + matcher := Equals(float32(32769)) + ExpectEq("32769", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32769. + equalsTestCase{32769.0, true, false, ""}, + equalsTestCase{32769 + 0i, true, false, ""}, + equalsTestCase{int(32769), true, false, ""}, + equalsTestCase{int32(32769), true, false, ""}, + equalsTestCase{int64(32769), true, false, ""}, + equalsTestCase{uint(32769), true, false, ""}, + equalsTestCase{uint32(32769), true, false, ""}, + equalsTestCase{uint64(32769), true, false, ""}, + equalsTestCase{uintptr(32769), true, false, ""}, + equalsTestCase{float32(32769), true, false, ""}, + equalsTestCase{float64(32769), true, false, ""}, + equalsTestCase{complex64(32769), true, false, ""}, + equalsTestCase{complex128(32769), true, false, ""}, + equalsTestCase{interface{}(float32(32769)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(32770), false, false, ""}, + equalsTestCase{uint64(32770), false, false, ""}, + equalsTestCase{float32(32769.1), false, false, ""}, + equalsTestCase{float32(32768.9), false, false, ""}, + equalsTestCase{float64(32769.1), false, false, ""}, + equalsTestCase{float64(32768.9), false, false, ""}, + equalsTestCase{complex128(32768), false, false, ""}, + equalsTestCase{complex128(32769 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveNonIntegralFloat32() { + matcher := Equals(float32(32769.1)) + ExpectEq("32769.1", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32769.1. + equalsTestCase{32769.1, true, false, ""}, + equalsTestCase{32769.1 + 0i, true, false, ""}, + equalsTestCase{float32(32769.1), true, false, ""}, + equalsTestCase{float64(32769.1), true, false, ""}, + equalsTestCase{complex64(32769.1), true, false, ""}, + equalsTestCase{complex128(32769.1), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int32(32769), false, false, ""}, + equalsTestCase{int32(32770), false, false, ""}, + equalsTestCase{uint64(32769), false, false, ""}, + equalsTestCase{uint64(32770), false, false, ""}, + equalsTestCase{float32(32769.2), false, false, ""}, + equalsTestCase{float32(32769.0), false, false, ""}, + equalsTestCase{float64(32769.2), false, false, ""}, + equalsTestCase{complex128(32769.1 + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargePositiveFloat32() { + const kExpected = 1 << 65 + matcher := Equals(float32(kExpected)) + ExpectEq("3.689349e+19", matcher.Description()) + + floatExpected := float32(kExpected) + castedInt := uint64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{uint64(0), false, false, ""}, + equalsTestCase{uint64(math.MaxUint64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Float32AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(float32(kTwoTo25 + 1)) + ExpectEq("3.3554432e+07", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{int64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 3), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// float64 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegralFloat64() { + const kExpected = -(1 << 50) + matcher := Equals(float64(kExpected)) + ExpectEq("-1.125899906842624e+15", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{-1125899906842624.0, true, false, ""}, + equalsTestCase{-1125899906842624.0 + 0i, true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Values that would be kExpected in two's complement. + equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NegativeNonIntegralFloat64() { + const kTwoTo50 = 1 << 50 + const kExpected = -kTwoTo50 - 0.25 + + matcher := Equals(float64(kExpected)) + ExpectEq("-1.1258999068426242e+15", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(-kTwoTo50), false, false, ""}, + equalsTestCase{int64(-kTwoTo50 - 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeNegativeFloat64() { + const kExpected = -1 * (1 << 65) + matcher := Equals(float64(kExpected)) + ExpectEq("-3.6893488147419103e+19", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := int64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroFloat64() { + matcher := Equals(float64(0)) + ExpectEq("0", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of zero. + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(float32(0)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{int64(-1), false, false, ""}, + equalsTestCase{float32(1), false, false, ""}, + equalsTestCase{float32(-1), false, false, ""}, + equalsTestCase{complex128(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegralFloat64() { + const kExpected = 1 << 50 + matcher := Equals(float64(kExpected)) + ExpectEq("1.125899906842624e+15", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32769. + equalsTestCase{1125899906842624.0, true, false, ""}, + equalsTestCase{1125899906842624.0 + 0i, true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveNonIntegralFloat64() { + const kTwoTo50 = 1 << 50 + const kExpected = kTwoTo50 + 0.25 + matcher := Equals(float64(kExpected)) + ExpectEq("1.1258999068426242e+15", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kTwoTo50), false, false, ""}, + equalsTestCase{int64(kTwoTo50 - 1), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargePositiveFloat64() { + const kExpected = 1 << 65 + matcher := Equals(float64(kExpected)) + ExpectEq("3.6893488147419103e+19", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := uint64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{uint64(0), false, false, ""}, + equalsTestCase{uint64(math.MaxUint64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Float64AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := Equals(float64(kTwoTo54 + 1)) + ExpectEq("1.8014398509481984e+16", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{int64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{uint64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// complex64 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegralComplex64() { + const kExpected = -32769 + matcher := Equals(complex64(kExpected)) + ExpectEq("(-32769+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{-32769.0, true, false, ""}, + equalsTestCase{-32769.0 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Values that would be kExpected in two's complement. + equalsTestCase{uint32((1 << 32) + kExpected), false, false, ""}, + equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, + equalsTestCase{uintptr((1 << 64) + kExpected), false, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex64(kExpected - 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NegativeNonIntegralComplex64() { + const kTwoTo20 = 1 << 20 + const kExpected = -kTwoTo20 - 0.25 + + matcher := Equals(complex64(kExpected)) + ExpectEq("(-1.0485762e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(-kTwoTo20), false, false, ""}, + equalsTestCase{int(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{int32(-kTwoTo20), false, false, ""}, + equalsTestCase{int32(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{int64(-kTwoTo20), false, false, ""}, + equalsTestCase{int64(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex64(kExpected - 0.75), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected - 0.75), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeNegativeComplex64() { + const kExpected = -1 * (1 << 65) + matcher := Equals(complex64(kExpected)) + ExpectEq("(-3.689349e+19+0i)", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := int64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroComplex64() { + matcher := Equals(complex64(0)) + ExpectEq("(0+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of zero. + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(float32(0)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{int64(-1), false, false, ""}, + equalsTestCase{float32(1), false, false, ""}, + equalsTestCase{float32(-1), false, false, ""}, + equalsTestCase{float64(1), false, false, ""}, + equalsTestCase{float64(-1), false, false, ""}, + equalsTestCase{complex64(0 + 2i), false, false, ""}, + equalsTestCase{complex128(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegralComplex64() { + const kExpected = 1 << 20 + matcher := Equals(complex64(kExpected)) + ExpectEq("(1.048576e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32769. + equalsTestCase{1048576.0, true, false, ""}, + equalsTestCase{1048576.0 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveNonIntegralComplex64() { + const kTwoTo20 = 1 << 20 + const kExpected = kTwoTo20 + 0.25 + matcher := Equals(complex64(kExpected)) + ExpectEq("(1.0485762e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kTwoTo20), false, false, ""}, + equalsTestCase{int64(kTwoTo20 - 1), false, false, ""}, + equalsTestCase{uint64(kTwoTo20), false, false, ""}, + equalsTestCase{uint64(kTwoTo20 - 1), false, false, ""}, + equalsTestCase{float32(kExpected - 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex64(kExpected - 1), false, false, ""}, + equalsTestCase{complex64(kExpected - 1i), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected - 1i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargePositiveComplex64() { + const kExpected = 1 << 65 + matcher := Equals(complex64(kExpected)) + ExpectEq("(3.689349e+19+0i)", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := uint64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{uint64(0), false, false, ""}, + equalsTestCase{uint64(math.MaxUint64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Complex64AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := Equals(complex64(kTwoTo25 + 1)) + ExpectEq("(3.3554432e+07+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{int64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{int64(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{uint64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{uint64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{uint64(kTwoTo25 + 3), false, false, ""}, + + // Single-precision floating point. + equalsTestCase{float32(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float32(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex64(kTwoTo25 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo25 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo25 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo25 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Complex64WithNonZeroImaginaryPart() { + const kRealPart = 17 + const kImagPart = 0.25i + const kExpected = kRealPart + kImagPart + matcher := Equals(complex64(kExpected)) + ExpectEq("(17+0.25i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kRealPart + kImagPart, true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(kRealPart), false, false, ""}, + equalsTestCase{int8(kRealPart), false, false, ""}, + equalsTestCase{int16(kRealPart), false, false, ""}, + equalsTestCase{int32(kRealPart), false, false, ""}, + equalsTestCase{int64(kRealPart), false, false, ""}, + equalsTestCase{uint(kRealPart), false, false, ""}, + equalsTestCase{uint8(kRealPart), false, false, ""}, + equalsTestCase{uint16(kRealPart), false, false, ""}, + equalsTestCase{uint32(kRealPart), false, false, ""}, + equalsTestCase{uint64(kRealPart), false, false, ""}, + equalsTestCase{float32(kRealPart), false, false, ""}, + equalsTestCase{float64(kRealPart), false, false, ""}, + equalsTestCase{complex64(kRealPart), false, false, ""}, + equalsTestCase{complex64(kRealPart + kImagPart + 0.5), false, false, ""}, + equalsTestCase{complex64(kRealPart + kImagPart + 0.5i), false, false, ""}, + equalsTestCase{complex128(kRealPart), false, false, ""}, + equalsTestCase{complex128(kRealPart + kImagPart + 0.5), false, false, ""}, + equalsTestCase{complex128(kRealPart + kImagPart + 0.5i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// complex128 +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NegativeIntegralComplex128() { + const kExpected = -32769 + matcher := Equals(complex128(kExpected)) + ExpectEq("(-32769+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{-32769.0, true, false, ""}, + equalsTestCase{-32769.0 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Values that would be kExpected in two's complement. + equalsTestCase{uint32((1 << 32) + kExpected), false, false, ""}, + equalsTestCase{uint64((1 << 64) + kExpected), false, false, ""}, + equalsTestCase{uintptr((1 << 64) + kExpected), false, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex64(kExpected - 1), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NegativeNonIntegralComplex128() { + const kTwoTo20 = 1 << 20 + const kExpected = -kTwoTo20 - 0.25 + + matcher := Equals(complex128(kExpected)) + ExpectEq("(-1.04857625e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(-kTwoTo20), false, false, ""}, + equalsTestCase{int(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{int32(-kTwoTo20), false, false, ""}, + equalsTestCase{int32(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{int64(-kTwoTo20), false, false, ""}, + equalsTestCase{int64(-kTwoTo20 - 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex64(kExpected - 0.75), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected - 0.75), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargeNegativeComplex128() { + const kExpected = -1 * (1 << 65) + matcher := Equals(complex128(kExpected)) + ExpectEq("(-3.6893488147419103e+19+0i)", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := int64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex64(kExpected + 2i), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ZeroComplex128() { + matcher := Equals(complex128(0)) + ExpectEq("(0+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of zero. + equalsTestCase{0.0, true, false, ""}, + equalsTestCase{0 + 0i, true, false, ""}, + equalsTestCase{int(0), true, false, ""}, + equalsTestCase{int8(0), true, false, ""}, + equalsTestCase{int16(0), true, false, ""}, + equalsTestCase{int32(0), true, false, ""}, + equalsTestCase{int64(0), true, false, ""}, + equalsTestCase{uint(0), true, false, ""}, + equalsTestCase{uint8(0), true, false, ""}, + equalsTestCase{uint16(0), true, false, ""}, + equalsTestCase{uint32(0), true, false, ""}, + equalsTestCase{uint64(0), true, false, ""}, + equalsTestCase{uintptr(0), true, false, ""}, + equalsTestCase{float32(0), true, false, ""}, + equalsTestCase{float64(0), true, false, ""}, + equalsTestCase{complex64(0), true, false, ""}, + equalsTestCase{complex128(0), true, false, ""}, + equalsTestCase{interface{}(float32(0)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(1), false, false, ""}, + equalsTestCase{int64(-1), false, false, ""}, + equalsTestCase{float32(1), false, false, ""}, + equalsTestCase{float32(-1), false, false, ""}, + equalsTestCase{float64(1), false, false, ""}, + equalsTestCase{float64(-1), false, false, ""}, + equalsTestCase{complex64(0 + 2i), false, false, ""}, + equalsTestCase{complex128(0 + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveIntegralComplex128() { + const kExpected = 1 << 20 + matcher := Equals(complex128(kExpected)) + ExpectEq("(1.048576e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of 32769. + equalsTestCase{1048576.0, true, false, ""}, + equalsTestCase{1048576.0 + 0i, true, false, ""}, + equalsTestCase{int(kExpected), true, false, ""}, + equalsTestCase{int32(kExpected), true, false, ""}, + equalsTestCase{int64(kExpected), true, false, ""}, + equalsTestCase{uint(kExpected), true, false, ""}, + equalsTestCase{uint32(kExpected), true, false, ""}, + equalsTestCase{uint64(kExpected), true, false, ""}, + equalsTestCase{uintptr(kExpected), true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + equalsTestCase{interface{}(float64(kExpected)), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(kExpected + 1), false, false, ""}, + equalsTestCase{int32(kExpected + 1), false, false, ""}, + equalsTestCase{int64(kExpected + 1), false, false, ""}, + equalsTestCase{uint(kExpected + 1), false, false, ""}, + equalsTestCase{uint32(kExpected + 1), false, false, ""}, + equalsTestCase{uint64(kExpected + 1), false, false, ""}, + equalsTestCase{uintptr(kExpected + 1), false, false, ""}, + equalsTestCase{float32(kExpected - (1 << 30)), false, false, ""}, + equalsTestCase{float32(kExpected + (1 << 30)), false, false, ""}, + equalsTestCase{float64(kExpected - 0.5), false, false, ""}, + equalsTestCase{float64(kExpected + 0.5), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + + // Non-numeric types. + equalsTestCase{true, false, true, "which is not numeric"}, + equalsTestCase{[...]int{}, false, true, "which is not numeric"}, + equalsTestCase{make(chan int), false, true, "which is not numeric"}, + equalsTestCase{func() {}, false, true, "which is not numeric"}, + equalsTestCase{map[int]int{}, false, true, "which is not numeric"}, + equalsTestCase{&someInt, false, true, "which is not numeric"}, + equalsTestCase{[]int{}, false, true, "which is not numeric"}, + equalsTestCase{"taco", false, true, "which is not numeric"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not numeric"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) PositiveNonIntegralComplex128() { + const kTwoTo20 = 1 << 20 + const kExpected = kTwoTo20 + 0.25 + matcher := Equals(complex128(kExpected)) + ExpectEq("(1.04857625e+06+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int64(kTwoTo20), false, false, ""}, + equalsTestCase{int64(kTwoTo20 - 1), false, false, ""}, + equalsTestCase{uint64(kTwoTo20), false, false, ""}, + equalsTestCase{uint64(kTwoTo20 - 1), false, false, ""}, + equalsTestCase{float32(kExpected - 1), false, false, ""}, + equalsTestCase{float32(kExpected + 1), false, false, ""}, + equalsTestCase{float64(kExpected - 0.25), false, false, ""}, + equalsTestCase{float64(kExpected + 0.25), false, false, ""}, + equalsTestCase{complex64(kExpected - 1), false, false, ""}, + equalsTestCase{complex64(kExpected - 1i), false, false, ""}, + equalsTestCase{complex128(kExpected - 1), false, false, ""}, + equalsTestCase{complex128(kExpected - 1i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) LargePositiveComplex128() { + const kExpected = 1 << 65 + matcher := Equals(complex128(kExpected)) + ExpectEq("(3.6893488147419103e+19+0i)", matcher.Description()) + + floatExpected := float64(kExpected) + castedInt := uint64(floatExpected) + + cases := []equalsTestCase{ + // Equal values of numeric type. + equalsTestCase{kExpected + 0i, true, false, ""}, + equalsTestCase{float32(kExpected), true, false, ""}, + equalsTestCase{float64(kExpected), true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{castedInt, false, false, ""}, + equalsTestCase{int64(0), false, false, ""}, + equalsTestCase{int64(math.MinInt64), false, false, ""}, + equalsTestCase{int64(math.MaxInt64), false, false, ""}, + equalsTestCase{uint64(0), false, false, ""}, + equalsTestCase{uint64(math.MaxUint64), false, false, ""}, + equalsTestCase{float32(kExpected / 2), false, false, ""}, + equalsTestCase{float64(kExpected / 2), false, false, ""}, + equalsTestCase{complex128(kExpected + 2i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Complex128AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := Equals(complex128(kTwoTo54 + 1)) + ExpectEq("(1.8014398509481984e+16+0i)", matcher.Description()) + + cases := []equalsTestCase{ + // Integers. + equalsTestCase{int64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{int64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{int64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{uint64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{uint64(kTwoTo54 + 3), false, false, ""}, + + // Double-precision floating point. + equalsTestCase{float64(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{float64(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{float64(kTwoTo54 + 3), false, false, ""}, + + equalsTestCase{complex128(kTwoTo54 - 2), false, false, ""}, + equalsTestCase{complex128(kTwoTo54 - 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 0), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 1), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 2), true, false, ""}, + equalsTestCase{complex128(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) Complex128WithNonZeroImaginaryPart() { + const kRealPart = 17 + const kImagPart = 0.25i + const kExpected = kRealPart + kImagPart + matcher := Equals(complex128(kExpected)) + ExpectEq("(17+0.25i)", matcher.Description()) + + cases := []equalsTestCase{ + // Various types of the expected value. + equalsTestCase{kExpected, true, false, ""}, + equalsTestCase{kRealPart + kImagPart, true, false, ""}, + equalsTestCase{complex64(kExpected), true, false, ""}, + equalsTestCase{complex128(kExpected), true, false, ""}, + + // Non-equal values of numeric type. + equalsTestCase{int(kRealPart), false, false, ""}, + equalsTestCase{int8(kRealPart), false, false, ""}, + equalsTestCase{int16(kRealPart), false, false, ""}, + equalsTestCase{int32(kRealPart), false, false, ""}, + equalsTestCase{int64(kRealPart), false, false, ""}, + equalsTestCase{uint(kRealPart), false, false, ""}, + equalsTestCase{uint8(kRealPart), false, false, ""}, + equalsTestCase{uint16(kRealPart), false, false, ""}, + equalsTestCase{uint32(kRealPart), false, false, ""}, + equalsTestCase{uint64(kRealPart), false, false, ""}, + equalsTestCase{float32(kRealPart), false, false, ""}, + equalsTestCase{float64(kRealPart), false, false, ""}, + equalsTestCase{complex64(kRealPart), false, false, ""}, + equalsTestCase{complex64(kRealPart + kImagPart + 0.5), false, false, ""}, + equalsTestCase{complex64(kRealPart + kImagPart + 0.5i), false, false, ""}, + equalsTestCase{complex128(kRealPart), false, false, ""}, + equalsTestCase{complex128(kRealPart + kImagPart + 0.5), false, false, ""}, + equalsTestCase{complex128(kRealPart + kImagPart + 0.5i), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Arrays +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) ArrayOfComparableType() { + expected := [3]uint{17, 19, 23} + + matcher := Equals(expected) + ExpectEq("[17 19 23]", matcher.Description()) + + // To defeat constant de-duping by the compiler. + makeArray := func(i, j, k uint) [3]uint { return [3]uint{i, j, k} } + + type arrayAlias [3]uint + type uintAlias uint + + cases := []equalsTestCase{ + // Correct types, equal. + equalsTestCase{expected, true, false, ""}, + equalsTestCase{[3]uint{17, 19, 23}, true, false, ""}, + equalsTestCase{makeArray(17, 19, 23), true, false, ""}, + + // Correct types, not equal. + equalsTestCase{[3]uint{0, 0, 0}, false, false, ""}, + equalsTestCase{[3]uint{18, 19, 23}, false, false, ""}, + equalsTestCase{[3]uint{17, 20, 23}, false, false, ""}, + equalsTestCase{[3]uint{17, 19, 22}, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not [3]uint"}, + equalsTestCase{bool(false), false, true, "which is not [3]uint"}, + equalsTestCase{int(0), false, true, "which is not [3]uint"}, + equalsTestCase{int8(0), false, true, "which is not [3]uint"}, + equalsTestCase{int16(0), false, true, "which is not [3]uint"}, + equalsTestCase{int32(0), false, true, "which is not [3]uint"}, + equalsTestCase{int64(0), false, true, "which is not [3]uint"}, + equalsTestCase{uint(0), false, true, "which is not [3]uint"}, + equalsTestCase{uint8(0), false, true, "which is not [3]uint"}, + equalsTestCase{uint16(0), false, true, "which is not [3]uint"}, + equalsTestCase{uint32(0), false, true, "which is not [3]uint"}, + equalsTestCase{uint64(0), false, true, "which is not [3]uint"}, + equalsTestCase{true, false, true, "which is not [3]uint"}, + equalsTestCase{[...]int{}, false, true, "which is not [3]uint"}, + equalsTestCase{func() {}, false, true, "which is not [3]uint"}, + equalsTestCase{map[int]int{}, false, true, "which is not [3]uint"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not [3]uint"}, + equalsTestCase{[2]uint{17, 19}, false, true, "which is not [3]uint"}, + equalsTestCase{[4]uint{17, 19, 23, 0}, false, true, "which is not [3]uint"}, + equalsTestCase{arrayAlias{17, 19, 23}, false, true, "which is not [3]uint"}, + equalsTestCase{[3]uintAlias{17, 19, 23}, false, true, "which is not [3]uint"}, + equalsTestCase{[3]int32{17, 19, 23}, false, true, "which is not [3]uint"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ArrayOfNonComparableType() { + type nonComparableArray [2]map[string]string + f := func() { + ExpectEq(nonComparableArray{}, nonComparableArray{}) + } + + ExpectThat(f, Panics(MatchesRegexp("uncomparable.*nonComparableArray"))) +} + +//////////////////////////////////////////////////////////////////////// +// chan +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NilChan() { + var nilChan1 chan int + var nilChan2 chan int + var nilChan3 chan uint + var nonNilChan1 chan int = make(chan int) + var nonNilChan2 chan uint = make(chan uint) + + matcher := Equals(nilChan1) + ExpectEq("", matcher.Description()) + + cases := []equalsTestCase{ + // int channels + equalsTestCase{nilChan1, true, false, ""}, + equalsTestCase{nilChan2, true, false, ""}, + equalsTestCase{nonNilChan1, false, false, ""}, + + // uint channels + equalsTestCase{nilChan3, false, true, "which is not a chan int"}, + equalsTestCase{nonNilChan2, false, true, "which is not a chan int"}, + + // Other types. + equalsTestCase{0, false, true, "which is not a chan int"}, + equalsTestCase{bool(false), false, true, "which is not a chan int"}, + equalsTestCase{int(0), false, true, "which is not a chan int"}, + equalsTestCase{int8(0), false, true, "which is not a chan int"}, + equalsTestCase{int16(0), false, true, "which is not a chan int"}, + equalsTestCase{int32(0), false, true, "which is not a chan int"}, + equalsTestCase{int64(0), false, true, "which is not a chan int"}, + equalsTestCase{uint(0), false, true, "which is not a chan int"}, + equalsTestCase{uint8(0), false, true, "which is not a chan int"}, + equalsTestCase{uint16(0), false, true, "which is not a chan int"}, + equalsTestCase{uint32(0), false, true, "which is not a chan int"}, + equalsTestCase{uint64(0), false, true, "which is not a chan int"}, + equalsTestCase{true, false, true, "which is not a chan int"}, + equalsTestCase{[...]int{}, false, true, "which is not a chan int"}, + equalsTestCase{func() {}, false, true, "which is not a chan int"}, + equalsTestCase{map[int]int{}, false, true, "which is not a chan int"}, + equalsTestCase{&someInt, false, true, "which is not a chan int"}, + equalsTestCase{[]int{}, false, true, "which is not a chan int"}, + equalsTestCase{"taco", false, true, "which is not a chan int"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a chan int"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonNilChan() { + var nilChan1 chan int + var nilChan2 chan uint + var nonNilChan1 chan int = make(chan int) + var nonNilChan2 chan int = make(chan int) + var nonNilChan3 chan uint = make(chan uint) + + matcher := Equals(nonNilChan1) + ExpectEq(fmt.Sprintf("%v", nonNilChan1), matcher.Description()) + + cases := []equalsTestCase{ + // int channels + equalsTestCase{nonNilChan1, true, false, ""}, + equalsTestCase{nonNilChan2, false, false, ""}, + equalsTestCase{nilChan1, false, false, ""}, + + // uint channels + equalsTestCase{nilChan2, false, true, "which is not a chan int"}, + equalsTestCase{nonNilChan3, false, true, "which is not a chan int"}, + + // Other types. + equalsTestCase{0, false, true, "which is not a chan int"}, + equalsTestCase{bool(false), false, true, "which is not a chan int"}, + equalsTestCase{int(0), false, true, "which is not a chan int"}, + equalsTestCase{int8(0), false, true, "which is not a chan int"}, + equalsTestCase{int16(0), false, true, "which is not a chan int"}, + equalsTestCase{int32(0), false, true, "which is not a chan int"}, + equalsTestCase{int64(0), false, true, "which is not a chan int"}, + equalsTestCase{uint(0), false, true, "which is not a chan int"}, + equalsTestCase{uint8(0), false, true, "which is not a chan int"}, + equalsTestCase{uint16(0), false, true, "which is not a chan int"}, + equalsTestCase{uint32(0), false, true, "which is not a chan int"}, + equalsTestCase{uint64(0), false, true, "which is not a chan int"}, + equalsTestCase{true, false, true, "which is not a chan int"}, + equalsTestCase{[...]int{}, false, true, "which is not a chan int"}, + equalsTestCase{func() {}, false, true, "which is not a chan int"}, + equalsTestCase{map[int]int{}, false, true, "which is not a chan int"}, + equalsTestCase{&someInt, false, true, "which is not a chan int"}, + equalsTestCase{[]int{}, false, true, "which is not a chan int"}, + equalsTestCase{"taco", false, true, "which is not a chan int"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a chan int"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) ChanDirection() { + var chan1 chan<- int + var chan2 <-chan int + var chan3 chan int + + matcher := Equals(chan1) + ExpectEq(fmt.Sprintf("%v", chan1), matcher.Description()) + + cases := []equalsTestCase{ + equalsTestCase{chan1, true, false, ""}, + equalsTestCase{chan2, false, true, "which is not a chan<- int"}, + equalsTestCase{chan3, false, true, "which is not a chan<- int"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// func +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) Functions() { + func1 := func() {} + func2 := func() {} + func3 := func(x int) {} + + matcher := Equals(func1) + ExpectEq(fmt.Sprintf("%v", func1), matcher.Description()) + + cases := []equalsTestCase{ + // Functions. + equalsTestCase{func1, true, false, ""}, + equalsTestCase{func2, false, false, ""}, + equalsTestCase{func3, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a function"}, + equalsTestCase{bool(false), false, true, "which is not a function"}, + equalsTestCase{int(0), false, true, "which is not a function"}, + equalsTestCase{int8(0), false, true, "which is not a function"}, + equalsTestCase{int16(0), false, true, "which is not a function"}, + equalsTestCase{int32(0), false, true, "which is not a function"}, + equalsTestCase{int64(0), false, true, "which is not a function"}, + equalsTestCase{uint(0), false, true, "which is not a function"}, + equalsTestCase{uint8(0), false, true, "which is not a function"}, + equalsTestCase{uint16(0), false, true, "which is not a function"}, + equalsTestCase{uint32(0), false, true, "which is not a function"}, + equalsTestCase{uint64(0), false, true, "which is not a function"}, + equalsTestCase{true, false, true, "which is not a function"}, + equalsTestCase{[...]int{}, false, true, "which is not a function"}, + equalsTestCase{map[int]int{}, false, true, "which is not a function"}, + equalsTestCase{&someInt, false, true, "which is not a function"}, + equalsTestCase{[]int{}, false, true, "which is not a function"}, + equalsTestCase{"taco", false, true, "which is not a function"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a function"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// map +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NilMap() { + var nilMap1 map[int]int + var nilMap2 map[int]int + var nilMap3 map[int]uint + var nonNilMap1 map[int]int = make(map[int]int) + var nonNilMap2 map[int]uint = make(map[int]uint) + + matcher := Equals(nilMap1) + ExpectEq("map[]", matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nilMap1, true, false, ""}, + equalsTestCase{nilMap2, true, false, ""}, + equalsTestCase{nilMap3, true, false, ""}, + equalsTestCase{nonNilMap1, false, false, ""}, + equalsTestCase{nonNilMap2, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a map"}, + equalsTestCase{bool(false), false, true, "which is not a map"}, + equalsTestCase{int(0), false, true, "which is not a map"}, + equalsTestCase{int8(0), false, true, "which is not a map"}, + equalsTestCase{int16(0), false, true, "which is not a map"}, + equalsTestCase{int32(0), false, true, "which is not a map"}, + equalsTestCase{int64(0), false, true, "which is not a map"}, + equalsTestCase{uint(0), false, true, "which is not a map"}, + equalsTestCase{uint8(0), false, true, "which is not a map"}, + equalsTestCase{uint16(0), false, true, "which is not a map"}, + equalsTestCase{uint32(0), false, true, "which is not a map"}, + equalsTestCase{uint64(0), false, true, "which is not a map"}, + equalsTestCase{true, false, true, "which is not a map"}, + equalsTestCase{[...]int{}, false, true, "which is not a map"}, + equalsTestCase{func() {}, false, true, "which is not a map"}, + equalsTestCase{&someInt, false, true, "which is not a map"}, + equalsTestCase{[]int{}, false, true, "which is not a map"}, + equalsTestCase{"taco", false, true, "which is not a map"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a map"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonNilMap() { + var nilMap1 map[int]int + var nilMap2 map[int]uint + var nonNilMap1 map[int]int = make(map[int]int) + var nonNilMap2 map[int]int = make(map[int]int) + var nonNilMap3 map[int]uint = make(map[int]uint) + + matcher := Equals(nonNilMap1) + ExpectEq("map[]", matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nonNilMap1, true, false, ""}, + equalsTestCase{nonNilMap2, false, false, ""}, + equalsTestCase{nonNilMap3, false, false, ""}, + equalsTestCase{nilMap1, false, false, ""}, + equalsTestCase{nilMap2, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a map"}, + equalsTestCase{bool(false), false, true, "which is not a map"}, + equalsTestCase{int(0), false, true, "which is not a map"}, + equalsTestCase{int8(0), false, true, "which is not a map"}, + equalsTestCase{int16(0), false, true, "which is not a map"}, + equalsTestCase{int32(0), false, true, "which is not a map"}, + equalsTestCase{int64(0), false, true, "which is not a map"}, + equalsTestCase{uint(0), false, true, "which is not a map"}, + equalsTestCase{uint8(0), false, true, "which is not a map"}, + equalsTestCase{uint16(0), false, true, "which is not a map"}, + equalsTestCase{uint32(0), false, true, "which is not a map"}, + equalsTestCase{uint64(0), false, true, "which is not a map"}, + equalsTestCase{true, false, true, "which is not a map"}, + equalsTestCase{[...]int{}, false, true, "which is not a map"}, + equalsTestCase{func() {}, false, true, "which is not a map"}, + equalsTestCase{&someInt, false, true, "which is not a map"}, + equalsTestCase{[]int{}, false, true, "which is not a map"}, + equalsTestCase{"taco", false, true, "which is not a map"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a map"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Pointers +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NilPointer() { + var someInt int = 17 + var someUint uint = 17 + + var nilInt1 *int + var nilInt2 *int + var nilUint *uint + var nonNilInt *int = &someInt + var nonNilUint *uint = &someUint + + matcher := Equals(nilInt1) + ExpectEq("", matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nilInt1, true, false, ""}, + equalsTestCase{nilInt2, true, false, ""}, + equalsTestCase{nonNilInt, false, false, ""}, + + // Incorrect type. + equalsTestCase{nilUint, false, true, "which is not a *int"}, + equalsTestCase{nonNilUint, false, true, "which is not a *int"}, + + // Other types. + equalsTestCase{0, false, true, "which is not a *int"}, + equalsTestCase{bool(false), false, true, "which is not a *int"}, + equalsTestCase{int(0), false, true, "which is not a *int"}, + equalsTestCase{int8(0), false, true, "which is not a *int"}, + equalsTestCase{int16(0), false, true, "which is not a *int"}, + equalsTestCase{int32(0), false, true, "which is not a *int"}, + equalsTestCase{int64(0), false, true, "which is not a *int"}, + equalsTestCase{uint(0), false, true, "which is not a *int"}, + equalsTestCase{uint8(0), false, true, "which is not a *int"}, + equalsTestCase{uint16(0), false, true, "which is not a *int"}, + equalsTestCase{uint32(0), false, true, "which is not a *int"}, + equalsTestCase{uint64(0), false, true, "which is not a *int"}, + equalsTestCase{true, false, true, "which is not a *int"}, + equalsTestCase{[...]int{}, false, true, "which is not a *int"}, + equalsTestCase{func() {}, false, true, "which is not a *int"}, + equalsTestCase{map[int]int{}, false, true, "which is not a *int"}, + equalsTestCase{[]int{}, false, true, "which is not a *int"}, + equalsTestCase{"taco", false, true, "which is not a *int"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a *int"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonNilPointer() { + var someInt int = 17 + var someOtherInt int = 17 + var someUint uint = 17 + + var nilInt *int + var nilUint *uint + var nonNilInt1 *int = &someInt + var nonNilInt2 *int = &someOtherInt + var nonNilUint *uint = &someUint + + matcher := Equals(nonNilInt1) + ExpectEq(fmt.Sprintf("%v", nonNilInt1), matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nonNilInt1, true, false, ""}, + equalsTestCase{nonNilInt2, false, false, ""}, + equalsTestCase{nilInt, false, false, ""}, + + // Incorrect type. + equalsTestCase{nilUint, false, true, "which is not a *int"}, + equalsTestCase{nonNilUint, false, true, "which is not a *int"}, + + // Other types. + equalsTestCase{0, false, true, "which is not a *int"}, + equalsTestCase{bool(false), false, true, "which is not a *int"}, + equalsTestCase{int(0), false, true, "which is not a *int"}, + equalsTestCase{int8(0), false, true, "which is not a *int"}, + equalsTestCase{int16(0), false, true, "which is not a *int"}, + equalsTestCase{int32(0), false, true, "which is not a *int"}, + equalsTestCase{int64(0), false, true, "which is not a *int"}, + equalsTestCase{uint(0), false, true, "which is not a *int"}, + equalsTestCase{uint8(0), false, true, "which is not a *int"}, + equalsTestCase{uint16(0), false, true, "which is not a *int"}, + equalsTestCase{uint32(0), false, true, "which is not a *int"}, + equalsTestCase{uint64(0), false, true, "which is not a *int"}, + equalsTestCase{true, false, true, "which is not a *int"}, + equalsTestCase{[...]int{}, false, true, "which is not a *int"}, + equalsTestCase{func() {}, false, true, "which is not a *int"}, + equalsTestCase{map[int]int{}, false, true, "which is not a *int"}, + equalsTestCase{[]int{}, false, true, "which is not a *int"}, + equalsTestCase{"taco", false, true, "which is not a *int"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a *int"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Slices +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NilSlice() { + var nilInt1 []int + var nilInt2 []int + var nilUint []uint + + var nonNilInt []int = make([]int, 0) + var nonNilUint []uint = make([]uint, 0) + + matcher := Equals(nilInt1) + ExpectEq("[]", matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nilInt1, true, false, ""}, + equalsTestCase{nilInt2, true, false, ""}, + equalsTestCase{nonNilInt, false, false, ""}, + + // Incorrect type. + equalsTestCase{nilUint, false, true, "which is not a []int"}, + equalsTestCase{nonNilUint, false, true, "which is not a []int"}, + + // Other types. + equalsTestCase{0, false, true, "which is not a []int"}, + equalsTestCase{bool(false), false, true, "which is not a []int"}, + equalsTestCase{int(0), false, true, "which is not a []int"}, + equalsTestCase{int8(0), false, true, "which is not a []int"}, + equalsTestCase{int16(0), false, true, "which is not a []int"}, + equalsTestCase{int32(0), false, true, "which is not a []int"}, + equalsTestCase{int64(0), false, true, "which is not a []int"}, + equalsTestCase{uint(0), false, true, "which is not a []int"}, + equalsTestCase{uint8(0), false, true, "which is not a []int"}, + equalsTestCase{uint16(0), false, true, "which is not a []int"}, + equalsTestCase{uint32(0), false, true, "which is not a []int"}, + equalsTestCase{uint64(0), false, true, "which is not a []int"}, + equalsTestCase{true, false, true, "which is not a []int"}, + equalsTestCase{[...]int{}, false, true, "which is not a []int"}, + equalsTestCase{func() {}, false, true, "which is not a []int"}, + equalsTestCase{map[int]int{}, false, true, "which is not a []int"}, + equalsTestCase{"taco", false, true, "which is not a []int"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a []int"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonNilSlice() { + nonNil := make([]int, 0) + f := func() { Equals(nonNil) } + ExpectThat(f, Panics(HasSubstr("non-nil slice"))) +} + +//////////////////////////////////////////////////////////////////////// +// string +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) String() { + partial := "taco" + expected := fmt.Sprintf("%s%d", partial, 1) + + matcher := Equals(expected) + ExpectEq("taco1", matcher.Description()) + + type stringAlias string + + cases := []equalsTestCase{ + // Correct types. + equalsTestCase{"taco1", true, false, ""}, + equalsTestCase{"taco" + "1", true, false, ""}, + equalsTestCase{expected, true, false, ""}, + equalsTestCase{stringAlias("taco1"), true, false, ""}, + + equalsTestCase{"", false, false, ""}, + equalsTestCase{"taco", false, false, ""}, + equalsTestCase{"taco1\x00", false, false, ""}, + equalsTestCase{"taco2", false, false, ""}, + equalsTestCase{stringAlias("taco2"), false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a string"}, + equalsTestCase{bool(false), false, true, "which is not a string"}, + equalsTestCase{int(0), false, true, "which is not a string"}, + equalsTestCase{int8(0), false, true, "which is not a string"}, + equalsTestCase{int16(0), false, true, "which is not a string"}, + equalsTestCase{int32(0), false, true, "which is not a string"}, + equalsTestCase{int64(0), false, true, "which is not a string"}, + equalsTestCase{uint(0), false, true, "which is not a string"}, + equalsTestCase{uint8(0), false, true, "which is not a string"}, + equalsTestCase{uint16(0), false, true, "which is not a string"}, + equalsTestCase{uint32(0), false, true, "which is not a string"}, + equalsTestCase{uint64(0), false, true, "which is not a string"}, + equalsTestCase{true, false, true, "which is not a string"}, + equalsTestCase{[...]int{}, false, true, "which is not a string"}, + equalsTestCase{func() {}, false, true, "which is not a string"}, + equalsTestCase{map[int]int{}, false, true, "which is not a string"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a string"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) StringAlias() { + type stringAlias string + + matcher := Equals(stringAlias("taco")) + ExpectEq("taco", matcher.Description()) + + cases := []equalsTestCase{ + // Correct types. + equalsTestCase{stringAlias("taco"), true, false, ""}, + equalsTestCase{"taco", true, false, ""}, + + equalsTestCase{"burrito", false, false, ""}, + equalsTestCase{stringAlias("burrito"), false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a string"}, + equalsTestCase{bool(false), false, true, "which is not a string"}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// struct +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) Struct() { + type someStruct struct{ foo uint } + f := func() { Equals(someStruct{17}) } + ExpectThat(f, Panics(HasSubstr("unsupported kind struct"))) +} + +//////////////////////////////////////////////////////////////////////// +// unsafe.Pointer +//////////////////////////////////////////////////////////////////////// + +func (t *EqualsTest) NilUnsafePointer() { + someInt := int(17) + + var nilPtr1 unsafe.Pointer + var nilPtr2 unsafe.Pointer + var nonNilPtr unsafe.Pointer = unsafe.Pointer(&someInt) + + matcher := Equals(nilPtr1) + ExpectEq("", matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nilPtr1, true, false, ""}, + equalsTestCase{nilPtr2, true, false, ""}, + equalsTestCase{nonNilPtr, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{bool(false), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int8(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int16(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int32(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int64(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint8(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint16(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint32(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint64(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{true, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{[...]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{make(chan int), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{func() {}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{map[int]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{&someInt, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{[]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{"taco", false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a unsafe.Pointer"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *EqualsTest) NonNilUnsafePointer() { + someInt := int(17) + someOtherInt := int(17) + + var nilPtr unsafe.Pointer + var nonNilPtr1 unsafe.Pointer = unsafe.Pointer(&someInt) + var nonNilPtr2 unsafe.Pointer = unsafe.Pointer(&someOtherInt) + + matcher := Equals(nonNilPtr1) + ExpectEq(fmt.Sprintf("%v", nonNilPtr1), matcher.Description()) + + cases := []equalsTestCase{ + // Correct type. + equalsTestCase{nonNilPtr1, true, false, ""}, + equalsTestCase{nonNilPtr2, false, false, ""}, + equalsTestCase{nilPtr, false, false, ""}, + + // Other types. + equalsTestCase{0, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{bool(false), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int8(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int16(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int32(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{int64(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint8(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint16(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint32(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{uint64(0), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{true, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{[...]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{make(chan int), false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{func() {}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{map[int]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{&someInt, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{[]int{}, false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{"taco", false, true, "which is not a unsafe.Pointer"}, + equalsTestCase{equalsTestCase{}, false, true, "which is not a unsafe.Pointer"}, + } + + t.checkTestCases(matcher, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/error.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/error.go new file mode 100644 index 0000000000..8a078e36d8 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/error.go @@ -0,0 +1,51 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +// Error returns a matcher that matches non-nil values implementing the +// built-in error interface for whom the return value of Error() matches the +// supplied matcher. +// +// For example: +// +// err := errors.New("taco burrito") +// +// Error(Equals("taco burrito")) // matches err +// Error(HasSubstr("taco")) // matches err +// Error(HasSubstr("enchilada")) // doesn't match err +// +func Error(m Matcher) Matcher { + return &errorMatcher{m} +} + +type errorMatcher struct { + wrappedMatcher Matcher +} + +func (m *errorMatcher) Description() string { + return "error " + m.wrappedMatcher.Description() +} + +func (m *errorMatcher) Matches(c interface{}) error { + // Make sure that c is an error. + e, ok := c.(error) + if !ok { + return NewFatalError("which is not an error") + } + + // Pass on the error text to the wrapped matcher. + return m.wrappedMatcher.Matches(e.Error()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/error_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/error_test.go new file mode 100644 index 0000000000..8859b8a2ff --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/error_test.go @@ -0,0 +1,92 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type ErrorTest struct { + matcherCalled bool + suppliedCandidate interface{} + wrappedError error + + matcher Matcher +} + +func init() { RegisterTestSuite(&ErrorTest{}) } + +func (t *ErrorTest) SetUp(i *TestInfo) { + wrapped := &fakeMatcher{ + func(c interface{}) error { + t.matcherCalled = true + t.suppliedCandidate = c + return t.wrappedError + }, + "is foo", + } + + t.matcher = Error(wrapped) +} + +func isFatal(err error) bool { + _, isFatal := err.(*FatalError) + return isFatal +} + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *ErrorTest) Description() { + ExpectThat(t.matcher.Description(), Equals("error is foo")) +} + +func (t *ErrorTest) CandidateIsNil() { + err := t.matcher.Matches(nil) + + ExpectThat(t.matcherCalled, Equals(false)) + ExpectThat(err.Error(), Equals("which is not an error")) + ExpectTrue(isFatal(err)) +} + +func (t *ErrorTest) CandidateIsString() { + err := t.matcher.Matches("taco") + + ExpectThat(t.matcherCalled, Equals(false)) + ExpectThat(err.Error(), Equals("which is not an error")) + ExpectTrue(isFatal(err)) +} + +func (t *ErrorTest) CallsWrappedMatcher() { + candidate := errors.New("taco") + t.matcher.Matches(candidate) + + ExpectThat(t.matcherCalled, Equals(true)) + ExpectThat(t.suppliedCandidate, Equals("taco")) +} + +func (t *ErrorTest) ReturnsWrappedMatcherResult() { + t.wrappedError = errors.New("burrito") + err := t.matcher.Matches(errors.New("")) + ExpectThat(err, Equals(t.wrappedError)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal.go new file mode 100644 index 0000000000..4b9d103a38 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal.go @@ -0,0 +1,39 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "fmt" + "reflect" +) + +// GreaterOrEqual returns a matcher that matches integer, floating point, or +// strings values v such that v >= x. Comparison is not defined between numeric +// and string types, but is defined between all integer and floating point +// types. +// +// x must itself be an integer, floating point, or string type; otherwise, +// GreaterOrEqual will panic. +func GreaterOrEqual(x interface{}) Matcher { + desc := fmt.Sprintf("greater than or equal to %v", x) + + // Special case: make it clear that strings are strings. + if reflect.TypeOf(x).Kind() == reflect.String { + desc = fmt.Sprintf("greater than or equal to \"%s\"", x) + } + + return transformDescription(Not(LessThan(x)), desc) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal_test.go new file mode 100644 index 0000000000..7f4a6310db --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_or_equal_test.go @@ -0,0 +1,1101 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "math" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type GreaterOrEqualTest struct { +} + +func init() { RegisterTestSuite(&GreaterOrEqualTest{}) } + +type geTestCase struct { + candidate interface{} + expectedResult bool + shouldBeFatal bool + expectedError string +} + +func (t *GreaterOrEqualTest) checkTestCases(matcher Matcher, cases []geTestCase) { + for i, c := range cases { + err := matcher.Matches(c.candidate) + + ExpectThat( + (err == nil), + Equals(c.expectedResult), + "Case %d (candidate %v)", + i, + c.candidate) + + if err == nil { + continue + } + + _, isFatal := err.(*FatalError) + ExpectEq( + c.shouldBeFatal, + isFatal, + "Case %d (candidate %v)", + i, + c.candidate) + + ExpectThat( + err, + Error(Equals(c.expectedError)), + "Case %d (candidate %v)", + i, + c.candidate) + } +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterOrEqualTest) IntegerCandidateBadTypes() { + matcher := GreaterOrEqual(int(-150)) + + cases := []geTestCase{ + geTestCase{true, false, true, "which is not comparable"}, + geTestCase{complex64(-151), false, true, "which is not comparable"}, + geTestCase{complex128(-151), false, true, "which is not comparable"}, + geTestCase{[...]int{-151}, false, true, "which is not comparable"}, + geTestCase{make(chan int), false, true, "which is not comparable"}, + geTestCase{func() {}, false, true, "which is not comparable"}, + geTestCase{map[int]int{}, false, true, "which is not comparable"}, + geTestCase{&geTestCase{}, false, true, "which is not comparable"}, + geTestCase{make([]int, 0), false, true, "which is not comparable"}, + geTestCase{"-151", false, true, "which is not comparable"}, + geTestCase{geTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) FloatCandidateBadTypes() { + matcher := GreaterOrEqual(float32(-150)) + + cases := []geTestCase{ + geTestCase{true, false, true, "which is not comparable"}, + geTestCase{complex64(-151), false, true, "which is not comparable"}, + geTestCase{complex128(-151), false, true, "which is not comparable"}, + geTestCase{[...]int{-151}, false, true, "which is not comparable"}, + geTestCase{make(chan int), false, true, "which is not comparable"}, + geTestCase{func() {}, false, true, "which is not comparable"}, + geTestCase{map[int]int{}, false, true, "which is not comparable"}, + geTestCase{&geTestCase{}, false, true, "which is not comparable"}, + geTestCase{make([]int, 0), false, true, "which is not comparable"}, + geTestCase{"-151", false, true, "which is not comparable"}, + geTestCase{geTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) StringCandidateBadTypes() { + matcher := GreaterOrEqual("17") + + cases := []geTestCase{ + geTestCase{true, false, true, "which is not comparable"}, + geTestCase{int(0), false, true, "which is not comparable"}, + geTestCase{int8(0), false, true, "which is not comparable"}, + geTestCase{int16(0), false, true, "which is not comparable"}, + geTestCase{int32(0), false, true, "which is not comparable"}, + geTestCase{int64(0), false, true, "which is not comparable"}, + geTestCase{uint(0), false, true, "which is not comparable"}, + geTestCase{uint8(0), false, true, "which is not comparable"}, + geTestCase{uint16(0), false, true, "which is not comparable"}, + geTestCase{uint32(0), false, true, "which is not comparable"}, + geTestCase{uint64(0), false, true, "which is not comparable"}, + geTestCase{float32(0), false, true, "which is not comparable"}, + geTestCase{float64(0), false, true, "which is not comparable"}, + geTestCase{complex64(-151), false, true, "which is not comparable"}, + geTestCase{complex128(-151), false, true, "which is not comparable"}, + geTestCase{[...]int{-151}, false, true, "which is not comparable"}, + geTestCase{make(chan int), false, true, "which is not comparable"}, + geTestCase{func() {}, false, true, "which is not comparable"}, + geTestCase{map[int]int{}, false, true, "which is not comparable"}, + geTestCase{&geTestCase{}, false, true, "which is not comparable"}, + geTestCase{make([]int, 0), false, true, "which is not comparable"}, + geTestCase{geTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) BadArgument() { + panicked := false + + defer func() { + ExpectThat(panicked, Equals(true)) + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + GreaterOrEqual(complex128(0)) +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterOrEqualTest) NegativeIntegerLiteral() { + matcher := GreaterOrEqual(-150) + desc := matcher.Description() + expectedDesc := "greater than or equal to -150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-(1 << 30), false, false, ""}, + geTestCase{-151, false, false, ""}, + geTestCase{-150, true, false, ""}, + geTestCase{0, true, false, ""}, + geTestCase{17, true, false, ""}, + + geTestCase{int(-(1 << 30)), false, false, ""}, + geTestCase{int(-151), false, false, ""}, + geTestCase{int(-150), true, false, ""}, + geTestCase{int(0), true, false, ""}, + geTestCase{int(17), true, false, ""}, + + geTestCase{int8(-127), true, false, ""}, + geTestCase{int8(0), true, false, ""}, + geTestCase{int8(17), true, false, ""}, + + geTestCase{int16(-(1 << 14)), false, false, ""}, + geTestCase{int16(-151), false, false, ""}, + geTestCase{int16(-150), true, false, ""}, + geTestCase{int16(0), true, false, ""}, + geTestCase{int16(17), true, false, ""}, + + geTestCase{int32(-(1 << 30)), false, false, ""}, + geTestCase{int32(-151), false, false, ""}, + geTestCase{int32(-150), true, false, ""}, + geTestCase{int32(0), true, false, ""}, + geTestCase{int32(17), true, false, ""}, + + geTestCase{int64(-(1 << 30)), false, false, ""}, + geTestCase{int64(-151), false, false, ""}, + geTestCase{int64(-150), true, false, ""}, + geTestCase{int64(0), true, false, ""}, + geTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + geTestCase{uint((1 << 32) - 151), true, false, ""}, + geTestCase{uint(0), true, false, ""}, + geTestCase{uint(17), true, false, ""}, + + geTestCase{uint8(0), true, false, ""}, + geTestCase{uint8(17), true, false, ""}, + geTestCase{uint8(253), true, false, ""}, + + geTestCase{uint16((1 << 16) - 151), true, false, ""}, + geTestCase{uint16(0), true, false, ""}, + geTestCase{uint16(17), true, false, ""}, + + geTestCase{uint32((1 << 32) - 151), true, false, ""}, + geTestCase{uint32(0), true, false, ""}, + geTestCase{uint32(17), true, false, ""}, + + geTestCase{uint64((1 << 64) - 151), true, false, ""}, + geTestCase{uint64(0), true, false, ""}, + geTestCase{uint64(17), true, false, ""}, + + geTestCase{uintptr((1 << 64) - 151), true, false, ""}, + geTestCase{uintptr(0), true, false, ""}, + geTestCase{uintptr(17), true, false, ""}, + + // Floating point. + geTestCase{float32(-(1 << 30)), false, false, ""}, + geTestCase{float32(-151), false, false, ""}, + geTestCase{float32(-150.1), false, false, ""}, + geTestCase{float32(-150), true, false, ""}, + geTestCase{float32(-149.9), true, false, ""}, + geTestCase{float32(0), true, false, ""}, + geTestCase{float32(17), true, false, ""}, + geTestCase{float32(160), true, false, ""}, + + geTestCase{float64(-(1 << 30)), false, false, ""}, + geTestCase{float64(-151), false, false, ""}, + geTestCase{float64(-150.1), false, false, ""}, + geTestCase{float64(-150), true, false, ""}, + geTestCase{float64(-149.9), true, false, ""}, + geTestCase{float64(0), true, false, ""}, + geTestCase{float64(17), true, false, ""}, + geTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) ZeroIntegerLiteral() { + matcher := GreaterOrEqual(0) + desc := matcher.Description() + expectedDesc := "greater than or equal to 0" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-(1 << 30), false, false, ""}, + geTestCase{-1, false, false, ""}, + geTestCase{0, true, false, ""}, + geTestCase{1, true, false, ""}, + geTestCase{17, true, false, ""}, + geTestCase{(1 << 30), true, false, ""}, + + geTestCase{int(-(1 << 30)), false, false, ""}, + geTestCase{int(-1), false, false, ""}, + geTestCase{int(0), true, false, ""}, + geTestCase{int(1), true, false, ""}, + geTestCase{int(17), true, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(0), true, false, ""}, + geTestCase{int8(1), true, false, ""}, + + geTestCase{int16(-(1 << 14)), false, false, ""}, + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(0), true, false, ""}, + geTestCase{int16(1), true, false, ""}, + geTestCase{int16(17), true, false, ""}, + + geTestCase{int32(-(1 << 30)), false, false, ""}, + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(0), true, false, ""}, + geTestCase{int32(1), true, false, ""}, + geTestCase{int32(17), true, false, ""}, + + geTestCase{int64(-(1 << 30)), false, false, ""}, + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(0), true, false, ""}, + geTestCase{int64(1), true, false, ""}, + geTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + geTestCase{uint((1 << 32) - 1), true, false, ""}, + geTestCase{uint(0), true, false, ""}, + geTestCase{uint(17), true, false, ""}, + + geTestCase{uint8(0), true, false, ""}, + geTestCase{uint8(17), true, false, ""}, + geTestCase{uint8(253), true, false, ""}, + + geTestCase{uint16((1 << 16) - 1), true, false, ""}, + geTestCase{uint16(0), true, false, ""}, + geTestCase{uint16(17), true, false, ""}, + + geTestCase{uint32((1 << 32) - 1), true, false, ""}, + geTestCase{uint32(0), true, false, ""}, + geTestCase{uint32(17), true, false, ""}, + + geTestCase{uint64((1 << 64) - 1), true, false, ""}, + geTestCase{uint64(0), true, false, ""}, + geTestCase{uint64(17), true, false, ""}, + + geTestCase{uintptr((1 << 64) - 1), true, false, ""}, + geTestCase{uintptr(0), true, false, ""}, + geTestCase{uintptr(17), true, false, ""}, + + // Floating point. + geTestCase{float32(-(1 << 30)), false, false, ""}, + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(-0.1), false, false, ""}, + geTestCase{float32(-0.0), true, false, ""}, + geTestCase{float32(0), true, false, ""}, + geTestCase{float32(0.1), true, false, ""}, + geTestCase{float32(17), true, false, ""}, + geTestCase{float32(160), true, false, ""}, + + geTestCase{float64(-(1 << 30)), false, false, ""}, + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(-0.1), false, false, ""}, + geTestCase{float64(-0), true, false, ""}, + geTestCase{float64(0), true, false, ""}, + geTestCase{float64(17), true, false, ""}, + geTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) PositiveIntegerLiteral() { + matcher := GreaterOrEqual(150) + desc := matcher.Description() + expectedDesc := "greater than or equal to 150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{149, false, false, ""}, + geTestCase{150, true, false, ""}, + geTestCase{151, true, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(149), false, false, ""}, + geTestCase{int(150), true, false, ""}, + geTestCase{int(151), true, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(0), false, false, ""}, + geTestCase{int8(17), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(149), false, false, ""}, + geTestCase{int16(150), true, false, ""}, + geTestCase{int16(151), true, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(149), false, false, ""}, + geTestCase{int32(150), true, false, ""}, + geTestCase{int32(151), true, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(149), false, false, ""}, + geTestCase{int64(150), true, false, ""}, + geTestCase{int64(151), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(149), false, false, ""}, + geTestCase{uint(150), true, false, ""}, + geTestCase{uint(151), true, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(127), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(149), false, false, ""}, + geTestCase{uint16(150), true, false, ""}, + geTestCase{uint16(151), true, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(149), false, false, ""}, + geTestCase{uint32(150), true, false, ""}, + geTestCase{uint32(151), true, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(149), false, false, ""}, + geTestCase{uint64(150), true, false, ""}, + geTestCase{uint64(151), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(149), false, false, ""}, + geTestCase{uintptr(150), true, false, ""}, + geTestCase{uintptr(151), true, false, ""}, + + // Floating point. + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(149), false, false, ""}, + geTestCase{float32(149.9), false, false, ""}, + geTestCase{float32(150), true, false, ""}, + geTestCase{float32(150.1), true, false, ""}, + geTestCase{float32(151), true, false, ""}, + + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(149), false, false, ""}, + geTestCase{float64(149.9), false, false, ""}, + geTestCase{float64(150), true, false, ""}, + geTestCase{float64(150.1), true, false, ""}, + geTestCase{float64(151), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Float literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterOrEqualTest) NegativeFloatLiteral() { + matcher := GreaterOrEqual(-150.1) + desc := matcher.Description() + expectedDesc := "greater than or equal to -150.1" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-(1 << 30), false, false, ""}, + geTestCase{-151, false, false, ""}, + geTestCase{-150, true, false, ""}, + geTestCase{0, true, false, ""}, + geTestCase{17, true, false, ""}, + + geTestCase{int(-(1 << 30)), false, false, ""}, + geTestCase{int(-151), false, false, ""}, + geTestCase{int(-150), true, false, ""}, + geTestCase{int(0), true, false, ""}, + geTestCase{int(17), true, false, ""}, + + geTestCase{int8(-127), true, false, ""}, + geTestCase{int8(0), true, false, ""}, + geTestCase{int8(17), true, false, ""}, + + geTestCase{int16(-(1 << 14)), false, false, ""}, + geTestCase{int16(-151), false, false, ""}, + geTestCase{int16(-150), true, false, ""}, + geTestCase{int16(0), true, false, ""}, + geTestCase{int16(17), true, false, ""}, + + geTestCase{int32(-(1 << 30)), false, false, ""}, + geTestCase{int32(-151), false, false, ""}, + geTestCase{int32(-150), true, false, ""}, + geTestCase{int32(0), true, false, ""}, + geTestCase{int32(17), true, false, ""}, + + geTestCase{int64(-(1 << 30)), false, false, ""}, + geTestCase{int64(-151), false, false, ""}, + geTestCase{int64(-150), true, false, ""}, + geTestCase{int64(0), true, false, ""}, + geTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + geTestCase{uint((1 << 32) - 151), true, false, ""}, + geTestCase{uint(0), true, false, ""}, + geTestCase{uint(17), true, false, ""}, + + geTestCase{uint8(0), true, false, ""}, + geTestCase{uint8(17), true, false, ""}, + geTestCase{uint8(253), true, false, ""}, + + geTestCase{uint16((1 << 16) - 151), true, false, ""}, + geTestCase{uint16(0), true, false, ""}, + geTestCase{uint16(17), true, false, ""}, + + geTestCase{uint32((1 << 32) - 151), true, false, ""}, + geTestCase{uint32(0), true, false, ""}, + geTestCase{uint32(17), true, false, ""}, + + geTestCase{uint64((1 << 64) - 151), true, false, ""}, + geTestCase{uint64(0), true, false, ""}, + geTestCase{uint64(17), true, false, ""}, + + geTestCase{uintptr((1 << 64) - 151), true, false, ""}, + geTestCase{uintptr(0), true, false, ""}, + geTestCase{uintptr(17), true, false, ""}, + + // Floating point. + geTestCase{float32(-(1 << 30)), false, false, ""}, + geTestCase{float32(-151), false, false, ""}, + geTestCase{float32(-150.2), false, false, ""}, + geTestCase{float32(-150.1), true, false, ""}, + geTestCase{float32(-150), true, false, ""}, + geTestCase{float32(0), true, false, ""}, + geTestCase{float32(17), true, false, ""}, + geTestCase{float32(160), true, false, ""}, + + geTestCase{float64(-(1 << 30)), false, false, ""}, + geTestCase{float64(-151), false, false, ""}, + geTestCase{float64(-150.2), false, false, ""}, + geTestCase{float64(-150.1), true, false, ""}, + geTestCase{float64(-150), true, false, ""}, + geTestCase{float64(0), true, false, ""}, + geTestCase{float64(17), true, false, ""}, + geTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) PositiveFloatLiteral() { + matcher := GreaterOrEqual(149.9) + desc := matcher.Description() + expectedDesc := "greater than or equal to 149.9" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{149, false, false, ""}, + geTestCase{150, true, false, ""}, + geTestCase{151, true, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(149), false, false, ""}, + geTestCase{int(150), true, false, ""}, + geTestCase{int(151), true, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(0), false, false, ""}, + geTestCase{int8(17), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(149), false, false, ""}, + geTestCase{int16(150), true, false, ""}, + geTestCase{int16(151), true, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(149), false, false, ""}, + geTestCase{int32(150), true, false, ""}, + geTestCase{int32(151), true, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(149), false, false, ""}, + geTestCase{int64(150), true, false, ""}, + geTestCase{int64(151), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(149), false, false, ""}, + geTestCase{uint(150), true, false, ""}, + geTestCase{uint(151), true, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(127), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(149), false, false, ""}, + geTestCase{uint16(150), true, false, ""}, + geTestCase{uint16(151), true, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(149), false, false, ""}, + geTestCase{uint32(150), true, false, ""}, + geTestCase{uint32(151), true, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(149), false, false, ""}, + geTestCase{uint64(150), true, false, ""}, + geTestCase{uint64(151), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(149), false, false, ""}, + geTestCase{uintptr(150), true, false, ""}, + geTestCase{uintptr(151), true, false, ""}, + + // Floating point. + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(149), false, false, ""}, + geTestCase{float32(149.8), false, false, ""}, + geTestCase{float32(149.9), true, false, ""}, + geTestCase{float32(150), true, false, ""}, + geTestCase{float32(151), true, false, ""}, + + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(149), false, false, ""}, + geTestCase{float64(149.8), false, false, ""}, + geTestCase{float64(149.9), true, false, ""}, + geTestCase{float64(150), true, false, ""}, + geTestCase{float64(151), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Subtle cases +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterOrEqualTest) Int64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterOrEqual(int64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{kTwoTo25 + 0, false, false, ""}, + geTestCase{kTwoTo25 + 1, true, false, ""}, + geTestCase{kTwoTo25 + 2, true, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(kTwoTo25 + 0), false, false, ""}, + geTestCase{int(kTwoTo25 + 1), true, false, ""}, + geTestCase{int(kTwoTo25 + 2), true, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(0), false, false, ""}, + geTestCase{int16(32767), false, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(kTwoTo25 + 0), false, false, ""}, + geTestCase{int32(kTwoTo25 + 1), true, false, ""}, + geTestCase{int32(kTwoTo25 + 2), true, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo25 + 0), false, false, ""}, + geTestCase{int64(kTwoTo25 + 1), true, false, ""}, + geTestCase{int64(kTwoTo25 + 2), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(255), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(65535), false, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint32(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint32(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(kTwoTo25 + 0), false, false, ""}, + geTestCase{uintptr(kTwoTo25 + 1), true, false, ""}, + geTestCase{uintptr(kTwoTo25 + 2), true, false, ""}, + + // Floating point. + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(kTwoTo25 - 2), false, false, ""}, + geTestCase{float32(kTwoTo25 - 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 0), true, false, ""}, + geTestCase{float32(kTwoTo25 + 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 2), true, false, ""}, + geTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo25 - 2), false, false, ""}, + geTestCase{float64(kTwoTo25 - 1), false, false, ""}, + geTestCase{float64(kTwoTo25 + 0), false, false, ""}, + geTestCase{float64(kTwoTo25 + 1), true, false, ""}, + geTestCase{float64(kTwoTo25 + 2), true, false, ""}, + geTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) Int64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterOrEqual(int64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{1 << 30, false, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(math.MaxInt32), false, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(0), false, false, ""}, + geTestCase{int16(32767), false, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(math.MaxInt32), false, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo54 - 1), false, false, ""}, + geTestCase{int64(kTwoTo54 + 0), false, false, ""}, + geTestCase{int64(kTwoTo54 + 1), true, false, ""}, + geTestCase{int64(kTwoTo54 + 2), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(math.MaxUint32), false, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(255), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(65535), false, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(math.MaxUint32), false, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + geTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(kTwoTo54 - 1), false, false, ""}, + geTestCase{uintptr(kTwoTo54 + 0), false, false, ""}, + geTestCase{uintptr(kTwoTo54 + 1), true, false, ""}, + geTestCase{uintptr(kTwoTo54 + 2), true, false, ""}, + + // Floating point. + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo54 - 2), false, false, ""}, + geTestCase{float64(kTwoTo54 - 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 0), true, false, ""}, + geTestCase{float64(kTwoTo54 + 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 2), true, false, ""}, + geTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) Uint64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterOrEqual(uint64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{kTwoTo25 + 0, false, false, ""}, + geTestCase{kTwoTo25 + 1, true, false, ""}, + geTestCase{kTwoTo25 + 2, true, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(kTwoTo25 + 0), false, false, ""}, + geTestCase{int(kTwoTo25 + 1), true, false, ""}, + geTestCase{int(kTwoTo25 + 2), true, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(0), false, false, ""}, + geTestCase{int16(32767), false, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(kTwoTo25 + 0), false, false, ""}, + geTestCase{int32(kTwoTo25 + 1), true, false, ""}, + geTestCase{int32(kTwoTo25 + 2), true, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo25 + 0), false, false, ""}, + geTestCase{int64(kTwoTo25 + 1), true, false, ""}, + geTestCase{int64(kTwoTo25 + 2), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(255), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(65535), false, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint32(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint32(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(kTwoTo25 + 0), false, false, ""}, + geTestCase{uintptr(kTwoTo25 + 1), true, false, ""}, + geTestCase{uintptr(kTwoTo25 + 2), true, false, ""}, + + // Floating point. + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(kTwoTo25 - 2), false, false, ""}, + geTestCase{float32(kTwoTo25 - 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 0), true, false, ""}, + geTestCase{float32(kTwoTo25 + 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 2), true, false, ""}, + geTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo25 - 2), false, false, ""}, + geTestCase{float64(kTwoTo25 - 1), false, false, ""}, + geTestCase{float64(kTwoTo25 + 0), false, false, ""}, + geTestCase{float64(kTwoTo25 + 1), true, false, ""}, + geTestCase{float64(kTwoTo25 + 2), true, false, ""}, + geTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) Uint64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterOrEqual(uint64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{-1, false, false, ""}, + geTestCase{1 << 30, false, false, ""}, + + geTestCase{int(-1), false, false, ""}, + geTestCase{int(math.MaxInt32), false, false, ""}, + + geTestCase{int8(-1), false, false, ""}, + geTestCase{int8(127), false, false, ""}, + + geTestCase{int16(-1), false, false, ""}, + geTestCase{int16(0), false, false, ""}, + geTestCase{int16(32767), false, false, ""}, + + geTestCase{int32(-1), false, false, ""}, + geTestCase{int32(math.MaxInt32), false, false, ""}, + + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo54 - 1), false, false, ""}, + geTestCase{int64(kTwoTo54 + 0), false, false, ""}, + geTestCase{int64(kTwoTo54 + 1), true, false, ""}, + geTestCase{int64(kTwoTo54 + 2), true, false, ""}, + + // Unsigned integers. + geTestCase{uint(0), false, false, ""}, + geTestCase{uint(math.MaxUint32), false, false, ""}, + + geTestCase{uint8(0), false, false, ""}, + geTestCase{uint8(255), false, false, ""}, + + geTestCase{uint16(0), false, false, ""}, + geTestCase{uint16(65535), false, false, ""}, + + geTestCase{uint32(0), false, false, ""}, + geTestCase{uint32(math.MaxUint32), false, false, ""}, + + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + geTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + + geTestCase{uintptr(0), false, false, ""}, + geTestCase{uintptr(kTwoTo54 - 1), false, false, ""}, + geTestCase{uintptr(kTwoTo54 + 0), false, false, ""}, + geTestCase{uintptr(kTwoTo54 + 1), true, false, ""}, + geTestCase{uintptr(kTwoTo54 + 2), true, false, ""}, + + // Floating point. + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo54 - 2), false, false, ""}, + geTestCase{float64(kTwoTo54 - 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 0), true, false, ""}, + geTestCase{float64(kTwoTo54 + 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 2), true, false, ""}, + geTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) Float32AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterOrEqual(float32(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 3.3554432e+07" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo25 - 2), false, false, ""}, + geTestCase{int64(kTwoTo25 - 1), true, false, ""}, + geTestCase{int64(kTwoTo25 + 0), true, false, ""}, + geTestCase{int64(kTwoTo25 + 1), true, false, ""}, + geTestCase{int64(kTwoTo25 + 2), true, false, ""}, + geTestCase{int64(kTwoTo25 + 3), true, false, ""}, + + // Unsigned integers. + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo25 - 2), false, false, ""}, + geTestCase{uint64(kTwoTo25 - 1), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + geTestCase{uint64(kTwoTo25 + 3), true, false, ""}, + + // Floating point. + geTestCase{float32(-1), false, false, ""}, + geTestCase{float32(kTwoTo25 - 2), false, false, ""}, + geTestCase{float32(kTwoTo25 - 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 0), true, false, ""}, + geTestCase{float32(kTwoTo25 + 1), true, false, ""}, + geTestCase{float32(kTwoTo25 + 2), true, false, ""}, + geTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo25 - 2), false, false, ""}, + geTestCase{float64(kTwoTo25 - 1), true, false, ""}, + geTestCase{float64(kTwoTo25 + 0), true, false, ""}, + geTestCase{float64(kTwoTo25 + 1), true, false, ""}, + geTestCase{float64(kTwoTo25 + 2), true, false, ""}, + geTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) Float64AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterOrEqual(float64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than or equal to 1.8014398509481984e+16" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + // Signed integers. + geTestCase{int64(-1), false, false, ""}, + geTestCase{int64(kTwoTo54 - 2), false, false, ""}, + geTestCase{int64(kTwoTo54 - 1), true, false, ""}, + geTestCase{int64(kTwoTo54 + 0), true, false, ""}, + geTestCase{int64(kTwoTo54 + 1), true, false, ""}, + geTestCase{int64(kTwoTo54 + 2), true, false, ""}, + geTestCase{int64(kTwoTo54 + 3), true, false, ""}, + + // Unsigned integers. + geTestCase{uint64(0), false, false, ""}, + geTestCase{uint64(kTwoTo54 - 2), false, false, ""}, + geTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + geTestCase{uint64(kTwoTo54 + 3), true, false, ""}, + + // Floating point. + geTestCase{float64(-1), false, false, ""}, + geTestCase{float64(kTwoTo54 - 2), false, false, ""}, + geTestCase{float64(kTwoTo54 - 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 0), true, false, ""}, + geTestCase{float64(kTwoTo54 + 1), true, false, ""}, + geTestCase{float64(kTwoTo54 + 2), true, false, ""}, + geTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// String literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterOrEqualTest) EmptyString() { + matcher := GreaterOrEqual("") + desc := matcher.Description() + expectedDesc := "greater than or equal to \"\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + geTestCase{"", true, false, ""}, + geTestCase{"\x00", true, false, ""}, + geTestCase{"a", true, false, ""}, + geTestCase{"foo", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) SingleNullByte() { + matcher := GreaterOrEqual("\x00") + desc := matcher.Description() + expectedDesc := "greater than or equal to \"\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + geTestCase{"", false, false, ""}, + geTestCase{"\x00", true, false, ""}, + geTestCase{"a", true, false, ""}, + geTestCase{"foo", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterOrEqualTest) LongerString() { + matcher := GreaterOrEqual("foo\x00") + desc := matcher.Description() + expectedDesc := "greater than or equal to \"foo\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []geTestCase{ + geTestCase{"", false, false, ""}, + geTestCase{"\x00", false, false, ""}, + geTestCase{"bar", false, false, ""}, + geTestCase{"foo", false, false, ""}, + geTestCase{"foo\x00", true, false, ""}, + geTestCase{"fooa", true, false, ""}, + geTestCase{"qux", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than.go new file mode 100644 index 0000000000..3eef32178f --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than.go @@ -0,0 +1,39 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "fmt" + "reflect" +) + +// GreaterThan returns a matcher that matches integer, floating point, or +// strings values v such that v > x. Comparison is not defined between numeric +// and string types, but is defined between all integer and floating point +// types. +// +// x must itself be an integer, floating point, or string type; otherwise, +// GreaterThan will panic. +func GreaterThan(x interface{}) Matcher { + desc := fmt.Sprintf("greater than %v", x) + + // Special case: make it clear that strings are strings. + if reflect.TypeOf(x).Kind() == reflect.String { + desc = fmt.Sprintf("greater than \"%s\"", x) + } + + return transformDescription(Not(LessOrEqual(x)), desc) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than_test.go new file mode 100644 index 0000000000..07265c1426 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/greater_than_test.go @@ -0,0 +1,1077 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "math" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type GreaterThanTest struct { +} + +func init() { RegisterTestSuite(&GreaterThanTest{}) } + +type gtTestCase struct { + candidate interface{} + expectedResult bool + shouldBeFatal bool + expectedError string +} + +func (t *GreaterThanTest) checkTestCases(matcher Matcher, cases []gtTestCase) { + for i, c := range cases { + err := matcher.Matches(c.candidate) + + ExpectThat( + (err == nil), + Equals(c.expectedResult), + "Case %d (candidate %v)", + i, + c.candidate) + + if err == nil { + continue + } + + _, isFatal := err.(*FatalError) + ExpectEq( + c.shouldBeFatal, + isFatal, + "Case %d (candidate %v)", + i, + c.candidate) + + ExpectThat( + err, + Error(Equals(c.expectedError)), + "Case %d (candidate %v)", + i, + c.candidate) + } +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterThanTest) IntegerCandidateBadTypes() { + matcher := GreaterThan(int(-150)) + + cases := []gtTestCase{ + gtTestCase{true, false, true, "which is not comparable"}, + gtTestCase{complex64(-151), false, true, "which is not comparable"}, + gtTestCase{complex128(-151), false, true, "which is not comparable"}, + gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, + gtTestCase{make(chan int), false, true, "which is not comparable"}, + gtTestCase{func() {}, false, true, "which is not comparable"}, + gtTestCase{map[int]int{}, false, true, "which is not comparable"}, + gtTestCase{>TestCase{}, false, true, "which is not comparable"}, + gtTestCase{make([]int, 0), false, true, "which is not comparable"}, + gtTestCase{"-151", false, true, "which is not comparable"}, + gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) FloatCandidateBadTypes() { + matcher := GreaterThan(float32(-150)) + + cases := []gtTestCase{ + gtTestCase{true, false, true, "which is not comparable"}, + gtTestCase{complex64(-151), false, true, "which is not comparable"}, + gtTestCase{complex128(-151), false, true, "which is not comparable"}, + gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, + gtTestCase{make(chan int), false, true, "which is not comparable"}, + gtTestCase{func() {}, false, true, "which is not comparable"}, + gtTestCase{map[int]int{}, false, true, "which is not comparable"}, + gtTestCase{>TestCase{}, false, true, "which is not comparable"}, + gtTestCase{make([]int, 0), false, true, "which is not comparable"}, + gtTestCase{"-151", false, true, "which is not comparable"}, + gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) StringCandidateBadTypes() { + matcher := GreaterThan("17") + + cases := []gtTestCase{ + gtTestCase{true, false, true, "which is not comparable"}, + gtTestCase{int(0), false, true, "which is not comparable"}, + gtTestCase{int8(0), false, true, "which is not comparable"}, + gtTestCase{int16(0), false, true, "which is not comparable"}, + gtTestCase{int32(0), false, true, "which is not comparable"}, + gtTestCase{int64(0), false, true, "which is not comparable"}, + gtTestCase{uint(0), false, true, "which is not comparable"}, + gtTestCase{uint8(0), false, true, "which is not comparable"}, + gtTestCase{uint16(0), false, true, "which is not comparable"}, + gtTestCase{uint32(0), false, true, "which is not comparable"}, + gtTestCase{uint64(0), false, true, "which is not comparable"}, + gtTestCase{float32(0), false, true, "which is not comparable"}, + gtTestCase{float64(0), false, true, "which is not comparable"}, + gtTestCase{complex64(-151), false, true, "which is not comparable"}, + gtTestCase{complex128(-151), false, true, "which is not comparable"}, + gtTestCase{[...]int{-151}, false, true, "which is not comparable"}, + gtTestCase{make(chan int), false, true, "which is not comparable"}, + gtTestCase{func() {}, false, true, "which is not comparable"}, + gtTestCase{map[int]int{}, false, true, "which is not comparable"}, + gtTestCase{>TestCase{}, false, true, "which is not comparable"}, + gtTestCase{make([]int, 0), false, true, "which is not comparable"}, + gtTestCase{gtTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) BadArgument() { + panicked := false + + defer func() { + ExpectThat(panicked, Equals(true)) + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + GreaterThan(complex128(0)) +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterThanTest) NegativeIntegerLiteral() { + matcher := GreaterThan(-150) + desc := matcher.Description() + expectedDesc := "greater than -150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-(1 << 30), false, false, ""}, + gtTestCase{-151, false, false, ""}, + gtTestCase{-150, false, false, ""}, + gtTestCase{-149, true, false, ""}, + gtTestCase{0, true, false, ""}, + gtTestCase{17, true, false, ""}, + + gtTestCase{int(-(1 << 30)), false, false, ""}, + gtTestCase{int(-151), false, false, ""}, + gtTestCase{int(-150), false, false, ""}, + gtTestCase{int(-149), true, false, ""}, + gtTestCase{int(0), true, false, ""}, + gtTestCase{int(17), true, false, ""}, + + gtTestCase{int8(-127), true, false, ""}, + gtTestCase{int8(0), true, false, ""}, + gtTestCase{int8(17), true, false, ""}, + + gtTestCase{int16(-(1 << 14)), false, false, ""}, + gtTestCase{int16(-151), false, false, ""}, + gtTestCase{int16(-150), false, false, ""}, + gtTestCase{int16(-149), true, false, ""}, + gtTestCase{int16(0), true, false, ""}, + gtTestCase{int16(17), true, false, ""}, + + gtTestCase{int32(-(1 << 30)), false, false, ""}, + gtTestCase{int32(-151), false, false, ""}, + gtTestCase{int32(-150), false, false, ""}, + gtTestCase{int32(-149), true, false, ""}, + gtTestCase{int32(0), true, false, ""}, + gtTestCase{int32(17), true, false, ""}, + + gtTestCase{int64(-(1 << 30)), false, false, ""}, + gtTestCase{int64(-151), false, false, ""}, + gtTestCase{int64(-150), false, false, ""}, + gtTestCase{int64(-149), true, false, ""}, + gtTestCase{int64(0), true, false, ""}, + gtTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint((1 << 32) - 151), true, false, ""}, + gtTestCase{uint(0), true, false, ""}, + gtTestCase{uint(17), true, false, ""}, + + gtTestCase{uint8(0), true, false, ""}, + gtTestCase{uint8(17), true, false, ""}, + gtTestCase{uint8(253), true, false, ""}, + + gtTestCase{uint16((1 << 16) - 151), true, false, ""}, + gtTestCase{uint16(0), true, false, ""}, + gtTestCase{uint16(17), true, false, ""}, + + gtTestCase{uint32((1 << 32) - 151), true, false, ""}, + gtTestCase{uint32(0), true, false, ""}, + gtTestCase{uint32(17), true, false, ""}, + + gtTestCase{uint64((1 << 64) - 151), true, false, ""}, + gtTestCase{uint64(0), true, false, ""}, + gtTestCase{uint64(17), true, false, ""}, + + // Floating point. + gtTestCase{float32(-(1 << 30)), false, false, ""}, + gtTestCase{float32(-151), false, false, ""}, + gtTestCase{float32(-150.1), false, false, ""}, + gtTestCase{float32(-150), false, false, ""}, + gtTestCase{float32(-149.9), true, false, ""}, + gtTestCase{float32(0), true, false, ""}, + gtTestCase{float32(17), true, false, ""}, + gtTestCase{float32(160), true, false, ""}, + + gtTestCase{float64(-(1 << 30)), false, false, ""}, + gtTestCase{float64(-151), false, false, ""}, + gtTestCase{float64(-150.1), false, false, ""}, + gtTestCase{float64(-150), false, false, ""}, + gtTestCase{float64(-149.9), true, false, ""}, + gtTestCase{float64(0), true, false, ""}, + gtTestCase{float64(17), true, false, ""}, + gtTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) ZeroIntegerLiteral() { + matcher := GreaterThan(0) + desc := matcher.Description() + expectedDesc := "greater than 0" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-(1 << 30), false, false, ""}, + gtTestCase{-1, false, false, ""}, + gtTestCase{0, false, false, ""}, + gtTestCase{1, true, false, ""}, + gtTestCase{17, true, false, ""}, + gtTestCase{(1 << 30), true, false, ""}, + + gtTestCase{int(-(1 << 30)), false, false, ""}, + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(0), false, false, ""}, + gtTestCase{int(1), true, false, ""}, + gtTestCase{int(17), true, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(0), false, false, ""}, + gtTestCase{int8(1), true, false, ""}, + + gtTestCase{int16(-(1 << 14)), false, false, ""}, + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(0), false, false, ""}, + gtTestCase{int16(1), true, false, ""}, + gtTestCase{int16(17), true, false, ""}, + + gtTestCase{int32(-(1 << 30)), false, false, ""}, + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(0), false, false, ""}, + gtTestCase{int32(1), true, false, ""}, + gtTestCase{int32(17), true, false, ""}, + + gtTestCase{int64(-(1 << 30)), false, false, ""}, + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(0), false, false, ""}, + gtTestCase{int64(1), true, false, ""}, + gtTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint((1 << 32) - 1), true, false, ""}, + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(1), true, false, ""}, + gtTestCase{uint(17), true, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(1), true, false, ""}, + gtTestCase{uint8(17), true, false, ""}, + gtTestCase{uint8(253), true, false, ""}, + + gtTestCase{uint16((1 << 16) - 1), true, false, ""}, + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(1), true, false, ""}, + gtTestCase{uint16(17), true, false, ""}, + + gtTestCase{uint32((1 << 32) - 1), true, false, ""}, + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(1), true, false, ""}, + gtTestCase{uint32(17), true, false, ""}, + + gtTestCase{uint64((1 << 64) - 1), true, false, ""}, + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(1), true, false, ""}, + gtTestCase{uint64(17), true, false, ""}, + + // Floating point. + gtTestCase{float32(-(1 << 30)), false, false, ""}, + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(-0.1), false, false, ""}, + gtTestCase{float32(-0.0), false, false, ""}, + gtTestCase{float32(0), false, false, ""}, + gtTestCase{float32(0.1), true, false, ""}, + gtTestCase{float32(17), true, false, ""}, + gtTestCase{float32(160), true, false, ""}, + + gtTestCase{float64(-(1 << 30)), false, false, ""}, + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(-0.1), false, false, ""}, + gtTestCase{float64(-0), false, false, ""}, + gtTestCase{float64(0), false, false, ""}, + gtTestCase{float64(0.1), true, false, ""}, + gtTestCase{float64(17), true, false, ""}, + gtTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) PositiveIntegerLiteral() { + matcher := GreaterThan(150) + desc := matcher.Description() + expectedDesc := "greater than 150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{149, false, false, ""}, + gtTestCase{150, false, false, ""}, + gtTestCase{151, true, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(149), false, false, ""}, + gtTestCase{int(150), false, false, ""}, + gtTestCase{int(151), true, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(0), false, false, ""}, + gtTestCase{int8(17), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(149), false, false, ""}, + gtTestCase{int16(150), false, false, ""}, + gtTestCase{int16(151), true, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(149), false, false, ""}, + gtTestCase{int32(150), false, false, ""}, + gtTestCase{int32(151), true, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(149), false, false, ""}, + gtTestCase{int64(150), false, false, ""}, + gtTestCase{int64(151), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(149), false, false, ""}, + gtTestCase{uint(150), false, false, ""}, + gtTestCase{uint(151), true, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(127), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(149), false, false, ""}, + gtTestCase{uint16(150), false, false, ""}, + gtTestCase{uint16(151), true, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(149), false, false, ""}, + gtTestCase{uint32(150), false, false, ""}, + gtTestCase{uint32(151), true, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(149), false, false, ""}, + gtTestCase{uint64(150), false, false, ""}, + gtTestCase{uint64(151), true, false, ""}, + + // Floating point. + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(149), false, false, ""}, + gtTestCase{float32(149.9), false, false, ""}, + gtTestCase{float32(150), false, false, ""}, + gtTestCase{float32(150.1), true, false, ""}, + gtTestCase{float32(151), true, false, ""}, + + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(149), false, false, ""}, + gtTestCase{float64(149.9), false, false, ""}, + gtTestCase{float64(150), false, false, ""}, + gtTestCase{float64(150.1), true, false, ""}, + gtTestCase{float64(151), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Float literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterThanTest) NegativeFloatLiteral() { + matcher := GreaterThan(-150.1) + desc := matcher.Description() + expectedDesc := "greater than -150.1" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-(1 << 30), false, false, ""}, + gtTestCase{-151, false, false, ""}, + gtTestCase{-150.1, false, false, ""}, + gtTestCase{-150, true, false, ""}, + gtTestCase{-149, true, false, ""}, + gtTestCase{0, true, false, ""}, + gtTestCase{17, true, false, ""}, + + gtTestCase{int(-(1 << 30)), false, false, ""}, + gtTestCase{int(-151), false, false, ""}, + gtTestCase{int(-150), true, false, ""}, + gtTestCase{int(-149), true, false, ""}, + gtTestCase{int(0), true, false, ""}, + gtTestCase{int(17), true, false, ""}, + + gtTestCase{int8(-127), true, false, ""}, + gtTestCase{int8(0), true, false, ""}, + gtTestCase{int8(17), true, false, ""}, + + gtTestCase{int16(-(1 << 14)), false, false, ""}, + gtTestCase{int16(-151), false, false, ""}, + gtTestCase{int16(-150), true, false, ""}, + gtTestCase{int16(-149), true, false, ""}, + gtTestCase{int16(0), true, false, ""}, + gtTestCase{int16(17), true, false, ""}, + + gtTestCase{int32(-(1 << 30)), false, false, ""}, + gtTestCase{int32(-151), false, false, ""}, + gtTestCase{int32(-150), true, false, ""}, + gtTestCase{int32(-149), true, false, ""}, + gtTestCase{int32(0), true, false, ""}, + gtTestCase{int32(17), true, false, ""}, + + gtTestCase{int64(-(1 << 30)), false, false, ""}, + gtTestCase{int64(-151), false, false, ""}, + gtTestCase{int64(-150), true, false, ""}, + gtTestCase{int64(-149), true, false, ""}, + gtTestCase{int64(0), true, false, ""}, + gtTestCase{int64(17), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint((1 << 32) - 151), true, false, ""}, + gtTestCase{uint(0), true, false, ""}, + gtTestCase{uint(17), true, false, ""}, + + gtTestCase{uint8(0), true, false, ""}, + gtTestCase{uint8(17), true, false, ""}, + gtTestCase{uint8(253), true, false, ""}, + + gtTestCase{uint16((1 << 16) - 151), true, false, ""}, + gtTestCase{uint16(0), true, false, ""}, + gtTestCase{uint16(17), true, false, ""}, + + gtTestCase{uint32((1 << 32) - 151), true, false, ""}, + gtTestCase{uint32(0), true, false, ""}, + gtTestCase{uint32(17), true, false, ""}, + + gtTestCase{uint64((1 << 64) - 151), true, false, ""}, + gtTestCase{uint64(0), true, false, ""}, + gtTestCase{uint64(17), true, false, ""}, + + // Floating point. + gtTestCase{float32(-(1 << 30)), false, false, ""}, + gtTestCase{float32(-151), false, false, ""}, + gtTestCase{float32(-150.2), false, false, ""}, + gtTestCase{float32(-150.1), false, false, ""}, + gtTestCase{float32(-150), true, false, ""}, + gtTestCase{float32(0), true, false, ""}, + gtTestCase{float32(17), true, false, ""}, + gtTestCase{float32(160), true, false, ""}, + + gtTestCase{float64(-(1 << 30)), false, false, ""}, + gtTestCase{float64(-151), false, false, ""}, + gtTestCase{float64(-150.2), false, false, ""}, + gtTestCase{float64(-150.1), false, false, ""}, + gtTestCase{float64(-150), true, false, ""}, + gtTestCase{float64(0), true, false, ""}, + gtTestCase{float64(17), true, false, ""}, + gtTestCase{float64(160), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) PositiveFloatLiteral() { + matcher := GreaterThan(149.9) + desc := matcher.Description() + expectedDesc := "greater than 149.9" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{149, false, false, ""}, + gtTestCase{149.9, false, false, ""}, + gtTestCase{150, true, false, ""}, + gtTestCase{151, true, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(149), false, false, ""}, + gtTestCase{int(150), true, false, ""}, + gtTestCase{int(151), true, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(0), false, false, ""}, + gtTestCase{int8(17), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(149), false, false, ""}, + gtTestCase{int16(150), true, false, ""}, + gtTestCase{int16(151), true, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(149), false, false, ""}, + gtTestCase{int32(150), true, false, ""}, + gtTestCase{int32(151), true, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(149), false, false, ""}, + gtTestCase{int64(150), true, false, ""}, + gtTestCase{int64(151), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(149), false, false, ""}, + gtTestCase{uint(150), true, false, ""}, + gtTestCase{uint(151), true, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(127), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(149), false, false, ""}, + gtTestCase{uint16(150), true, false, ""}, + gtTestCase{uint16(151), true, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(149), false, false, ""}, + gtTestCase{uint32(150), true, false, ""}, + gtTestCase{uint32(151), true, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(149), false, false, ""}, + gtTestCase{uint64(150), true, false, ""}, + gtTestCase{uint64(151), true, false, ""}, + + // Floating point. + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(149), false, false, ""}, + gtTestCase{float32(149.8), false, false, ""}, + gtTestCase{float32(149.9), false, false, ""}, + gtTestCase{float32(150), true, false, ""}, + gtTestCase{float32(151), true, false, ""}, + + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(149), false, false, ""}, + gtTestCase{float64(149.8), false, false, ""}, + gtTestCase{float64(149.9), false, false, ""}, + gtTestCase{float64(150), true, false, ""}, + gtTestCase{float64(151), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Subtle cases +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterThanTest) Int64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterThan(int64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{kTwoTo25 + 0, false, false, ""}, + gtTestCase{kTwoTo25 + 1, false, false, ""}, + gtTestCase{kTwoTo25 + 2, true, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(0), false, false, ""}, + gtTestCase{int16(32767), false, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 2), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(255), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(65535), false, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + + // Floating point. + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 2), true, false, ""}, + gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) Int64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterThan(int64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{1 << 30, false, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(math.MaxInt32), false, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(0), false, false, ""}, + gtTestCase{int16(32767), false, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(math.MaxInt32), false, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 2), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(math.MaxUint32), false, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(255), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(65535), false, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(math.MaxUint32), false, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + + // Floating point. + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) Uint64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterThan(uint64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{kTwoTo25 + 0, false, false, ""}, + gtTestCase{kTwoTo25 + 1, false, false, ""}, + gtTestCase{kTwoTo25 + 2, true, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(0), false, false, ""}, + gtTestCase{int16(32767), false, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int32(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 2), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(255), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(65535), false, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint32(kTwoTo25 + 2), true, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + + // Floating point. + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 2), true, false, ""}, + gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) Uint64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterThan(uint64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{-1, false, false, ""}, + gtTestCase{1 << 30, false, false, ""}, + + gtTestCase{int(-1), false, false, ""}, + gtTestCase{int(math.MaxInt32), false, false, ""}, + + gtTestCase{int8(-1), false, false, ""}, + gtTestCase{int8(127), false, false, ""}, + + gtTestCase{int16(-1), false, false, ""}, + gtTestCase{int16(0), false, false, ""}, + gtTestCase{int16(32767), false, false, ""}, + + gtTestCase{int32(-1), false, false, ""}, + gtTestCase{int32(math.MaxInt32), false, false, ""}, + + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 2), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint(0), false, false, ""}, + gtTestCase{uint(math.MaxUint32), false, false, ""}, + + gtTestCase{uint8(0), false, false, ""}, + gtTestCase{uint8(255), false, false, ""}, + + gtTestCase{uint16(0), false, false, ""}, + gtTestCase{uint16(65535), false, false, ""}, + + gtTestCase{uint32(0), false, false, ""}, + gtTestCase{uint32(math.MaxUint32), false, false, ""}, + + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + + // Floating point. + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) Float32AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := GreaterThan(float32(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 3.3554432e+07" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo25 - 2), false, false, ""}, + gtTestCase{int64(kTwoTo25 - 1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 2), false, false, ""}, + gtTestCase{int64(kTwoTo25 + 3), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 - 2), false, false, ""}, + gtTestCase{uint64(kTwoTo25 - 1), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + gtTestCase{uint64(kTwoTo25 + 3), true, false, ""}, + + // Floating point. + gtTestCase{float32(-1), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 2), false, false, ""}, + gtTestCase{float32(kTwoTo25 + 3), true, false, ""}, + + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo25 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 2), false, false, ""}, + gtTestCase{float64(kTwoTo25 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) Float64AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := GreaterThan(float64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "greater than 1.8014398509481984e+16" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + // Signed integers. + gtTestCase{int64(-1), false, false, ""}, + gtTestCase{int64(kTwoTo54 - 2), false, false, ""}, + gtTestCase{int64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 2), false, false, ""}, + gtTestCase{int64(kTwoTo54 + 3), true, false, ""}, + + // Unsigned integers. + gtTestCase{uint64(0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 - 2), false, false, ""}, + gtTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + gtTestCase{uint64(kTwoTo54 + 3), true, false, ""}, + + // Floating point. + gtTestCase{float64(-1), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 - 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 0), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 1), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 2), false, false, ""}, + gtTestCase{float64(kTwoTo54 + 3), true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// String literals +//////////////////////////////////////////////////////////////////////// + +func (t *GreaterThanTest) EmptyString() { + matcher := GreaterThan("") + desc := matcher.Description() + expectedDesc := "greater than \"\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + gtTestCase{"", false, false, ""}, + gtTestCase{"\x00", true, false, ""}, + gtTestCase{"a", true, false, ""}, + gtTestCase{"foo", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) SingleNullByte() { + matcher := GreaterThan("\x00") + desc := matcher.Description() + expectedDesc := "greater than \"\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + gtTestCase{"", false, false, ""}, + gtTestCase{"\x00", false, false, ""}, + gtTestCase{"\x00\x00", true, false, ""}, + gtTestCase{"a", true, false, ""}, + gtTestCase{"foo", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *GreaterThanTest) LongerString() { + matcher := GreaterThan("foo\x00") + desc := matcher.Description() + expectedDesc := "greater than \"foo\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []gtTestCase{ + gtTestCase{"", false, false, ""}, + gtTestCase{"\x00", false, false, ""}, + gtTestCase{"bar", false, false, ""}, + gtTestCase{"foo", false, false, ""}, + gtTestCase{"foo\x00", false, false, ""}, + gtTestCase{"foo\x00\x00", true, false, ""}, + gtTestCase{"fooa", true, false, ""}, + gtTestCase{"qux", true, false, ""}, + } + + t.checkTestCases(matcher, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as.go new file mode 100644 index 0000000000..3b286f7321 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as.go @@ -0,0 +1,37 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "fmt" + "reflect" +) + +// HasSameTypeAs returns a matcher that matches values with exactly the same +// type as the supplied prototype. +func HasSameTypeAs(p interface{}) Matcher { + expected := reflect.TypeOf(p) + pred := func(c interface{}) error { + actual := reflect.TypeOf(c) + if actual != expected { + return fmt.Errorf("which has type %v", actual) + } + + return nil + } + + return NewMatcher(pred, fmt.Sprintf("has type %v", expected)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as_test.go new file mode 100644 index 0000000000..3f55b8621b --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_same_type_as_test.go @@ -0,0 +1,181 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "io" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +func TestHasSameTypeAs(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////////////////// +// Boilerplate +//////////////////////////////////////////////////////////////////////// + +type HasSameTypeAsTest struct { +} + +func init() { RegisterTestSuite(&HasSameTypeAsTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *HasSameTypeAsTest) CandidateIsLiteralNil() { + matcher := HasSameTypeAs(nil) + var err error + + // Description + ExpectEq("has type ", matcher.Description()) + + // Literal nil + err = matcher.Matches(nil) + ExpectEq(nil, err) + + // nil in interface variable + var r io.Reader + err = matcher.Matches(r) + ExpectEq(nil, err) + + // int + err = matcher.Matches(17) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type int"))) + + // string + err = matcher.Matches("") + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type string"))) + + // nil map + var m map[string]string + err = matcher.Matches(m) + + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type map[string]string"))) + + // Non-nil map + m = make(map[string]string) + err = matcher.Matches(m) + + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type map[string]string"))) +} + +func (t *HasSameTypeAsTest) CandidateIsNilMap() { + var m map[string]string + matcher := HasSameTypeAs(m) + var err error + + // Description + ExpectEq("has type map[string]string", matcher.Description()) + + // nil map + m = nil + err = matcher.Matches(m) + ExpectEq(nil, err) + + // Non-nil map + m = make(map[string]string) + err = matcher.Matches(m) + ExpectEq(nil, err) + + // Literal nil + err = matcher.Matches(nil) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type "))) + + // int + err = matcher.Matches(17) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type int"))) + + // string + err = matcher.Matches("") + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type string"))) +} + +func (t *HasSameTypeAsTest) CandidateIsNilInInterfaceVariable() { + var r io.Reader + matcher := HasSameTypeAs(r) + var err error + + // Description + ExpectEq("has type ", matcher.Description()) + + // nil in interface variable + r = nil + err = matcher.Matches(r) + ExpectEq(nil, err) + + // Literal nil + err = matcher.Matches(nil) + ExpectEq(nil, err) + + // int + err = matcher.Matches(17) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type int"))) +} + +func (t *HasSameTypeAsTest) CandidateIsString() { + matcher := HasSameTypeAs("") + var err error + + // Description + ExpectEq("has type string", matcher.Description()) + + // string + err = matcher.Matches("taco") + ExpectEq(nil, err) + + // string alias + type Foo string + err = matcher.Matches(Foo("taco")) + ExpectThat(err, Error(MatchesRegexp("which has type .*Foo"))) + + // Literal nil + err = matcher.Matches(nil) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type "))) + + // int + err = matcher.Matches(17) + AssertNe(nil, err) + ExpectThat(err, Error(Equals("which has type int"))) +} + +func (t *HasSameTypeAsTest) CandidateIsStringAlias() { + type Foo string + matcher := HasSameTypeAs(Foo("")) + var err error + + // Description + ExpectThat(matcher.Description(), MatchesRegexp("has type .*Foo")) + + // string alias + err = matcher.Matches(Foo("taco")) + ExpectEq(nil, err) + + // string + err = matcher.Matches("taco") + ExpectThat(err, Error(Equals("which has type string"))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr.go new file mode 100644 index 0000000000..bf5bd6ae6d --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr.go @@ -0,0 +1,46 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" + "strings" +) + +// HasSubstr returns a matcher that matches strings containing s as a +// substring. +func HasSubstr(s string) Matcher { + return NewMatcher( + func(c interface{}) error { return hasSubstr(s, c) }, + fmt.Sprintf("has substring \"%s\"", s)) +} + +func hasSubstr(needle string, c interface{}) error { + v := reflect.ValueOf(c) + if v.Kind() != reflect.String { + return NewFatalError("which is not a string") + } + + // Perform the substring search. + haystack := v.String() + if strings.Contains(haystack, needle) { + return nil + } + + return errors.New("") +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr_test.go new file mode 100644 index 0000000000..30261849b7 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/has_substr_test.go @@ -0,0 +1,92 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type HasSubstrTest struct { +} + +func init() { RegisterTestSuite(&HasSubstrTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *HasSubstrTest) Description() { + matcher := HasSubstr("taco") + ExpectThat(matcher.Description(), Equals("has substring \"taco\"")) +} + +func (t *HasSubstrTest) CandidateIsNil() { + matcher := HasSubstr("") + err := matcher.Matches(nil) + + ExpectThat(err, Error(Equals("which is not a string"))) + ExpectTrue(isFatal(err)) +} + +func (t *HasSubstrTest) CandidateIsInteger() { + matcher := HasSubstr("") + err := matcher.Matches(17) + + ExpectThat(err, Error(Equals("which is not a string"))) + ExpectTrue(isFatal(err)) +} + +func (t *HasSubstrTest) CandidateIsByteSlice() { + matcher := HasSubstr("") + err := matcher.Matches([]byte{17}) + + ExpectThat(err, Error(Equals("which is not a string"))) + ExpectTrue(isFatal(err)) +} + +func (t *HasSubstrTest) CandidateDoesntHaveSubstring() { + matcher := HasSubstr("taco") + err := matcher.Matches("tac") + + ExpectThat(err, Error(Equals(""))) + ExpectFalse(isFatal(err)) +} + +func (t *HasSubstrTest) CandidateEqualsArg() { + matcher := HasSubstr("taco") + err := matcher.Matches("taco") + + ExpectThat(err, Equals(nil)) +} + +func (t *HasSubstrTest) CandidateHasProperSubstring() { + matcher := HasSubstr("taco") + err := matcher.Matches("burritos and tacos") + + ExpectThat(err, Equals(nil)) +} + +func (t *HasSubstrTest) EmptyStringIsAlwaysSubString() { + matcher := HasSubstr("") + err := matcher.Matches("asdf") + + ExpectThat(err, Equals(nil)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to.go new file mode 100644 index 0000000000..ae6460ed96 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to.go @@ -0,0 +1,134 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" +) + +// Is the type comparable according to the definition here? +// +// http://weekly.golang.org/doc/go_spec.html#Comparison_operators +// +func isComparable(t reflect.Type) bool { + switch t.Kind() { + case reflect.Array: + return isComparable(t.Elem()) + + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if !isComparable(t.Field(i).Type) { + return false + } + } + + return true + + case reflect.Slice, reflect.Map, reflect.Func: + return false + } + + return true +} + +// Should the supplied type be allowed as an argument to IdenticalTo? +func isLegalForIdenticalTo(t reflect.Type) (bool, error) { + // Allow the zero type. + if t == nil { + return true, nil + } + + // Reference types are always okay; we compare pointers. + switch t.Kind() { + case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan: + return true, nil + } + + // Reject other non-comparable types. + if !isComparable(t) { + return false, errors.New(fmt.Sprintf("%v is not comparable", t)) + } + + return true, nil +} + +// IdenticalTo(x) returns a matcher that matches values v with type identical +// to x such that: +// +// 1. If v and x are of a reference type (slice, map, function, channel), then +// they are either both nil or are references to the same object. +// +// 2. Otherwise, if v and x are not of a reference type but have a valid type, +// then v == x. +// +// If v and x are both the invalid type (which results from the predeclared nil +// value, or from nil interface variables), then the matcher is satisfied. +// +// This function will panic if x is of a value type that is not comparable. For +// example, x cannot be an array of functions. +func IdenticalTo(x interface{}) Matcher { + t := reflect.TypeOf(x) + + // Reject illegal arguments. + if ok, err := isLegalForIdenticalTo(t); !ok { + panic("IdenticalTo: " + err.Error()) + } + + return &identicalToMatcher{x} +} + +type identicalToMatcher struct { + x interface{} +} + +func (m *identicalToMatcher) Description() string { + t := reflect.TypeOf(m.x) + return fmt.Sprintf("identical to <%v> %v", t, m.x) +} + +func (m *identicalToMatcher) Matches(c interface{}) error { + // Make sure the candidate's type is correct. + t := reflect.TypeOf(m.x) + if ct := reflect.TypeOf(c); t != ct { + return NewFatalError(fmt.Sprintf("which is of type %v", ct)) + } + + // Special case: two values of the invalid type are always identical. + if t == nil { + return nil + } + + // Handle reference types. + switch t.Kind() { + case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan: + xv := reflect.ValueOf(m.x) + cv := reflect.ValueOf(c) + if xv.Pointer() == cv.Pointer() { + return nil + } + + return errors.New("which is not an identical reference") + } + + // Are the values equal? + if m.x == c { + return nil + } + + return errors.New("") +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to_test.go new file mode 100644 index 0000000000..f514c3f068 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/identical_to_test.go @@ -0,0 +1,849 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "fmt" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "io" + "unsafe" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type IdenticalToTest struct { +} + +func init() { RegisterTestSuite(&IdenticalToTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *IdenticalToTest) TypesNotIdentical() { + var m Matcher + var err error + + type intAlias int + + // Type alias expected value + m = IdenticalTo(intAlias(17)) + err = m.Matches(int(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int"))) + + // Type alias candidate + m = IdenticalTo(int(17)) + err = m.Matches(intAlias(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.intAlias"))) + + // int and uint + m = IdenticalTo(int(17)) + err = m.Matches(uint(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type uint"))) +} + +func (t *IdenticalToTest) PredeclaredNilIdentifier() { + var m Matcher + var err error + + // Nil literal + m = IdenticalTo(nil) + err = m.Matches(nil) + ExpectEq(nil, err) + + // Zero interface var (which is the same as above since IdenticalTo takes an + // interface{} as an arg) + var nilReader io.Reader + var nilWriter io.Writer + + m = IdenticalTo(nilReader) + err = m.Matches(nilWriter) + ExpectEq(nil, err) + + // Typed nil value. + m = IdenticalTo(nil) + err = m.Matches((chan int)(nil)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type chan int"))) + + // Non-nil value. + m = IdenticalTo(nil) + err = m.Matches("taco") + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type string"))) +} + +func (t *IdenticalToTest) Slices() { + var m Matcher + var err error + + // Nil expected value + m = IdenticalTo(([]int)(nil)) + ExpectEq("identical to <[]int> []", m.Description()) + + err = m.Matches(([]int)(nil)) + ExpectEq(nil, err) + + err = m.Matches([]int{}) + ExpectThat(err, Error(Equals("which is not an identical reference"))) + + // Non-nil expected value + o1 := make([]int, 1) + o2 := make([]int, 1) + m = IdenticalTo(o1) + ExpectEq(fmt.Sprintf("identical to <[]int> %v", o1), m.Description()) + + err = m.Matches(o1) + ExpectEq(nil, err) + + err = m.Matches(o2) + ExpectThat(err, Error(Equals("which is not an identical reference"))) +} + +func (t *IdenticalToTest) Maps() { + var m Matcher + var err error + + // Nil expected value + m = IdenticalTo((map[int]int)(nil)) + ExpectEq("identical to map[]", m.Description()) + + err = m.Matches((map[int]int)(nil)) + ExpectEq(nil, err) + + err = m.Matches(map[int]int{}) + ExpectThat(err, Error(Equals("which is not an identical reference"))) + + // Non-nil expected value + o1 := map[int]int{} + o2 := map[int]int{} + m = IdenticalTo(o1) + ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) + + err = m.Matches(o1) + ExpectEq(nil, err) + + err = m.Matches(o2) + ExpectThat(err, Error(Equals("which is not an identical reference"))) +} + +func (t *IdenticalToTest) Functions() { + var m Matcher + var err error + + // Nil expected value + m = IdenticalTo((func())(nil)) + ExpectEq("identical to ", m.Description()) + + err = m.Matches((func())(nil)) + ExpectEq(nil, err) + + err = m.Matches(func() {}) + ExpectThat(err, Error(Equals("which is not an identical reference"))) + + // Non-nil expected value + o1 := func() {} + o2 := func() {} + m = IdenticalTo(o1) + ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) + + err = m.Matches(o1) + ExpectEq(nil, err) + + err = m.Matches(o2) + ExpectThat(err, Error(Equals("which is not an identical reference"))) +} + +func (t *IdenticalToTest) Channels() { + var m Matcher + var err error + + // Nil expected value + m = IdenticalTo((chan int)(nil)) + ExpectEq("identical to ", m.Description()) + + err = m.Matches((chan int)(nil)) + ExpectEq(nil, err) + + err = m.Matches(make(chan int)) + ExpectThat(err, Error(Equals("which is not an identical reference"))) + + // Non-nil expected value + o1 := make(chan int) + o2 := make(chan int) + m = IdenticalTo(o1) + ExpectEq(fmt.Sprintf("identical to %v", o1), m.Description()) + + err = m.Matches(o1) + ExpectEq(nil, err) + + err = m.Matches(o2) + ExpectThat(err, Error(Equals("which is not an identical reference"))) +} + +func (t *IdenticalToTest) Bools() { + var m Matcher + var err error + + // false + m = IdenticalTo(false) + ExpectEq("identical to false", m.Description()) + + err = m.Matches(false) + ExpectEq(nil, err) + + err = m.Matches(true) + ExpectThat(err, Error(Equals(""))) + + // true + m = IdenticalTo(true) + ExpectEq("identical to true", m.Description()) + + err = m.Matches(false) + ExpectThat(err, Error(Equals(""))) + + err = m.Matches(true) + ExpectEq(nil, err) +} + +func (t *IdenticalToTest) Ints() { + var m Matcher + var err error + + m = IdenticalTo(int(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(int(17)) + ExpectEq(nil, err) + + // Type alias + type myType int + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Int8s() { + var m Matcher + var err error + + m = IdenticalTo(int8(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(int8(17)) + ExpectEq(nil, err) + + // Type alias + type myType int8 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Int16s() { + var m Matcher + var err error + + m = IdenticalTo(int16(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(int16(17)) + ExpectEq(nil, err) + + // Type alias + type myType int16 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Int32s() { + var m Matcher + var err error + + m = IdenticalTo(int32(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(int32(17)) + ExpectEq(nil, err) + + // Type alias + type myType int32 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int16(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int16"))) +} + +func (t *IdenticalToTest) Int64s() { + var m Matcher + var err error + + m = IdenticalTo(int64(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(int64(17)) + ExpectEq(nil, err) + + // Type alias + type myType int64 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uints() { + var m Matcher + var err error + + m = IdenticalTo(uint(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uint(17)) + ExpectEq(nil, err) + + // Type alias + type myType uint + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uint8s() { + var m Matcher + var err error + + m = IdenticalTo(uint8(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uint8(17)) + ExpectEq(nil, err) + + // Type alias + type myType uint8 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uint16s() { + var m Matcher + var err error + + m = IdenticalTo(uint16(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uint16(17)) + ExpectEq(nil, err) + + // Type alias + type myType uint16 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uint32s() { + var m Matcher + var err error + + m = IdenticalTo(uint32(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uint32(17)) + ExpectEq(nil, err) + + // Type alias + type myType uint32 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uint64s() { + var m Matcher + var err error + + m = IdenticalTo(uint64(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uint64(17)) + ExpectEq(nil, err) + + // Type alias + type myType uint64 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Uintptrs() { + var m Matcher + var err error + + m = IdenticalTo(uintptr(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(uintptr(17)) + ExpectEq(nil, err) + + // Type alias + type myType uintptr + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Float32s() { + var m Matcher + var err error + + m = IdenticalTo(float32(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(float32(17)) + ExpectEq(nil, err) + + // Type alias + type myType float32 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Float64s() { + var m Matcher + var err error + + m = IdenticalTo(float64(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(float64(17)) + ExpectEq(nil, err) + + // Type alias + type myType float64 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Complex64s() { + var m Matcher + var err error + + m = IdenticalTo(complex64(17)) + ExpectEq("identical to (17+0i)", m.Description()) + + // Identical value + err = m.Matches(complex64(17)) + ExpectEq(nil, err) + + // Type alias + type myType complex64 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) Complex128s() { + var m Matcher + var err error + + m = IdenticalTo(complex128(17)) + ExpectEq("identical to (17+0i)", m.Description()) + + // Identical value + err = m.Matches(complex128(17)) + ExpectEq(nil, err) + + // Type alias + type myType complex128 + err = m.Matches(myType(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) EmptyComparableArrays() { + var m Matcher + var err error + + m = IdenticalTo([0]int{}) + ExpectEq("identical to <[0]int> []", m.Description()) + + // Identical value + err = m.Matches([0]int{}) + ExpectEq(nil, err) + + // Length too long + err = m.Matches([1]int{17}) + ExpectThat(err, Error(Equals("which is of type [1]int"))) + + // Element type alias + type myType int + err = m.Matches([0]myType{}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type [0]oglematchers_test.myType"))) + + // Completely wrong element type + err = m.Matches([0]int32{}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type [0]int32"))) +} + +func (t *IdenticalToTest) NonEmptyComparableArrays() { + var m Matcher + var err error + + m = IdenticalTo([2]int{17, 19}) + ExpectEq("identical to <[2]int> [17 19]", m.Description()) + + // Identical value + err = m.Matches([2]int{17, 19}) + ExpectEq(nil, err) + + // Length too short + err = m.Matches([1]int{17}) + ExpectThat(err, Error(Equals("which is of type [1]int"))) + + // Length too long + err = m.Matches([3]int{17, 19, 23}) + ExpectThat(err, Error(Equals("which is of type [3]int"))) + + // First element different + err = m.Matches([2]int{13, 19}) + ExpectThat(err, Error(Equals(""))) + + // Second element different + err = m.Matches([2]int{17, 23}) + ExpectThat(err, Error(Equals(""))) + + // Element type alias + type myType int + err = m.Matches([2]myType{17, 19}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type [2]oglematchers_test.myType"))) + + // Completely wrong element type + err = m.Matches([2]int32{17, 19}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type [2]int32"))) +} + +func (t *IdenticalToTest) NonEmptyArraysOfComparableArrays() { + var m Matcher + var err error + + x := [2][2]int{ + [2]int{17, 19}, + [2]int{23, 29}, + } + m = IdenticalTo(x) + ExpectEq("identical to <[2][2]int> [[17 19] [23 29]]", m.Description()) + + // Identical value + err = m.Matches([2][2]int{[2]int{17, 19}, [2]int{23, 29}}) + ExpectEq(nil, err) + + // Outer length too short + err = m.Matches([1][2]int{[2]int{17, 19}}) + ExpectThat(err, Error(Equals("which is of type [1][2]int"))) + + // Inner length too short + err = m.Matches([2][1]int{[1]int{17}, [1]int{23}}) + ExpectThat(err, Error(Equals("which is of type [2][1]int"))) + + // First element different + err = m.Matches([2][2]int{[2]int{13, 19}, [2]int{23, 29}}) + ExpectThat(err, Error(Equals(""))) + + // Element type alias + type myType int + err = m.Matches([2][2]myType{[2]myType{17, 19}, [2]myType{23, 29}}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type [2][2]oglematchers_test.myType"))) +} + +func (t *IdenticalToTest) NonComparableArrays() { + x := [0]func(){} + f := func() { IdenticalTo(x) } + ExpectThat(f, Panics(HasSubstr("is not comparable"))) +} + +func (t *IdenticalToTest) ArraysOfNonComparableArrays() { + x := [0][0]func(){} + f := func() { IdenticalTo(x) } + ExpectThat(f, Panics(HasSubstr("is not comparable"))) +} + +func (t *IdenticalToTest) Strings() { + var m Matcher + var err error + + m = IdenticalTo("taco") + ExpectEq("identical to taco", m.Description()) + + // Identical value + err = m.Matches("ta" + "co") + ExpectEq(nil, err) + + // Type alias + type myType string + err = m.Matches(myType("taco")) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) ComparableStructs() { + var m Matcher + var err error + + type subStruct struct { + i int + } + + type myStruct struct { + u uint + s subStruct + } + + x := myStruct{17, subStruct{19}} + m = IdenticalTo(x) + ExpectEq("identical to {17 {19}}", m.Description()) + + // Identical value + err = m.Matches(myStruct{17, subStruct{19}}) + ExpectEq(nil, err) + + // Wrong outer field + err = m.Matches(myStruct{13, subStruct{19}}) + ExpectThat(err, Error(Equals(""))) + + // Wrong inner field + err = m.Matches(myStruct{17, subStruct{23}}) + ExpectThat(err, Error(Equals(""))) + + // Type alias + type myType myStruct + err = m.Matches(myType{17, subStruct{19}}) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) NonComparableStructs() { + type subStruct struct { + s []int + } + + type myStruct struct { + u uint + s subStruct + } + + x := myStruct{17, subStruct{[]int{19}}} + f := func() { IdenticalTo(x) } + ExpectThat(f, Panics(AllOf(HasSubstr("IdenticalTo"), HasSubstr("comparable")))) +} + +func (t *IdenticalToTest) NilUnsafePointer() { + var m Matcher + var err error + + x := unsafe.Pointer(nil) + m = IdenticalTo(x) + ExpectEq(fmt.Sprintf("identical to %v", x), m.Description()) + + // Identical value + err = m.Matches(unsafe.Pointer(nil)) + ExpectEq(nil, err) + + // Wrong value + j := 17 + err = m.Matches(unsafe.Pointer(&j)) + ExpectThat(err, Error(Equals(""))) + + // Type alias + type myType unsafe.Pointer + err = m.Matches(myType(unsafe.Pointer(nil))) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) NonNilUnsafePointer() { + var m Matcher + var err error + + i := 17 + x := unsafe.Pointer(&i) + m = IdenticalTo(x) + ExpectEq(fmt.Sprintf("identical to %v", x), m.Description()) + + // Identical value + err = m.Matches(unsafe.Pointer(&i)) + ExpectEq(nil, err) + + // Nil value + err = m.Matches(unsafe.Pointer(nil)) + ExpectThat(err, Error(Equals(""))) + + // Wrong value + j := 17 + err = m.Matches(unsafe.Pointer(&j)) + ExpectThat(err, Error(Equals(""))) + + // Type alias + type myType unsafe.Pointer + err = m.Matches(myType(unsafe.Pointer(&i))) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type oglematchers_test.myType"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} + +func (t *IdenticalToTest) IntAlias() { + var m Matcher + var err error + + type intAlias int + + m = IdenticalTo(intAlias(17)) + ExpectEq("identical to 17", m.Description()) + + // Identical value + err = m.Matches(intAlias(17)) + ExpectEq(nil, err) + + // Int + err = m.Matches(int(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int"))) + + // Completely wrong type + err = m.Matches(int32(17)) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("which is of type int32"))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal.go new file mode 100644 index 0000000000..8402cdeaf0 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal.go @@ -0,0 +1,41 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "fmt" + "reflect" +) + +// LessOrEqual returns a matcher that matches integer, floating point, or +// strings values v such that v <= x. Comparison is not defined between numeric +// and string types, but is defined between all integer and floating point +// types. +// +// x must itself be an integer, floating point, or string type; otherwise, +// LessOrEqual will panic. +func LessOrEqual(x interface{}) Matcher { + desc := fmt.Sprintf("less than or equal to %v", x) + + // Special case: make it clear that strings are strings. + if reflect.TypeOf(x).Kind() == reflect.String { + desc = fmt.Sprintf("less than or equal to \"%s\"", x) + } + + // Put LessThan last so that its error messages will be used in the event of + // failure. + return transformDescription(AnyOf(Equals(x), LessThan(x)), desc) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal_test.go new file mode 100644 index 0000000000..735712bdaf --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_or_equal_test.go @@ -0,0 +1,1077 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "math" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type LessOrEqualTest struct { +} + +func init() { RegisterTestSuite(&LessOrEqualTest{}) } + +type leTestCase struct { + candidate interface{} + expectedResult bool + shouldBeFatal bool + expectedError string +} + +func (t *LessOrEqualTest) checkTestCases(matcher Matcher, cases []leTestCase) { + for i, c := range cases { + err := matcher.Matches(c.candidate) + + ExpectThat( + (err == nil), + Equals(c.expectedResult), + "Case %d (candidate %v)", + i, + c.candidate) + + if err == nil { + continue + } + + _, isFatal := err.(*FatalError) + ExpectEq( + c.shouldBeFatal, + isFatal, + "Case %d (candidate %v)", + i, + c.candidate) + + ExpectThat( + err, + Error(Equals(c.expectedError)), + "Case %d (candidate %v)", + i, + c.candidate) + } +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessOrEqualTest) IntegerCandidateBadTypes() { + matcher := LessOrEqual(int(-150)) + + cases := []leTestCase{ + leTestCase{true, false, true, "which is not comparable"}, + leTestCase{complex64(-151), false, true, "which is not comparable"}, + leTestCase{complex128(-151), false, true, "which is not comparable"}, + leTestCase{[...]int{-151}, false, true, "which is not comparable"}, + leTestCase{make(chan int), false, true, "which is not comparable"}, + leTestCase{func() {}, false, true, "which is not comparable"}, + leTestCase{map[int]int{}, false, true, "which is not comparable"}, + leTestCase{&leTestCase{}, false, true, "which is not comparable"}, + leTestCase{make([]int, 0), false, true, "which is not comparable"}, + leTestCase{"-151", false, true, "which is not comparable"}, + leTestCase{leTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) FloatCandidateBadTypes() { + matcher := LessOrEqual(float32(-150)) + + cases := []leTestCase{ + leTestCase{true, false, true, "which is not comparable"}, + leTestCase{complex64(-151), false, true, "which is not comparable"}, + leTestCase{complex128(-151), false, true, "which is not comparable"}, + leTestCase{[...]int{-151}, false, true, "which is not comparable"}, + leTestCase{make(chan int), false, true, "which is not comparable"}, + leTestCase{func() {}, false, true, "which is not comparable"}, + leTestCase{map[int]int{}, false, true, "which is not comparable"}, + leTestCase{&leTestCase{}, false, true, "which is not comparable"}, + leTestCase{make([]int, 0), false, true, "which is not comparable"}, + leTestCase{"-151", false, true, "which is not comparable"}, + leTestCase{leTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) StringCandidateBadTypes() { + matcher := LessOrEqual("17") + + cases := []leTestCase{ + leTestCase{true, false, true, "which is not comparable"}, + leTestCase{int(0), false, true, "which is not comparable"}, + leTestCase{int8(0), false, true, "which is not comparable"}, + leTestCase{int16(0), false, true, "which is not comparable"}, + leTestCase{int32(0), false, true, "which is not comparable"}, + leTestCase{int64(0), false, true, "which is not comparable"}, + leTestCase{uint(0), false, true, "which is not comparable"}, + leTestCase{uint8(0), false, true, "which is not comparable"}, + leTestCase{uint16(0), false, true, "which is not comparable"}, + leTestCase{uint32(0), false, true, "which is not comparable"}, + leTestCase{uint64(0), false, true, "which is not comparable"}, + leTestCase{float32(0), false, true, "which is not comparable"}, + leTestCase{float64(0), false, true, "which is not comparable"}, + leTestCase{complex64(-151), false, true, "which is not comparable"}, + leTestCase{complex128(-151), false, true, "which is not comparable"}, + leTestCase{[...]int{-151}, false, true, "which is not comparable"}, + leTestCase{make(chan int), false, true, "which is not comparable"}, + leTestCase{func() {}, false, true, "which is not comparable"}, + leTestCase{map[int]int{}, false, true, "which is not comparable"}, + leTestCase{&leTestCase{}, false, true, "which is not comparable"}, + leTestCase{make([]int, 0), false, true, "which is not comparable"}, + leTestCase{leTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) BadArgument() { + panicked := false + + defer func() { + ExpectThat(panicked, Equals(true)) + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + LessOrEqual(complex128(0)) +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessOrEqualTest) NegativeIntegerLiteral() { + matcher := LessOrEqual(-150) + desc := matcher.Description() + expectedDesc := "less than or equal to -150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-(1 << 30), true, false, ""}, + leTestCase{-151, true, false, ""}, + leTestCase{-150, true, false, ""}, + leTestCase{-149, false, false, ""}, + leTestCase{0, false, false, ""}, + leTestCase{17, false, false, ""}, + + leTestCase{int(-(1 << 30)), true, false, ""}, + leTestCase{int(-151), true, false, ""}, + leTestCase{int(-150), true, false, ""}, + leTestCase{int(-149), false, false, ""}, + leTestCase{int(0), false, false, ""}, + leTestCase{int(17), false, false, ""}, + + leTestCase{int8(-127), false, false, ""}, + leTestCase{int8(0), false, false, ""}, + leTestCase{int8(17), false, false, ""}, + + leTestCase{int16(-(1 << 14)), true, false, ""}, + leTestCase{int16(-151), true, false, ""}, + leTestCase{int16(-150), true, false, ""}, + leTestCase{int16(-149), false, false, ""}, + leTestCase{int16(0), false, false, ""}, + leTestCase{int16(17), false, false, ""}, + + leTestCase{int32(-(1 << 30)), true, false, ""}, + leTestCase{int32(-151), true, false, ""}, + leTestCase{int32(-150), true, false, ""}, + leTestCase{int32(-149), false, false, ""}, + leTestCase{int32(0), false, false, ""}, + leTestCase{int32(17), false, false, ""}, + + leTestCase{int64(-(1 << 30)), true, false, ""}, + leTestCase{int64(-151), true, false, ""}, + leTestCase{int64(-150), true, false, ""}, + leTestCase{int64(-149), false, false, ""}, + leTestCase{int64(0), false, false, ""}, + leTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + leTestCase{uint((1 << 32) - 151), false, false, ""}, + leTestCase{uint(0), false, false, ""}, + leTestCase{uint(17), false, false, ""}, + + leTestCase{uint8(0), false, false, ""}, + leTestCase{uint8(17), false, false, ""}, + leTestCase{uint8(253), false, false, ""}, + + leTestCase{uint16((1 << 16) - 151), false, false, ""}, + leTestCase{uint16(0), false, false, ""}, + leTestCase{uint16(17), false, false, ""}, + + leTestCase{uint32((1 << 32) - 151), false, false, ""}, + leTestCase{uint32(0), false, false, ""}, + leTestCase{uint32(17), false, false, ""}, + + leTestCase{uint64((1 << 64) - 151), false, false, ""}, + leTestCase{uint64(0), false, false, ""}, + leTestCase{uint64(17), false, false, ""}, + + // Floating point. + leTestCase{float32(-(1 << 30)), true, false, ""}, + leTestCase{float32(-151), true, false, ""}, + leTestCase{float32(-150.1), true, false, ""}, + leTestCase{float32(-150), true, false, ""}, + leTestCase{float32(-149.9), false, false, ""}, + leTestCase{float32(0), false, false, ""}, + leTestCase{float32(17), false, false, ""}, + leTestCase{float32(160), false, false, ""}, + + leTestCase{float64(-(1 << 30)), true, false, ""}, + leTestCase{float64(-151), true, false, ""}, + leTestCase{float64(-150.1), true, false, ""}, + leTestCase{float64(-150), true, false, ""}, + leTestCase{float64(-149.9), false, false, ""}, + leTestCase{float64(0), false, false, ""}, + leTestCase{float64(17), false, false, ""}, + leTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) ZeroIntegerLiteral() { + matcher := LessOrEqual(0) + desc := matcher.Description() + expectedDesc := "less than or equal to 0" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-(1 << 30), true, false, ""}, + leTestCase{-1, true, false, ""}, + leTestCase{0, true, false, ""}, + leTestCase{1, false, false, ""}, + leTestCase{17, false, false, ""}, + leTestCase{(1 << 30), false, false, ""}, + + leTestCase{int(-(1 << 30)), true, false, ""}, + leTestCase{int(-1), true, false, ""}, + leTestCase{int(0), true, false, ""}, + leTestCase{int(1), false, false, ""}, + leTestCase{int(17), false, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(0), true, false, ""}, + leTestCase{int8(1), false, false, ""}, + + leTestCase{int16(-(1 << 14)), true, false, ""}, + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(0), true, false, ""}, + leTestCase{int16(1), false, false, ""}, + leTestCase{int16(17), false, false, ""}, + + leTestCase{int32(-(1 << 30)), true, false, ""}, + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(0), true, false, ""}, + leTestCase{int32(1), false, false, ""}, + leTestCase{int32(17), false, false, ""}, + + leTestCase{int64(-(1 << 30)), true, false, ""}, + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(0), true, false, ""}, + leTestCase{int64(1), false, false, ""}, + leTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + leTestCase{uint((1 << 32) - 1), false, false, ""}, + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(1), false, false, ""}, + leTestCase{uint(17), false, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(1), false, false, ""}, + leTestCase{uint8(17), false, false, ""}, + leTestCase{uint8(253), false, false, ""}, + + leTestCase{uint16((1 << 16) - 1), false, false, ""}, + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(1), false, false, ""}, + leTestCase{uint16(17), false, false, ""}, + + leTestCase{uint32((1 << 32) - 1), false, false, ""}, + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(1), false, false, ""}, + leTestCase{uint32(17), false, false, ""}, + + leTestCase{uint64((1 << 64) - 1), false, false, ""}, + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(1), false, false, ""}, + leTestCase{uint64(17), false, false, ""}, + + // Floating point. + leTestCase{float32(-(1 << 30)), true, false, ""}, + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(-0.1), true, false, ""}, + leTestCase{float32(-0.0), true, false, ""}, + leTestCase{float32(0), true, false, ""}, + leTestCase{float32(0.1), false, false, ""}, + leTestCase{float32(17), false, false, ""}, + leTestCase{float32(160), false, false, ""}, + + leTestCase{float64(-(1 << 30)), true, false, ""}, + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(-0.1), true, false, ""}, + leTestCase{float64(-0), true, false, ""}, + leTestCase{float64(0), true, false, ""}, + leTestCase{float64(0.1), false, false, ""}, + leTestCase{float64(17), false, false, ""}, + leTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) PositiveIntegerLiteral() { + matcher := LessOrEqual(150) + desc := matcher.Description() + expectedDesc := "less than or equal to 150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{149, true, false, ""}, + leTestCase{150, true, false, ""}, + leTestCase{151, false, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(149), true, false, ""}, + leTestCase{int(150), true, false, ""}, + leTestCase{int(151), false, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(0), true, false, ""}, + leTestCase{int8(17), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(149), true, false, ""}, + leTestCase{int16(150), true, false, ""}, + leTestCase{int16(151), false, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(149), true, false, ""}, + leTestCase{int32(150), true, false, ""}, + leTestCase{int32(151), false, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(149), true, false, ""}, + leTestCase{int64(150), true, false, ""}, + leTestCase{int64(151), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(149), true, false, ""}, + leTestCase{uint(150), true, false, ""}, + leTestCase{uint(151), false, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(127), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(149), true, false, ""}, + leTestCase{uint16(150), true, false, ""}, + leTestCase{uint16(151), false, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(149), true, false, ""}, + leTestCase{uint32(150), true, false, ""}, + leTestCase{uint32(151), false, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(149), true, false, ""}, + leTestCase{uint64(150), true, false, ""}, + leTestCase{uint64(151), false, false, ""}, + + // Floating point. + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(149), true, false, ""}, + leTestCase{float32(149.9), true, false, ""}, + leTestCase{float32(150), true, false, ""}, + leTestCase{float32(150.1), false, false, ""}, + leTestCase{float32(151), false, false, ""}, + + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(149), true, false, ""}, + leTestCase{float64(149.9), true, false, ""}, + leTestCase{float64(150), true, false, ""}, + leTestCase{float64(150.1), false, false, ""}, + leTestCase{float64(151), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Float literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessOrEqualTest) NegativeFloatLiteral() { + matcher := LessOrEqual(-150.1) + desc := matcher.Description() + expectedDesc := "less than or equal to -150.1" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-(1 << 30), true, false, ""}, + leTestCase{-151, true, false, ""}, + leTestCase{-150.1, true, false, ""}, + leTestCase{-150, false, false, ""}, + leTestCase{-149, false, false, ""}, + leTestCase{0, false, false, ""}, + leTestCase{17, false, false, ""}, + + leTestCase{int(-(1 << 30)), true, false, ""}, + leTestCase{int(-151), true, false, ""}, + leTestCase{int(-150), false, false, ""}, + leTestCase{int(-149), false, false, ""}, + leTestCase{int(0), false, false, ""}, + leTestCase{int(17), false, false, ""}, + + leTestCase{int8(-127), false, false, ""}, + leTestCase{int8(0), false, false, ""}, + leTestCase{int8(17), false, false, ""}, + + leTestCase{int16(-(1 << 14)), true, false, ""}, + leTestCase{int16(-151), true, false, ""}, + leTestCase{int16(-150), false, false, ""}, + leTestCase{int16(-149), false, false, ""}, + leTestCase{int16(0), false, false, ""}, + leTestCase{int16(17), false, false, ""}, + + leTestCase{int32(-(1 << 30)), true, false, ""}, + leTestCase{int32(-151), true, false, ""}, + leTestCase{int32(-150), false, false, ""}, + leTestCase{int32(-149), false, false, ""}, + leTestCase{int32(0), false, false, ""}, + leTestCase{int32(17), false, false, ""}, + + leTestCase{int64(-(1 << 30)), true, false, ""}, + leTestCase{int64(-151), true, false, ""}, + leTestCase{int64(-150), false, false, ""}, + leTestCase{int64(-149), false, false, ""}, + leTestCase{int64(0), false, false, ""}, + leTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + leTestCase{uint((1 << 32) - 151), false, false, ""}, + leTestCase{uint(0), false, false, ""}, + leTestCase{uint(17), false, false, ""}, + + leTestCase{uint8(0), false, false, ""}, + leTestCase{uint8(17), false, false, ""}, + leTestCase{uint8(253), false, false, ""}, + + leTestCase{uint16((1 << 16) - 151), false, false, ""}, + leTestCase{uint16(0), false, false, ""}, + leTestCase{uint16(17), false, false, ""}, + + leTestCase{uint32((1 << 32) - 151), false, false, ""}, + leTestCase{uint32(0), false, false, ""}, + leTestCase{uint32(17), false, false, ""}, + + leTestCase{uint64((1 << 64) - 151), false, false, ""}, + leTestCase{uint64(0), false, false, ""}, + leTestCase{uint64(17), false, false, ""}, + + // Floating point. + leTestCase{float32(-(1 << 30)), true, false, ""}, + leTestCase{float32(-151), true, false, ""}, + leTestCase{float32(-150.2), true, false, ""}, + leTestCase{float32(-150.1), true, false, ""}, + leTestCase{float32(-150), false, false, ""}, + leTestCase{float32(0), false, false, ""}, + leTestCase{float32(17), false, false, ""}, + leTestCase{float32(160), false, false, ""}, + + leTestCase{float64(-(1 << 30)), true, false, ""}, + leTestCase{float64(-151), true, false, ""}, + leTestCase{float64(-150.2), true, false, ""}, + leTestCase{float64(-150.1), true, false, ""}, + leTestCase{float64(-150), false, false, ""}, + leTestCase{float64(0), false, false, ""}, + leTestCase{float64(17), false, false, ""}, + leTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) PositiveFloatLiteral() { + matcher := LessOrEqual(149.9) + desc := matcher.Description() + expectedDesc := "less than or equal to 149.9" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{149, true, false, ""}, + leTestCase{149.9, true, false, ""}, + leTestCase{150, false, false, ""}, + leTestCase{151, false, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(149), true, false, ""}, + leTestCase{int(150), false, false, ""}, + leTestCase{int(151), false, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(0), true, false, ""}, + leTestCase{int8(17), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(149), true, false, ""}, + leTestCase{int16(150), false, false, ""}, + leTestCase{int16(151), false, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(149), true, false, ""}, + leTestCase{int32(150), false, false, ""}, + leTestCase{int32(151), false, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(149), true, false, ""}, + leTestCase{int64(150), false, false, ""}, + leTestCase{int64(151), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(149), true, false, ""}, + leTestCase{uint(150), false, false, ""}, + leTestCase{uint(151), false, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(127), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(149), true, false, ""}, + leTestCase{uint16(150), false, false, ""}, + leTestCase{uint16(151), false, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(149), true, false, ""}, + leTestCase{uint32(150), false, false, ""}, + leTestCase{uint32(151), false, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(149), true, false, ""}, + leTestCase{uint64(150), false, false, ""}, + leTestCase{uint64(151), false, false, ""}, + + // Floating point. + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(149), true, false, ""}, + leTestCase{float32(149.8), true, false, ""}, + leTestCase{float32(149.9), true, false, ""}, + leTestCase{float32(150), false, false, ""}, + leTestCase{float32(151), false, false, ""}, + + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(149), true, false, ""}, + leTestCase{float64(149.8), true, false, ""}, + leTestCase{float64(149.9), true, false, ""}, + leTestCase{float64(150), false, false, ""}, + leTestCase{float64(151), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Subtle cases +//////////////////////////////////////////////////////////////////////// + +func (t *LessOrEqualTest) Int64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessOrEqual(int64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{kTwoTo25 + 0, true, false, ""}, + leTestCase{kTwoTo25 + 1, true, false, ""}, + leTestCase{kTwoTo25 + 2, false, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(kTwoTo25 + 0), true, false, ""}, + leTestCase{int(kTwoTo25 + 1), true, false, ""}, + leTestCase{int(kTwoTo25 + 2), false, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(0), true, false, ""}, + leTestCase{int16(32767), true, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(kTwoTo25 + 0), true, false, ""}, + leTestCase{int32(kTwoTo25 + 1), true, false, ""}, + leTestCase{int32(kTwoTo25 + 2), false, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 0), true, false, ""}, + leTestCase{int64(kTwoTo25 + 1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint(kTwoTo25 + 2), false, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(255), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(65535), true, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 2), false, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Floating point. + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(kTwoTo25 - 2), true, false, ""}, + leTestCase{float32(kTwoTo25 - 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 0), true, false, ""}, + leTestCase{float32(kTwoTo25 + 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 2), true, false, ""}, + leTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo25 - 2), true, false, ""}, + leTestCase{float64(kTwoTo25 - 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 0), true, false, ""}, + leTestCase{float64(kTwoTo25 + 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 2), false, false, ""}, + leTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) Int64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessOrEqual(int64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{1 << 30, true, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(math.MaxInt32), true, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(0), true, false, ""}, + leTestCase{int16(32767), true, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(math.MaxInt32), true, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo54 - 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 0), true, false, ""}, + leTestCase{int64(kTwoTo54 + 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(math.MaxUint32), true, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(255), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(65535), true, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(math.MaxUint32), true, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Floating point. + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo54 - 2), true, false, ""}, + leTestCase{float64(kTwoTo54 - 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 0), true, false, ""}, + leTestCase{float64(kTwoTo54 + 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 2), true, false, ""}, + leTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) Uint64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessOrEqual(uint64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{kTwoTo25 + 0, true, false, ""}, + leTestCase{kTwoTo25 + 1, true, false, ""}, + leTestCase{kTwoTo25 + 2, false, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(kTwoTo25 + 0), true, false, ""}, + leTestCase{int(kTwoTo25 + 1), true, false, ""}, + leTestCase{int(kTwoTo25 + 2), false, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(0), true, false, ""}, + leTestCase{int16(32767), true, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(kTwoTo25 + 0), true, false, ""}, + leTestCase{int32(kTwoTo25 + 1), true, false, ""}, + leTestCase{int32(kTwoTo25 + 2), false, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 0), true, false, ""}, + leTestCase{int64(kTwoTo25 + 1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint(kTwoTo25 + 2), false, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(255), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(65535), true, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint32(kTwoTo25 + 2), false, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Floating point. + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(kTwoTo25 - 2), true, false, ""}, + leTestCase{float32(kTwoTo25 - 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 0), true, false, ""}, + leTestCase{float32(kTwoTo25 + 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 2), true, false, ""}, + leTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo25 - 2), true, false, ""}, + leTestCase{float64(kTwoTo25 - 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 0), true, false, ""}, + leTestCase{float64(kTwoTo25 + 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 2), false, false, ""}, + leTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) Uint64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessOrEqual(uint64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{-1, true, false, ""}, + leTestCase{1 << 30, true, false, ""}, + + leTestCase{int(-1), true, false, ""}, + leTestCase{int(math.MaxInt32), true, false, ""}, + + leTestCase{int8(-1), true, false, ""}, + leTestCase{int8(127), true, false, ""}, + + leTestCase{int16(-1), true, false, ""}, + leTestCase{int16(0), true, false, ""}, + leTestCase{int16(32767), true, false, ""}, + + leTestCase{int32(-1), true, false, ""}, + leTestCase{int32(math.MaxInt32), true, false, ""}, + + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo54 - 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 0), true, false, ""}, + leTestCase{int64(kTwoTo54 + 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + // Unsigned integers. + leTestCase{uint(0), true, false, ""}, + leTestCase{uint(math.MaxUint32), true, false, ""}, + + leTestCase{uint8(0), true, false, ""}, + leTestCase{uint8(255), true, false, ""}, + + leTestCase{uint16(0), true, false, ""}, + leTestCase{uint16(65535), true, false, ""}, + + leTestCase{uint32(0), true, false, ""}, + leTestCase{uint32(math.MaxUint32), true, false, ""}, + + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Floating point. + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo54 - 2), true, false, ""}, + leTestCase{float64(kTwoTo54 - 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 0), true, false, ""}, + leTestCase{float64(kTwoTo54 + 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 2), true, false, ""}, + leTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) Float32AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessOrEqual(float32(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 3.3554432e+07" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo25 - 2), true, false, ""}, + leTestCase{int64(kTwoTo25 - 1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 0), true, false, ""}, + leTestCase{int64(kTwoTo25 + 1), true, false, ""}, + leTestCase{int64(kTwoTo25 + 2), true, false, ""}, + leTestCase{int64(kTwoTo25 + 3), false, false, ""}, + + // Unsigned integers. + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo25 - 2), true, false, ""}, + leTestCase{uint64(kTwoTo25 - 1), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 2), true, false, ""}, + leTestCase{uint64(kTwoTo25 + 3), false, false, ""}, + + // Floating point. + leTestCase{float32(-1), true, false, ""}, + leTestCase{float32(kTwoTo25 - 2), true, false, ""}, + leTestCase{float32(kTwoTo25 - 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 0), true, false, ""}, + leTestCase{float32(kTwoTo25 + 1), true, false, ""}, + leTestCase{float32(kTwoTo25 + 2), true, false, ""}, + leTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo25 - 2), true, false, ""}, + leTestCase{float64(kTwoTo25 - 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 0), true, false, ""}, + leTestCase{float64(kTwoTo25 + 1), true, false, ""}, + leTestCase{float64(kTwoTo25 + 2), true, false, ""}, + leTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) Float64AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessOrEqual(float64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than or equal to 1.8014398509481984e+16" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + // Signed integers. + leTestCase{int64(-1), true, false, ""}, + leTestCase{int64(kTwoTo54 - 2), true, false, ""}, + leTestCase{int64(kTwoTo54 - 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 0), true, false, ""}, + leTestCase{int64(kTwoTo54 + 1), true, false, ""}, + leTestCase{int64(kTwoTo54 + 2), true, false, ""}, + leTestCase{int64(kTwoTo54 + 3), false, false, ""}, + + // Unsigned integers. + leTestCase{uint64(0), true, false, ""}, + leTestCase{uint64(kTwoTo54 - 2), true, false, ""}, + leTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 1), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 2), true, false, ""}, + leTestCase{uint64(kTwoTo54 + 3), false, false, ""}, + + // Floating point. + leTestCase{float64(-1), true, false, ""}, + leTestCase{float64(kTwoTo54 - 2), true, false, ""}, + leTestCase{float64(kTwoTo54 - 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 0), true, false, ""}, + leTestCase{float64(kTwoTo54 + 1), true, false, ""}, + leTestCase{float64(kTwoTo54 + 2), true, false, ""}, + leTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// String literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessOrEqualTest) EmptyString() { + matcher := LessOrEqual("") + desc := matcher.Description() + expectedDesc := "less than or equal to \"\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + leTestCase{"", true, false, ""}, + leTestCase{"\x00", false, false, ""}, + leTestCase{"a", false, false, ""}, + leTestCase{"foo", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) SingleNullByte() { + matcher := LessOrEqual("\x00") + desc := matcher.Description() + expectedDesc := "less than or equal to \"\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + leTestCase{"", true, false, ""}, + leTestCase{"\x00", true, false, ""}, + leTestCase{"\x00\x00", false, false, ""}, + leTestCase{"a", false, false, ""}, + leTestCase{"foo", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessOrEqualTest) LongerString() { + matcher := LessOrEqual("foo\x00") + desc := matcher.Description() + expectedDesc := "less than or equal to \"foo\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []leTestCase{ + leTestCase{"", true, false, ""}, + leTestCase{"\x00", true, false, ""}, + leTestCase{"bar", true, false, ""}, + leTestCase{"foo", true, false, ""}, + leTestCase{"foo\x00", true, false, ""}, + leTestCase{"foo\x00\x00", false, false, ""}, + leTestCase{"fooa", false, false, ""}, + leTestCase{"qux", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than.go new file mode 100644 index 0000000000..8258e45d99 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than.go @@ -0,0 +1,152 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +// LessThan returns a matcher that matches integer, floating point, or strings +// values v such that v < x. Comparison is not defined between numeric and +// string types, but is defined between all integer and floating point types. +// +// x must itself be an integer, floating point, or string type; otherwise, +// LessThan will panic. +func LessThan(x interface{}) Matcher { + v := reflect.ValueOf(x) + kind := v.Kind() + + switch { + case isInteger(v): + case isFloat(v): + case kind == reflect.String: + + default: + panic(fmt.Sprintf("LessThan: unexpected kind %v", kind)) + } + + return &lessThanMatcher{v} +} + +type lessThanMatcher struct { + limit reflect.Value +} + +func (m *lessThanMatcher) Description() string { + // Special case: make it clear that strings are strings. + if m.limit.Kind() == reflect.String { + return fmt.Sprintf("less than \"%s\"", m.limit.String()) + } + + return fmt.Sprintf("less than %v", m.limit.Interface()) +} + +func compareIntegers(v1, v2 reflect.Value) (err error) { + err = errors.New("") + + switch { + case isSignedInteger(v1) && isSignedInteger(v2): + if v1.Int() < v2.Int() { + err = nil + } + return + + case isSignedInteger(v1) && isUnsignedInteger(v2): + if v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() { + err = nil + } + return + + case isUnsignedInteger(v1) && isSignedInteger(v2): + if v1.Uint() <= math.MaxInt64 && int64(v1.Uint()) < v2.Int() { + err = nil + } + return + + case isUnsignedInteger(v1) && isUnsignedInteger(v2): + if v1.Uint() < v2.Uint() { + err = nil + } + return + } + + panic(fmt.Sprintf("compareIntegers: %v %v", v1, v2)) +} + +func getFloat(v reflect.Value) float64 { + switch { + case isSignedInteger(v): + return float64(v.Int()) + + case isUnsignedInteger(v): + return float64(v.Uint()) + + case isFloat(v): + return v.Float() + } + + panic(fmt.Sprintf("getFloat: %v", v)) +} + +func (m *lessThanMatcher) Matches(c interface{}) (err error) { + v1 := reflect.ValueOf(c) + v2 := m.limit + + err = errors.New("") + + // Handle strings as a special case. + if v1.Kind() == reflect.String && v2.Kind() == reflect.String { + if v1.String() < v2.String() { + err = nil + } + return + } + + // If we get here, we require that we are dealing with integers or floats. + v1Legal := isInteger(v1) || isFloat(v1) + v2Legal := isInteger(v2) || isFloat(v2) + if !v1Legal || !v2Legal { + err = NewFatalError("which is not comparable") + return + } + + // Handle the various comparison cases. + switch { + // Both integers + case isInteger(v1) && isInteger(v2): + return compareIntegers(v1, v2) + + // At least one float32 + case v1.Kind() == reflect.Float32 || v2.Kind() == reflect.Float32: + if float32(getFloat(v1)) < float32(getFloat(v2)) { + err = nil + } + return + + // At least one float64 + case v1.Kind() == reflect.Float64 || v2.Kind() == reflect.Float64: + if getFloat(v1) < getFloat(v2) { + err = nil + } + return + } + + // We shouldn't get here. + panic(fmt.Sprintf("lessThanMatcher.Matches: Shouldn't get here: %v %v", v1, v2)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than_test.go new file mode 100644 index 0000000000..23dbcfd013 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/less_than_test.go @@ -0,0 +1,1057 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "math" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type LessThanTest struct { +} + +func init() { RegisterTestSuite(&LessThanTest{}) } + +type ltTestCase struct { + candidate interface{} + expectedResult bool + shouldBeFatal bool + expectedError string +} + +func (t *LessThanTest) checkTestCases(matcher Matcher, cases []ltTestCase) { + for i, c := range cases { + err := matcher.Matches(c.candidate) + + ExpectThat( + (err == nil), + Equals(c.expectedResult), + "Case %d (candidate %v)", + i, + c.candidate) + + if err == nil { + continue + } + + _, isFatal := err.(*FatalError) + ExpectEq( + c.shouldBeFatal, + isFatal, + "Case %d (candidate %v)", + i, + c.candidate) + + ExpectThat( + err, + Error(Equals(c.expectedError)), + "Case %d (candidate %v)", + i, + c.candidate) + } +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessThanTest) IntegerCandidateBadTypes() { + matcher := LessThan(int(-150)) + + cases := []ltTestCase{ + ltTestCase{true, false, true, "which is not comparable"}, + ltTestCase{complex64(-151), false, true, "which is not comparable"}, + ltTestCase{complex128(-151), false, true, "which is not comparable"}, + ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, + ltTestCase{make(chan int), false, true, "which is not comparable"}, + ltTestCase{func() {}, false, true, "which is not comparable"}, + ltTestCase{map[int]int{}, false, true, "which is not comparable"}, + ltTestCase{<TestCase{}, false, true, "which is not comparable"}, + ltTestCase{make([]int, 0), false, true, "which is not comparable"}, + ltTestCase{"-151", false, true, "which is not comparable"}, + ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) FloatCandidateBadTypes() { + matcher := LessThan(float32(-150)) + + cases := []ltTestCase{ + ltTestCase{true, false, true, "which is not comparable"}, + ltTestCase{complex64(-151), false, true, "which is not comparable"}, + ltTestCase{complex128(-151), false, true, "which is not comparable"}, + ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, + ltTestCase{make(chan int), false, true, "which is not comparable"}, + ltTestCase{func() {}, false, true, "which is not comparable"}, + ltTestCase{map[int]int{}, false, true, "which is not comparable"}, + ltTestCase{<TestCase{}, false, true, "which is not comparable"}, + ltTestCase{make([]int, 0), false, true, "which is not comparable"}, + ltTestCase{"-151", false, true, "which is not comparable"}, + ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) StringCandidateBadTypes() { + matcher := LessThan("17") + + cases := []ltTestCase{ + ltTestCase{true, false, true, "which is not comparable"}, + ltTestCase{int(0), false, true, "which is not comparable"}, + ltTestCase{int8(0), false, true, "which is not comparable"}, + ltTestCase{int16(0), false, true, "which is not comparable"}, + ltTestCase{int32(0), false, true, "which is not comparable"}, + ltTestCase{int64(0), false, true, "which is not comparable"}, + ltTestCase{uint(0), false, true, "which is not comparable"}, + ltTestCase{uint8(0), false, true, "which is not comparable"}, + ltTestCase{uint16(0), false, true, "which is not comparable"}, + ltTestCase{uint32(0), false, true, "which is not comparable"}, + ltTestCase{uint64(0), false, true, "which is not comparable"}, + ltTestCase{float32(0), false, true, "which is not comparable"}, + ltTestCase{float64(0), false, true, "which is not comparable"}, + ltTestCase{complex64(-151), false, true, "which is not comparable"}, + ltTestCase{complex128(-151), false, true, "which is not comparable"}, + ltTestCase{[...]int{-151}, false, true, "which is not comparable"}, + ltTestCase{make(chan int), false, true, "which is not comparable"}, + ltTestCase{func() {}, false, true, "which is not comparable"}, + ltTestCase{map[int]int{}, false, true, "which is not comparable"}, + ltTestCase{<TestCase{}, false, true, "which is not comparable"}, + ltTestCase{make([]int, 0), false, true, "which is not comparable"}, + ltTestCase{ltTestCase{}, false, true, "which is not comparable"}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) BadArgument() { + panicked := false + + defer func() { + ExpectThat(panicked, Equals(true)) + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + LessThan(complex128(0)) +} + +//////////////////////////////////////////////////////////////////////// +// Integer literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessThanTest) NegativeIntegerLiteral() { + matcher := LessThan(-150) + desc := matcher.Description() + expectedDesc := "less than -150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-(1 << 30), true, false, ""}, + ltTestCase{-151, true, false, ""}, + ltTestCase{-150, false, false, ""}, + ltTestCase{0, false, false, ""}, + ltTestCase{17, false, false, ""}, + + ltTestCase{int(-(1 << 30)), true, false, ""}, + ltTestCase{int(-151), true, false, ""}, + ltTestCase{int(-150), false, false, ""}, + ltTestCase{int(0), false, false, ""}, + ltTestCase{int(17), false, false, ""}, + + ltTestCase{int8(-127), false, false, ""}, + ltTestCase{int8(0), false, false, ""}, + ltTestCase{int8(17), false, false, ""}, + + ltTestCase{int16(-(1 << 14)), true, false, ""}, + ltTestCase{int16(-151), true, false, ""}, + ltTestCase{int16(-150), false, false, ""}, + ltTestCase{int16(0), false, false, ""}, + ltTestCase{int16(17), false, false, ""}, + + ltTestCase{int32(-(1 << 30)), true, false, ""}, + ltTestCase{int32(-151), true, false, ""}, + ltTestCase{int32(-150), false, false, ""}, + ltTestCase{int32(0), false, false, ""}, + ltTestCase{int32(17), false, false, ""}, + + ltTestCase{int64(-(1 << 30)), true, false, ""}, + ltTestCase{int64(-151), true, false, ""}, + ltTestCase{int64(-150), false, false, ""}, + ltTestCase{int64(0), false, false, ""}, + ltTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint((1 << 32) - 151), false, false, ""}, + ltTestCase{uint(0), false, false, ""}, + ltTestCase{uint(17), false, false, ""}, + + ltTestCase{uint8(0), false, false, ""}, + ltTestCase{uint8(17), false, false, ""}, + ltTestCase{uint8(253), false, false, ""}, + + ltTestCase{uint16((1 << 16) - 151), false, false, ""}, + ltTestCase{uint16(0), false, false, ""}, + ltTestCase{uint16(17), false, false, ""}, + + ltTestCase{uint32((1 << 32) - 151), false, false, ""}, + ltTestCase{uint32(0), false, false, ""}, + ltTestCase{uint32(17), false, false, ""}, + + ltTestCase{uint64((1 << 64) - 151), false, false, ""}, + ltTestCase{uint64(0), false, false, ""}, + ltTestCase{uint64(17), false, false, ""}, + + // Floating point. + ltTestCase{float32(-(1 << 30)), true, false, ""}, + ltTestCase{float32(-151), true, false, ""}, + ltTestCase{float32(-150.1), true, false, ""}, + ltTestCase{float32(-150), false, false, ""}, + ltTestCase{float32(-149.9), false, false, ""}, + ltTestCase{float32(0), false, false, ""}, + ltTestCase{float32(17), false, false, ""}, + ltTestCase{float32(160), false, false, ""}, + + ltTestCase{float64(-(1 << 30)), true, false, ""}, + ltTestCase{float64(-151), true, false, ""}, + ltTestCase{float64(-150.1), true, false, ""}, + ltTestCase{float64(-150), false, false, ""}, + ltTestCase{float64(-149.9), false, false, ""}, + ltTestCase{float64(0), false, false, ""}, + ltTestCase{float64(17), false, false, ""}, + ltTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) ZeroIntegerLiteral() { + matcher := LessThan(0) + desc := matcher.Description() + expectedDesc := "less than 0" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-(1 << 30), true, false, ""}, + ltTestCase{-1, true, false, ""}, + ltTestCase{0, false, false, ""}, + ltTestCase{1, false, false, ""}, + ltTestCase{17, false, false, ""}, + ltTestCase{(1 << 30), false, false, ""}, + + ltTestCase{int(-(1 << 30)), true, false, ""}, + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(0), false, false, ""}, + ltTestCase{int(1), false, false, ""}, + ltTestCase{int(17), false, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(0), false, false, ""}, + ltTestCase{int8(1), false, false, ""}, + + ltTestCase{int16(-(1 << 14)), true, false, ""}, + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(0), false, false, ""}, + ltTestCase{int16(1), false, false, ""}, + ltTestCase{int16(17), false, false, ""}, + + ltTestCase{int32(-(1 << 30)), true, false, ""}, + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(0), false, false, ""}, + ltTestCase{int32(1), false, false, ""}, + ltTestCase{int32(17), false, false, ""}, + + ltTestCase{int64(-(1 << 30)), true, false, ""}, + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(0), false, false, ""}, + ltTestCase{int64(1), false, false, ""}, + ltTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint((1 << 32) - 1), false, false, ""}, + ltTestCase{uint(0), false, false, ""}, + ltTestCase{uint(17), false, false, ""}, + + ltTestCase{uint8(0), false, false, ""}, + ltTestCase{uint8(17), false, false, ""}, + ltTestCase{uint8(253), false, false, ""}, + + ltTestCase{uint16((1 << 16) - 1), false, false, ""}, + ltTestCase{uint16(0), false, false, ""}, + ltTestCase{uint16(17), false, false, ""}, + + ltTestCase{uint32((1 << 32) - 1), false, false, ""}, + ltTestCase{uint32(0), false, false, ""}, + ltTestCase{uint32(17), false, false, ""}, + + ltTestCase{uint64((1 << 64) - 1), false, false, ""}, + ltTestCase{uint64(0), false, false, ""}, + ltTestCase{uint64(17), false, false, ""}, + + // Floating point. + ltTestCase{float32(-(1 << 30)), true, false, ""}, + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(-0.1), true, false, ""}, + ltTestCase{float32(-0.0), false, false, ""}, + ltTestCase{float32(0), false, false, ""}, + ltTestCase{float32(0.1), false, false, ""}, + ltTestCase{float32(17), false, false, ""}, + ltTestCase{float32(160), false, false, ""}, + + ltTestCase{float64(-(1 << 30)), true, false, ""}, + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(-0.1), true, false, ""}, + ltTestCase{float64(-0), false, false, ""}, + ltTestCase{float64(0), false, false, ""}, + ltTestCase{float64(17), false, false, ""}, + ltTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) PositiveIntegerLiteral() { + matcher := LessThan(150) + desc := matcher.Description() + expectedDesc := "less than 150" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{149, true, false, ""}, + ltTestCase{150, false, false, ""}, + ltTestCase{151, false, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(149), true, false, ""}, + ltTestCase{int(150), false, false, ""}, + ltTestCase{int(151), false, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(0), true, false, ""}, + ltTestCase{int8(17), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(149), true, false, ""}, + ltTestCase{int16(150), false, false, ""}, + ltTestCase{int16(151), false, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(149), true, false, ""}, + ltTestCase{int32(150), false, false, ""}, + ltTestCase{int32(151), false, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(149), true, false, ""}, + ltTestCase{int64(150), false, false, ""}, + ltTestCase{int64(151), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(149), true, false, ""}, + ltTestCase{uint(150), false, false, ""}, + ltTestCase{uint(151), false, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(127), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(149), true, false, ""}, + ltTestCase{uint16(150), false, false, ""}, + ltTestCase{uint16(151), false, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(149), true, false, ""}, + ltTestCase{uint32(150), false, false, ""}, + ltTestCase{uint32(151), false, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(149), true, false, ""}, + ltTestCase{uint64(150), false, false, ""}, + ltTestCase{uint64(151), false, false, ""}, + + // Floating point. + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(149), true, false, ""}, + ltTestCase{float32(149.9), true, false, ""}, + ltTestCase{float32(150), false, false, ""}, + ltTestCase{float32(150.1), false, false, ""}, + ltTestCase{float32(151), false, false, ""}, + + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(149), true, false, ""}, + ltTestCase{float64(149.9), true, false, ""}, + ltTestCase{float64(150), false, false, ""}, + ltTestCase{float64(150.1), false, false, ""}, + ltTestCase{float64(151), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Float literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessThanTest) NegativeFloatLiteral() { + matcher := LessThan(-150.1) + desc := matcher.Description() + expectedDesc := "less than -150.1" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-(1 << 30), true, false, ""}, + ltTestCase{-151, true, false, ""}, + ltTestCase{-150, false, false, ""}, + ltTestCase{0, false, false, ""}, + ltTestCase{17, false, false, ""}, + + ltTestCase{int(-(1 << 30)), true, false, ""}, + ltTestCase{int(-151), true, false, ""}, + ltTestCase{int(-150), false, false, ""}, + ltTestCase{int(0), false, false, ""}, + ltTestCase{int(17), false, false, ""}, + + ltTestCase{int8(-127), false, false, ""}, + ltTestCase{int8(0), false, false, ""}, + ltTestCase{int8(17), false, false, ""}, + + ltTestCase{int16(-(1 << 14)), true, false, ""}, + ltTestCase{int16(-151), true, false, ""}, + ltTestCase{int16(-150), false, false, ""}, + ltTestCase{int16(0), false, false, ""}, + ltTestCase{int16(17), false, false, ""}, + + ltTestCase{int32(-(1 << 30)), true, false, ""}, + ltTestCase{int32(-151), true, false, ""}, + ltTestCase{int32(-150), false, false, ""}, + ltTestCase{int32(0), false, false, ""}, + ltTestCase{int32(17), false, false, ""}, + + ltTestCase{int64(-(1 << 30)), true, false, ""}, + ltTestCase{int64(-151), true, false, ""}, + ltTestCase{int64(-150), false, false, ""}, + ltTestCase{int64(0), false, false, ""}, + ltTestCase{int64(17), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint((1 << 32) - 151), false, false, ""}, + ltTestCase{uint(0), false, false, ""}, + ltTestCase{uint(17), false, false, ""}, + + ltTestCase{uint8(0), false, false, ""}, + ltTestCase{uint8(17), false, false, ""}, + ltTestCase{uint8(253), false, false, ""}, + + ltTestCase{uint16((1 << 16) - 151), false, false, ""}, + ltTestCase{uint16(0), false, false, ""}, + ltTestCase{uint16(17), false, false, ""}, + + ltTestCase{uint32((1 << 32) - 151), false, false, ""}, + ltTestCase{uint32(0), false, false, ""}, + ltTestCase{uint32(17), false, false, ""}, + + ltTestCase{uint64((1 << 64) - 151), false, false, ""}, + ltTestCase{uint64(0), false, false, ""}, + ltTestCase{uint64(17), false, false, ""}, + + // Floating point. + ltTestCase{float32(-(1 << 30)), true, false, ""}, + ltTestCase{float32(-151), true, false, ""}, + ltTestCase{float32(-150.2), true, false, ""}, + ltTestCase{float32(-150.1), false, false, ""}, + ltTestCase{float32(-150), false, false, ""}, + ltTestCase{float32(0), false, false, ""}, + ltTestCase{float32(17), false, false, ""}, + ltTestCase{float32(160), false, false, ""}, + + ltTestCase{float64(-(1 << 30)), true, false, ""}, + ltTestCase{float64(-151), true, false, ""}, + ltTestCase{float64(-150.2), true, false, ""}, + ltTestCase{float64(-150.1), false, false, ""}, + ltTestCase{float64(-150), false, false, ""}, + ltTestCase{float64(0), false, false, ""}, + ltTestCase{float64(17), false, false, ""}, + ltTestCase{float64(160), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) PositiveFloatLiteral() { + matcher := LessThan(149.9) + desc := matcher.Description() + expectedDesc := "less than 149.9" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{149, true, false, ""}, + ltTestCase{150, false, false, ""}, + ltTestCase{151, false, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(149), true, false, ""}, + ltTestCase{int(150), false, false, ""}, + ltTestCase{int(151), false, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(0), true, false, ""}, + ltTestCase{int8(17), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(149), true, false, ""}, + ltTestCase{int16(150), false, false, ""}, + ltTestCase{int16(151), false, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(149), true, false, ""}, + ltTestCase{int32(150), false, false, ""}, + ltTestCase{int32(151), false, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(149), true, false, ""}, + ltTestCase{int64(150), false, false, ""}, + ltTestCase{int64(151), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(149), true, false, ""}, + ltTestCase{uint(150), false, false, ""}, + ltTestCase{uint(151), false, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(127), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(149), true, false, ""}, + ltTestCase{uint16(150), false, false, ""}, + ltTestCase{uint16(151), false, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(149), true, false, ""}, + ltTestCase{uint32(150), false, false, ""}, + ltTestCase{uint32(151), false, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(149), true, false, ""}, + ltTestCase{uint64(150), false, false, ""}, + ltTestCase{uint64(151), false, false, ""}, + + // Floating point. + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(149), true, false, ""}, + ltTestCase{float32(149.8), true, false, ""}, + ltTestCase{float32(149.9), false, false, ""}, + ltTestCase{float32(150), false, false, ""}, + ltTestCase{float32(151), false, false, ""}, + + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(149), true, false, ""}, + ltTestCase{float64(149.8), true, false, ""}, + ltTestCase{float64(149.9), false, false, ""}, + ltTestCase{float64(150), false, false, ""}, + ltTestCase{float64(151), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// Subtle cases +//////////////////////////////////////////////////////////////////////// + +func (t *LessThanTest) Int64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessThan(int64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{kTwoTo25 + 0, true, false, ""}, + ltTestCase{kTwoTo25 + 1, false, false, ""}, + ltTestCase{kTwoTo25 + 2, false, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(0), true, false, ""}, + ltTestCase{int16(32767), true, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int32(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(255), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(65535), true, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint32(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Floating point. + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 1), true, false, ""}, + ltTestCase{float64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) Int64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessThan(int64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{1 << 30, true, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(math.MaxInt32), true, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(0), true, false, ""}, + ltTestCase{int16(32767), true, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(math.MaxInt32), true, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo54 - 1), true, false, ""}, + ltTestCase{int64(kTwoTo54 + 0), true, false, ""}, + ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(math.MaxUint32), true, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(255), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(65535), true, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(math.MaxUint32), true, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + ltTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Floating point. + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) Uint64NotExactlyRepresentableBySinglePrecision() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessThan(uint64(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 33554433" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{kTwoTo25 + 0, true, false, ""}, + ltTestCase{kTwoTo25 + 1, false, false, ""}, + ltTestCase{kTwoTo25 + 2, false, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(0), true, false, ""}, + ltTestCase{int16(32767), true, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int32(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(255), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(65535), true, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint32(kTwoTo25 + 2), false, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + + // Floating point. + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 1), true, false, ""}, + ltTestCase{float64(kTwoTo25 + 0), true, false, ""}, + ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) Uint64NotExactlyRepresentableByDoublePrecision() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessThan(uint64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 18014398509481985" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{-1, true, false, ""}, + ltTestCase{1 << 30, true, false, ""}, + + ltTestCase{int(-1), true, false, ""}, + ltTestCase{int(math.MaxInt32), true, false, ""}, + + ltTestCase{int8(-1), true, false, ""}, + ltTestCase{int8(127), true, false, ""}, + + ltTestCase{int16(-1), true, false, ""}, + ltTestCase{int16(0), true, false, ""}, + ltTestCase{int16(32767), true, false, ""}, + + ltTestCase{int32(-1), true, false, ""}, + ltTestCase{int32(math.MaxInt32), true, false, ""}, + + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo54 - 1), true, false, ""}, + ltTestCase{int64(kTwoTo54 + 0), true, false, ""}, + ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint(0), true, false, ""}, + ltTestCase{uint(math.MaxUint32), true, false, ""}, + + ltTestCase{uint8(0), true, false, ""}, + ltTestCase{uint8(255), true, false, ""}, + + ltTestCase{uint16(0), true, false, ""}, + ltTestCase{uint16(65535), true, false, ""}, + + ltTestCase{uint32(0), true, false, ""}, + ltTestCase{uint32(math.MaxUint32), true, false, ""}, + + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo54 - 1), true, false, ""}, + ltTestCase{uint64(kTwoTo54 + 0), true, false, ""}, + ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + + // Floating point. + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) Float32AboveExactIntegerRange() { + // Single-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^25-1, 2^25+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo25 = 1 << 25 + matcher := LessThan(float32(kTwoTo25 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 3.3554432e+07" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo25 - 2), true, false, ""}, + ltTestCase{int64(kTwoTo25 - 1), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 0), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 2), false, false, ""}, + ltTestCase{int64(kTwoTo25 + 3), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo25 - 2), true, false, ""}, + ltTestCase{uint64(kTwoTo25 - 1), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 0), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 2), false, false, ""}, + ltTestCase{uint64(kTwoTo25 + 3), false, false, ""}, + + // Floating point. + ltTestCase{float32(-1), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float32(kTwoTo25 - 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 0), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float32(kTwoTo25 + 3), false, false, ""}, + + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo25 - 1), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 0), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo25 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) Float64AboveExactIntegerRange() { + // Double-precision floats don't have enough bits to represent the integers + // near this one distinctly, so [2^54-1, 2^54+2] all receive the same value + // and should be treated as equivalent when floats are in the mix. + const kTwoTo54 = 1 << 54 + matcher := LessThan(float64(kTwoTo54 + 1)) + + desc := matcher.Description() + expectedDesc := "less than 1.8014398509481984e+16" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + // Signed integers. + ltTestCase{int64(-1), true, false, ""}, + ltTestCase{int64(kTwoTo54 - 2), true, false, ""}, + ltTestCase{int64(kTwoTo54 - 1), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 0), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 2), false, false, ""}, + ltTestCase{int64(kTwoTo54 + 3), false, false, ""}, + + // Unsigned integers. + ltTestCase{uint64(0), true, false, ""}, + ltTestCase{uint64(kTwoTo54 - 2), true, false, ""}, + ltTestCase{uint64(kTwoTo54 - 1), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 0), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 2), false, false, ""}, + ltTestCase{uint64(kTwoTo54 + 3), false, false, ""}, + + // Floating point. + ltTestCase{float64(-1), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 2), true, false, ""}, + ltTestCase{float64(kTwoTo54 - 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 0), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 1), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 2), false, false, ""}, + ltTestCase{float64(kTwoTo54 + 3), false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +//////////////////////////////////////////////////////////////////////// +// String literals +//////////////////////////////////////////////////////////////////////// + +func (t *LessThanTest) EmptyString() { + matcher := LessThan("") + desc := matcher.Description() + expectedDesc := "less than \"\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + ltTestCase{"", false, false, ""}, + ltTestCase{"\x00", false, false, ""}, + ltTestCase{"a", false, false, ""}, + ltTestCase{"foo", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) SingleNullByte() { + matcher := LessThan("\x00") + desc := matcher.Description() + expectedDesc := "less than \"\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + ltTestCase{"", true, false, ""}, + ltTestCase{"\x00", false, false, ""}, + ltTestCase{"a", false, false, ""}, + ltTestCase{"foo", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} + +func (t *LessThanTest) LongerString() { + matcher := LessThan("foo\x00") + desc := matcher.Description() + expectedDesc := "less than \"foo\x00\"" + + ExpectThat(desc, Equals(expectedDesc)) + + cases := []ltTestCase{ + ltTestCase{"", true, false, ""}, + ltTestCase{"\x00", true, false, ""}, + ltTestCase{"bar", true, false, ""}, + ltTestCase{"foo", true, false, ""}, + ltTestCase{"foo\x00", false, false, ""}, + ltTestCase{"fooa", false, false, ""}, + ltTestCase{"qux", false, false, ""}, + } + + t.checkTestCases(matcher, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/matcher.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matcher.go new file mode 100644 index 0000000000..78159a0727 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matcher.go @@ -0,0 +1,86 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers provides a set of matchers useful in a testing or +// mocking framework. These matchers are inspired by and mostly compatible with +// Google Test for C++ and Google JS Test. +// +// This package is used by github.com/smartystreets/assertions/internal/ogletest and +// github.com/smartystreets/assertions/internal/oglemock, which may be more directly useful if you're not +// writing your own testing package or defining your own matchers. +package oglematchers + +// A Matcher is some predicate implicitly defining a set of values that it +// matches. For example, GreaterThan(17) matches all numeric values greater +// than 17, and HasSubstr("taco") matches all strings with the substring +// "taco". +// +// Matchers are typically exposed to tests via constructor functions like +// HasSubstr. In order to implement such a function you can either define your +// own matcher type or use NewMatcher. +type Matcher interface { + // Check whether the supplied value belongs to the the set defined by the + // matcher. Return a non-nil error if and only if it does not. + // + // The error describes why the value doesn't match. The error text is a + // relative clause that is suitable for being placed after the value. For + // example, a predicate that matches strings with a particular substring may, + // when presented with a numerical value, return the following error text: + // + // "which is not a string" + // + // Then the failure message may look like: + // + // Expected: has substring "taco" + // Actual: 17, which is not a string + // + // If the error is self-apparent based on the description of the matcher, the + // error text may be empty (but the error still non-nil). For example: + // + // Expected: 17 + // Actual: 19 + // + // If you are implementing a new matcher, see also the documentation on + // FatalError. + Matches(candidate interface{}) error + + // Description returns a string describing the property that values matching + // this matcher have, as a verb phrase where the subject is the value. For + // example, "is greather than 17" or "has substring "taco"". + Description() string +} + +// FatalError is an implementation of the error interface that may be returned +// from matchers, indicating the error should be propagated. Returning a +// *FatalError indicates that the matcher doesn't process values of the +// supplied type, or otherwise doesn't know how to handle the value. +// +// For example, if GreaterThan(17) returned false for the value "taco" without +// a fatal error, then Not(GreaterThan(17)) would return true. This is +// technically correct, but is surprising and may mask failures where the wrong +// sort of matcher is accidentally used. Instead, GreaterThan(17) can return a +// fatal error, which will be propagated by Not(). +type FatalError struct { + errorText string +} + +// NewFatalError creates a FatalError struct with the supplied error text. +func NewFatalError(s string) *FatalError { + return &FatalError{s} +} + +func (e *FatalError) Error() string { + return e.errorText +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp.go new file mode 100644 index 0000000000..1ed63f30c4 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp.go @@ -0,0 +1,69 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" + "regexp" +) + +// MatchesRegexp returns a matcher that matches strings and byte slices whose +// contents match the supplied regular expression. The semantics are those of +// regexp.Match. In particular, that means the match is not implicitly anchored +// to the ends of the string: MatchesRegexp("bar") will match "foo bar baz". +func MatchesRegexp(pattern string) Matcher { + re, err := regexp.Compile(pattern) + if err != nil { + panic("MatchesRegexp: " + err.Error()) + } + + return &matchesRegexpMatcher{re} +} + +type matchesRegexpMatcher struct { + re *regexp.Regexp +} + +func (m *matchesRegexpMatcher) Description() string { + return fmt.Sprintf("matches regexp \"%s\"", m.re.String()) +} + +func (m *matchesRegexpMatcher) Matches(c interface{}) (err error) { + v := reflect.ValueOf(c) + isString := v.Kind() == reflect.String + isByteSlice := v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Uint8 + + err = errors.New("") + + switch { + case isString: + if m.re.MatchString(v.String()) { + err = nil + } + + case isByteSlice: + if m.re.Match(v.Bytes()) { + err = nil + } + + default: + err = NewFatalError("which is not a string or []byte") + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp_test.go new file mode 100644 index 0000000000..0412bbd77d --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/matches_regexp_test.go @@ -0,0 +1,92 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type MatchesRegexpTest struct { +} + +func init() { RegisterTestSuite(&MatchesRegexpTest{}) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *MatchesRegexpTest) Description() { + m := MatchesRegexp("foo.*bar") + ExpectEq("matches regexp \"foo.*bar\"", m.Description()) +} + +func (t *MatchesRegexpTest) InvalidRegexp() { + ExpectThat( + func() { MatchesRegexp("(foo") }, + Panics(HasSubstr("missing closing )"))) +} + +func (t *MatchesRegexpTest) CandidateIsNil() { + m := MatchesRegexp("") + err := m.Matches(nil) + + ExpectThat(err, Error(Equals("which is not a string or []byte"))) + ExpectTrue(isFatal(err)) +} + +func (t *MatchesRegexpTest) CandidateIsInteger() { + m := MatchesRegexp("") + err := m.Matches(17) + + ExpectThat(err, Error(Equals("which is not a string or []byte"))) + ExpectTrue(isFatal(err)) +} + +func (t *MatchesRegexpTest) NonMatchingCandidates() { + m := MatchesRegexp("fo[op]\\s+x") + var err error + + err = m.Matches("fon x") + ExpectThat(err, Error(Equals(""))) + ExpectFalse(isFatal(err)) + + err = m.Matches("fopx") + ExpectThat(err, Error(Equals(""))) + ExpectFalse(isFatal(err)) + + err = m.Matches("fop ") + ExpectThat(err, Error(Equals(""))) + ExpectFalse(isFatal(err)) +} + +func (t *MatchesRegexpTest) MatchingCandidates() { + m := MatchesRegexp("fo[op]\\s+x") + var err error + + err = m.Matches("foo x") + ExpectEq(nil, err) + + err = m.Matches("fop x") + ExpectEq(nil, err) + + err = m.Matches("blah blah foo x blah blah") + ExpectEq(nil, err) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/new_matcher.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/new_matcher.go new file mode 100644 index 0000000000..c9d8398ee6 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/new_matcher.go @@ -0,0 +1,43 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +// Create a matcher with the given description and predicate function, which +// will be invoked to handle calls to Matchers. +// +// Using this constructor may be a convenience over defining your own type that +// implements Matcher if you do not need any logic in your Description method. +func NewMatcher( + predicate func(interface{}) error, + description string) Matcher { + return &predicateMatcher{ + predicate: predicate, + description: description, + } +} + +type predicateMatcher struct { + predicate func(interface{}) error + description string +} + +func (pm *predicateMatcher) Matches(c interface{}) error { + return pm.predicate(c) +} + +func (pm *predicateMatcher) Description() string { + return pm.description +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/not.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/not.go new file mode 100644 index 0000000000..623789fe28 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/not.go @@ -0,0 +1,53 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" +) + +// Not returns a matcher that inverts the set of values matched by the wrapped +// matcher. It does not transform the result for values for which the wrapped +// matcher returns a fatal error. +func Not(m Matcher) Matcher { + return ¬Matcher{m} +} + +type notMatcher struct { + wrapped Matcher +} + +func (m *notMatcher) Matches(c interface{}) (err error) { + err = m.wrapped.Matches(c) + + // Did the wrapped matcher say yes? + if err == nil { + return errors.New("") + } + + // Did the wrapped matcher return a fatal error? + if _, isFatal := err.(*FatalError); isFatal { + return err + } + + // The wrapped matcher returned a non-fatal error. + return nil +} + +func (m *notMatcher) Description() string { + return fmt.Sprintf("not(%s)", m.wrapped.Description()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/not_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/not_test.go new file mode 100644 index 0000000000..9503b018f7 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/not_test.go @@ -0,0 +1,107 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "testing" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type fakeMatcher struct { + matchFunc func(interface{}) error + description string +} + +func (m *fakeMatcher) Matches(c interface{}) error { + return m.matchFunc(c) +} + +func (m *fakeMatcher) Description() string { + return m.description +} + +type NotTest struct { +} + +func init() { RegisterTestSuite(&NotTest{}) } +func TestOgletest(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *NotTest) CallsWrapped() { + var suppliedCandidate interface{} + matchFunc := func(c interface{}) error { + suppliedCandidate = c + return nil + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Not(wrapped) + + matcher.Matches(17) + ExpectThat(suppliedCandidate, Equals(17)) +} + +func (t *NotTest) WrappedReturnsTrue() { + matchFunc := func(c interface{}) error { + return nil + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Not(wrapped) + + err := matcher.Matches(0) + ExpectThat(err, Error(Equals(""))) +} + +func (t *NotTest) WrappedReturnsNonFatalError() { + matchFunc := func(c interface{}) error { + return errors.New("taco") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Not(wrapped) + + err := matcher.Matches(0) + ExpectEq(nil, err) +} + +func (t *NotTest) WrappedReturnsFatalError() { + matchFunc := func(c interface{}) error { + return NewFatalError("taco") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Not(wrapped) + + err := matcher.Matches(0) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *NotTest) Description() { + wrapped := &fakeMatcher{nil, "taco"} + matcher := Not(wrapped) + + ExpectEq("not(taco)", matcher.Description()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics.go new file mode 100644 index 0000000000..d2cfc97869 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics.go @@ -0,0 +1,74 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" +) + +// Panics matches zero-arg functions which, when invoked, panic with an error +// that matches the supplied matcher. +// +// NOTE(jacobsa): This matcher cannot detect the case where the function panics +// using panic(nil), by design of the language. See here for more info: +// +// http://goo.gl/9aIQL +// +func Panics(m Matcher) Matcher { + return &panicsMatcher{m} +} + +type panicsMatcher struct { + wrappedMatcher Matcher +} + +func (m *panicsMatcher) Description() string { + return "panics with: " + m.wrappedMatcher.Description() +} + +func (m *panicsMatcher) Matches(c interface{}) (err error) { + // Make sure c is a zero-arg function. + v := reflect.ValueOf(c) + if v.Kind() != reflect.Func || v.Type().NumIn() != 0 { + err = NewFatalError("which is not a zero-arg function") + return + } + + // Call the function and check its panic error. + defer func() { + if e := recover(); e != nil { + err = m.wrappedMatcher.Matches(e) + + // Set a clearer error message if the matcher said no. + if err != nil { + wrappedClause := "" + if err.Error() != "" { + wrappedClause = ", " + err.Error() + } + + err = errors.New(fmt.Sprintf("which panicked with: %v%s", e, wrappedClause)) + } + } + }() + + v.Call([]reflect.Value{}) + + // If we get here, the function didn't panic. + err = errors.New("which didn't panic") + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics_test.go new file mode 100644 index 0000000000..81b227d26e --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/panics_test.go @@ -0,0 +1,141 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type PanicsTest struct { + matcherCalled bool + suppliedCandidate interface{} + wrappedError error + + matcher Matcher +} + +func init() { RegisterTestSuite(&PanicsTest{}) } + +func (t *PanicsTest) SetUp(i *TestInfo) { + wrapped := &fakeMatcher{ + func(c interface{}) error { + t.matcherCalled = true + t.suppliedCandidate = c + return t.wrappedError + }, + "foo", + } + + t.matcher = Panics(wrapped) +} + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *PanicsTest) Description() { + ExpectThat(t.matcher.Description(), Equals("panics with: foo")) +} + +func (t *PanicsTest) CandidateIsNil() { + err := t.matcher.Matches(nil) + + ExpectThat(err, Error(Equals("which is not a zero-arg function"))) + ExpectTrue(isFatal(err)) +} + +func (t *PanicsTest) CandidateIsString() { + err := t.matcher.Matches("taco") + + ExpectThat(err, Error(Equals("which is not a zero-arg function"))) + ExpectTrue(isFatal(err)) +} + +func (t *PanicsTest) CandidateTakesArgs() { + err := t.matcher.Matches(func(i int) string { return "" }) + + ExpectThat(err, Error(Equals("which is not a zero-arg function"))) + ExpectTrue(isFatal(err)) +} + +func (t *PanicsTest) CallsFunction() { + callCount := 0 + t.matcher.Matches(func() string { + callCount++ + return "" + }) + + ExpectThat(callCount, Equals(1)) +} + +func (t *PanicsTest) FunctionDoesntPanic() { + err := t.matcher.Matches(func() {}) + + ExpectThat(err, Error(Equals("which didn't panic"))) + ExpectFalse(isFatal(err)) +} + +func (t *PanicsTest) CallsWrappedMatcher() { + expectedErr := 17 + t.wrappedError = errors.New("") + t.matcher.Matches(func() { panic(expectedErr) }) + + ExpectThat(t.suppliedCandidate, Equals(expectedErr)) +} + +func (t *PanicsTest) WrappedReturnsTrue() { + err := t.matcher.Matches(func() { panic("") }) + + ExpectEq(nil, err) +} + +func (t *PanicsTest) WrappedReturnsFatalErrorWithoutText() { + t.wrappedError = NewFatalError("") + err := t.matcher.Matches(func() { panic(17) }) + + ExpectThat(err, Error(Equals("which panicked with: 17"))) + ExpectFalse(isFatal(err)) +} + +func (t *PanicsTest) WrappedReturnsFatalErrorWithText() { + t.wrappedError = NewFatalError("which blah") + err := t.matcher.Matches(func() { panic(17) }) + + ExpectThat(err, Error(Equals("which panicked with: 17, which blah"))) + ExpectFalse(isFatal(err)) +} + +func (t *PanicsTest) WrappedReturnsNonFatalErrorWithoutText() { + t.wrappedError = errors.New("") + err := t.matcher.Matches(func() { panic(17) }) + + ExpectThat(err, Error(Equals("which panicked with: 17"))) + ExpectFalse(isFatal(err)) +} + +func (t *PanicsTest) WrappedReturnsNonFatalErrorWithText() { + t.wrappedError = errors.New("which blah") + err := t.matcher.Matches(func() { panic(17) }) + + ExpectThat(err, Error(Equals("which panicked with: 17, which blah"))) + ExpectFalse(isFatal(err)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee.go new file mode 100644 index 0000000000..c5383f2402 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee.go @@ -0,0 +1,65 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +import ( + "errors" + "fmt" + "reflect" +) + +// Return a matcher that matches non-nil pointers whose pointee matches the +// wrapped matcher. +func Pointee(m Matcher) Matcher { + return &pointeeMatcher{m} +} + +type pointeeMatcher struct { + wrapped Matcher +} + +func (m *pointeeMatcher) Matches(c interface{}) (err error) { + // Make sure the candidate is of the appropriate type. + cv := reflect.ValueOf(c) + if !cv.IsValid() || cv.Kind() != reflect.Ptr { + return NewFatalError("which is not a pointer") + } + + // Make sure the candidate is non-nil. + if cv.IsNil() { + return NewFatalError("") + } + + // Defer to the wrapped matcher. Fix up empty errors so that failure messages + // are more helpful than just printing a pointer for "Actual". + pointee := cv.Elem().Interface() + err = m.wrapped.Matches(pointee) + if err != nil && err.Error() == "" { + s := fmt.Sprintf("whose pointee is %v", pointee) + + if _, ok := err.(*FatalError); ok { + err = NewFatalError(s) + } else { + err = errors.New(s) + } + } + + return err +} + +func (m *pointeeMatcher) Description() string { + return fmt.Sprintf("pointee(%s)", m.wrapped.Description()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee_test.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee_test.go new file mode 100644 index 0000000000..70ed1c1d7a --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/pointee_test.go @@ -0,0 +1,153 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "testing" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type PointeeTest struct{} + +func init() { RegisterTestSuite(&PointeeTest{}) } + +func TestPointee(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *PointeeTest) Description() { + wrapped := &fakeMatcher{nil, "taco"} + matcher := Pointee(wrapped) + + ExpectEq("pointee(taco)", matcher.Description()) +} + +func (t *PointeeTest) CandidateIsNotAPointer() { + matcher := Pointee(HasSubstr("")) + err := matcher.Matches([]byte{}) + + ExpectThat(err, Error(Equals("which is not a pointer"))) + ExpectTrue(isFatal(err)) +} + +func (t *PointeeTest) CandidateIsANilLiteral() { + matcher := Pointee(HasSubstr("")) + err := matcher.Matches(nil) + + ExpectThat(err, Error(Equals("which is not a pointer"))) + ExpectTrue(isFatal(err)) +} + +func (t *PointeeTest) CandidateIsANilPointer() { + matcher := Pointee(HasSubstr("")) + err := matcher.Matches((*int)(nil)) + + ExpectThat(err, Error(Equals(""))) + ExpectTrue(isFatal(err)) +} + +func (t *PointeeTest) CallsWrapped() { + var suppliedCandidate interface{} + matchFunc := func(c interface{}) error { + suppliedCandidate = c + return nil + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + someSlice := []byte{} + matcher.Matches(&someSlice) + ExpectThat(suppliedCandidate, IdenticalTo(someSlice)) +} + +func (t *PointeeTest) WrappedReturnsOkay() { + matchFunc := func(c interface{}) error { + return nil + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + err := matcher.Matches(new(int)) + ExpectEq(nil, err) +} + +func (t *PointeeTest) WrappedReturnsNonFatalNonEmptyError() { + matchFunc := func(c interface{}) error { + return errors.New("taco") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + i := 17 + err := matcher.Matches(&i) + ExpectFalse(isFatal(err)) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *PointeeTest) WrappedReturnsNonFatalEmptyError() { + matchFunc := func(c interface{}) error { + return errors.New("") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + i := 17 + err := matcher.Matches(&i) + ExpectFalse(isFatal(err)) + ExpectThat(err, Error(HasSubstr("whose pointee"))) + ExpectThat(err, Error(HasSubstr("17"))) +} + +func (t *PointeeTest) WrappedReturnsFatalNonEmptyError() { + matchFunc := func(c interface{}) error { + return NewFatalError("taco") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + i := 17 + err := matcher.Matches(&i) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(Equals("taco"))) +} + +func (t *PointeeTest) WrappedReturnsFatalEmptyError() { + matchFunc := func(c interface{}) error { + return NewFatalError("") + } + + wrapped := &fakeMatcher{matchFunc, ""} + matcher := Pointee(wrapped) + + i := 17 + err := matcher.Matches(&i) + ExpectTrue(isFatal(err)) + ExpectThat(err, Error(HasSubstr("whose pointee"))) + ExpectThat(err, Error(HasSubstr("17"))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglematchers/transform_description.go b/vendor/github.com/smartystreets/assertions/internal/oglematchers/transform_description.go new file mode 100644 index 0000000000..8ea2807c6f --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglematchers/transform_description.go @@ -0,0 +1,36 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglematchers + +// transformDescription returns a matcher that is equivalent to the supplied +// one, except that it has the supplied description instead of the one attached +// to the existing matcher. +func transformDescription(m Matcher, newDesc string) Matcher { + return &transformDescriptionMatcher{newDesc, m} +} + +type transformDescriptionMatcher struct { + desc string + wrappedMatcher Matcher +} + +func (m *transformDescriptionMatcher) Description() string { + return m.desc +} + +func (m *transformDescriptionMatcher) Matches(c interface{}) error { + return m.wrappedMatcher.Matches(c) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/LICENSE b/vendor/github.com/smartystreets/assertions/internal/oglemock/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/README.md b/vendor/github.com/smartystreets/assertions/internal/oglemock/README.md new file mode 100644 index 0000000000..c5cb5c06b3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/README.md @@ -0,0 +1,103 @@ +[![GoDoc](https://godoc.org/github.com/smartystreets/assertions/internal/oglemock?status.svg)](https://godoc.org/github.com/smartystreets/assertions/internal/oglemock) + +`oglemock` is a mocking framework for the Go programming language with the +following features: + + * An extensive and extensible set of matchers for expressing call + expectations (provided by the [oglematchers][] package). + + * Clean, readable output that tells you exactly what you need to know. + + * Style and semantics similar to [Google Mock][googlemock] and + [Google JS Test][google-js-test]. + + * Seamless integration with the [ogletest][] unit testing framework. + +It can be integrated into any testing framework (including Go's `testing` +package), but out of the box support is built in to [ogletest][] and that is the +easiest place to use it. + + +Installation +------------ + +First, make sure you have installed Go 1.0.2 or newer. See +[here][golang-install] for instructions. + +Use the following command to install `oglemock` and its dependencies, and to +keep them up to date: + + go get -u github.com/smartystreets/assertions/internal/oglemock + go get -u github.com/smartystreets/assertions/internal/oglemock/createmock + +Those commands will install the `oglemock` package itself, along with the +`createmock` tool that is used to auto-generate mock types. + + +Generating and using mock types +------------------------------- + +Automatically generating a mock implementation of an interface is easy. If you +want to mock interfaces `Bar` and `Baz` from package `foo`, simply run the +following: + + createmock foo Bar Baz + +That will print source code that can be saved to a file and used in your tests. +For example, to create a `mock_io` package containing mock implementations of +`io.Reader` and `io.Writer`: + + mkdir mock_io + createmock io Reader Writer > mock_io/mock_io.go + +The new package will be named `mock_io`, and contain types called `MockReader` +and `MockWriter`, which implement `io.Reader` and `io.Writer` respectively. + +For each generated mock type, there is a corresponding function for creating an +instance of that type given a `Controller` object (see below). For example, to +create a mock reader: + +```go +someController := [...] // See next section. +someReader := mock_io.NewMockReader(someController, "Mock file reader") +``` + +The snippet above creates a mock `io.Reader` that reports failures to +`someController`. The reader can subsequently have expectations set up and be +passed to your code under test that uses an `io.Reader`. + + +Getting ahold of a controller +----------------------------- + +[oglemock.Controller][controller-ref] is used to create mock objects, and to set +up and verify expectations for them. You can create one by calling +`NewController` with an `ErrorReporter`, which is the basic type used to +interface between `oglemock` and the testing framework within which it is being +used. + +If you are using [ogletest][] you don't need to worry about any of this, since +the `TestInfo` struct provided to your test's `SetUp` function already contains +a working `Controller` that you can use to create mock object, and you can use +the built-in `ExpectCall` function for setting expectations. (See the +[ogletest documentation][ogletest-docs] for more info.) Otherwise, you will need +to implement the simple [ErrorReporter interface][reporter-ref] for your test +environment. + + +Documentation +------------- + +For thorough documentation, including information on how to set up expectations, +see [here][oglemock-docs]. + + +[controller-ref]: http://godoc.org/github.com/smartystreets/assertions/internal/oglemock#Controller +[reporter-ref]: http://godoc.org/github.com/smartystreets/assertions/internal/oglemock#ErrorReporter +[golang-install]: http://golang.org/doc/install.html +[google-js-test]: http://code.google.com/p/google-js-test/ +[googlemock]: http://code.google.com/p/googlemock/ +[oglematchers]: https://github.com/smartystreets/assertions/internal/oglematchers +[oglemock-docs]: http://godoc.org/github.com/smartystreets/assertions/internal/oglemock +[ogletest]: https://github.com/smartystreets/assertions/internal/ogletest +[ogletest-docs]: http://godoc.org/github.com/smartystreets/assertions/internal/ogletest diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/action.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/action.go new file mode 100644 index 0000000000..9fd40d81fe --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/action.go @@ -0,0 +1,36 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "reflect" +) + +// Action represents an action to be taken in response to a call to a mock +// method. +type Action interface { + // Set the signature of the function with which this action is being used. + // This must be called before Invoke is called. + SetSignature(signature reflect.Type) error + + // Invoke runs the specified action, given the arguments to the mock method. + // It returns zero or more values that may be treated as the return values of + // the method. If the action doesn't return any values, it may return the nil + // slice. + // + // You must call SetSignature before calling Invoke. + Invoke(methodArgs []interface{}) []interface{} +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/controller.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/controller.go new file mode 100644 index 0000000000..93a1d6239e --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/controller.go @@ -0,0 +1,480 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "errors" + "fmt" + "log" + "math" + "reflect" + "sync" +) + +// PartialExpecation is a function that should be called exactly once with +// expected arguments or matchers in order to set up an expected method call. +// See Controller.ExpectMethodCall below. It returns an expectation that can be +// further modified (e.g. by calling WillOnce). +// +// If the arguments are of the wrong type, the function reports a fatal error +// and returns nil. +type PartialExpecation func(...interface{}) Expectation + +// Controller represents an object that implements the central logic of +// oglemock: recording and verifying expectations, responding to mock method +// calls, and so on. +type Controller interface { + // ExpectCall expresses an expectation that the method of the given name + // should be called on the supplied mock object. It returns a function that + // should be called with the expected arguments, matchers for the arguments, + // or a mix of both. + // + // fileName and lineNumber should indicate the line on which the expectation + // was made, if known. + // + // For example: + // + // mockWriter := [...] + // controller.ExpectCall(mockWriter, "Write", "foo.go", 17)(ElementsAre(0x1)) + // .WillOnce(Return(1, nil)) + // + // If the mock object doesn't have a method of the supplied name, the + // function reports a fatal error and returns nil. + ExpectCall( + o MockObject, + methodName string, + fileName string, + lineNumber int) PartialExpecation + + // Finish causes the controller to check for any unsatisfied expectations, + // and report them as errors if they exist. + // + // The controller may panic if any of its methods (including this one) are + // called after Finish is called. + Finish() + + // HandleMethodCall looks for a registered expectation matching the call of + // the given method on mock object o, invokes the appropriate action (if + // any), and returns the values returned by that action (if any). + // + // If the action returns nothing, the controller returns zero values. If + // there is no matching expectation, the controller reports an error and + // returns zero values. + // + // If the mock object doesn't have a method of the supplied name, the + // arguments are of the wrong type, or the action returns the wrong types, + // the function reports a fatal error. + // + // HandleMethodCall is exported for the sake of mock implementations, and + // should not be used directly. + HandleMethodCall( + o MockObject, + methodName string, + fileName string, + lineNumber int, + args []interface{}) []interface{} +} + +// methodMap represents a map from method name to set of expectations for that +// method. +type methodMap map[string][]*InternalExpectation + +// objectMap represents a map from mock object ID to a methodMap for that object. +type objectMap map[uintptr]methodMap + +// NewController sets up a fresh controller, without any expectations set, and +// configures the controller to use the supplied error reporter. +func NewController(reporter ErrorReporter) Controller { + return &controllerImpl{reporter, sync.RWMutex{}, objectMap{}} +} + +type controllerImpl struct { + reporter ErrorReporter + + mutex sync.RWMutex + expectationsByObject objectMap // Protected by mutex +} + +// Return the list of registered expectations for the named method of the +// supplied object, or an empty slice if none have been registered. When this +// method returns, it is guaranteed that c.expectationsByObject has an entry +// for the object. +// +// c.mutex must be held for reading. +func (c *controllerImpl) getExpectationsLocked( + o MockObject, + methodName string) []*InternalExpectation { + id := o.Oglemock_Id() + + // Look up the mock object. + expectationsByMethod, ok := c.expectationsByObject[id] + if !ok { + expectationsByMethod = methodMap{} + c.expectationsByObject[id] = expectationsByMethod + } + + result, ok := expectationsByMethod[methodName] + if !ok { + return []*InternalExpectation{} + } + + return result +} + +// Add an expectation to the list registered for the named method of the +// supplied mock object. +// +// c.mutex must be held for writing. +func (c *controllerImpl) addExpectationLocked( + o MockObject, + methodName string, + exp *InternalExpectation) { + // Get the existing list. + existing := c.getExpectationsLocked(o, methodName) + + // Store a modified list. + id := o.Oglemock_Id() + c.expectationsByObject[id][methodName] = append(existing, exp) +} + +func (c *controllerImpl) ExpectCall( + o MockObject, + methodName string, + fileName string, + lineNumber int) PartialExpecation { + // Find the signature for the requested method. + ov := reflect.ValueOf(o) + method := ov.MethodByName(methodName) + if method.Kind() == reflect.Invalid { + c.reporter.ReportFatalError( + fileName, + lineNumber, + errors.New("Unknown method: "+methodName)) + return nil + } + + partialAlreadyCalled := false // Protected by c.mutex + return func(args ...interface{}) Expectation { + c.mutex.Lock() + defer c.mutex.Unlock() + + // This function should only be called once. + if partialAlreadyCalled { + c.reporter.ReportFatalError( + fileName, + lineNumber, + errors.New("Partial expectation called more than once.")) + return nil + } + + partialAlreadyCalled = true + + // Make sure that the number of args is legal. Keep in mind that the + // method's type has an extra receiver arg. + if len(args) != method.Type().NumIn() { + c.reporter.ReportFatalError( + fileName, + lineNumber, + errors.New( + fmt.Sprintf( + "Expectation for %s given wrong number of arguments: "+ + "expected %d, got %d.", + methodName, + method.Type().NumIn(), + len(args)))) + return nil + } + + // Create an expectation and insert it into the controller's map. + exp := InternalNewExpectation( + c.reporter, + method.Type(), + args, + fileName, + lineNumber) + + c.addExpectationLocked(o, methodName, exp) + + // Return the expectation to the user. + return exp + } +} + +func (c *controllerImpl) Finish() { + c.mutex.Lock() + defer c.mutex.Unlock() + + // Check whether the minimum cardinality for each registered expectation has + // been satisfied. + for _, expectationsByMethod := range c.expectationsByObject { + for methodName, expectations := range expectationsByMethod { + for _, exp := range expectations { + exp.mutex.Lock() + defer exp.mutex.Unlock() + + minCardinality, _ := computeCardinalityLocked(exp) + if exp.NumMatches < minCardinality { + c.reporter.ReportError( + exp.FileName, + exp.LineNumber, + errors.New( + fmt.Sprintf( + "Unsatisfied expectation; expected %s to be called "+ + "at least %d times; called %d times.", + methodName, + minCardinality, + exp.NumMatches))) + } + } + } + } +} + +// expectationMatches checks the matchers for the expectation against the +// supplied arguments. +func expectationMatches(exp *InternalExpectation, args []interface{}) bool { + matchers := exp.ArgMatchers + if len(args) != len(matchers) { + panic("expectationMatches: len(args)") + } + + // Check each matcher. + for i, matcher := range matchers { + if err := matcher.Matches(args[i]); err != nil { + return false + } + } + + return true +} + +// Return the expectation that matches the supplied arguments. If there is more +// than one such expectation, the one furthest along in the list for the method +// is returned. If there is no such expectation, nil is returned. +// +// c.mutex must be held for reading. +func (c *controllerImpl) chooseExpectationLocked( + o MockObject, + methodName string, + args []interface{}) *InternalExpectation { + // Do we have any expectations for this method? + expectations := c.getExpectationsLocked(o, methodName) + if len(expectations) == 0 { + return nil + } + + for i := len(expectations) - 1; i >= 0; i-- { + if expectationMatches(expectations[i], args) { + return expectations[i] + } + } + + return nil +} + +// makeZeroReturnValues creates a []interface{} containing appropriate zero +// values for returning from the supplied method type. +func makeZeroReturnValues(signature reflect.Type) []interface{} { + result := make([]interface{}, signature.NumOut()) + + for i, _ := range result { + outType := signature.Out(i) + zeroVal := reflect.Zero(outType) + result[i] = zeroVal.Interface() + } + + return result +} + +// computeCardinality decides on the [min, max] range of the number of expected +// matches for the supplied expectations, according to the rules documented in +// expectation.go. +// +// exp.mutex must be held for reading. +func computeCardinalityLocked(exp *InternalExpectation) (min, max uint) { + // Explicit cardinality. + if exp.ExpectedNumMatches >= 0 { + min = uint(exp.ExpectedNumMatches) + max = min + return + } + + // Implicit count based on one-time actions. + if len(exp.OneTimeActions) != 0 { + min = uint(len(exp.OneTimeActions)) + max = min + + // If there is a fallback action, this is only a lower bound. + if exp.FallbackAction != nil { + max = math.MaxUint32 + } + + return + } + + // Implicit lack of restriction based on a fallback action being configured. + if exp.FallbackAction != nil { + min = 0 + max = math.MaxUint32 + return + } + + // Implicit cardinality of one. + min = 1 + max = 1 + return +} + +// chooseAction returns the action that should be invoked for the i'th match to +// the supplied expectation (counting from zero). If the implicit "return zero +// values" action should be used, it returns nil. +// +// exp.mutex must be held for reading. +func chooseActionLocked(i uint, exp *InternalExpectation) Action { + // Exhaust one-time actions first. + if i < uint(len(exp.OneTimeActions)) { + return exp.OneTimeActions[i] + } + + // Fallback action (or nil if none is configured). + return exp.FallbackAction +} + +// Find an action for the method call, updating expectation match state in the +// process. Return either an action that should be invoked or a set of zero +// values to return immediately. +// +// This is split out from HandleMethodCall in order to more easily avoid +// invoking the action with locks held. +func (c *controllerImpl) chooseActionAndUpdateExpectations( + o MockObject, + methodName string, + fileName string, + lineNumber int, + args []interface{}, +) (action Action, zeroVals []interface{}) { + c.mutex.Lock() + defer c.mutex.Unlock() + + // Find the signature for the requested method. + ov := reflect.ValueOf(o) + method := ov.MethodByName(methodName) + if method.Kind() == reflect.Invalid { + c.reporter.ReportFatalError( + fileName, + lineNumber, + errors.New("Unknown method: "+methodName), + ) + + // Should never get here in real code. + log.Println("ReportFatalError unexpectedly returned.") + return + } + + // HACK(jacobsa): Make sure we got the correct number of arguments. This will + // need to be refined when issue #5 (variadic methods) is handled. + if len(args) != method.Type().NumIn() { + c.reporter.ReportFatalError( + fileName, + lineNumber, + errors.New( + fmt.Sprintf( + "Wrong number of arguments: expected %d; got %d", + method.Type().NumIn(), + len(args), + ), + ), + ) + + // Should never get here in real code. + log.Println("ReportFatalError unexpectedly returned.") + return + } + + // Find an expectation matching this call. + expectation := c.chooseExpectationLocked(o, methodName, args) + if expectation == nil { + c.reporter.ReportError( + fileName, + lineNumber, + errors.New( + fmt.Sprintf("Unexpected call to %s with args: %v", methodName, args), + ), + ) + + zeroVals = makeZeroReturnValues(method.Type()) + return + } + + expectation.mutex.Lock() + defer expectation.mutex.Unlock() + + // Increase the number of matches recorded, and check whether we're over the + // number expected. + expectation.NumMatches++ + _, maxCardinality := computeCardinalityLocked(expectation) + if expectation.NumMatches > maxCardinality { + c.reporter.ReportError( + expectation.FileName, + expectation.LineNumber, + errors.New( + fmt.Sprintf( + "Unexpected call to %s: "+ + "expected to be called at most %d times; called %d times.", + methodName, + maxCardinality, + expectation.NumMatches, + ), + ), + ) + + zeroVals = makeZeroReturnValues(method.Type()) + return + } + + // Choose an action to invoke. If there is none, just return zero values. + action = chooseActionLocked(expectation.NumMatches-1, expectation) + if action == nil { + zeroVals = makeZeroReturnValues(method.Type()) + return + } + + // Let the action take over. + return +} + +func (c *controllerImpl) HandleMethodCall( + o MockObject, + methodName string, + fileName string, + lineNumber int, + args []interface{}, +) []interface{} { + // Figure out whether to invoke an action or return zero values. + action, zeroVals := c.chooseActionAndUpdateExpectations( + o, + methodName, + fileName, + lineNumber, + args, + ) + + if action != nil { + return action.Invoke(args) + } + + return zeroVals +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/controller_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/controller_test.go new file mode 100644 index 0000000000..003c587070 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/controller_test.go @@ -0,0 +1,1249 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "reflect" +) + +//////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////// + +type errorReport struct { + fileName string + lineNumber int + err error +} + +type fakeErrorReporter struct { + errors []errorReport + fatalErrors []errorReport +} + +func (r *fakeErrorReporter) ReportError(fileName string, lineNumber int, err error) { + report := errorReport{fileName, lineNumber, err} + r.errors = append(r.errors, report) +} + +func (r *fakeErrorReporter) ReportFatalError(fileName string, lineNumber int, err error) { + report := errorReport{fileName, lineNumber, err} + r.fatalErrors = append(r.fatalErrors, report) +} + +type trivialMockObject struct { + id uintptr + desc string +} + +func (o *trivialMockObject) Oglemock_Id() uintptr { + return o.id +} + +func (o *trivialMockObject) Oglemock_Description() string { + return o.desc +} + +// Method being mocked +func (o *trivialMockObject) StringToInt(s string) int { + return 0 +} + +// Method being mocked +func (o *trivialMockObject) TwoIntsToString(i, j int) string { + return "" +} + +type ControllerTest struct { + reporter fakeErrorReporter + controller Controller + + mock1 MockObject + mock2 MockObject +} + +func (t *ControllerTest) SetUp(c *TestInfo) { + t.reporter.errors = make([]errorReport, 0) + t.reporter.fatalErrors = make([]errorReport, 0) + t.controller = NewController(&t.reporter) + + t.mock1 = &trivialMockObject{17, "taco"} + t.mock2 = &trivialMockObject{19, "burrito"} +} + +func init() { RegisterTestSuite(&ControllerTest{}) } + +//////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////// + +func (t *ControllerTest) FinishWithoutAnyEvents() { + t.controller.Finish() + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) HandleCallForUnknownObject() { + p := []byte{255} + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "taco.go", + 112, + []interface{}{p}) + + // The error should be reported immediately. + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("taco.go", t.reporter.errors[0].fileName) + ExpectEq(112, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unexpected"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("[255]"))) + + // Finish should change nothing. + t.controller.Finish() + + ExpectEq(1, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ExpectCallForUnknownMethod() { + ExpectEq( + nil, + t.controller.ExpectCall(t.mock1, "Frobnicate", "burrito.go", 117)) + + // A fatal error should be reported immediately. + AssertEq(0, len(t.reporter.errors)) + AssertEq(1, len(t.reporter.fatalErrors)) + + report := t.reporter.fatalErrors[0] + ExpectEq("burrito.go", report.fileName) + ExpectEq(117, report.lineNumber) + ExpectThat(report.err, Error(HasSubstr("Unknown method"))) + ExpectThat(report.err, Error(HasSubstr("Frobnicate"))) +} + +func (t *ControllerTest) PartialExpectationGivenWrongNumberOfArgs() { + ExpectEq( + nil, + t.controller.ExpectCall(t.mock1, "TwoIntsToString", "burrito.go", 117)( + 17, 19, 23)) + + // A fatal error should be reported immediately. + AssertEq(0, len(t.reporter.errors)) + AssertEq(1, len(t.reporter.fatalErrors)) + + report := t.reporter.fatalErrors[0] + ExpectEq("burrito.go", report.fileName) + ExpectEq(117, report.lineNumber) + ExpectThat(report.err, Error(HasSubstr("TwoIntsToString"))) + ExpectThat(report.err, Error(HasSubstr("arguments"))) + ExpectThat(report.err, Error(HasSubstr("expected 2"))) + ExpectThat(report.err, Error(HasSubstr("got 3"))) +} + +func (t *ControllerTest) PartialExpectationCalledTwice() { + partial := t.controller.ExpectCall(t.mock1, "StringToInt", "burrito.go", 117) + AssertNe(nil, partial("taco")) + ExpectEq(nil, partial("taco")) + + // A fatal error should be reported immediately. + AssertEq(0, len(t.reporter.errors)) + AssertEq(1, len(t.reporter.fatalErrors)) + + report := t.reporter.fatalErrors[0] + ExpectEq("burrito.go", report.fileName) + ExpectEq(117, report.lineNumber) + ExpectThat(report.err, Error(HasSubstr("called more than once"))) +} + +func (t *ControllerTest) HandleMethodCallForUnknownMethod() { + ExpectEq( + nil, + t.controller.HandleMethodCall( + t.mock1, + "Frobnicate", + "burrito.go", + 117, + []interface{}{})) + + // A fatal error should be reported immediately. + AssertEq(0, len(t.reporter.errors)) + AssertEq(1, len(t.reporter.fatalErrors)) + + report := t.reporter.fatalErrors[0] + ExpectEq("burrito.go", report.fileName) + ExpectEq(117, report.lineNumber) + ExpectThat(report.err, Error(HasSubstr("Unknown method"))) + ExpectThat(report.err, Error(HasSubstr("Frobnicate"))) +} + +func (t *ControllerTest) HandleMethodCallGivenWrongNumberOfArgs() { + t.controller.ExpectCall(t.mock1, "TwoIntsToString", "", 0)(17, 19) + + ExpectEq( + nil, + t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "burrito.go", + 117, + []interface{}{17, 19, 23})) + + // A fatal error should be reported immediately. + AssertEq(0, len(t.reporter.errors)) + AssertEq(1, len(t.reporter.fatalErrors)) + + report := t.reporter.fatalErrors[0] + ExpectEq("burrito.go", report.fileName) + ExpectEq(117, report.lineNumber) + ExpectThat(report.err, Error(HasSubstr("arguments"))) + ExpectThat(report.err, Error(HasSubstr("expected 2"))) + ExpectThat(report.err, Error(HasSubstr("got 3"))) +} + +func (t *ControllerTest) ExpectThenNonMatchingCall() { + // Expectation -- set up a fallback action to make it optional. + partial := t.controller.ExpectCall( + t.mock1, + "TwoIntsToString", + "burrito.go", + 117) + + exp := partial(LessThan(10), Equals(2)) + exp.WillRepeatedly(Return("")) + + // Call + t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "taco.go", + 112, + []interface{}{8, 1}) + + // The error should be reported immediately. + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("taco.go", t.reporter.errors[0].fileName) + ExpectEq(112, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unexpected"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("TwoIntsToString"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("[8 1]"))) + + // Finish should change nothing. + t.controller.Finish() + + ExpectEq(1, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ExplicitCardinalityNotSatisfied() { + // Expectation -- set up an explicit cardinality of three. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.Times(3) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should not yet be reported. + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) + + // Finish should cause the error to be reported. + t.controller.Finish() + + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unsatisfied"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at least 3 times"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 2 times"))) +} + +func (t *ControllerTest) ImplicitOneTimeActionCountNotSatisfied() { + // Expectation -- add three one-time actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + exp.WillOnce(Return(2)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should not yet be reported. + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) + + // Finish should cause the error to be reported. + t.controller.Finish() + + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unsatisfied"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at least 3 times"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 2 times"))) +} + +func (t *ControllerTest) ImplicitOneTimeActionLowerBoundNotSatisfied() { + // Expectation -- add three one-time actions and a fallback. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + exp.WillOnce(Return(2)) + exp.WillRepeatedly(Return(3)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should not yet be reported. + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) + + // Finish should cause the error to be reported. + t.controller.Finish() + + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unsatisfied"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at least 3 times"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 2 times"))) +} + +func (t *ControllerTest) ImplicitCardinalityOfOneNotSatisfied() { + // Expectation -- add no actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + partial(HasSubstr("")) + + // Don't call. + + // The error should not yet be reported. + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) + + // Finish should cause the error to be reported. + t.controller.Finish() + + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unsatisfied"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at least 1 time"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 0 times"))) +} + +func (t *ControllerTest) ExplicitCardinalityOverrun() { + // Expectation -- call times(2). + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.Times(2) + + // Call three times. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should be reported immediately. + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unexpected"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at most 2 times"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 3 times"))) + + // Finish should change nothing. + t.controller.Finish() + + ExpectEq(1, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitOneTimeActionCountOverrun() { + // Expectation -- add a one-time action. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should be reported immediately. + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unexpected"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at most 1 time"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 2 times"))) + + // Finish should change nothing. + t.controller.Finish() + + ExpectEq(1, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitCardinalityOfOneOverrun() { + // Expectation -- don't add any actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + partial(HasSubstr("")) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // The error should be reported immediately. + AssertEq(1, len(t.reporter.errors)) + AssertEq(0, len(t.reporter.fatalErrors)) + + ExpectEq("burrito.go", t.reporter.errors[0].fileName) + ExpectEq(117, t.reporter.errors[0].lineNumber) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("Unexpected"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("StringToInt"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("at most 1 time"))) + ExpectThat(t.reporter.errors[0].err, Error(HasSubstr("called 2 times"))) + + // Finish should change nothing. + t.controller.Finish() + + ExpectEq(1, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ExplicitCardinalitySatisfied() { + // Expectation -- set up an explicit cardinality of two. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.Times(2) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitOneTimeActionCountSatisfied() { + // Expectation -- set up two one-time actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitOneTimeActionLowerBoundJustSatisfied() { + // Expectation -- set up two one-time actions and a fallback. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + exp.WillRepeatedly(Return(2)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitOneTimeActionLowerBoundMoreThanSatisfied() { + // Expectation -- set up two one-time actions and a fallback. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + exp.WillRepeatedly(Return(2)) + + // Call four times. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) FallbackActionConfiguredWithZeroCalls() { + // Expectation -- set up a fallback action. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(0)) + + // Don't call. + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) FallbackActionConfiguredWithMultipleCalls() { + // Expectation -- set up a fallback action. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(0)) + + // Call twice. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) ImplicitCardinalityOfOneSatisfied() { + // Expectation -- don't add actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + partial(HasSubstr("")) + + // Call once. + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + // There should be no errors. + t.controller.Finish() + + ExpectEq(0, len(t.reporter.errors)) + ExpectEq(0, len(t.reporter.fatalErrors)) +} + +func (t *ControllerTest) InvokesOneTimeActions() { + var res []interface{} + + // Expectation -- set up two one-time actions. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + suppliedArg := "" + expectedReturn := 17 + + f := func(s string) int { + suppliedArg = s + return expectedReturn + } + + exp := partial(HasSubstr("")) + exp.WillOnce(Invoke(f)) + exp.WillOnce(Return(1)) + + AssertThat(t.reporter.fatalErrors, ElementsAre()) + + // Call 0 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{"taco"}) + + ExpectEq("taco", suppliedArg) + ExpectThat(res, ElementsAre(IdenticalTo(expectedReturn))) + + // Call 1 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(1)) +} + +func (t *ControllerTest) InvokesFallbackActionAfterOneTimeActions() { + var res []interface{} + + // Expectation -- set up two one-time actions and a fallback. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(0)) + exp.WillOnce(Return(1)) + exp.WillRepeatedly(Return(2)) + + // Call 0 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(0)) + + // Call 1 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(1)) + + // Call 2 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(2)) + + // Call 3 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(2)) +} + +func (t *ControllerTest) InvokesFallbackActionWithoutOneTimeActions() { + var res []interface{} + + // Expectation -- set up only a fallback action. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(2)) + + // Call 0 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(2)) + + // Call 1 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(2)) + + // Call 2 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(2)) +} + +func (t *ControllerTest) ImplicitActionReturnsZeroInts() { + var res []interface{} + + // Expectation -- set up a cardinality of two. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.Times(2) + + // Call 0 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(reflect.TypeOf(res[0]), Equals(reflect.TypeOf(int(0)))) + ExpectThat(res[0], Equals(0)) + + // Call 1 + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(reflect.TypeOf(res[0]), Equals(reflect.TypeOf(int(0)))) + ExpectThat(res[0], Equals(0)) +} + +func (t *ControllerTest) ImplicitActionReturnsEmptyStrings() { + var res []interface{} + + // Expectation -- set up a cardinality of two. + partial := t.controller.ExpectCall( + t.mock1, + "TwoIntsToString", + "burrito.go", + 117) + + exp := partial(LessThan(100), LessThan(100)) + exp.Times(2) + + // Call 0 + res = t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "", + 0, + []interface{}{0, 0}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals("")) + + // Call 1 + res = t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "", + 0, + []interface{}{0, 0}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals("")) +} + +func (t *ControllerTest) ExpectationsAreMatchedLastToFirst() { + var res []interface{} + + // General expectation + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(17)) + + // More specific expectation + partial = t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp = partial(Equals("taco")) + exp.WillRepeatedly(Return(19)) + + // Call -- the second expectation should match. + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{"taco"}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(19)) + + // Call -- the first expectation should match because the second doesn't. + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{"burrito"}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(17)) +} + +func (t *ControllerTest) ExpectationsAreSegregatedByMockObject() { + var res []interface{} + + // Expectation for mock1 -- return 17. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(17)) + + // Expectation for mock2 -- return 19. + partial = t.controller.ExpectCall( + t.mock2, + "StringToInt", + "burrito.go", + 117) + + exp = partial(HasSubstr("")) + exp.WillRepeatedly(Return(19)) + + // Call mock1. + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(17)) + + // Call mock2. + res = t.controller.HandleMethodCall( + t.mock2, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(19)) +} + +func (t *ControllerTest) ExpectationsAreSegregatedByMethodName() { + var res []interface{} + + // Expectation for StringToInt + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillRepeatedly(Return(17)) + + // Expectation for TwoIntsToString + partial = t.controller.ExpectCall( + t.mock1, + "TwoIntsToString", + "burrito.go", + 117) + + exp = partial(1, 2) + exp.WillRepeatedly(Return("taco")) + + // Call StringToInt. + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals(17)) + + // Call TwoIntsToString. + res = t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "", + 0, + []interface{}{1, 2}) + + ExpectThat(len(res), Equals(1)) + ExpectThat(res[0], Equals("taco")) +} + +func (t *ControllerTest) ActionCallsAgainMatchingDifferentExpectation() { + var res []interface{} + + // Expectation for StringToInt + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.WillOnce(Return(17)) + + // Expectation for TwoIntsToString -- pretend we call StringToInt. + partial = t.controller.ExpectCall( + t.mock1, + "TwoIntsToString", + "burrito.go", + 117) + + exp = partial(1, 2) + exp.WillOnce(Invoke(func(int, int) string { + t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "taco.go", + 112, + []interface{}{""}) + + return "queso" + })) + + // Call TwoIntsToString. + res = t.controller.HandleMethodCall( + t.mock1, + "TwoIntsToString", + "", + 0, + []interface{}{1, 2}) + + AssertThat(res, ElementsAre("queso")) + + // Finish. Everything should be satisfied. + t.controller.Finish() + + ExpectThat(t.reporter.errors, ElementsAre()) + ExpectThat(t.reporter.fatalErrors, ElementsAre()) +} + +func (t *ControllerTest) ActionCallsAgainMatchingSameExpectation() { + var res []interface{} + + // Expectation for StringToInt -- should be called twice. The first time it + // should call itself. + partial := t.controller.ExpectCall( + t.mock1, + "StringToInt", + "burrito.go", + 117) + + exp := partial(HasSubstr("")) + exp.Times(2) + exp.WillOnce(Invoke(func(string) int { + subCallRes := t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "taco.go", + 112, + []interface{}{""}) + + return subCallRes[0].(int) + 19 + })) + + exp.WillOnce(Return(17)) + + // Call. + res = t.controller.HandleMethodCall( + t.mock1, + "StringToInt", + "", + 0, + []interface{}{""}) + + AssertThat(res, ElementsAre(17+19)) + + // Finish. Everything should be satisfied. + t.controller.Finish() + + ExpectThat(t.reporter.errors, ElementsAre()) + ExpectThat(t.reporter.fatalErrors, ElementsAre()) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all.go new file mode 100644 index 0000000000..c0cd3ffbd6 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all.go @@ -0,0 +1,53 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "fmt" + "reflect" +) + +// Create an Action that invokes the supplied actions one after another. The +// return values from the final action are used; others are ignored. +func DoAll(first Action, others ...Action) Action { + return &doAll{ + wrapped: append([]Action{first}, others...), + } +} + +type doAll struct { + wrapped []Action +} + +func (a *doAll) SetSignature(signature reflect.Type) (err error) { + for i, w := range a.wrapped { + err = w.SetSignature(signature) + if err != nil { + err = fmt.Errorf("Action %v: %v", i, err) + return + } + } + + return +} + +func (a *doAll) Invoke(methodArgs []interface{}) (rets []interface{}) { + for _, w := range a.wrapped { + rets = w.Invoke(methodArgs) + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all_test.go new file mode 100644 index 0000000000..2fa5d909d8 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/do_all_test.go @@ -0,0 +1,90 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + "reflect" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +func TestDoAll(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////// +// Boilerplate +//////////////////////////////////////////////////////////// + +type DoAllTest struct { +} + +func init() { RegisterTestSuite(&DoAllTest{}) } + +//////////////////////////////////////////////////////////// +// Test functions +//////////////////////////////////////////////////////////// + +func (t *DoAllTest) FirstActionDoesntLikeSignature() { + f := func(a int, b string) {} + + a0 := oglemock.Invoke(func() {}) + a1 := oglemock.Invoke(f) + a2 := oglemock.Return() + + err := oglemock.DoAll(a0, a1, a2).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("Action 0"))) + ExpectThat(err, Error(HasSubstr("func()"))) +} + +func (t *DoAllTest) LastActionDoesntLikeSignature() { + f := func(a int, b string) {} + + a0 := oglemock.Invoke(f) + a1 := oglemock.Invoke(f) + a2 := oglemock.Return(17) + + err := oglemock.DoAll(a0, a1, a2).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("Action 2"))) + ExpectThat(err, Error(HasSubstr("1 vals; expected 0"))) +} + +func (t *DoAllTest) SingleAction() { + f := func(a int) string { return "" } + a0 := oglemock.Return("taco") + + action := oglemock.DoAll(a0) + AssertEq(nil, action.SetSignature(reflect.TypeOf(f))) + + rets := action.Invoke([]interface{}{17}) + ExpectThat(rets, ElementsAre("taco")) +} + +func (t *DoAllTest) MultipleActions() { + f := func(a int) string { return "" } + + var saved int + a0 := oglemock.SaveArg(0, &saved) + a1 := oglemock.Return("taco") + + action := oglemock.DoAll(a0, a1) + AssertEq(nil, action.SetSignature(reflect.TypeOf(f))) + + rets := action.Invoke([]interface{}{17}) + ExpectEq(17, saved) + ExpectThat(rets, ElementsAre("taco")) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/error_reporter.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/error_reporter.go new file mode 100644 index 0000000000..0c3a65ee18 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/error_reporter.go @@ -0,0 +1,29 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +// ErrorReporter is an interface that wraps methods for reporting errors that +// should cause test failures. +type ErrorReporter interface { + // Report that some failure (e.g. an unsatisfied expectation) occurred. If + // known, fileName and lineNumber should contain information about where it + // occurred. The test may continue if the test framework supports it. + ReportError(fileName string, lineNumber int, err error) + + // Like ReportError, but the test should be halted immediately. It is assumed + // that this method does not return. + ReportFatalError(fileName string, lineNumber int, err error) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/expectation.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/expectation.go new file mode 100644 index 0000000000..d18bfb8bce --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/expectation.go @@ -0,0 +1,59 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +// Expectation is an expectation for zero or more calls to a mock method with +// particular arguments or sets of arguments. +type Expectation interface { + // Times expresses that a matching method call should happen exactly N times. + // Times must not be called more than once, and must not be called after + // WillOnce or WillRepeatedly. + // + // The full rules for the cardinality of an expectation are as follows: + // + // 1. If an explicit cardinality is set with Times(N), then anything other + // than exactly N matching calls will cause a test failure. + // + // 2. Otherwise, if there are any one-time actions set up, then it is + // expected there will be at least that many matching calls. If there is + // not also a fallback action, then it is expected that there will be + // exactly that many. + // + // 3. Otherwise, if there is a fallback action configured, any number of + // matching calls (including zero) is allowed. + // + // 4. Otherwise, the implicit cardinality is one. + // + Times(n uint) Expectation + + // WillOnce configures a "one-time action". WillOnce can be called zero or + // more times, but must be called after any call to Times and before any call + // to WillRepeatedly. + // + // When matching method calls are made on the mock object, one-time actions + // are invoked one per matching call in the order that they were set up until + // they are exhausted. Afterward the fallback action, if any, will be used. + WillOnce(a Action) Expectation + + // WillRepeatedly configures a "fallback action". WillRepeatedly can be + // called zero or one times, and must not be called before Times or WillOnce. + // + // Once all one-time actions are exhausted (see above), the fallback action + // will be invoked for any further method calls. If WillRepeatedly is not + // called, the fallback action is implicitly an action that returns zero + // values for the method's return values. + WillRepeatedly(a Action) Expectation +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/integration_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/integration_test.go new file mode 100644 index 0000000000..f875ea0102 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/integration_test.go @@ -0,0 +1,129 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + "errors" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock/sample/mock_io" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "path" + "runtime" +) + +//////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////// + +func getLineNumber() int { + _, _, line, _ := runtime.Caller(1) + return line +} + +type IntegrationTest struct { + reporter fakeErrorReporter + controller oglemock.Controller + + reader mock_io.MockReader +} + +func init() { RegisterTestSuite(&IntegrationTest{}) } + +func (t *IntegrationTest) SetUp(c *TestInfo) { + t.reporter.errors = make([]errorReport, 0) + t.reporter.fatalErrors = make([]errorReport, 0) + t.controller = oglemock.NewController(&t.reporter) + + t.reader = mock_io.NewMockReader(t.controller, "") +} + +//////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////// + +func (t *IntegrationTest) UnexpectedCall() { + t.reader.Read([]uint8{1, 2, 3}) + expectedLine := getLineNumber() - 1 + + // An error should have been reported. + AssertEq(1, len(t.reporter.errors), "%v", t.reporter.errors) + AssertEq(0, len(t.reporter.fatalErrors), "%v", t.reporter.fatalErrors) + + r := t.reporter.errors[0] + ExpectEq("integration_test.go", path.Base(r.fileName)) + ExpectEq(expectedLine, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Unexpected"))) + ExpectThat(r.err, Error(HasSubstr("Read"))) + ExpectThat(r.err, Error(HasSubstr("[1 2 3]"))) +} + +func (t *IntegrationTest) ZeroValues() { + // Make an unexpected call. + n, err := t.reader.Read([]uint8{}) + + // Check the return values. + ExpectEq(0, n) + ExpectEq(nil, err) +} + +func (t *IntegrationTest) ExpectedCalls() { + // Expectations + t.controller.ExpectCall(t.reader, "Read", "", 112)(nil). + WillOnce(oglemock.Return(17, nil)). + WillOnce(oglemock.Return(19, nil)) + + t.controller.ExpectCall(t.reader, "Read", "", 112)(Not(Equals(nil))). + WillOnce(oglemock.Return(23, errors.New("taco"))) + + // Calls + var n int + var err error + + n, err = t.reader.Read(nil) + ExpectEq(17, n) + ExpectEq(nil, err) + + n, err = t.reader.Read([]byte{}) + ExpectEq(23, n) + ExpectThat(err, Error(Equals("taco"))) + + n, err = t.reader.Read(nil) + ExpectEq(19, n) + ExpectEq(nil, err) + + // Errors + AssertEq(0, len(t.reporter.errors), "%v", t.reporter.errors) + AssertEq(0, len(t.reporter.fatalErrors), "%v", t.reporter.fatalErrors) +} + +func (t *IntegrationTest) WrongTypeForReturn() { + t.controller.ExpectCall(t.reader, "Read", "foo.go", 112)(nil). + WillOnce(oglemock.Return(0, errors.New(""))). + WillOnce(oglemock.Return("taco", errors.New(""))) + + // Errors + AssertEq(0, len(t.reporter.errors), "%v", t.reporter.errors) + AssertEq(1, len(t.reporter.fatalErrors), "%v", t.reporter.fatalErrors) + + r := t.reporter.fatalErrors[0] + ExpectEq("foo.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Return"))) + ExpectThat(r.err, Error(HasSubstr("arg 0"))) + ExpectThat(r.err, Error(HasSubstr("int"))) + ExpectThat(r.err, Error(HasSubstr("string"))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation.go new file mode 100644 index 0000000000..dc76355e5c --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation.go @@ -0,0 +1,180 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "errors" + "fmt" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "reflect" + "sync" +) + +// InternalExpectation is exported for purposes of testing only. You should not +// touch it. +// +// InternalExpectation represents an expectation for zero or more calls to a +// mock method, and a set of actions to be taken when those calls are received. +type InternalExpectation struct { + // The signature of the method to which this expectation is bound, for + // checking action types. + methodSignature reflect.Type + + // An error reporter to use for reporting errors in the way that expectations + // are set. + errorReporter ErrorReporter + + // A mutex protecting mutable fields of the struct. + mutex sync.Mutex + + // Matchers that the arguments to the mock method must satisfy in order to + // match this expectation. + ArgMatchers []oglematchers.Matcher + + // The name of the file in which this expectation was expressed. + FileName string + + // The line number at which this expectation was expressed. + LineNumber int + + // The number of times this expectation should be matched, as explicitly + // listed by the user. If there was no explicit number expressed, this is -1. + ExpectedNumMatches int + + // Actions to be taken for the first N calls, one per call in order, where N + // is the length of this slice. + OneTimeActions []Action + + // An action to be taken when the one-time actions have expired, or nil if + // there is no such action. + FallbackAction Action + + // The number of times this expectation has been matched so far. + NumMatches uint +} + +// InternalNewExpectation is exported for purposes of testing only. You should +// not touch it. +func InternalNewExpectation( + reporter ErrorReporter, + methodSignature reflect.Type, + args []interface{}, + fileName string, + lineNumber int) *InternalExpectation { + result := &InternalExpectation{} + + // Store fields that can be stored directly. + result.methodSignature = methodSignature + result.errorReporter = reporter + result.FileName = fileName + result.LineNumber = lineNumber + + // Set up defaults. + result.ExpectedNumMatches = -1 + result.OneTimeActions = make([]Action, 0) + + // Set up the ArgMatchers slice, using Equals(x) for each x that is not a + // matcher itself. + result.ArgMatchers = make([]oglematchers.Matcher, len(args)) + for i, x := range args { + if matcher, ok := x.(oglematchers.Matcher); ok { + result.ArgMatchers[i] = matcher + } else { + result.ArgMatchers[i] = oglematchers.Equals(x) + } + } + + return result +} + +func (e *InternalExpectation) Times(n uint) Expectation { + e.mutex.Lock() + defer e.mutex.Unlock() + + // It is illegal to call this more than once. + if e.ExpectedNumMatches != -1 { + e.reportFatalError("Times called more than once.") + return nil + } + + // It is illegal to call this after any actions are configured. + if len(e.OneTimeActions) != 0 { + e.reportFatalError("Times called after WillOnce.") + return nil + } + + if e.FallbackAction != nil { + e.reportFatalError("Times called after WillRepeatedly.") + return nil + } + + // Make sure the number is reasonable (and will fit in an int). + if n > 1000 { + e.reportFatalError("Expectation.Times: N must be at most 1000") + return nil + } + + e.ExpectedNumMatches = int(n) + return e +} + +func (e *InternalExpectation) WillOnce(a Action) Expectation { + e.mutex.Lock() + defer e.mutex.Unlock() + + // It is illegal to call this after WillRepeatedly. + if e.FallbackAction != nil { + e.reportFatalError("WillOnce called after WillRepeatedly.") + return nil + } + + // Tell the action about the method's signature. + if err := a.SetSignature(e.methodSignature); err != nil { + e.reportFatalError(fmt.Sprintf("WillOnce given invalid action: %v", err)) + return nil + } + + // Store the action. + e.OneTimeActions = append(e.OneTimeActions, a) + + return e +} + +func (e *InternalExpectation) WillRepeatedly(a Action) Expectation { + e.mutex.Lock() + defer e.mutex.Unlock() + + // It is illegal to call this twice. + if e.FallbackAction != nil { + e.reportFatalError("WillRepeatedly called more than once.") + return nil + } + + // Tell the action about the method's signature. + if err := a.SetSignature(e.methodSignature); err != nil { + e.reportFatalError(fmt.Sprintf("WillRepeatedly given invalid action: %v", err)) + return nil + } + + // Store the action. + e.FallbackAction = a + + return e +} + +func (e *InternalExpectation) reportFatalError(errorText string) { + e.errorReporter.ReportFatalError(e.FileName, e.LineNumber, errors.New(errorText)) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation_test.go new file mode 100644 index 0000000000..d3ed54c333 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/internal_expectation_test.go @@ -0,0 +1,265 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "reflect" +) + +//////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////// + +var emptyReturnSig reflect.Type = reflect.TypeOf(func(i int) {}) +var float64ReturnSig reflect.Type = reflect.TypeOf(func(i int) float64 { return 17.0 }) + +type InternalExpectationTest struct { + reporter fakeErrorReporter +} + +func init() { RegisterTestSuite(&InternalExpectationTest{}) } + +func (t *InternalExpectationTest) SetUp(c *TestInfo) { + t.reporter.errors = make([]errorReport, 0) + t.reporter.fatalErrors = make([]errorReport, 0) +} + +func (t *InternalExpectationTest) makeExpectation( + sig reflect.Type, + args []interface{}, + fileName string, + lineNumber int) *InternalExpectation { + return InternalNewExpectation(&t.reporter, sig, args, fileName, lineNumber) +} + +//////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////// + +func (t *InternalExpectationTest) StoresFileNameAndLineNumber() { + args := []interface{}{} + exp := t.makeExpectation(emptyReturnSig, args, "taco", 17) + + ExpectThat(exp.FileName, Equals("taco")) + ExpectThat(exp.LineNumber, Equals(17)) +} + +func (t *InternalExpectationTest) NoArgs() { + args := []interface{}{} + exp := t.makeExpectation(emptyReturnSig, args, "", 0) + + ExpectThat(len(exp.ArgMatchers), Equals(0)) +} + +func (t *InternalExpectationTest) MixOfMatchersAndNonMatchers() { + args := []interface{}{Equals(17), 19, Equals(23)} + exp := t.makeExpectation(emptyReturnSig, args, "", 0) + + // Matcher args + ExpectThat(len(exp.ArgMatchers), Equals(3)) + ExpectThat(exp.ArgMatchers[0], Equals(args[0])) + ExpectThat(exp.ArgMatchers[2], Equals(args[2])) + + // Non-matcher arg + var err error + matcher1 := exp.ArgMatchers[1] + + err = matcher1.Matches(17) + ExpectNe(nil, err) + + err = matcher1.Matches(19) + ExpectEq(nil, err) + + err = matcher1.Matches(23) + ExpectNe(nil, err) +} + +func (t *InternalExpectationTest) NoTimes() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "", 0) + + ExpectThat(exp.ExpectedNumMatches, Equals(-1)) +} + +func (t *InternalExpectationTest) TimesN() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "", 0) + exp.Times(17) + + ExpectThat(exp.ExpectedNumMatches, Equals(17)) +} + +func (t *InternalExpectationTest) NoActions() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "", 0) + + ExpectThat(len(exp.OneTimeActions), Equals(0)) + ExpectThat(exp.FallbackAction, Equals(nil)) +} + +func (t *InternalExpectationTest) WillOnce() { + action0 := Return(17.0) + action1 := Return(19.0) + + exp := t.makeExpectation(float64ReturnSig, []interface{}{}, "", 0) + exp.WillOnce(action0).WillOnce(action1) + + ExpectThat(len(exp.OneTimeActions), Equals(2)) + ExpectThat(exp.OneTimeActions[0], Equals(action0)) + ExpectThat(exp.OneTimeActions[1], Equals(action1)) +} + +func (t *InternalExpectationTest) WillRepeatedly() { + action := Return(17.0) + + exp := t.makeExpectation(float64ReturnSig, []interface{}{}, "", 0) + exp.WillRepeatedly(action) + + ExpectThat(exp.FallbackAction, Equals(action)) +} + +func (t *InternalExpectationTest) BothKindsOfAction() { + action0 := Return(17.0) + action1 := Return(19.0) + action2 := Return(23.0) + + exp := t.makeExpectation(float64ReturnSig, []interface{}{}, "", 0) + exp.WillOnce(action0).WillOnce(action1).WillRepeatedly(action2) + + ExpectThat(len(exp.OneTimeActions), Equals(2)) + ExpectThat(exp.OneTimeActions[0], Equals(action0)) + ExpectThat(exp.OneTimeActions[1], Equals(action1)) + ExpectThat(exp.FallbackAction, Equals(action2)) +} + +func (t *InternalExpectationTest) TimesCalledWithHugeNumber() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.Times(1 << 30) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Times"))) + ExpectThat(r.err, Error(HasSubstr("N must be at most 1000"))) +} + +func (t *InternalExpectationTest) TimesCalledTwice() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.Times(17) + exp.Times(17) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Times"))) + ExpectThat(r.err, Error(HasSubstr("more than once"))) +} + +func (t *InternalExpectationTest) TimesCalledAfterWillOnce() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.WillOnce(Return()) + exp.Times(17) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Times"))) + ExpectThat(r.err, Error(HasSubstr("after WillOnce"))) +} + +func (t *InternalExpectationTest) TimesCalledAfterWillRepeatedly() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.WillRepeatedly(Return()) + exp.Times(17) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("Times"))) + ExpectThat(r.err, Error(HasSubstr("after WillRepeatedly"))) +} + +func (t *InternalExpectationTest) WillOnceCalledAfterWillRepeatedly() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.WillRepeatedly(Return()) + exp.WillOnce(Return()) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("WillOnce"))) + ExpectThat(r.err, Error(HasSubstr("after WillRepeatedly"))) +} + +func (t *InternalExpectationTest) OneTimeActionRejectsSignature() { + exp := t.makeExpectation(float64ReturnSig, []interface{}{}, "taco.go", 112) + exp.WillOnce(Return("taco")) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("arg 0"))) + ExpectThat(r.err, Error(HasSubstr("expected float64"))) + ExpectThat(r.err, Error(HasSubstr("given string"))) +} + +func (t *InternalExpectationTest) WillRepeatedlyCalledTwice() { + exp := t.makeExpectation(emptyReturnSig, []interface{}{}, "taco.go", 112) + exp.WillRepeatedly(Return()) + exp.WillRepeatedly(Return()) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("WillRepeatedly"))) + ExpectThat(r.err, Error(HasSubstr("once"))) +} + +func (t *InternalExpectationTest) FallbackActionRejectsSignature() { + exp := t.makeExpectation(float64ReturnSig, []interface{}{}, "taco.go", 112) + exp.WillRepeatedly(Return("taco")) + + AssertEq(1, len(t.reporter.fatalErrors)) + AssertEq(0, len(t.reporter.errors)) + + r := t.reporter.fatalErrors[0] + ExpectEq("taco.go", r.fileName) + ExpectEq(112, r.lineNumber) + ExpectThat(r.err, Error(HasSubstr("arg 0"))) + ExpectThat(r.err, Error(HasSubstr("expected float64"))) + ExpectThat(r.err, Error(HasSubstr("given string"))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke.go new file mode 100644 index 0000000000..07630cbbb7 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke.go @@ -0,0 +1,73 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "errors" + "fmt" + "reflect" +) + +// Create an Action that invokes the supplied function, returning whatever it +// returns. The signature of the function must match that of the mocked method +// exactly. +func Invoke(f interface{}) Action { + // Make sure f is a function. + fv := reflect.ValueOf(f) + fk := fv.Kind() + + if fk != reflect.Func { + desc := "" + if fk != reflect.Invalid { + desc = fv.Type().String() + } + + panic(fmt.Sprintf("Invoke: expected function, got %s", desc)) + } + + return &invokeAction{fv} +} + +type invokeAction struct { + f reflect.Value +} + +func (a *invokeAction) SetSignature(signature reflect.Type) error { + // The signature must match exactly. + ft := a.f.Type() + if ft != signature { + return errors.New(fmt.Sprintf("Invoke: expected %v, got %v", signature, ft)) + } + + return nil +} + +func (a *invokeAction) Invoke(vals []interface{}) []interface{} { + // Create a slice of args for the function. + in := make([]reflect.Value, len(vals)) + for i, x := range vals { + in[i] = reflect.ValueOf(x) + } + + // Call the function and return its return values. + out := a.f.Call(in) + result := make([]interface{}, len(out)) + for i, v := range out { + result[i] = v.Interface() + } + + return result +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke_test.go new file mode 100644 index 0000000000..c99ef265d3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/invoke_test.go @@ -0,0 +1,110 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "reflect" +) + +//////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////// + +type InvokeTest struct { +} + +func init() { RegisterTestSuite(&InvokeTest{}) } + +//////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////// + +func (t *InvokeTest) ArgumentIsNil() { + f := func() { oglemock.Invoke(nil) } + ExpectThat(f, Panics(MatchesRegexp("Invoke.*function.*"))) +} + +func (t *InvokeTest) ArgumentIsInt() { + f := func() { oglemock.Invoke(17) } + ExpectThat(f, Panics(MatchesRegexp("Invoke.*function.*int"))) +} + +func (t *InvokeTest) FunctionHasOneWrongInputType() { + f := func(a int, b int32, c string) {} + g := func(a int, b int, c string) {} + + err := oglemock.Invoke(f).SetSignature(reflect.TypeOf(g)) + ExpectThat(err, Error(HasSubstr("func(int, int32, string)"))) + ExpectThat(err, Error(HasSubstr("func(int, int, string)"))) +} + +func (t *InvokeTest) FunctionHasOneWrongOutputType() { + f := func() (int32, string) { return 0, "" } + g := func() (int, string) { return 0, "" } + + err := oglemock.Invoke(f).SetSignature(reflect.TypeOf(g)) + ExpectThat(err, Error(HasSubstr("func() (int32, string)"))) + ExpectThat(err, Error(HasSubstr("func() (int, string)"))) +} + +func (t *InvokeTest) CallsFunction() { + var actualArg0, actualArg1 interface{} + + f := func(a uintptr, b int8) { + actualArg0 = a + actualArg1 = b + } + + a := oglemock.Invoke(f) + + // Set signature. + AssertEq(nil, a.SetSignature(reflect.TypeOf(f))) + + // Call the action. + expectedArg0 := uintptr(17) + expectedArg1 := int8(-7) + + a.Invoke([]interface{}{expectedArg0, expectedArg1}) + + ExpectThat(actualArg0, IdenticalTo(expectedArg0)) + ExpectThat(actualArg1, IdenticalTo(expectedArg1)) +} + +func (t *InvokeTest) ReturnsFunctionResult() { + expectedReturn0 := int16(3) + expectedReturn1 := "taco" + + f := func() (int16, string) { + return expectedReturn0, expectedReturn1 + } + + a := oglemock.Invoke(f) + + // Set signature. + AssertEq(nil, a.SetSignature(reflect.TypeOf(f))) + + // Call the action. + res := a.Invoke([]interface{}{}) + + ExpectThat( + res, + ElementsAre( + IdenticalTo(expectedReturn0), + IdenticalTo(expectedReturn1))) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/mock_object.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/mock_object.go new file mode 100644 index 0000000000..de995efc66 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/mock_object.go @@ -0,0 +1,30 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +// MockObject is an interface that mock object implementations must conform to +// in order to register expectations with and hand off calls to a +// MockController. Users should not interact with this interface directly. +type MockObject interface { + // Oglemock_Id returns an identifier for the mock object that is guaranteed + // to be unique within the process at least until the mock object is garbage + // collected. + Oglemock_Id() uintptr + + // Oglemock_Description returns a description of the mock object that may be + // helpful in test failure messages. + Oglemock_Description() string +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/return.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/return.go new file mode 100644 index 0000000000..c66d248f44 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/return.go @@ -0,0 +1,251 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +var intType = reflect.TypeOf(int(0)) +var float64Type = reflect.TypeOf(float64(0)) +var complex128Type = reflect.TypeOf(complex128(0)) + +// Return creates an Action that returns the values passed to Return as +// arguments, after suitable legal type conversions. The following rules apply. +// Given an argument x to Return and a corresponding type T in the method's +// signature, at least one of the following must hold: +// +// * x is assignable to T. (See "Assignability" in the language spec.) Note +// that this in particular applies that x may be a type that implements an +// interface T. It also implies that the nil literal can be used if T is a +// pointer, function, interface, slice, channel, or map type. +// +// * T is any numeric type, and x is an int that is in-range for that type. +// This facilities using raw integer constants: Return(17). +// +// * T is a floating-point or complex number type, and x is a float64. This +// facilities using raw floating-point constants: Return(17.5). +// +// * T is a complex number type, and x is a complex128. This facilities using +// raw complex constants: Return(17+2i). +// +func Return(vals ...interface{}) Action { + return &returnAction{vals, nil} +} + +type returnAction struct { + returnVals []interface{} + signature reflect.Type +} + +func (a *returnAction) Invoke(vals []interface{}) []interface{} { + if a.signature == nil { + panic("You must first call SetSignature with a valid signature.") + } + + res, err := a.buildInvokeResult(a.signature) + if err != nil { + panic(err) + } + + return res +} + +func (a *returnAction) SetSignature(signature reflect.Type) error { + if _, err := a.buildInvokeResult(signature); err != nil { + return err + } + + a.signature = signature + return nil +} + +// A version of Invoke that does error checking, used by both public methods. +func (a *returnAction) buildInvokeResult( + sig reflect.Type) (res []interface{}, err error) { + // Check the length of the return value. + numOut := sig.NumOut() + numVals := len(a.returnVals) + + if numOut != numVals { + err = errors.New( + fmt.Sprintf("Return given %d vals; expected %d.", numVals, numOut)) + return + } + + // Attempt to coerce each return value. + res = make([]interface{}, numOut) + + for i, val := range a.returnVals { + resType := sig.Out(i) + res[i], err = a.coerce(val, resType) + + if err != nil { + res = nil + err = errors.New(fmt.Sprintf("Return: arg %d: %v", i, err)) + return + } + } + + return +} + +func (a *returnAction) coerce(x interface{}, t reflect.Type) (interface{}, error) { + xv := reflect.ValueOf(x) + rv := reflect.New(t).Elem() + + // Special case: the language spec says that the predeclared identifier nil + // is assignable to pointers, functions, interface, slices, channels, and map + // types. However, reflect.ValueOf(nil) returns an invalid value that will + // not cooperate below. So handle invalid values here, assuming that they + // resulted from Return(nil). + if !xv.IsValid() { + switch t.Kind() { + case reflect.Ptr, reflect.Func, reflect.Interface, reflect.Chan, reflect.Slice, reflect.Map, reflect.UnsafePointer: + return rv.Interface(), nil + } + + return nil, errors.New(fmt.Sprintf("expected %v, given ", t)) + } + + // If x is assignable to type t, let the reflect package do the heavy + // lifting. + if reflect.TypeOf(x).AssignableTo(t) { + rv.Set(xv) + return rv.Interface(), nil + } + + // Handle numeric types as described in the documentation on Return. + switch { + case xv.Type() == intType && a.isNumeric(t): + return a.coerceInt(xv.Int(), t) + + case xv.Type() == float64Type && (a.isFloatingPoint(t) || a.isComplex(t)): + return a.coerceFloat(xv.Float(), t) + + case xv.Type() == complex128Type && a.isComplex(t): + return a.coerceComplex(xv.Complex(), t) + } + + // The value wasn't of a legal type. + return nil, errors.New(fmt.Sprintf("expected %v, given %v", t, xv.Type())) +} + +func (a *returnAction) isNumeric(t reflect.Type) bool { + return (t.Kind() >= reflect.Int && t.Kind() <= reflect.Uint64) || + a.isFloatingPoint(t) || + a.isComplex(t) +} + +func (a *returnAction) isFloatingPoint(t reflect.Type) bool { + return t.Kind() == reflect.Float32 || t.Kind() == reflect.Float64 +} + +func (a *returnAction) isComplex(t reflect.Type) bool { + return t.Kind() == reflect.Complex64 || t.Kind() == reflect.Complex128 +} + +func (a *returnAction) coerceInt(x int64, t reflect.Type) (interface{}, error) { + k := t.Kind() + + // Floating point and complex numbers: promote appropriately. + if a.isFloatingPoint(t) || a.isComplex(t) { + return a.coerceFloat(float64(x), t) + } + + // Integers: range check. + var min, max int64 + unsigned := false + + switch k { + case reflect.Int8: + min = math.MinInt8 + max = math.MaxInt8 + + case reflect.Int16: + min = math.MinInt16 + max = math.MaxInt16 + + case reflect.Int32: + min = math.MinInt32 + max = math.MaxInt32 + + case reflect.Int64: + min = math.MinInt64 + max = math.MaxInt64 + + case reflect.Uint: + unsigned = true + min = 0 + max = math.MaxUint32 + + case reflect.Uint8: + unsigned = true + min = 0 + max = math.MaxUint8 + + case reflect.Uint16: + unsigned = true + min = 0 + max = math.MaxUint16 + + case reflect.Uint32: + unsigned = true + min = 0 + max = math.MaxUint32 + + case reflect.Uint64: + unsigned = true + min = 0 + max = math.MaxInt64 + + default: + panic(fmt.Sprintf("Unexpected type: %v", t)) + } + + if x < min || x > max { + return nil, errors.New("int value out of range") + } + + rv := reflect.New(t).Elem() + if unsigned { + rv.SetUint(uint64(x)) + } else { + rv.SetInt(x) + } + + return rv.Interface(), nil +} + +func (a *returnAction) coerceFloat(x float64, t reflect.Type) (interface{}, error) { + // Promote complex numbers. + if a.isComplex(t) { + return a.coerceComplex(complex(x, 0), t) + } + + rv := reflect.New(t).Elem() + rv.SetFloat(x) + return rv.Interface(), nil +} + +func (a *returnAction) coerceComplex(x complex128, t reflect.Type) (interface{}, error) { + rv := reflect.New(t).Elem() + rv.SetComplex(x) + return rv.Interface(), nil +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/return_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/return_test.go new file mode 100644 index 0000000000..da0a43a65d --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/return_test.go @@ -0,0 +1,978 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + "bytes" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "io" + "math" + "reflect" + "testing" + "unsafe" +) + +//////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////// + +var someInt int = 17 + +type ReturnTest struct { +} + +func init() { RegisterTestSuite(&ReturnTest{}) } +func TestOgletest(t *testing.T) { RunTests(t) } + +type returnTestCase struct { + suppliedVal interface{} + expectedVal interface{} + expectedSetSignatureErrorSubstring string +} + +func (t *ReturnTest) runTestCases(signature reflect.Type, cases []returnTestCase) { + for i, c := range cases { + a := oglemock.Return(c.suppliedVal) + + // SetSignature + err := a.SetSignature(signature) + if c.expectedSetSignatureErrorSubstring == "" { + ExpectEq(nil, err, "Test case %d: %v", i, c) + + if err != nil { + continue + } + } else { + ExpectThat(err, Error(HasSubstr(c.expectedSetSignatureErrorSubstring)), + "Test case %d: %v", i, c) + continue + } + + // Invoke + res := a.Invoke([]interface{}{}) + AssertThat(res, ElementsAre(Any())) + ExpectThat(res[0], IdenticalTo(c.expectedVal), "Test case %d: %v", i, c) + } +} + +//////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////// + +func (t *ReturnTest) SetSignatureNotCalled() { + a := oglemock.Return() + f := func() { a.Invoke([]interface{}{}) } + ExpectThat(f, Panics(MatchesRegexp("first call SetSignature"))) +} + +func (t *ReturnTest) NoReturnValues() { + sig := reflect.TypeOf(func() {}) + var a oglemock.Action + var err error + var vals []interface{} + + // No values. + a = oglemock.Return() + err = a.SetSignature(sig) + AssertEq(nil, err) + + vals = a.Invoke([]interface{}{}) + ExpectThat(vals, ElementsAre()) + + // One value. + a = oglemock.Return(17) + err = a.SetSignature(sig) + ExpectThat(err, Error(HasSubstr("given 1 val"))) + ExpectThat(err, Error(HasSubstr("expected 0"))) + + // Two values. + a = oglemock.Return(17, 19) + err = a.SetSignature(sig) + ExpectThat(err, Error(HasSubstr("given 2 vals"))) + ExpectThat(err, Error(HasSubstr("expected 0"))) +} + +func (t *ReturnTest) MultipleReturnValues() { + sig := reflect.TypeOf(func() (int, string) { return 0, "" }) + var a oglemock.Action + var err error + var vals []interface{} + + // No values. + a = oglemock.Return() + err = a.SetSignature(sig) + ExpectThat(err, Error(HasSubstr("given 0 vals"))) + ExpectThat(err, Error(HasSubstr("expected 2"))) + + // One value. + a = oglemock.Return(17) + err = a.SetSignature(sig) + ExpectThat(err, Error(HasSubstr("given 1 val"))) + ExpectThat(err, Error(HasSubstr("expected 2"))) + + // Two values. + a = oglemock.Return(17, "taco") + err = a.SetSignature(sig) + AssertEq(nil, err) + + vals = a.Invoke([]interface{}{}) + ExpectThat(vals, ElementsAre(IdenticalTo(int(17)), "taco")) +} + +func (t *ReturnTest) Bool() { + sig := reflect.TypeOf(func() bool { return false }) + cases := []returnTestCase{ + // Identical types. + {bool(true), bool(true), ""}, + {bool(false), bool(false), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Int() { + sig := reflect.TypeOf(func() int { return 0 }) + cases := []returnTestCase{ + // Identical types. + {int(math.MinInt32), int(math.MinInt32), ""}, + {int(math.MaxInt32), int(math.MaxInt32), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Int8() { + sig := reflect.TypeOf(func() int8 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {int8(math.MinInt8), int8(math.MinInt8), ""}, + {int8(math.MaxInt8), int8(math.MaxInt8), ""}, + + // In-range ints. + {int(math.MinInt8), int8(math.MinInt8), ""}, + {int(math.MaxInt8), int8(math.MaxInt8), ""}, + + // Out of range ints. + {int(math.MinInt8 - 1), nil, "out of range"}, + {int(math.MaxInt8 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Int16() { + sig := reflect.TypeOf(func() int16 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {int16(math.MinInt16), int16(math.MinInt16), ""}, + {int16(math.MaxInt16), int16(math.MaxInt16), ""}, + + // In-range ints. + {int(math.MinInt16), int16(math.MinInt16), ""}, + {int(math.MaxInt16), int16(math.MaxInt16), ""}, + + // Out of range ints. + {int(math.MinInt16 - 1), nil, "out of range"}, + {int(math.MaxInt16 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int8(1), nil, "given int8"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Int32() { + sig := reflect.TypeOf(func() int32 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {int32(math.MinInt32), int32(math.MinInt32), ""}, + {int32(math.MaxInt32), int32(math.MaxInt32), ""}, + + // Aliased version of type. + {rune(17), int32(17), ""}, + + // In-range ints. + {int(math.MinInt32), int32(math.MinInt32), ""}, + {int(math.MaxInt32), int32(math.MaxInt32), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Rune() { + sig := reflect.TypeOf(func() rune { return 0 }) + cases := []returnTestCase{ + // Identical types. + {rune(math.MinInt32), rune(math.MinInt32), ""}, + {rune(math.MaxInt32), rune(math.MaxInt32), ""}, + + // Aliased version of type. + {int32(17), rune(17), ""}, + + // In-range ints. + {int(math.MinInt32), rune(math.MinInt32), ""}, + {int(math.MaxInt32), rune(math.MaxInt32), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Int64() { + sig := reflect.TypeOf(func() int64 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {int64(math.MinInt64), int64(math.MinInt64), ""}, + {int64(math.MaxInt64), int64(math.MaxInt64), ""}, + + // In-range ints. + {int(math.MinInt32), int64(math.MinInt32), ""}, + {int(math.MaxInt32), int64(math.MaxInt32), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uint() { + sig := reflect.TypeOf(func() uint { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uint(0), uint(0), ""}, + {uint(math.MaxUint32), uint(math.MaxUint32), ""}, + + // In-range ints. + {int(0), uint(0), ""}, + {int(math.MaxInt32), uint(math.MaxInt32), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uint8() { + sig := reflect.TypeOf(func() uint8 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uint8(0), uint8(0), ""}, + {uint8(math.MaxUint8), uint8(math.MaxUint8), ""}, + + // Aliased version of type. + {byte(17), uint8(17), ""}, + + // In-range ints. + {int(0), uint8(0), ""}, + {int(math.MaxUint8), uint8(math.MaxUint8), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + {int(math.MaxUint8 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Byte() { + sig := reflect.TypeOf(func() byte { return 0 }) + cases := []returnTestCase{ + // Identical types. + {byte(0), byte(0), ""}, + {byte(math.MaxUint8), byte(math.MaxUint8), ""}, + + // Aliased version of type. + {uint8(17), byte(17), ""}, + + // In-range ints. + {int(0), byte(0), ""}, + {int(math.MaxUint8), byte(math.MaxUint8), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + {int(math.MaxUint8 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uint16() { + sig := reflect.TypeOf(func() uint16 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uint16(0), uint16(0), ""}, + {uint16(math.MaxUint16), uint16(math.MaxUint16), ""}, + + // In-range ints. + {int(0), uint16(0), ""}, + {int(math.MaxUint16), uint16(math.MaxUint16), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + {int(math.MaxUint16 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uint32() { + sig := reflect.TypeOf(func() uint32 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uint32(0), uint32(0), ""}, + {uint32(math.MaxUint32), uint32(math.MaxUint32), ""}, + + // In-range ints. + {int(0), uint32(0), ""}, + {int(math.MaxInt32), uint32(math.MaxInt32), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uint64() { + sig := reflect.TypeOf(func() uint64 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uint64(0), uint64(0), ""}, + {uint64(math.MaxUint64), uint64(math.MaxUint64), ""}, + + // In-range ints. + {int(0), uint64(0), ""}, + {int(math.MaxInt32), uint64(math.MaxInt32), ""}, + + // Out of range ints. + {int(-1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Uintptr() { + sig := reflect.TypeOf(func() uintptr { return 0 }) + cases := []returnTestCase{ + // Identical types. + {uintptr(17), uintptr(17), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Float32() { + sig := reflect.TypeOf(func() float32 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {float32(-17.5), float32(-17.5), ""}, + {float32(17.5), float32(17.5), ""}, + + // In-range ints. + {int(-17), float32(-17), ""}, + {int(17), float32(17), ""}, + + // Float64s + {float64(-17.5), float32(-17.5), ""}, + {float64(17.5), float32(17.5), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Float64() { + sig := reflect.TypeOf(func() float64 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {float64(-17.5), float64(-17.5), ""}, + {float64(17.5), float64(17.5), ""}, + + // In-range ints. + {int(-17), float64(-17), ""}, + {int(17), float64(17), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float32(1), nil, "given float32"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Complex64() { + sig := reflect.TypeOf(func() complex64 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {complex64(-17.5 - 1i), complex64(-17.5 - 1i), ""}, + {complex64(17.5 + 1i), complex64(17.5 + 1i), ""}, + + // In-range ints. + {int(-17), complex64(-17), ""}, + {int(17), complex64(17), ""}, + + // Float64s + {float64(-17.5), complex64(-17.5), ""}, + {float64(17.5), complex64(17.5), ""}, + + // Complex128s + {complex128(-17.5 - 1i), complex64(-17.5 - 1i), ""}, + {complex128(17.5 + 1i), complex64(17.5 + 1i), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float32(1), nil, "given float32"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Complex128() { + sig := reflect.TypeOf(func() complex128 { return 0 }) + cases := []returnTestCase{ + // Identical types. + {complex128(-17.5 - 1i), complex128(-17.5 - 1i), ""}, + {complex128(17.5 + 1i), complex128(17.5 + 1i), ""}, + + // In-range ints. + {int(-17), complex128(-17), ""}, + {int(17), complex128(17), ""}, + + // Float64s + {float64(-17.5), complex128(-17.5), ""}, + {float64(17.5), complex128(17.5), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float32(1), nil, "given float32"}, + {complex64(1), nil, "given complex64"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) ArrayOfInt() { + type namedElemType int + + sig := reflect.TypeOf(func() [2]int { return [2]int{0, 0} }) + cases := []returnTestCase{ + // Identical types. + {[2]int{19, 23}, [2]int{19, 23}, ""}, + + // Wrong length. + {[1]int{17}, nil, "given [1]int"}, + + // Wrong element types. + {[2]namedElemType{19, 23}, nil, "given [2]oglemock_test.namedElemType"}, + {[2]string{"", ""}, nil, "given [2]string"}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) ChanOfInt() { + type namedElemType int + someChan := make(chan int) + + sig := reflect.TypeOf(func() chan int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someChan, someChan, ""}, + + // Nil values. + {(interface{})(nil), (chan int)(nil), ""}, + {(chan int)(nil), (chan int)(nil), ""}, + + // Wrong element types. + {make(chan string), nil, "given chan string"}, + {make(chan namedElemType), nil, "given chan oglemock_test.namedElemType"}, + + // Wrong direction + {(<-chan int)(someChan), nil, "given <-chan int"}, + {(chan<- int)(someChan), nil, "given chan<- int"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) SendChanOfInt() { + type namedElemType int + + someChan := make(chan<- int) + someBidirectionalChannel := make(chan int) + + sig := reflect.TypeOf(func() chan<- int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someChan, someChan, ""}, + + // Nil values. + {(interface{})(nil), (chan<- int)(nil), ""}, + {(chan int)(nil), (chan<- int)(nil), ""}, + + // Bidirectional channel + {someBidirectionalChannel, (chan<- int)(someBidirectionalChannel), ""}, + + // Wrong direction + {(<-chan int)(someBidirectionalChannel), nil, "given <-chan int"}, + + // Wrong element types. + {make(chan string), nil, "given chan string"}, + {make(chan namedElemType), nil, "given chan oglemock_test.namedElemType"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) RecvChanOfInt() { + type namedElemType int + + someChan := make(<-chan int) + someBidirectionalChannel := make(chan int) + + sig := reflect.TypeOf(func() <-chan int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someChan, someChan, ""}, + + // Nil values. + {(interface{})(nil), (<-chan int)(nil), ""}, + {(chan int)(nil), (<-chan int)(nil), ""}, + + // Bidirectional channel + {someBidirectionalChannel, (<-chan int)(someBidirectionalChannel), ""}, + + // Wrong direction + {(chan<- int)(someBidirectionalChannel), nil, "given chan<- int"}, + + // Wrong element types. + {make(chan string), nil, "given chan string"}, + {make(chan namedElemType), nil, "given chan oglemock_test.namedElemType"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Func() { + someFunc := func(string) int { return 0 } + + sig := reflect.TypeOf(func() func(string) int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someFunc, someFunc, ""}, + + // Nil values. + {(interface{})(nil), (func(string) int)(nil), ""}, + {(func(string) int)(nil), (func(string) int)(nil), ""}, + + // Wrong parameter and return types. + {func(int) int { return 0 }, nil, "given func(int) int"}, + {func(string) string { return "" }, nil, "given func(string) string"}, + + // Wrong types. + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {(chan int)(nil), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Interface() { + sig := reflect.TypeOf(func() io.Reader { return nil }) + + someBuffer := new(bytes.Buffer) + + cases := []returnTestCase{ + // Type that implements interface. + {someBuffer, someBuffer, ""}, + + // Nil value. + {(interface{})(nil), (interface{})(nil), ""}, + + // Non-implementing types. + {(chan int)(nil), nil, "given chan int"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) MapFromStringToInt() { + type namedElemType string + + someMap := make(map[string]int) + + sig := reflect.TypeOf(func() map[string]int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someMap, someMap, ""}, + + // Nil values. + {(interface{})(nil), (map[string]int)(nil), ""}, + {(map[string]int)(nil), (map[string]int)(nil), ""}, + + // Wrong element types. + {make(map[int]int), nil, "given map[int]int"}, + {make(map[namedElemType]int), nil, "given map[oglemock_test.namedElemType]int"}, + {make(map[string]string), nil, "given map[string]string"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) PointerToString() { + type namedElemType string + + someStr := "" + + sig := reflect.TypeOf(func() *string { return nil }) + cases := []returnTestCase{ + // Identical types. + {(*string)(&someStr), (*string)(&someStr), ""}, + + // Nil values. + {(interface{})(nil), (*string)(nil), ""}, + {(*string)(nil), (*string)(nil), ""}, + + // Wrong element types. + {&someInt, nil, "given *int"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {unsafe.Pointer(&someStr), nil, "given unsafe.Pointer"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) SliceOfInts() { + type namedElemType int + + someSlice := make([]int, 1) + + sig := reflect.TypeOf(func() []int { return nil }) + cases := []returnTestCase{ + // Identical types. + {someSlice, someSlice, ""}, + + // Nil values. + {(interface{})(nil), ([]int)(nil), ""}, + {([]int)(nil), ([]int)(nil), ""}, + + // Wrong element types. + {make([]string, 1), nil, "given []string"}, + {make([]namedElemType, 1), nil, "given []oglemock_test.namedElemType"}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) String() { + sig := reflect.TypeOf(func() string { return "" }) + cases := []returnTestCase{ + // Identical types. + {string(""), string(""), ""}, + {string("taco"), string("taco"), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) Struct() { + type myStruct struct { + a int + } + + type otherStruct struct{} + + sig := reflect.TypeOf(func() myStruct { return myStruct{0} }) + cases := []returnTestCase{ + // Identical types. + {myStruct{17}, myStruct{17}, ""}, + + // Wrong field types. + {otherStruct{}, nil, "given oglemock_test.otherStruct"}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) UnsafePointer() { + someStr := "" + + sig := reflect.TypeOf(func() unsafe.Pointer { return nil }) + cases := []returnTestCase{ + // Identical types. + {unsafe.Pointer(&someStr), unsafe.Pointer(&someStr), ""}, + + // Nil values. + {(interface{})(nil), unsafe.Pointer(nil), ""}, + {unsafe.Pointer(nil), unsafe.Pointer(nil), ""}, + + // Wrong types. + {(func())(nil), nil, "given func()"}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {(*string)(&someStr), nil, "given *string"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) UserDefinedNumericType() { + type myType int16 + + sig := reflect.TypeOf(func() myType { return 0 }) + cases := []returnTestCase{ + // Identical types. + {myType(math.MinInt16), myType(math.MinInt16), ""}, + {myType(math.MaxInt16), myType(math.MaxInt16), ""}, + + // In-range ints. + {int(math.MinInt16), myType(math.MinInt16), ""}, + {int(math.MaxInt16), myType(math.MaxInt16), ""}, + + // Out of range ints. + {int(math.MinInt16 - 1), nil, "out of range"}, + {int(math.MaxInt16 + 1), nil, "out of range"}, + + // Wrong types. + {nil, nil, "given "}, + {int16(1), nil, "given int16"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} + +func (t *ReturnTest) UserDefinedNonNumericType() { + type myType string + + sig := reflect.TypeOf(func() myType { return "" }) + cases := []returnTestCase{ + // Identical types. + {myType("taco"), myType("taco"), ""}, + + // Wrong types. + {nil, nil, "given "}, + {int(1), nil, "given int"}, + {float64(1), nil, "given float64"}, + {complex128(1), nil, "given complex128"}, + {string(""), nil, "given string"}, + {&someInt, nil, "given *int"}, + {make(chan int), nil, "given chan int"}, + } + + t.runTestCases(sig, cases) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/sample/mock_io/mock_io.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/sample/mock_io/mock_io.go new file mode 100644 index 0000000000..0f6a891c65 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/sample/mock_io/mock_io.go @@ -0,0 +1,71 @@ +// This file was auto-generated using createmock. See the following page for +// more information: +// +// https://github.com/smartystreets/assertions/internal/oglemock +// + +package mock_io + +import ( + fmt "fmt" + oglemock "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + io "io" + runtime "runtime" + unsafe "unsafe" +) + +type MockReader interface { + io.Reader + oglemock.MockObject +} + +type mockReader struct { + controller oglemock.Controller + description string +} + +func NewMockReader( + c oglemock.Controller, + desc string) MockReader { + return &mockReader{ + controller: c, + description: desc, + } +} + +func (m *mockReader) Oglemock_Id() uintptr { + return uintptr(unsafe.Pointer(m)) +} + +func (m *mockReader) Oglemock_Description() string { + return m.description +} + +func (m *mockReader) Read(p0 []uint8) (o0 int, o1 error) { + // Get a file name and line number for the caller. + _, file, line, _ := runtime.Caller(1) + + // Hand the call off to the controller, which does most of the work. + retVals := m.controller.HandleMethodCall( + m, + "Read", + file, + line, + []interface{}{p0}) + + if len(retVals) != 2 { + panic(fmt.Sprintf("mockReader.Read: invalid return values: %v", retVals)) + } + + // o0 int + if retVals[0] != nil { + o0 = retVals[0].(int) + } + + // o1 error + if retVals[1] != nil { + o1 = retVals[1].(error) + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg.go new file mode 100644 index 0000000000..27cfcf6193 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg.go @@ -0,0 +1,83 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock + +import ( + "fmt" + "reflect" +) + +// Create an Action that saves the argument at the given zero-based index to +// the supplied destination, which must be a pointer to a type that is +// assignable from the argument type. +func SaveArg(index int, dst interface{}) Action { + return &saveArg{ + index: index, + dstPointer: dst, + } +} + +type saveArg struct { + index int + dstPointer interface{} + + // Set by SetSignature. + dstValue reflect.Value +} + +func (a *saveArg) SetSignature(signature reflect.Type) (err error) { + // Extract the source type. + if a.index >= signature.NumIn() { + err = fmt.Errorf( + "Out of range argument index %v for function type %v", + a.index, + signature) + return + } + + srcType := signature.In(a.index) + + // The destination must be a pointer. + v := reflect.ValueOf(a.dstPointer) + if v.Kind() != reflect.Ptr { + err = fmt.Errorf("Destination is %v, not a pointer", v.Kind()) + return + } + + // Dereference the pointer. + if v.IsNil() { + err = fmt.Errorf("Destination pointer must be non-nil") + return + } + + a.dstValue = v.Elem() + + // The destination must be assignable from the source. + if !srcType.AssignableTo(a.dstValue.Type()) { + err = fmt.Errorf( + "%v is not assignable to %v", + srcType, + a.dstValue.Type()) + return + } + + return +} + +func (a *saveArg) Invoke(methodArgs []interface{}) (rets []interface{}) { + a.dstValue.Set(reflect.ValueOf(methodArgs[a.index])) + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg_test.go b/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg_test.go new file mode 100644 index 0000000000..79212455ff --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/oglemock/save_arg_test.go @@ -0,0 +1,132 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 oglemock_test + +import ( + "io" + "os" + "reflect" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" +) + +func TestSaveArg(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////// +// Boilerplate +//////////////////////////////////////////////////////////// + +type SaveArgTest struct { +} + +func init() { RegisterTestSuite(&SaveArgTest{}) } + +//////////////////////////////////////////////////////////// +// Test functions +//////////////////////////////////////////////////////////// + +func (t *SaveArgTest) FunctionHasNoArguments() { + const index = 0 + var dst int + f := func() (int, string) { return 0, "" } + + err := oglemock.SaveArg(index, &dst).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("index 0"))) + ExpectThat(err, Error(HasSubstr("Out of range"))) + ExpectThat(err, Error(HasSubstr("func() (int, string)"))) +} + +func (t *SaveArgTest) ArgumentIndexOutOfRange() { + const index = 2 + var dst int + f := func(a int, b int) {} + + err := oglemock.SaveArg(index, &dst).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("index 2"))) + ExpectThat(err, Error(HasSubstr("Out of range"))) + ExpectThat(err, Error(HasSubstr("func(int, int)"))) +} + +func (t *SaveArgTest) DestinationIsLiteralNil() { + const index = 0 + f := func(a int, b int) {} + + err := oglemock.SaveArg(index, nil).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("not a pointer"))) +} + +func (t *SaveArgTest) DestinationIsNotAPointer() { + const index = 0 + f := func(a int, b int) {} + + err := oglemock.SaveArg(index, uint(17)).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("pointer"))) + ExpectThat(err, Error(HasSubstr("uint"))) +} + +func (t *SaveArgTest) DestinationIsNilPointer() { + const index = 1 + var dst *int + f := func(a int, b int) {} + + err := oglemock.SaveArg(index, dst).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("pointer"))) + ExpectThat(err, Error(HasSubstr("non-nil"))) +} + +func (t *SaveArgTest) DestinationNotAssignableFromSource() { + const index = 1 + var dst int + f := func(a int, b string) {} + + err := oglemock.SaveArg(index, &dst).SetSignature(reflect.TypeOf(f)) + ExpectThat(err, Error(HasSubstr("int"))) + ExpectThat(err, Error(HasSubstr("assignable"))) + ExpectThat(err, Error(HasSubstr("string"))) +} + +func (t *SaveArgTest) ExactTypeMatch() { + const index = 1 + var dst int + f := func(a int, b int) {} + + action := oglemock.SaveArg(index, &dst) + AssertEq(nil, action.SetSignature(reflect.TypeOf(f))) + + var a int = 17 + var b int = 19 + _ = action.Invoke([]interface{}{a, b}) + + ExpectEq(19, dst) +} + +func (t *SaveArgTest) AssignableTypeMatch() { + const index = 1 + var dst io.Reader + f := func(a int, b *os.File) {} + + action := oglemock.SaveArg(index, &dst) + AssertEq(nil, action.SetSignature(reflect.TypeOf(f))) + + var a int = 17 + var b *os.File = os.Stdout + _ = action.Invoke([]interface{}{a, b}) + + ExpectEq(os.Stdout, dst) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/LICENSE b/vendor/github.com/smartystreets/assertions/internal/ogletest/LICENSE new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/README.md b/vendor/github.com/smartystreets/assertions/internal/ogletest/README.md new file mode 100644 index 0000000000..8e54862082 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/README.md @@ -0,0 +1,151 @@ +[![GoDoc](https://godoc.org/github.com/smartystreets/assertions/internal/ogletest?status.svg)](https://godoc.org/github.com/smartystreets/assertions/internal/ogletest) + +`ogletest` is a unit testing framework for Go with the following features: + + * An extensive and extensible set of matchers for expressing expectations. + * Automatic failure messages; no need to say `t.Errorf("Expected %v, got + %v"...)`. + * Clean, readable output that tells you exactly what you need to know. + * Built-in support for mocking through the [oglemock][] package. + * Style and semantics similar to [Google Test][googletest] and + [Google JS Test][google-js-test]. + +It integrates with Go's built-in `testing` package, so it works with the +`go test` command, and even with other types of test within your package. Unlike +the `testing` package which offers only basic capabilities for signalling +failures, it offers ways to express expectations and get nice failure messages +automatically. + + +Installation +------------ + +First, make sure you have installed Go 1.0.2 or newer. See +[here][golang-install] for instructions. + +Use the following command to install `ogletest` and its dependencies, and to +keep them up to date: + + go get -u github.com/smartystreets/assertions/internal/ogletest + + +Documentation +------------- + +See [here][reference] for package documentation containing an exhaustive list of +exported symbols. Alternatively, you can install the package and then use +`godoc`: + + godoc github.com/smartystreets/assertions/internal/ogletest + +An important part of `ogletest` is its use of matchers provided by the +[oglematchers][matcher-reference] package. See that package's documentation +for information on the built-in matchers available, and check out the +`oglematchers.Matcher` interface if you want to define your own. + + +Example +------- + +Let's say you have a function in your package `people` with the following +signature: + +```go +// GetRandomPerson returns the name and phone number of Tony, Dennis, or Scott. +func GetRandomPerson() (name, phone string) { + [...] +} +``` + +A silly function, but it will do for an example. You can write a couple of tests +for it as follows: + +```go +package people + +import ( + "github.com/smartystreets/assertions/internal/oglematchers" + "github.com/smartystreets/assertions/internal/ogletest" + "testing" +) + +// Give ogletest a chance to run your tests when invoked by 'go test'. +func TestOgletest(t *testing.T) { ogletest.RunTests(t) } + +// Create a test suite, which groups together logically related test methods +// (defined below). You can share common setup and teardown code here; see the +// package docs for more info. +type PeopleTest struct {} +func init() { ogletest.RegisterTestSuite(&PeopleTest{}) } + +func (t *PeopleTest) ReturnsCorrectNames() { + // Call the function a few times, and make sure it never strays from the set + // of expected names. + for i := 0; i < 25; i++ { + name, _ := GetRandomPerson() + ogletest.ExpectThat(name, oglematchers.AnyOf("Tony", "Dennis", "Scott")) + } +} + +func (t *PeopleTest) FormatsPhoneNumbersCorrectly() { + // Call the function a few times, and make sure it returns phone numbers in a + // standard US format. + for i := 0; i < 25; i++ { + _, phone := GetRandomPerson() + ogletest.ExpectThat(phone, oglematchers.MatchesRegexp(`^\(\d{3}\) \d{3}-\d{4}$`)) +} +``` + +Note that test control functions (`RunTests`, `ExpectThat`, and so on) are part +of the `ogletest` package, whereas built-in matchers (`AnyOf`, `MatchesRegexp`, +and more) are part of the [oglematchers][matcher-reference] library. You can of +course use dot imports so that you don't need to prefix each function with its +package name: + +```go +import ( + . "github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/smartystreets/assertions/internal/ogletest" +) +``` + +If you save the test in a file whose name ends in `_test.go`, you can run your +tests by simply invoking the following in your package directory: + + go test + +Here's what the failure output of ogletest looks like, if your function's +implementation is bad. + + [----------] Running tests from PeopleTest + [ RUN ] PeopleTest.FormatsPhoneNumbersCorrectly + people_test.go:32: + Expected: matches regexp "^\(\d{3}\) \d{3}-\d{4}$" + Actual: +1 800 555 5555 + + [ FAILED ] PeopleTest.FormatsPhoneNumbersCorrectly + [ RUN ] PeopleTest.ReturnsCorrectNames + people_test.go:23: + Expected: or(Tony, Dennis, Scott) + Actual: Bart + + [ FAILED ] PeopleTest.ReturnsCorrectNames + [----------] Finished with tests from PeopleTest + +And if the test passes: + + [----------] Running tests from PeopleTest + [ RUN ] PeopleTest.FormatsPhoneNumbersCorrectly + [ OK ] PeopleTest.FormatsPhoneNumbersCorrectly + [ RUN ] PeopleTest.ReturnsCorrectNames + [ OK ] PeopleTest.ReturnsCorrectNames + [----------] Finished with tests from PeopleTest + + +[reference]: http://godoc.org/github.com/smartystreets/assertions/internal/ogletest +[matcher-reference]: http://godoc.org/github.com/smartystreets/assertions/internal/oglematchers +[golang-install]: http://golang.org/doc/install.html +[googletest]: http://code.google.com/p/googletest/ +[google-js-test]: http://code.google.com/p/google-js-test/ +[howtowrite]: http://golang.org/doc/code.html +[oglemock]: https://github.com/smartystreets/assertions/internal/oglemock diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_aliases.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_aliases.go new file mode 100644 index 0000000000..3cedbf29a3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_aliases.go @@ -0,0 +1,70 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +// AssertEq(e, a) is equivalent to AssertThat(a, oglematchers.Equals(e)). +func AssertEq(expected, actual interface{}, errorParts ...interface{}) { + assertThat( + actual, + oglematchers.Equals(expected), + 1, + errorParts) +} + +// AssertNe(e, a) is equivalent to +// AssertThat(a, oglematchers.Not(oglematchers.Equals(e))). +func AssertNe(expected, actual interface{}, errorParts ...interface{}) { + assertThat( + actual, + oglematchers.Not(oglematchers.Equals(expected)), + 1, + errorParts) +} + +// AssertLt(x, y) is equivalent to AssertThat(x, oglematchers.LessThan(y)). +func AssertLt(x, y interface{}, errorParts ...interface{}) { + assertThat(x, oglematchers.LessThan(y), 1, errorParts) +} + +// AssertLe(x, y) is equivalent to AssertThat(x, oglematchers.LessOrEqual(y)). +func AssertLe(x, y interface{}, errorParts ...interface{}) { + assertThat(x, oglematchers.LessOrEqual(y), 1, errorParts) +} + +// AssertGt(x, y) is equivalent to AssertThat(x, oglematchers.GreaterThan(y)). +func AssertGt(x, y interface{}, errorParts ...interface{}) { + assertThat(x, oglematchers.GreaterThan(y), 1, errorParts) +} + +// AssertGe(x, y) is equivalent to +// AssertThat(x, oglematchers.GreaterOrEqual(y)). +func AssertGe(x, y interface{}, errorParts ...interface{}) { + assertThat(x, oglematchers.GreaterOrEqual(y), 1, errorParts) +} + +// AssertTrue(b) is equivalent to AssertThat(b, oglematchers.Equals(true)). +func AssertTrue(b interface{}, errorParts ...interface{}) { + assertThat(b, oglematchers.Equals(true), 1, errorParts) +} + +// AssertFalse(b) is equivalent to AssertThat(b, oglematchers.Equals(false)). +func AssertFalse(b interface{}, errorParts ...interface{}) { + assertThat(b, oglematchers.Equals(false), 1, errorParts) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_that.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_that.go new file mode 100644 index 0000000000..5b4ce6d8c8 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/assert_that.go @@ -0,0 +1,46 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +func assertThat( + x interface{}, + m oglematchers.Matcher, + depth int, + errorParts []interface{}) { + passed := expectThat(x, m, depth+1, errorParts) + if !passed { + AbortTest() + } +} + +// AssertThat is identical to ExpectThat, except that in the event of failure +// it halts the currently running test immediately. It is thus useful for +// things like bounds checking: +// +// someSlice := [...] +// AssertEq(1, len(someSlice)) // Protects next line from panicking. +// ExpectEq("taco", someSlice[0]) +// +func AssertThat( + x interface{}, + m oglematchers.Matcher, + errorParts ...interface{}) { + assertThat(x, m, 1, errorParts) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/doc.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/doc.go new file mode 100644 index 0000000000..bf6507fae4 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/doc.go @@ -0,0 +1,51 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest provides a framework for writing expressive unit tests. It +// integrates with the builtin testing package, so it works with the gotest +// command. Unlike the testing package which offers only basic capabilities for +// signalling failures, it offers ways to express expectations and get nice +// failure messages automatically. +// +// For example: +// +// //////////////////////////////////////////////////////////////////////// +// // testing package test +// //////////////////////////////////////////////////////////////////////// +// +// someStr, err := ComputeSomeString() +// if err != nil { +// t.Errorf("ComputeSomeString: expected nil error, got %v", err) +// } +// +// !strings.Contains(someStr, "foo") { +// t.Errorf("ComputeSomeString: expected substring foo, got %v", someStr) +// } +// +// //////////////////////////////////////////////////////////////////////// +// // ogletest test +// //////////////////////////////////////////////////////////////////////// +// +// someStr, err := ComputeSomeString() +// ExpectEq(nil, err) +// ExpectThat(someStr, HasSubstr("foo") +// +// Failure messages require no work from the user, and look like the following: +// +// foo_test.go:103: +// Expected: has substring "foo" +// Actual: "bar baz" +// +package ogletest diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_aliases.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_aliases.go new file mode 100644 index 0000000000..91405f6df0 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_aliases.go @@ -0,0 +1,64 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + +// ExpectEq(e, a) is equivalent to ExpectThat(a, oglematchers.Equals(e)). +func ExpectEq(expected, actual interface{}, errorParts ...interface{}) { + expectThat(actual, oglematchers.Equals(expected), 1, errorParts) +} + +// ExpectNe(e, a) is equivalent to +// ExpectThat(a, oglematchers.Not(oglematchers.Equals(e))). +func ExpectNe(expected, actual interface{}, errorParts ...interface{}) { + expectThat( + actual, + oglematchers.Not(oglematchers.Equals(expected)), + 1, + errorParts) +} + +// ExpectLt(x, y) is equivalent to ExpectThat(x, oglematchers.LessThan(y)). +func ExpectLt(x, y interface{}, errorParts ...interface{}) { + expectThat(x, oglematchers.LessThan(y), 1, errorParts) +} + +// ExpectLe(x, y) is equivalent to ExpectThat(x, oglematchers.LessOrEqual(y)). +func ExpectLe(x, y interface{}, errorParts ...interface{}) { + expectThat(x, oglematchers.LessOrEqual(y), 1, errorParts) +} + +// ExpectGt(x, y) is equivalent to ExpectThat(x, oglematchers.GreaterThan(y)). +func ExpectGt(x, y interface{}, errorParts ...interface{}) { + expectThat(x, oglematchers.GreaterThan(y), 1, errorParts) +} + +// ExpectGe(x, y) is equivalent to +// ExpectThat(x, oglematchers.GreaterOrEqual(y)). +func ExpectGe(x, y interface{}, errorParts ...interface{}) { + expectThat(x, oglematchers.GreaterOrEqual(y), 1, errorParts) +} + +// ExpectTrue(b) is equivalent to ExpectThat(b, oglematchers.Equals(true)). +func ExpectTrue(b interface{}, errorParts ...interface{}) { + expectThat(b, oglematchers.Equals(true), 1, errorParts) +} + +// ExpectFalse(b) is equivalent to ExpectThat(b, oglematchers.Equals(false)). +func ExpectFalse(b interface{}, errorParts ...interface{}) { + expectThat(b, oglematchers.Equals(false), 1, errorParts) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_call.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_call.go new file mode 100644 index 0000000000..68e59a89ac --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_call.go @@ -0,0 +1,59 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" + "runtime" +) + +// ExpectCall expresses an expectation that the method of the given name +// should be called on the supplied mock object. It returns a function that +// should be called with the expected arguments, matchers for the arguments, +// or a mix of both. +// +// For example: +// +// mockWriter := [...] +// ogletest.ExpectCall(mockWriter, "Write")(oglematchers.ElementsAre(0x1)) +// .WillOnce(oglemock.Return(1, nil)) +// +// This is a shortcut for calling i.MockController.ExpectCall, where i is the +// TestInfo struct for the currently-running test. Unlike that direct approach, +// this function automatically sets the correct file name and line number for +// the expectation. +func ExpectCall(o oglemock.MockObject, method string) oglemock.PartialExpecation { + // Get information about the call site. + _, file, lineNumber, ok := runtime.Caller(1) + if !ok { + panic("ExpectCall: runtime.Caller") + } + + // Grab the current test info. + info := currentlyRunningTest + if info == nil { + panic("ExpectCall: no test info.") + } + + // Grab the mock controller. + controller := currentlyRunningTest.MockController + if controller == nil { + panic("ExpectCall: no mock controller.") + } + + // Report the expectation. + return controller.ExpectCall(o, method, file, lineNumber) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that.go new file mode 100644 index 0000000000..83cd757a6a --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that.go @@ -0,0 +1,100 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "fmt" + "path" + "reflect" + "runtime" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +// ExpectThat confirms that the supplied matcher matches the value x, adding a +// failure record to the currently running test if it does not. If additional +// parameters are supplied, the first will be used as a format string for the +// later ones, and the user-supplied error message will be added to the test +// output in the event of a failure. +// +// For example: +// +// ExpectThat(userName, Equals("jacobsa")) +// ExpectThat(users[i], Equals("jacobsa"), "while processing user %d", i) +// +func ExpectThat( + x interface{}, + m oglematchers.Matcher, + errorParts ...interface{}) { + expectThat(x, m, 1, errorParts) +} + +// The generalized form of ExpectThat. depth is the distance on the stack +// between the caller's frame and the user's frame. Returns passed iff the +// match succeeded. +func expectThat( + x interface{}, + m oglematchers.Matcher, + depth int, + errorParts []interface{}) (passed bool) { + // Check whether the value matches. If it does, we are finished. + matcherErr := m.Matches(x) + if matcherErr == nil { + passed = true + return + } + + var r FailureRecord + + // Get information about the call site. + var ok bool + if _, r.FileName, r.LineNumber, ok = runtime.Caller(depth + 1); !ok { + panic("expectThat: runtime.Caller") + } + + r.FileName = path.Base(r.FileName) + + // Create an appropriate failure message. Make sure that the expected and + // actual values align properly. + relativeClause := "" + if matcherErr.Error() != "" { + relativeClause = fmt.Sprintf(", %s", matcherErr.Error()) + } + + r.Error = fmt.Sprintf( + "Expected: %s\nActual: %v%s", + m.Description(), + x, + relativeClause) + + // Add the user error, if any. + if len(errorParts) != 0 { + v := reflect.ValueOf(errorParts[0]) + if v.Kind() != reflect.String { + panic(fmt.Sprintf("ExpectThat: invalid format string type %v", v.Kind())) + } + + r.Error = fmt.Sprintf( + "%s\n%s", + r.Error, + fmt.Sprintf(v.String(), errorParts[1:]...)) + } + + // Report the failure. + AddFailureRecord(r) + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that_test.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that_test.go new file mode 100644 index 0000000000..c246f2eb50 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/expect_that_test.go @@ -0,0 +1,168 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "errors" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +// Set up a new test state with empty fields. +func setUpCurrentTest() { + currentlyRunningTest = newTestInfo() +} + +type fakeExpectThatMatcher struct { + desc string + err error +} + +func (m *fakeExpectThatMatcher) Matches(c interface{}) error { + return m.err +} + +func (m *fakeExpectThatMatcher) Description() string { + return m.desc +} + +func assertEqInt(t *testing.T, e, c int) { + if e != c { + t.Fatalf("Expected %d, got %d", e, c) + } +} + +func expectEqInt(t *testing.T, e, c int) { + if e != c { + t.Errorf("Expected %v, got %v", e, c) + } +} + +func expectEqStr(t *testing.T, e, c string) { + if e != c { + t.Errorf("Expected %s, got %s", e, c) + } +} + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func TestNoCurrentTest(t *testing.T) { + panicked := false + + defer func() { + if !panicked { + t.Errorf("Expected panic; got none.") + } + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + currentlyRunningTest = nil + ExpectThat(17, Equals(19)) +} + +func TestNoFailure(t *testing.T) { + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"", nil} + ExpectThat(17, matcher) + + assertEqInt(t, 0, len(currentlyRunningTest.failureRecords)) +} + +func TestInvalidFormatString(t *testing.T) { + panicked := false + + defer func() { + if !panicked { + t.Errorf("Expected panic; got none.") + } + }() + + defer func() { + if r := recover(); r != nil { + panicked = true + } + }() + + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"", errors.New("")} + ExpectThat(17, matcher, 19, "blah") +} + +func TestNoMatchWithoutErrorText(t *testing.T) { + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"taco", errors.New("")} + ExpectThat(17, matcher) + + assertEqInt(t, 1, len(currentlyRunningTest.failureRecords)) + + record := currentlyRunningTest.failureRecords[0] + expectEqStr(t, "expect_that_test.go", record.FileName) + expectEqInt(t, 119, record.LineNumber) + expectEqStr(t, "Expected: taco\nActual: 17", record.Error) +} + +func TestNoMatchWithErrorTExt(t *testing.T) { + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"taco", errors.New("which is foo")} + ExpectThat(17, matcher) + + assertEqInt(t, 1, len(currentlyRunningTest.failureRecords)) + record := currentlyRunningTest.failureRecords[0] + + expectEqStr( + t, + "Expected: taco\nActual: 17, which is foo", + record.Error) +} + +func TestFailureWithUserMessage(t *testing.T) { + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"taco", errors.New("")} + ExpectThat(17, matcher, "Asd: %d %s", 19, "taco") + + assertEqInt(t, 1, len(currentlyRunningTest.failureRecords)) + record := currentlyRunningTest.failureRecords[0] + + expectEqStr(t, "Expected: taco\nActual: 17\nAsd: 19 taco", record.Error) +} + +func TestAdditionalFailure(t *testing.T) { + setUpCurrentTest() + matcher := &fakeExpectThatMatcher{"", errors.New("")} + + // Fail twice. + ExpectThat(17, matcher, "taco") + ExpectThat(19, matcher, "burrito") + + assertEqInt(t, 2, len(currentlyRunningTest.failureRecords)) + record1 := currentlyRunningTest.failureRecords[0] + record2 := currentlyRunningTest.failureRecords[1] + + expectEqStr(t, "Expected: \nActual: 17\ntaco", record1.Error) + expectEqStr(t, "Expected: \nActual: 19\nburrito", record2.Error) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/failure.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/failure.go new file mode 100644 index 0000000000..95be2cf450 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/failure.go @@ -0,0 +1,90 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "fmt" + "path" + "runtime" +) + +// FailureRecord represents a single failed expectation or assertion for a +// test. Most users don't want to interact with these directly; they are +// generated implicitly using ExpectThat, AssertThat, ExpectLt, etc. +type FailureRecord struct { + // The file name within which the expectation failed, e.g. "foo_test.go". + FileName string + + // The line number at which the expectation failed. + LineNumber int + + // The error associated with the file:line pair above. For example, the + // following expectation: + // + // ExpectEq(17, "taco")" + // + // May cause this error: + // + // Expected: 17 + // Actual: "taco", which is not numeric + // + Error string +} + +// Record a failure for the currently running test (and continue running it). +// Most users will want to use ExpectThat, ExpectEq, etc. instead of this +// function. Those that do want to report arbitrary errors will probably be +// satisfied with AddFailure, which is easier to use. +func AddFailureRecord(r FailureRecord) { + currentlyRunningTest.mu.Lock() + defer currentlyRunningTest.mu.Unlock() + + currentlyRunningTest.failureRecords = append( + currentlyRunningTest.failureRecords, + r) +} + +// Call AddFailureRecord with a record whose file name and line number come +// from the caller of this function, and whose error string is created by +// calling fmt.Sprintf using the arguments to this function. +func AddFailure(format string, a ...interface{}) { + r := FailureRecord{ + Error: fmt.Sprintf(format, a...), + } + + // Get information about the call site. + var ok bool + if _, r.FileName, r.LineNumber, ok = runtime.Caller(1); !ok { + panic("Can't find caller") + } + + r.FileName = path.Base(r.FileName) + + AddFailureRecord(r) +} + +// A sentinel type that is used in a conspiracy between AbortTest and runTests. +// If runTests sees an abortError as the value given to a panic() call, it will +// avoid printing the panic error. +type abortError struct { +} + +// Immediately stop executing the running test, causing it to fail with the +// failures previously recorded. Behavior is undefined if no failures have been +// recorded. +func AbortTest() { + panic(abortError{}) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/integration_test.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/integration_test.go new file mode 100644 index 0000000000..ec45184e32 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/integration_test.go @@ -0,0 +1,265 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest_test + +import ( + "errors" + "flag" + "fmt" + "go/build" + "io/ioutil" + "os" + "os/exec" + "path" + "regexp" + "strings" + "syscall" + "testing" +) + +const ogletestPkg = "github.com/smartystreets/assertions/internal/ogletest" + +var dumpNew = flag.Bool("dump_new", false, "Dump new golden files.") +var objDir string + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +// Install the possibly locally-modified copy of ogletest, so that these +// integration tests run using the package currently being worked on by the +// programmer. Also install other dependencies needed by the test cases, so +// that `go test` complaining about non-up-to-date packages doesn't make it +// into the golden files. +func installLocalPackages() error { + cmd := exec.Command( + "go", + "install", + ogletestPkg, + "github.com/smartystreets/assertions/internal/oglemock", + "github.com/smartystreets/assertions/internal/ogletest/test_cases/mock_image") + + output, err := cmd.CombinedOutput() + + if err != nil { + return errors.New(fmt.Sprintf("%v:\n%s", err, output)) + } + + return nil +} + +// getCaseNames looks for integration test cases as files in the test_cases +// directory. +func getCaseNames() ([]string, error) { + // Open the test cases directory. + dir, err := os.Open("test_cases") + if err != nil { + return nil, errors.New(fmt.Sprintf("Opening dir: %v", err)) + } + + // Get a list of the names in the directory. + names, err := dir.Readdirnames(0) + if err != nil { + return nil, errors.New(fmt.Sprintf("Readdirnames: %v", err)) + } + + // Filter the names. + result := make([]string, len(names)) + resultLen := 0 + for _, name := range names { + // Skip golden files and hidden files. + if strings.HasPrefix(name, "golden.") || strings.HasPrefix(name, ".") { + continue + } + + // Check for the right format. + if !strings.HasSuffix(name, ".test.go") { + continue + } + + // Store the name minus the extension. + result[resultLen] = name[:len(name)-8] + resultLen++ + } + + return result[:resultLen], nil +} + +func writeContentsToFileOrDie(contents []byte, path string) { + if err := ioutil.WriteFile(path, contents, 0600); err != nil { + panic("ioutil.WriteFile: " + err.Error()) + } +} + +func readFileOrDie(path string) []byte { + contents, err := ioutil.ReadFile(path) + if err != nil { + panic("ioutil.ReadFile: " + err.Error()) + } + + return contents +} + +// cleanOutput transforms the supplied output so that it no longer contains +// information that changes from run to run, making the golden tests less +// flaky. +func cleanOutput(o []byte, testPkg string) []byte { + // Replace references to the last component of the test package name, which + // contains a unique number. + o = []byte(strings.Replace(string(o), path.Base(testPkg), "somepkg", -1)) + + // Replace things that look like line numbers and process counters in stack + // traces. + stackFrameRe := regexp.MustCompile(`\t\S+\.(c|go):\d+`) + o = stackFrameRe.ReplaceAll(o, []byte("\tsome_file.txt:0")) + + // Replace full paths in failure messages with fake paths. + pathRe := regexp.MustCompile(`/\S+/(\w+\.(?:go|s):\d+)`) + o = pathRe.ReplaceAll(o, []byte("/some/path/$1")) + + // Replace unstable timings in gotest fail messages. + timingRe1 := regexp.MustCompile(`--- FAIL: .* \(\d\.\d{2}s\)`) + o = timingRe1.ReplaceAll(o, []byte("--- FAIL: TestSomething (1.23s)")) + + timingRe2 := regexp.MustCompile(`FAIL.*somepkg\s*\d\.\d{2,}s`) + o = timingRe2.ReplaceAll(o, []byte("FAIL somepkg 1.234s")) + + timingRe3 := regexp.MustCompile(`ok.*somepkg\s*\d\.\d{2,}s`) + o = timingRe3.ReplaceAll(o, []byte("ok somepkg 1.234s")) + + timingRe4 := regexp.MustCompile(`SlowTest \([0-9.]+ms\)`) + o = timingRe4.ReplaceAll(o, []byte("SlowTest (1234ms)")) + + return o +} + +// Create a temporary package directory somewhere that 'go test' can find, and +// return the directory and package name. +func createTempPackageDir(caseName string) (dir, pkg string) { + // Figure out where the local source code for ogletest is. + buildPkg, err := build.Import(ogletestPkg, "", build.FindOnly) + if err != nil { + panic("Finding ogletest tree: " + err.Error()) + } + + // Create a temporary directory underneath this. + ogletestPkgDir := buildPkg.Dir + prefix := fmt.Sprintf("tmp-%s-", caseName) + + dir, err = ioutil.TempDir(ogletestPkgDir, prefix) + if err != nil { + panic("ioutil.TempDir: " + err.Error()) + } + + pkg = path.Join("github.com/smartystreets/assertions/internal/ogletest", dir[len(ogletestPkgDir):]) + return +} + +// runTestCase runs the case with the supplied name (e.g. "passing"), and +// returns its output and exit code. +func runTestCase(name string) ([]byte, int, error) { + // Create a temporary directory for the test files. + testDir, testPkg := createTempPackageDir(name) + defer os.RemoveAll(testDir) + + // Create the test source file. + sourceFile := name + ".test.go" + testContents := readFileOrDie(path.Join("test_cases", sourceFile)) + writeContentsToFileOrDie(testContents, path.Join(testDir, name+"_test.go")) + + // Invoke 'go test'. Use the package directory as working dir instead of + // giving the package name as an argument so that 'go test' prints passing + // test output. Special case: pass a test filter to the filtered case. + cmd := exec.Command("go", "test") + if name == "filtered" { + cmd.Args = append(cmd.Args, "--ogletest.run=Test(Bar|Baz)") + } + + cmd.Dir = testDir + output, err := cmd.CombinedOutput() + + // Clean up the process's output. + output = cleanOutput(output, testPkg) + + // Did the process exist with zero code? + if err == nil { + return output, 0, nil + } + + // Make sure the process actually exited. + exitError, ok := err.(*exec.ExitError) + if !ok || !exitError.Exited() { + return nil, 0, errors.New("exec.Command.Output: " + err.Error()) + } + + return output, exitError.Sys().(syscall.WaitStatus).ExitStatus(), nil +} + +// checkGolden file checks the supplied actual output for the named test case +// against the golden file for that case. If requested by the user, it rewrites +// the golden file on failure. +func checkAgainstGoldenFile(caseName string, output []byte) bool { + goldenFile := path.Join("test_cases", "golden."+caseName+"_test") + goldenContents := readFileOrDie(goldenFile) + + result := string(output) == string(goldenContents) + if !result && *dumpNew { + writeContentsToFileOrDie(output, goldenFile) + } + + return result +} + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func TestGoldenFiles(t *testing.T) { + // Ensure the local package is installed. This will prevent the test cases + // from using the installed version, which may be out of date. + err := installLocalPackages() + if err != nil { + t.Fatalf("Error installing local ogletest: %v", err) + } + + // We expect there to be at least one case. + caseNames, err := getCaseNames() + if err != nil || len(caseNames) == 0 { + t.Fatalf("Error getting cases: %v", err) + } + + // Run each test case. + for _, caseName := range caseNames { + // Run the test case. + output, exitCode, err := runTestCase(caseName) + if err != nil { + t.Fatalf("Running test case %s: %v", caseName, err) + } + + // Check the status code. We assume all test cases fail except for the + // passing one. + shouldPass := (caseName == "passing" || caseName == "no_cases") + didPass := exitCode == 0 + if shouldPass != didPass { + t.Errorf("Bad exit code for test case %s: %d", caseName, exitCode) + } + + // Check the output against the golden file. + if !checkAgainstGoldenFile(caseName, output) { + t.Errorf("Output for test case %s doesn't match golden file.", caseName) + } + } +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/register.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/register.go new file mode 100644 index 0000000000..756f2aa9ad --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/register.go @@ -0,0 +1,86 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +// The input to ogletest.Register. Most users will want to use +// ogletest.RegisterTestSuite. +// +// A test suite is the basic unit of registration in ogletest. It consists of +// zero or more named test functions which will be run in sequence, along with +// optional setup and tear-down functions. +type TestSuite struct { + // The name of the overall suite, e.g. "MyPackageTest". + Name string + + // If non-nil, a function that will be run exactly once, before any of the + // test functions are run. + SetUp func() + + // The test functions comprising this suite. + TestFunctions []TestFunction + + // If non-nil, a function that will be run exactly once, after all of the + // test functions have run. + TearDown func() +} + +type TestFunction struct { + // The name of this test function, relative to the suite in which it resides. + // If the name is "TweaksFrobnicator", then the function might be presented + // in the ogletest UI as "FooTest.TweaksFrobnicator". + Name string + + // If non-nil, a function that is run before Run, passed a pointer to a + // struct containing information about the test run. + SetUp func(*TestInfo) + + // The function to invoke for the test body. Must be non-nil. Will not be run + // if SetUp panics. + Run func() + + // If non-nil, a function that is run after Run. + TearDown func() +} + +// Register a test suite for execution by RunTests. +// +// This is the most general registration mechanism. Most users will want +// RegisterTestSuite, which is a wrapper around this function that requires +// less boilerplate. +// +// Panics on invalid input. +func Register(suite TestSuite) { + // Make sure the suite is legal. + if suite.Name == "" { + panic("Test suites must have names.") + } + + for _, tf := range suite.TestFunctions { + if tf.Name == "" { + panic("Test functions must have names.") + } + + if tf.Run == nil { + panic("Test functions must have non-nil run fields.") + } + } + + // Save the suite for later. + registeredSuites = append(registeredSuites, suite) +} + +// The list of test suites previously registered. +var registeredSuites []TestSuite diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/register_test_suite.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/register_test_suite.go new file mode 100644 index 0000000000..2e7f827773 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/register_test_suite.go @@ -0,0 +1,193 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "fmt" + "reflect" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil" +) + +// Test suites that implement this interface have special meaning to +// RegisterTestSuite. +type SetUpTestSuiteInterface interface { + // This method will be called exactly once, before the first test method is + // run. The receiver of this method will be a zero value of the test suite + // type, and is not shared with any other methods. Use this method to set up + // any necessary global state shared by all of the test methods. + SetUpTestSuite() +} + +// Test suites that implement this interface have special meaning to +// RegisterTestSuite. +type TearDownTestSuiteInterface interface { + // This method will be called exactly once, after the last test method is + // run. The receiver of this method will be a zero value of the test suite + // type, and is not shared with any other methods. Use this method to clean + // up after any necessary global state shared by all of the test methods. + TearDownTestSuite() +} + +// Test suites that implement this interface have special meaning to +// Register. +type SetUpInterface interface { + // This method is called before each test method is invoked, with the same + // receiver as that test method. At the time this method is invoked, the + // receiver is a zero value for the test suite type. Use this method for + // common setup code that works on data not shared across tests. + SetUp(*TestInfo) +} + +// Test suites that implement this interface have special meaning to +// Register. +type TearDownInterface interface { + // This method is called after each test method is invoked, with the same + // receiver as that test method. Use this method for common cleanup code that + // works on data not shared across tests. + TearDown() +} + +// RegisterTestSuite tells ogletest about a test suite containing tests that it +// should run. Any exported method on the type pointed to by the supplied +// prototype value will be treated as test methods, with the exception of the +// methods defined by the following interfaces, which when present are treated +// as described in the documentation for those interfaces: +// +// * SetUpTestSuiteInterface +// * SetUpInterface +// * TearDownInterface +// * TearDownTestSuiteInterface +// +// Each test method is invoked on a different receiver, which is initially a +// zero value of the test suite type. +// +// Example: +// +// // Some value that is needed by the tests but is expensive to compute. +// var someExpensiveThing uint +// +// type FooTest struct { +// // Path to a temporary file used by the tests. Each test gets a +// // different temporary file. +// tempFile string +// } +// func init() { ogletest.RegisterTestSuite(&FooTest{}) } +// +// func (t *FooTest) SetUpTestSuite() { +// someExpensiveThing = ComputeSomeExpensiveThing() +// } +// +// func (t *FooTest) SetUp(ti *ogletest.TestInfo) { +// t.tempFile = CreateTempFile() +// } +// +// func (t *FooTest) TearDown() { +// DeleteTempFile(t.tempFile) +// } +// +// func (t *FooTest) FrobinicatorIsSuccessfullyTweaked() { +// res := DoSomethingWithExpensiveThing(someExpensiveThing, t.tempFile) +// ExpectThat(res, Equals(true)) +// } +// +func RegisterTestSuite(p interface{}) { + if p == nil { + panic("RegisterTestSuite called with nil suite.") + } + + val := reflect.ValueOf(p) + typ := val.Type() + var zeroInstance reflect.Value + + // We will transform to a TestSuite struct. + suite := TestSuite{} + suite.Name = typ.Elem().Name() + + zeroInstance = reflect.New(typ.Elem()) + if i, ok := zeroInstance.Interface().(SetUpTestSuiteInterface); ok { + suite.SetUp = func() { i.SetUpTestSuite() } + } + + zeroInstance = reflect.New(typ.Elem()) + if i, ok := zeroInstance.Interface().(TearDownTestSuiteInterface); ok { + suite.TearDown = func() { i.TearDownTestSuite() } + } + + // Transform a list of test methods for the suite, filtering them to just the + // ones that we don't need to skip. + for _, method := range filterMethods(suite.Name, srcutil.GetMethodsInSourceOrder(typ)) { + var tf TestFunction + tf.Name = method.Name + + // Create an instance to be operated on by all of the TestFunction's + // internal functions. + instance := reflect.New(typ.Elem()) + + // Bind the functions to the instance. + if i, ok := instance.Interface().(SetUpInterface); ok { + tf.SetUp = func(ti *TestInfo) { i.SetUp(ti) } + } + + methodCopy := method + tf.Run = func() { runTestMethod(instance, methodCopy) } + + if i, ok := instance.Interface().(TearDownInterface); ok { + tf.TearDown = func() { i.TearDown() } + } + + // Save the TestFunction. + suite.TestFunctions = append(suite.TestFunctions, tf) + } + + // Register the suite. + Register(suite) +} + +func runTestMethod(suite reflect.Value, method reflect.Method) { + if method.Func.Type().NumIn() != 1 { + panic(fmt.Sprintf( + "%s: expected 1 args, actually %d.", + method.Name, + method.Func.Type().NumIn())) + } + + method.Func.Call([]reflect.Value{suite}) +} + +func filterMethods(suiteName string, in []reflect.Method) (out []reflect.Method) { + for _, m := range in { + // Skip set up, tear down, and unexported methods. + if isSpecialMethod(m.Name) || !isExportedMethod(m.Name) { + continue + } + + out = append(out, m) + } + + return +} + +func isSpecialMethod(name string) bool { + return (name == "SetUpTestSuite") || + (name == "TearDownTestSuite") || + (name == "SetUp") || + (name == "TearDown") +} + +func isExportedMethod(name string) bool { + return len(name) > 0 && name[0] >= 'A' && name[0] <= 'Z' +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/run_tests.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/run_tests.go new file mode 100644 index 0000000000..0bff171e94 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/run_tests.go @@ -0,0 +1,354 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "bytes" + "flag" + "fmt" + "os" + "path" + "regexp" + "runtime" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/reqtrace" +) + +var fTestFilter = flag.String( + "ogletest.run", + "", + "Regexp for matching tests to run.") + +var fStopEarly = flag.Bool( + "ogletest.stop_early", + false, + "If true, stop after the first failure.") + +// runTestsOnce protects RunTests from executing multiple times. +var runTestsOnce sync.Once + +func isAbortError(x interface{}) bool { + _, ok := x.(abortError) + return ok +} + +// Run a single test function, returning a slice of failure records. +func runTestFunction(tf TestFunction) (failures []FailureRecord) { + // Set up a clean slate for this test. Make sure to reset it after everything + // below is finished, so we don't accidentally use it elsewhere. + currentlyRunningTest = newTestInfo() + defer func() { + currentlyRunningTest = nil + }() + + ti := currentlyRunningTest + + // Start a trace. + var reportOutcome reqtrace.ReportFunc + ti.Ctx, reportOutcome = reqtrace.Trace(ti.Ctx, tf.Name) + + // Run the SetUp function, if any, paying attention to whether it panics. + setUpPanicked := false + if tf.SetUp != nil { + setUpPanicked = runWithProtection(func() { tf.SetUp(ti) }) + } + + // Run the test function itself, but only if the SetUp function didn't panic. + // (This includes AssertThat errors.) + if !setUpPanicked { + runWithProtection(tf.Run) + } + + // Run the TearDown function, if any. + if tf.TearDown != nil { + runWithProtection(tf.TearDown) + } + + // Tell the mock controller for the tests to report any errors it's sitting + // on. + ti.MockController.Finish() + + // Report the outcome to reqtrace. + if len(ti.failureRecords) == 0 { + reportOutcome(nil) + } else { + reportOutcome(fmt.Errorf("%v failure records", len(ti.failureRecords))) + } + + return ti.failureRecords +} + +// Run everything registered with Register (including via the wrapper +// RegisterTestSuite). +// +// Failures are communicated to the supplied testing.T object. This is the +// bridge between ogletest and the testing package (and `go test`); you should +// ensure that it's called at least once by creating a test function compatible +// with `go test` and calling it there. +// +// For example: +// +// import ( +// "github.com/smartystreets/assertions/internal/ogletest" +// "testing" +// ) +// +// func TestOgletest(t *testing.T) { +// ogletest.RunTests(t) +// } +// +func RunTests(t *testing.T) { + runTestsOnce.Do(func() { runTestsInternal(t) }) +} + +// Signalling between RunTests and StopRunningTests. +var gStopRunning uint64 + +// Request that RunTests stop what it's doing. After the currently running test +// is finished, including tear-down, the program will exit with an error code. +func StopRunningTests() { + atomic.StoreUint64(&gStopRunning, 1) +} + +// runTestsInternal does the real work of RunTests, which simply wraps it in a +// sync.Once. +func runTestsInternal(t *testing.T) { + // Process each registered suite. + for _, suite := range registeredSuites { + // Stop now if we've already seen a failure and we've been told to stop + // early. + if t.Failed() && *fStopEarly { + break + } + + // Print a banner. + fmt.Printf("[----------] Running tests from %s\n", suite.Name) + + // Run the SetUp function, if any. + if suite.SetUp != nil { + suite.SetUp() + } + + // Run each test function that the user has not told us to skip. + stoppedEarly := false + for _, tf := range filterTestFunctions(suite) { + // Did the user request that we stop running tests? If so, skip the rest + // of this suite (and exit after tearing it down). + if atomic.LoadUint64(&gStopRunning) != 0 { + stoppedEarly = true + break + } + + // Print a banner for the start of this test function. + fmt.Printf("[ RUN ] %s.%s\n", suite.Name, tf.Name) + + // Run the test function. + startTime := time.Now() + failures := runTestFunction(tf) + runDuration := time.Since(startTime) + + // Print any failures, and mark the test as having failed if there are any. + for _, record := range failures { + t.Fail() + fmt.Printf( + "%s:%d:\n%s\n\n", + record.FileName, + record.LineNumber, + record.Error) + } + + // Print a banner for the end of the test. + bannerMessage := "[ OK ]" + if len(failures) != 0 { + bannerMessage = "[ FAILED ]" + } + + // Print a summary of the time taken, if long enough. + var timeMessage string + if runDuration >= 25*time.Millisecond { + timeMessage = fmt.Sprintf(" (%s)", runDuration.String()) + } + + fmt.Printf( + "%s %s.%s%s\n", + bannerMessage, + suite.Name, + tf.Name, + timeMessage) + + // Stop running tests from this suite if we've been told to stop early + // and this test failed. + if t.Failed() && *fStopEarly { + break + } + } + + // Run the suite's TearDown function, if any. + if suite.TearDown != nil { + suite.TearDown() + } + + // Were we told to exit early? + if stoppedEarly { + fmt.Println("Exiting early due to user request.") + os.Exit(1) + } + + fmt.Printf("[----------] Finished with tests from %s\n", suite.Name) + } +} + +// Return true iff the supplied program counter appears to lie within panic(). +func isPanic(pc uintptr) bool { + f := runtime.FuncForPC(pc) + if f == nil { + return false + } + + return f.Name() == "runtime.gopanic" || f.Name() == "runtime.sigpanic" +} + +// Find the deepest stack frame containing something that appears to be a +// panic. Return the 'skip' value that a caller to this function would need +// to supply to runtime.Caller for that frame, or a negative number if not found. +func findPanic() int { + localSkip := -1 + for i := 0; ; i++ { + // Stop if we've passed the base of the stack. + pc, _, _, ok := runtime.Caller(i) + if !ok { + break + } + + // Is this a panic? + if isPanic(pc) { + localSkip = i + } + } + + return localSkip - 1 +} + +// Attempt to find the file base name and line number for the ultimate source +// of a panic, on the panicking stack. Return a human-readable sentinel if +// unsuccessful. +func findPanicFileLine() (string, int) { + panicSkip := findPanic() + if panicSkip < 0 { + return "(unknown)", 0 + } + + // Find the trigger of the panic. + _, file, line, ok := runtime.Caller(panicSkip + 1) + if !ok { + return "(unknown)", 0 + } + + return path.Base(file), line +} + +// Run the supplied function, catching panics (including AssertThat errors) and +// reporting them to the currently-running test as appropriate. Return true iff +// the function panicked. +func runWithProtection(f func()) (panicked bool) { + defer func() { + // If the test didn't panic, we're done. + r := recover() + if r == nil { + return + } + + panicked = true + + // We modify the currently running test below. + currentlyRunningTest.mu.Lock() + defer currentlyRunningTest.mu.Unlock() + + // If the function panicked (and the panic was not due to an AssertThat + // failure), add a failure for the panic. + if !isAbortError(r) { + var panicRecord FailureRecord + panicRecord.FileName, panicRecord.LineNumber = findPanicFileLine() + panicRecord.Error = fmt.Sprintf( + "panic: %v\n\n%s", r, formatPanicStack()) + + currentlyRunningTest.failureRecords = append( + currentlyRunningTest.failureRecords, + panicRecord) + } + }() + + f() + return +} + +func formatPanicStack() string { + buf := new(bytes.Buffer) + + // Find the panic. If successful, we'll skip to below it. Otherwise, we'll + // format everything. + var initialSkip int + if panicSkip := findPanic(); panicSkip >= 0 { + initialSkip = panicSkip + 1 + } + + for i := initialSkip; ; i++ { + pc, file, line, ok := runtime.Caller(i) + if !ok { + break + } + + // Choose a function name to display. + funcName := "(unknown)" + if f := runtime.FuncForPC(pc); f != nil { + funcName = f.Name() + } + + // Stop if we've gotten as far as the test runner code. + if funcName == "github.com/smartystreets/assertions/internal/ogletest.runTestMethod" || + funcName == "github.com/smartystreets/assertions/internal/ogletest.runWithProtection" { + break + } + + // Add an entry for this frame. + fmt.Fprintf(buf, "%s\n\t%s:%d\n", funcName, file, line) + } + + return buf.String() +} + +// Filter test functions according to the user-supplied filter flag. +func filterTestFunctions(suite TestSuite) (out []TestFunction) { + re, err := regexp.Compile(*fTestFilter) + if err != nil { + panic("Invalid value for --ogletest.run: " + err.Error()) + } + + for _, tf := range suite.TestFunctions { + fullName := fmt.Sprintf("%s.%s", suite.Name, tf.Name) + if !re.MatchString(fullName) { + continue + } + + out = append(out, tf) + } + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/docs.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/docs.go new file mode 100644 index 0000000000..d9b9bc8e5f --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/docs.go @@ -0,0 +1,5 @@ +// Copyright 2015 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) + +// Functions for working with source code. +package srcutil diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods.go new file mode 100644 index 0000000000..a8c5828ea3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods.go @@ -0,0 +1,65 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 srcutil + +import ( + "fmt" + "reflect" + "runtime" + "sort" +) + +func getLine(m reflect.Method) int { + pc := m.Func.Pointer() + + f := runtime.FuncForPC(pc) + if f == nil { + panic(fmt.Sprintf("Couldn't get runtime func for method (pc=%d): %v", pc, m)) + } + + _, line := f.FileLine(pc) + return line +} + +type sortableMethodSet []reflect.Method + +func (s sortableMethodSet) Len() int { + return len(s) +} + +func (s sortableMethodSet) Less(i, j int) bool { + return getLine(s[i]) < getLine(s[j]) +} + +func (s sortableMethodSet) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Given a type t, return all of the methods of t sorted such that source file +// order is preserved. Order across files is undefined. Order within lines is +// undefined. +func GetMethodsInSourceOrder(t reflect.Type) []reflect.Method { + // Build the list of methods. + methods := sortableMethodSet{} + for i := 0; i < t.NumMethod(); i++ { + methods = append(methods, t.Method(i)) + } + + // Sort it. + sort.Sort(methods) + + return methods +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods_test.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods_test.go new file mode 100644 index 0000000000..db574ea028 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil/methods_test.go @@ -0,0 +1,107 @@ +// Copyright 2012 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 srcutil_test + +import ( + "fmt" + "reflect" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/ogletest/srcutil" +) + +func TestRegisterMethodsTest(t *testing.T) { RunTests(t) } + +//////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////// + +type MethodsTest struct { +} + +func init() { RegisterTestSuite(&MethodsTest{}) } + +type OneMethodType int + +func (x OneMethodType) Foo() {} + +type MultipleMethodsType int + +func (x MultipleMethodsType) Foo() {} +func (x MultipleMethodsType) Bar() {} +func (x MultipleMethodsType) Baz() {} + +type methodNameMatcher struct { + expected string +} + +func (m *methodNameMatcher) Description() string { + return fmt.Sprintf("method named %s", m.expected) +} + +func (m *methodNameMatcher) Matches(x interface{}) error { + method, ok := x.(reflect.Method) + if !ok { + panic("Invalid argument.") + } + + if method.Name != m.expected { + return fmt.Errorf("whose name is %s", method.Name) + } + + return nil +} + +func NameIs(name string) Matcher { + return &methodNameMatcher{name} +} + +//////////////////////////////////////////////////////////////////////// +// Tests +//////////////////////////////////////////////////////////////////////// + +func (t *MethodsTest) NoMethods() { + type foo int + + methods := srcutil.GetMethodsInSourceOrder(reflect.TypeOf(foo(17))) + ExpectThat(methods, ElementsAre()) +} + +func (t *MethodsTest) OneMethod() { + methods := srcutil.GetMethodsInSourceOrder(reflect.TypeOf(OneMethodType(17))) + ExpectThat( + methods, + ElementsAre( + NameIs("Foo"), + )) +} + +func (t *MethodsTest) MultipleMethods() { + methods := srcutil.GetMethodsInSourceOrder(reflect.TypeOf(MultipleMethodsType(17))) + ExpectThat( + methods, + ElementsAre( + NameIs("Foo"), + NameIs("Bar"), + NameIs("Baz"), + )) + + ExpectEq("Foo", methods[0].Name) + ExpectEq("Bar", methods[1].Name) + ExpectEq("Baz", methods[2].Name) +} diff --git a/vendor/github.com/smartystreets/assertions/internal/ogletest/test_info.go b/vendor/github.com/smartystreets/assertions/internal/ogletest/test_info.go new file mode 100644 index 0000000000..255494cfb9 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/ogletest/test_info.go @@ -0,0 +1,91 @@ +// Copyright 2011 Aaron Jacobs. All Rights Reserved. +// Author: aaronjjacobs@gmail.com (Aaron Jacobs) +// +// 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 ogletest + +import ( + "sync" + + "github.com/scaleway/scaleway-cli/vendor/golang.org/x/net/context" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglemock" +) + +// TestInfo represents information about a currently running or previously-run +// test. +type TestInfo struct { + // A mock controller that is set up to report errors to the ogletest test + // runner. This can be used for setting up mock expectations and handling + // mock calls. The Finish method should not be run by the user; ogletest will + // do that automatically after the test's TearDown method is run. + // + // Note that this feature is still experimental, and is subject to change. + MockController oglemock.Controller + + // A context that can be used by tests for long-running operations. In + // particular, this enables conveniently tracing the execution of a test + // function with reqtrace. + Ctx context.Context + + // A mutex protecting shared state. + mu sync.RWMutex + + // A set of failure records that the test has produced. + // + // GUARDED_BY(mu) + failureRecords []FailureRecord +} + +// currentlyRunningTest is the state for the currently running test, if any. +var currentlyRunningTest *TestInfo + +// newTestInfo creates a valid but empty TestInfo struct. +func newTestInfo() (info *TestInfo) { + info = &TestInfo{} + info.MockController = oglemock.NewController(&testInfoErrorReporter{info}) + info.Ctx = context.Background() + + return +} + +// testInfoErrorReporter is an oglemock.ErrorReporter that writes failure +// records into a test info struct. +type testInfoErrorReporter struct { + testInfo *TestInfo +} + +func (r *testInfoErrorReporter) ReportError( + fileName string, + lineNumber int, + err error) { + r.testInfo.mu.Lock() + defer r.testInfo.mu.Unlock() + + record := FailureRecord{ + FileName: fileName, + LineNumber: lineNumber, + Error: err.Error(), + } + + r.testInfo.failureRecords = append(r.testInfo.failureRecords, record) +} + +func (r *testInfoErrorReporter) ReportFatalError( + fileName string, + lineNumber int, + err error) { + r.ReportError(fileName, lineNumber, err) + AbortTest() +} diff --git a/vendor/github.com/smartystreets/assertions/internal/reqtrace/LICENSE b/vendor/github.com/smartystreets/assertions/internal/reqtrace/LICENSE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/reqtrace/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/github.com/smartystreets/assertions/internal/reqtrace/README.md b/vendor/github.com/smartystreets/assertions/internal/reqtrace/README.md new file mode 100644 index 0000000000..4392452b5b --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/reqtrace/README.md @@ -0,0 +1,53 @@ +[![GoDoc](https://godoc.org/github.com/smartystreets/assertions/internal/reqtrace?status.svg)](https://godoc.org/github.com/smartystreets/assertions/internal/reqtrace) + +reqtrace is a package for simple request tracing. It requires nothing of its +user except: + + * They must use [golang.org/x/net/context][context]. + * They must add a single line to each function they want to be visible in + traces. + +[context]: http://godoc.org/golang.org/x/net/context + +In particular, reqtrace is console-based and doesn't require an HTTP server. + +**Warning**: This package is still barebones and in its early days. I reserve +the right to make backwards-incompatible changes to its API. But if it's useful +to you in your current form, have at it. + +## Use + +Call reqtrace.Trace anywhere you want to start a new root trace. (This is +probably where you create your root context.) This returns a new context that +you should pass to child operations, and a reporting function that you must use +to inform reqtrace when the trace is complete. + +For example: + +```Go +func HandleRequest(r *someRequest) (err error) { + ctx, report := reqtrace.Trace(context.Background(), "HandleRequest") + defer func() { report(err) }() + + // Do two things for this request. + DoSomething(ctx, r) + DoSomethingElse(ctx, r) +} +``` + +Within other functions that you want to show up in the trace, you +reqtrace.StartSpan (or its more convenient sibling reqtrace.StartSpanWithError): + +```Go +func DoSomething(ctx context.Context, r *someRequest) (err error) { + defer reqtrace.StartSpanWithError(&ctx, &err, "DoSomething")() + + // Process the request somehow using ctx. If downstream code also annotes + // using reqtrace, reqtrace will know that its spans are descendants of + // this one. + CallAnotherLibrary(ctx, r.Param) +} +``` + +When `--reqtrace.enable` is set, the completion of a trace will cause helpful +ASCII art to be spit out. diff --git a/vendor/github.com/smartystreets/assertions/internal/reqtrace/reqtrace.go b/vendor/github.com/smartystreets/assertions/internal/reqtrace/reqtrace.go new file mode 100644 index 0000000000..1f3e1b7a43 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/reqtrace/reqtrace.go @@ -0,0 +1,132 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package reqtrace contains a very simple request tracing framework. +package reqtrace + +import ( + "flag" + + "github.com/scaleway/scaleway-cli/vendor/golang.org/x/net/context" +) + +type contextKey int + +var fEnabled = flag.Bool("reqtrace.enable", false, "Collect and print traces.") + +// The key used to associate a *traceState with a context. +const traceStateKey contextKey = 0 + +// A function that must be called exactly once to report the outcome of an +// operation represented by a span. +type ReportFunc func(error) + +// Return false only if traces are disabled, i.e. Trace will never cause a +// trace to be initiated. +// +// REQUIRES: flag.Parsed() +func Enabled() (enabled bool) { + enabled = *fEnabled + return +} + +// Begin a span within the current trace. Return a new context that should be +// used for operations that logically occur within the span, and a report +// function that must be called with the outcome of the logical operation +// represented by the span. +// +// If no trace is active, no span will be created but ctx and report will still +// be valid. +func StartSpan( + parent context.Context, + desc string) (ctx context.Context, report ReportFunc) { + // Look for the trace state. + val := parent.Value(traceStateKey) + if val == nil { + // Nothing to do. + ctx = parent + report = func(err error) {} + return + } + + ts := val.(*traceState) + + // Set up the report function. + report = ts.CreateSpan(desc) + + // For now we don't do anything interesting with the context. In the future, + // we may use it to record span hierarchy. + ctx = parent + + return +} + +// A wrapper around StartSpan that can be more convenient to use when the +// lifetime of a span matches the lifetime of a function. Intended to be used +// in a defer statement within a function using a named error return parameter. +// +// Equivalent to calling StartSpan with *ctx, replacing *ctx with the resulting +// new context, then setting f to a function that will invoke the report +// function with the contents of *error at the time that it is called. +// +// Example: +// +// func DoSomething(ctx context.Context) (err error) { +// defer reqtrace.StartSpanWithError(&ctx, &err, "DoSomething")() +// [...] +// } +// +func StartSpanWithError( + ctx *context.Context, + err *error, + desc string) (f func()) { + var report ReportFunc + *ctx, report = StartSpan(*ctx, desc) + f = func() { report(*err) } + return +} + +// Like StartSpan, but begins a root span for a new trace if no trace is active +// in the supplied context and tracing is enabled for the process. +func Trace( + parent context.Context, + desc string) (ctx context.Context, report ReportFunc) { + // If tracing is disabled, this is a no-op. + if !*fEnabled { + ctx = parent + report = func(err error) {} + return + } + + // Is this context already being traced? If so, simply add a span. + if parent.Value(traceStateKey) != nil { + ctx, report = StartSpan(parent, desc) + return + } + + // Set up a new trace state. + ts := new(traceState) + baseReport := ts.CreateSpan(desc) + + // Log when finished. + report = func(err error) { + baseReport(err) + ts.Log() + } + + // Set up the context. + ctx = context.WithValue(parent, traceStateKey, ts) + + return +} diff --git a/vendor/github.com/smartystreets/assertions/internal/reqtrace/trace_state.go b/vendor/github.com/smartystreets/assertions/internal/reqtrace/trace_state.go new file mode 100644 index 0000000000..614ef90d89 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/internal/reqtrace/trace_state.go @@ -0,0 +1,175 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package reqtrace + +import ( + "log" + "math" + "os" + "strings" + "sync" + "time" +) + +const logFlags = 0 + +var gLogger = log.New(os.Stderr, "reqtrace: ", logFlags) + +type span struct { + // Fixed at creation. + desc string + start time.Time + + // Updated by report functions. + finished bool + end time.Time + err error +} + +// All of the state for a particular trace root. The zero value is usable. +type traceState struct { + mu sync.Mutex + + // The list of spans associated with this state. Append-only. + // + // GUARDED_BY(mu) + spans []*span +} + +func (ts *traceState) report(spanIndex int, err error) { + ts.mu.Lock() + defer ts.mu.Unlock() + + s := ts.spans[spanIndex] + s.finished = true + s.end = time.Now() + s.err = err +} + +// Associate a new span with the trace. Return a function that will report its +// completion. +func (ts *traceState) CreateSpan(desc string) (report ReportFunc) { + ts.mu.Lock() + defer ts.mu.Unlock() + + index := len(ts.spans) + ts.spans = append(ts.spans, &span{desc: desc, start: time.Now()}) + + report = func(err error) { ts.report(index, err) } + return +} + +func round(x float64) float64 { + if x < 0 { + return math.Ceil(x - 0.5) + } + + return math.Floor(x + 0.5) +} + +// Log information about the spans in this trace. +func (ts *traceState) Log() { + ts.mu.Lock() + defer ts.mu.Unlock() + gLogger.Println() + + // Special case: we require at least one span. + if len(ts.spans) == 0 { + return + } + + // Print a banner for this trace. + const bannerHalfLength = 45 + + gLogger.Println() + gLogger.Printf( + "%s %s %s", + strings.Repeat("=", bannerHalfLength), + ts.spans[0].desc, + strings.Repeat("=", bannerHalfLength)) + gLogger.Printf("Start time: %v", ts.spans[0].start.Format(time.RFC3339Nano)) + gLogger.Println() + + // Find the minimum start time and maximum end time of all durations. + var minStart time.Time + var maxEnd time.Time + for _, s := range ts.spans { + if !s.finished { + continue + } + + if minStart.IsZero() || s.start.Before(minStart) { + minStart = s.start + } + + if maxEnd.Before(s.end) { + maxEnd = s.end + } + } + + // Bail out if something weird happened. + // + // TODO(jacobsa): Be more graceful. + totalDuration := maxEnd.Sub(minStart) + if minStart.IsZero() || maxEnd.IsZero() || totalDuration <= 0 { + gLogger.Println("(Weird trace)") + return + } + + // Calculate the number of nanoseconds elapsed, as a floating point number. + totalNs := float64(totalDuration / time.Nanosecond) + + // Log each span with some ASCII art showing its length relative to the + // total. + const totalNumCols float64 = 120 + for _, s := range ts.spans { + if !s.finished { + gLogger.Printf("(Unfinished: %s)", s.desc) + gLogger.Println() + continue + } + + // Calculate the duration of the span, and its width relative to the + // longest span. + d := s.end.Sub(s.start) + if d <= 0 { + gLogger.Println("(Weird duration)") + gLogger.Println() + continue + } + + durationRatio := float64(d/time.Nanosecond) / totalNs + + // We will offset the label and banner proportional to the time since the + // start of the earliest span. + offsetRatio := float64(s.start.Sub(minStart)/time.Nanosecond) / totalNs + offsetChars := int(round(offsetRatio * totalNumCols)) + offsetStr := strings.Repeat(" ", offsetChars) + + // Print the description and duration. + gLogger.Printf("%s%v", offsetStr, s.desc) + gLogger.Printf("%s%v", offsetStr, d) + + // Print a banner showing the duration graphically. + bannerChars := int(round(durationRatio * totalNumCols)) + var dashes string + if bannerChars > 2 { + dashes = strings.Repeat("-", bannerChars-2) + } + + gLogger.Printf("%s|%s|", offsetStr, dashes) + gLogger.Println() + } +} diff --git a/vendor/github.com/smartystreets/assertions/messages.go b/vendor/github.com/smartystreets/assertions/messages.go new file mode 100644 index 0000000000..e88906c00c --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/messages.go @@ -0,0 +1,89 @@ +package assertions + +const ( // equality + shouldHaveBeenEqual = "Expected: '%v'\nActual: '%v'\n(Should be equal)" + shouldNotHaveBeenEqual = "Expected '%v'\nto NOT equal '%v'\n(but it did)!" + shouldHaveBeenAlmostEqual = "Expected '%v' to almost equal '%v' (but it didn't)!" + shouldHaveNotBeenAlmostEqual = "Expected '%v' to NOT almost equal '%v' (but it did)!" + shouldHaveResembled = "Expected: '%#v'\nActual: '%#v'\n(Should resemble)!" + shouldHaveResembledTypeMismatch = "Expected: '%#v'\nActual: '%#v'\n(Type mismatch: '%T' vs '%T')!" + shouldNotHaveResembled = "Expected '%#v'\nto NOT resemble '%#v'\n(but it did)!" + shouldBePointers = "Both arguments should be pointers " + shouldHaveBeenNonNilPointer = shouldBePointers + "(the %s was %s)!" + shouldHavePointedTo = "Expected '%+v' (address: '%v') and '%+v' (address: '%v') to be the same address (but their weren't)!" + shouldNotHavePointedTo = "Expected '%+v' and '%+v' to be different references (but they matched: '%v')!" + shouldHaveBeenNil = "Expected: nil\nActual: '%v'" + shouldNotHaveBeenNil = "Expected '%+v' to NOT be nil (but it was)!" + shouldHaveBeenTrue = "Expected: true\nActual: %v" + shouldHaveBeenFalse = "Expected: false\nActual: %v" + shouldHaveBeenZeroValue = "'%+v' should have been the zero value" //"Expected: (zero value)\nActual: %v" +) + +const ( // quantity comparisons + shouldHaveBeenGreater = "Expected '%v' to be greater than '%v' (but it wasn't)!" + shouldHaveBeenGreaterOrEqual = "Expected '%v' to be greater than or equal to '%v' (but it wasn't)!" + shouldHaveBeenLess = "Expected '%v' to be less than '%v' (but it wasn't)!" + shouldHaveBeenLessOrEqual = "Expected '%v' to be less than or equal to '%v' (but it wasn't)!" + shouldHaveBeenBetween = "Expected '%v' to be between '%v' and '%v' (but it wasn't)!" + shouldNotHaveBeenBetween = "Expected '%v' NOT to be between '%v' and '%v' (but it was)!" + shouldHaveDifferentUpperAndLower = "The lower and upper bounds must be different values (they were both '%v')." + shouldHaveBeenBetweenOrEqual = "Expected '%v' to be between '%v' and '%v' or equal to one of them (but it wasn't)!" + shouldNotHaveBeenBetweenOrEqual = "Expected '%v' NOT to be between '%v' and '%v' or equal to one of them (but it was)!" +) + +const ( // collections + shouldHaveContained = "Expected the container (%v) to contain: '%v' (but it didn't)!" + shouldNotHaveContained = "Expected the container (%v) NOT to contain: '%v' (but it did)!" + shouldHaveContainedKey = "Expected the %v to contain the key: %v (but it didn't)!" + shouldNotHaveContainedKey = "Expected the %v NOT to contain the key: %v (but it did)!" + shouldHaveBeenIn = "Expected '%v' to be in the container (%v), but it wasn't!" + shouldNotHaveBeenIn = "Expected '%v' NOT to be in the container (%v), but it was!" + shouldHaveBeenAValidCollection = "You must provide a valid container (was %v)!" + shouldHaveBeenAValidMap = "You must provide a valid map type (was %v)!" + shouldHaveBeenEmpty = "Expected %+v to be empty (but it wasn't)!" + shouldNotHaveBeenEmpty = "Expected %+v to NOT be empty (but it was)!" +) + +const ( // strings + shouldHaveStartedWith = "Expected '%v'\nto start with '%v'\n(but it didn't)!" + shouldNotHaveStartedWith = "Expected '%v'\nNOT to start with '%v'\n(but it did)!" + shouldHaveEndedWith = "Expected '%v'\nto end with '%v'\n(but it didn't)!" + shouldNotHaveEndedWith = "Expected '%v'\nNOT to end with '%v'\n(but it did)!" + shouldBothBeStrings = "Both arguments to this assertion must be strings (you provided %v and %v)." + shouldBeString = "The argument to this assertion must be a string (you provided %v)." + shouldHaveContainedSubstring = "Expected '%s' to contain substring '%s' (but it didn't)!" + shouldNotHaveContainedSubstring = "Expected '%s' NOT to contain substring '%s' (but it did)!" + shouldHaveBeenBlank = "Expected '%s' to be blank (but it wasn't)!" + shouldNotHaveBeenBlank = "Expected value to NOT be blank (but it was)!" +) + +const ( // panics + shouldUseVoidNiladicFunction = "You must provide a void, niladic function as the first argument!" + shouldHavePanickedWith = "Expected func() to panic with '%v' (but it panicked with '%v')!" + shouldHavePanicked = "Expected func() to panic (but it didn't)!" + shouldNotHavePanicked = "Expected func() NOT to panic (error: '%+v')!" + shouldNotHavePanickedWith = "Expected func() NOT to panic with '%v' (but it did)!" +) + +const ( // type checking + shouldHaveBeenA = "Expected '%v' to be: '%v' (but was: '%v')!" + shouldNotHaveBeenA = "Expected '%v' to NOT be: '%v' (but it was)!" + + shouldHaveImplemented = "Expected: '%v interface support'\nActual: '%v' does not implement the interface!" + shouldNotHaveImplemented = "Expected '%v'\nto NOT implement '%v'\n(but it did)!" + shouldCompareWithInterfacePointer = "The expected value must be a pointer to an interface type (eg. *fmt.Stringer)" + shouldNotBeNilActual = "The actual value was 'nil' and should be a value or a pointer to a value!" +) + +const ( // time comparisons + shouldUseTimes = "You must provide time instances as arguments to this assertion." + shouldUseTimeSlice = "You must provide a slice of time instances as the first argument to this assertion." + shouldUseDurationAndTime = "You must provide a duration and a time as arguments to this assertion." + shouldHaveHappenedBefore = "Expected '%v' to happen before '%v' (it happened '%v' after)!" + shouldHaveHappenedAfter = "Expected '%v' to happen after '%v' (it happened '%v' before)!" + shouldHaveHappenedBetween = "Expected '%v' to happen between '%v' and '%v' (it happened '%v' outside threshold)!" + shouldNotHaveHappenedOnOrBetween = "Expected '%v' to NOT happen on or between '%v' and '%v' (but it did)!" + + // format params: incorrect-index, previous-index, previous-time, incorrect-index, incorrect-time + shouldHaveBeenChronological = "The 'Time' at index [%d] should have happened after the previous one (but it didn't!):\n [%d]: %s\n [%d]: %s (see, it happened before!)" +) diff --git a/vendor/github.com/smartystreets/assertions/panic.go b/vendor/github.com/smartystreets/assertions/panic.go new file mode 100644 index 0000000000..7e75db1784 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/panic.go @@ -0,0 +1,115 @@ +package assertions + +import "fmt" + +// ShouldPanic receives a void, niladic function and expects to recover a panic. +func ShouldPanic(actual interface{}, expected ...interface{}) (message string) { + if fail := need(0, expected); fail != success { + return fail + } + + action, _ := actual.(func()) + + if action == nil { + message = shouldUseVoidNiladicFunction + return + } + + defer func() { + recovered := recover() + if recovered == nil { + message = shouldHavePanicked + } else { + message = success + } + }() + action() + + return +} + +// ShouldNotPanic receives a void, niladic function and expects to execute the function without any panic. +func ShouldNotPanic(actual interface{}, expected ...interface{}) (message string) { + if fail := need(0, expected); fail != success { + return fail + } + + action, _ := actual.(func()) + + if action == nil { + message = shouldUseVoidNiladicFunction + return + } + + defer func() { + recovered := recover() + if recovered != nil { + message = fmt.Sprintf(shouldNotHavePanicked, recovered) + } else { + message = success + } + }() + action() + + return +} + +// ShouldPanicWith receives a void, niladic function and expects to recover a panic with the second argument as the content. +func ShouldPanicWith(actual interface{}, expected ...interface{}) (message string) { + if fail := need(1, expected); fail != success { + return fail + } + + action, _ := actual.(func()) + + if action == nil { + message = shouldUseVoidNiladicFunction + return + } + + defer func() { + recovered := recover() + if recovered == nil { + message = shouldHavePanicked + } else { + if equal := ShouldEqual(recovered, expected[0]); equal != success { + message = serializer.serialize(expected[0], recovered, fmt.Sprintf(shouldHavePanickedWith, expected[0], recovered)) + } else { + message = success + } + } + }() + action() + + return +} + +// ShouldNotPanicWith receives a void, niladic function and expects to recover a panic whose content differs from the second argument. +func ShouldNotPanicWith(actual interface{}, expected ...interface{}) (message string) { + if fail := need(1, expected); fail != success { + return fail + } + + action, _ := actual.(func()) + + if action == nil { + message = shouldUseVoidNiladicFunction + return + } + + defer func() { + recovered := recover() + if recovered == nil { + message = success + } else { + if equal := ShouldEqual(recovered, expected[0]); equal == success { + message = fmt.Sprintf(shouldNotHavePanickedWith, expected[0]) + } else { + message = success + } + } + }() + action() + + return +} diff --git a/vendor/github.com/smartystreets/assertions/panic_test.go b/vendor/github.com/smartystreets/assertions/panic_test.go new file mode 100644 index 0000000000..15eafac4fb --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/panic_test.go @@ -0,0 +1,53 @@ +package assertions + +import ( + "fmt" + "testing" +) + +func TestShouldPanic(t *testing.T) { + fail(t, so(func() {}, ShouldPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") + fail(t, so(func() {}, ShouldPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + + fail(t, so(1, ShouldPanic), shouldUseVoidNiladicFunction) + fail(t, so(func(i int) {}, ShouldPanic), shouldUseVoidNiladicFunction) + fail(t, so(func() int { panic("hi") }, ShouldPanic), shouldUseVoidNiladicFunction) + + fail(t, so(func() {}, ShouldPanic), shouldHavePanicked) + pass(t, so(func() { panic("hi") }, ShouldPanic)) +} + +func TestShouldNotPanic(t *testing.T) { + fail(t, so(func() {}, ShouldNotPanic, 1), "This assertion requires exactly 0 comparison values (you provided 1).") + fail(t, so(func() {}, ShouldNotPanic, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + + fail(t, so(1, ShouldNotPanic), shouldUseVoidNiladicFunction) + fail(t, so(func(i int) {}, ShouldNotPanic), shouldUseVoidNiladicFunction) + + fail(t, so(func() { panic("hi") }, ShouldNotPanic), fmt.Sprintf(shouldNotHavePanicked, "hi")) + pass(t, so(func() {}, ShouldNotPanic)) +} + +func TestShouldPanicWith(t *testing.T) { + fail(t, so(func() {}, ShouldPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(func() {}, ShouldPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(1, ShouldPanicWith, 1), shouldUseVoidNiladicFunction) + fail(t, so(func(i int) {}, ShouldPanicWith, "hi"), shouldUseVoidNiladicFunction) + fail(t, so(func() {}, ShouldPanicWith, "bye"), shouldHavePanicked) + fail(t, so(func() { panic("hi") }, ShouldPanicWith, "bye"), "bye|hi|Expected func() to panic with 'bye' (but it panicked with 'hi')!") + + pass(t, so(func() { panic("hi") }, ShouldPanicWith, "hi")) +} + +func TestShouldNotPanicWith(t *testing.T) { + fail(t, so(func() {}, ShouldNotPanicWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(func() {}, ShouldNotPanicWith, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(1, ShouldNotPanicWith, 1), shouldUseVoidNiladicFunction) + fail(t, so(func(i int) {}, ShouldNotPanicWith, "hi"), shouldUseVoidNiladicFunction) + fail(t, so(func() { panic("hi") }, ShouldNotPanicWith, "hi"), "Expected func() NOT to panic with 'hi' (but it did)!") + + pass(t, so(func() {}, ShouldNotPanicWith, "bye")) + pass(t, so(func() { panic("hi") }, ShouldNotPanicWith, "bye")) +} diff --git a/vendor/github.com/smartystreets/assertions/quantity.go b/vendor/github.com/smartystreets/assertions/quantity.go new file mode 100644 index 0000000000..a74c6d04ff --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/quantity.go @@ -0,0 +1,141 @@ +package assertions + +import ( + "fmt" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions/internal/oglematchers" +) + +// ShouldBeGreaterThan receives exactly two parameters and ensures that the first is greater than the second. +func ShouldBeGreaterThan(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + if matchError := oglematchers.GreaterThan(expected[0]).Matches(actual); matchError != nil { + return fmt.Sprintf(shouldHaveBeenGreater, actual, expected[0]) + } + return success +} + +// ShouldBeGreaterThanOrEqualTo receives exactly two parameters and ensures that the first is greater than or equal to the second. +func ShouldBeGreaterThanOrEqualTo(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } else if matchError := oglematchers.GreaterOrEqual(expected[0]).Matches(actual); matchError != nil { + return fmt.Sprintf(shouldHaveBeenGreaterOrEqual, actual, expected[0]) + } + return success +} + +// ShouldBeLessThan receives exactly two parameters and ensures that the first is less than the second. +func ShouldBeLessThan(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } else if matchError := oglematchers.LessThan(expected[0]).Matches(actual); matchError != nil { + return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0]) + } + return success +} + +// ShouldBeLessThan receives exactly two parameters and ensures that the first is less than or equal to the second. +func ShouldBeLessThanOrEqualTo(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } else if matchError := oglematchers.LessOrEqual(expected[0]).Matches(actual); matchError != nil { + return fmt.Sprintf(shouldHaveBeenLess, actual, expected[0]) + } + return success +} + +// ShouldBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound. +// It ensures that the actual value is between both bounds (but not equal to either of them). +func ShouldBeBetween(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + lower, upper, fail := deriveBounds(expected) + + if fail != success { + return fail + } else if !isBetween(actual, lower, upper) { + return fmt.Sprintf(shouldHaveBeenBetween, actual, lower, upper) + } + return success +} + +// ShouldNotBeBetween receives exactly three parameters: an actual value, a lower bound, and an upper bound. +// It ensures that the actual value is NOT between both bounds. +func ShouldNotBeBetween(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + lower, upper, fail := deriveBounds(expected) + + if fail != success { + return fail + } else if isBetween(actual, lower, upper) { + return fmt.Sprintf(shouldNotHaveBeenBetween, actual, lower, upper) + } + return success +} +func deriveBounds(values []interface{}) (lower interface{}, upper interface{}, fail string) { + lower = values[0] + upper = values[1] + + if ShouldNotEqual(lower, upper) != success { + return nil, nil, fmt.Sprintf(shouldHaveDifferentUpperAndLower, lower) + } else if ShouldBeLessThan(lower, upper) != success { + lower, upper = upper, lower + } + return lower, upper, success +} +func isBetween(value, lower, upper interface{}) bool { + if ShouldBeGreaterThan(value, lower) != success { + return false + } else if ShouldBeLessThan(value, upper) != success { + return false + } + return true +} + +// ShouldBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound. +// It ensures that the actual value is between both bounds or equal to one of them. +func ShouldBeBetweenOrEqual(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + lower, upper, fail := deriveBounds(expected) + + if fail != success { + return fail + } else if !isBetweenOrEqual(actual, lower, upper) { + return fmt.Sprintf(shouldHaveBeenBetweenOrEqual, actual, lower, upper) + } + return success +} + +// ShouldNotBeBetweenOrEqual receives exactly three parameters: an actual value, a lower bound, and an upper bound. +// It ensures that the actual value is nopt between the bounds nor equal to either of them. +func ShouldNotBeBetweenOrEqual(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + lower, upper, fail := deriveBounds(expected) + + if fail != success { + return fail + } else if isBetweenOrEqual(actual, lower, upper) { + return fmt.Sprintf(shouldNotHaveBeenBetweenOrEqual, actual, lower, upper) + } + return success +} + +func isBetweenOrEqual(value, lower, upper interface{}) bool { + if ShouldBeGreaterThanOrEqualTo(value, lower) != success { + return false + } else if ShouldBeLessThanOrEqualTo(value, upper) != success { + return false + } + return true +} diff --git a/vendor/github.com/smartystreets/assertions/quantity_test.go b/vendor/github.com/smartystreets/assertions/quantity_test.go new file mode 100644 index 0000000000..7546e7250a --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/quantity_test.go @@ -0,0 +1,145 @@ +package assertions + +import "testing" + +func TestShouldBeGreaterThan(t *testing.T) { + fail(t, so(1, ShouldBeGreaterThan), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldBeGreaterThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(1, ShouldBeGreaterThan, 0)) + pass(t, so(1.1, ShouldBeGreaterThan, 1)) + pass(t, so(1, ShouldBeGreaterThan, uint(0))) + pass(t, so("b", ShouldBeGreaterThan, "a")) + + fail(t, so(0, ShouldBeGreaterThan, 1), "Expected '0' to be greater than '1' (but it wasn't)!") + fail(t, so(1, ShouldBeGreaterThan, 1.1), "Expected '1' to be greater than '1.1' (but it wasn't)!") + fail(t, so(uint(0), ShouldBeGreaterThan, 1.1), "Expected '0' to be greater than '1.1' (but it wasn't)!") + fail(t, so("a", ShouldBeGreaterThan, "b"), "Expected 'a' to be greater than 'b' (but it wasn't)!") +} + +func TestShouldBeGreaterThanOrEqual(t *testing.T) { + fail(t, so(1, ShouldBeGreaterThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 1)) + pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1.1)) + pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(1))) + pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "b")) + + pass(t, so(1, ShouldBeGreaterThanOrEqualTo, 0)) + pass(t, so(1.1, ShouldBeGreaterThanOrEqualTo, 1)) + pass(t, so(1, ShouldBeGreaterThanOrEqualTo, uint(0))) + pass(t, so("b", ShouldBeGreaterThanOrEqualTo, "a")) + + fail(t, so(0, ShouldBeGreaterThanOrEqualTo, 1), "Expected '0' to be greater than or equal to '1' (but it wasn't)!") + fail(t, so(1, ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '1' to be greater than or equal to '1.1' (but it wasn't)!") + fail(t, so(uint(0), ShouldBeGreaterThanOrEqualTo, 1.1), "Expected '0' to be greater than or equal to '1.1' (but it wasn't)!") + fail(t, so("a", ShouldBeGreaterThanOrEqualTo, "b"), "Expected 'a' to be greater than or equal to 'b' (but it wasn't)!") +} + +func TestShouldBeLessThan(t *testing.T) { + fail(t, so(1, ShouldBeLessThan), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldBeLessThan, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(0, ShouldBeLessThan, 1)) + pass(t, so(1, ShouldBeLessThan, 1.1)) + pass(t, so(uint(0), ShouldBeLessThan, 1)) + pass(t, so("a", ShouldBeLessThan, "b")) + + fail(t, so(1, ShouldBeLessThan, 0), "Expected '1' to be less than '0' (but it wasn't)!") + fail(t, so(1.1, ShouldBeLessThan, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") + fail(t, so(1.1, ShouldBeLessThan, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") + fail(t, so("b", ShouldBeLessThan, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") +} + +func TestShouldBeLessThanOrEqualTo(t *testing.T) { + fail(t, so(1, ShouldBeLessThanOrEqualTo), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldBeLessThanOrEqualTo, 0, 0), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so(1, ShouldBeLessThanOrEqualTo, 1)) + pass(t, so(1.1, ShouldBeLessThanOrEqualTo, 1.1)) + pass(t, so(uint(1), ShouldBeLessThanOrEqualTo, 1)) + pass(t, so("b", ShouldBeLessThanOrEqualTo, "b")) + + pass(t, so(0, ShouldBeLessThanOrEqualTo, 1)) + pass(t, so(1, ShouldBeLessThanOrEqualTo, 1.1)) + pass(t, so(uint(0), ShouldBeLessThanOrEqualTo, 1)) + pass(t, so("a", ShouldBeLessThanOrEqualTo, "b")) + + fail(t, so(1, ShouldBeLessThanOrEqualTo, 0), "Expected '1' to be less than '0' (but it wasn't)!") + fail(t, so(1.1, ShouldBeLessThanOrEqualTo, 1), "Expected '1.1' to be less than '1' (but it wasn't)!") + fail(t, so(1.1, ShouldBeLessThanOrEqualTo, uint(0)), "Expected '1.1' to be less than '0' (but it wasn't)!") + fail(t, so("b", ShouldBeLessThanOrEqualTo, "a"), "Expected 'b' to be less than 'a' (but it wasn't)!") +} + +func TestShouldBeBetween(t *testing.T) { + fail(t, so(1, ShouldBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(1, ShouldBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(4, ShouldBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") + + fail(t, so(7, ShouldBeBetween, 8, 12), "Expected '7' to be between '8' and '12' (but it wasn't)!") + fail(t, so(8, ShouldBeBetween, 8, 12), "Expected '8' to be between '8' and '12' (but it wasn't)!") + pass(t, so(9, ShouldBeBetween, 8, 12)) + pass(t, so(10, ShouldBeBetween, 8, 12)) + pass(t, so(11, ShouldBeBetween, 8, 12)) + fail(t, so(12, ShouldBeBetween, 8, 12), "Expected '12' to be between '8' and '12' (but it wasn't)!") + fail(t, so(13, ShouldBeBetween, 8, 12), "Expected '13' to be between '8' and '12' (but it wasn't)!") + + pass(t, so(1, ShouldBeBetween, 2, 0)) + fail(t, so(-1, ShouldBeBetween, 2, 0), "Expected '-1' to be between '0' and '2' (but it wasn't)!") +} + +func TestShouldNotBeBetween(t *testing.T) { + fail(t, so(1, ShouldNotBeBetween), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(1, ShouldNotBeBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(4, ShouldNotBeBetween, 1, 1), "The lower and upper bounds must be different values (they were both '1').") + + pass(t, so(7, ShouldNotBeBetween, 8, 12)) + pass(t, so(8, ShouldNotBeBetween, 8, 12)) + fail(t, so(9, ShouldNotBeBetween, 8, 12), "Expected '9' NOT to be between '8' and '12' (but it was)!") + fail(t, so(10, ShouldNotBeBetween, 8, 12), "Expected '10' NOT to be between '8' and '12' (but it was)!") + fail(t, so(11, ShouldNotBeBetween, 8, 12), "Expected '11' NOT to be between '8' and '12' (but it was)!") + pass(t, so(12, ShouldNotBeBetween, 8, 12)) + pass(t, so(13, ShouldNotBeBetween, 8, 12)) + + pass(t, so(-1, ShouldNotBeBetween, 2, 0)) + fail(t, so(1, ShouldNotBeBetween, 2, 0), "Expected '1' NOT to be between '0' and '2' (but it was)!") +} + +func TestShouldBeBetweenOrEqual(t *testing.T) { + fail(t, so(1, ShouldBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(1, ShouldBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(4, ShouldBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") + + fail(t, so(7, ShouldBeBetweenOrEqual, 8, 12), "Expected '7' to be between '8' and '12' or equal to one of them (but it wasn't)!") + pass(t, so(8, ShouldBeBetweenOrEqual, 8, 12)) + pass(t, so(9, ShouldBeBetweenOrEqual, 8, 12)) + pass(t, so(10, ShouldBeBetweenOrEqual, 8, 12)) + pass(t, so(11, ShouldBeBetweenOrEqual, 8, 12)) + pass(t, so(12, ShouldBeBetweenOrEqual, 8, 12)) + fail(t, so(13, ShouldBeBetweenOrEqual, 8, 12), "Expected '13' to be between '8' and '12' or equal to one of them (but it wasn't)!") + + pass(t, so(1, ShouldBeBetweenOrEqual, 2, 0)) + fail(t, so(-1, ShouldBeBetweenOrEqual, 2, 0), "Expected '-1' to be between '0' and '2' or equal to one of them (but it wasn't)!") +} + +func TestShouldNotBeBetweenOrEqual(t *testing.T) { + fail(t, so(1, ShouldNotBeBetweenOrEqual), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(1, ShouldNotBeBetweenOrEqual, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(4, ShouldNotBeBetweenOrEqual, 1, 1), "The lower and upper bounds must be different values (they were both '1').") + + pass(t, so(7, ShouldNotBeBetweenOrEqual, 8, 12)) + fail(t, so(8, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '8' NOT to be between '8' and '12' or equal to one of them (but it was)!") + fail(t, so(9, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '9' NOT to be between '8' and '12' or equal to one of them (but it was)!") + fail(t, so(10, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '10' NOT to be between '8' and '12' or equal to one of them (but it was)!") + fail(t, so(11, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '11' NOT to be between '8' and '12' or equal to one of them (but it was)!") + fail(t, so(12, ShouldNotBeBetweenOrEqual, 8, 12), "Expected '12' NOT to be between '8' and '12' or equal to one of them (but it was)!") + pass(t, so(13, ShouldNotBeBetweenOrEqual, 8, 12)) + + pass(t, so(-1, ShouldNotBeBetweenOrEqual, 2, 0)) + fail(t, so(1, ShouldNotBeBetweenOrEqual, 2, 0), "Expected '1' NOT to be between '0' and '2' or equal to one of them (but it was)!") +} diff --git a/vendor/github.com/smartystreets/assertions/serializer.go b/vendor/github.com/smartystreets/assertions/serializer.go new file mode 100644 index 0000000000..6887cddffe --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/serializer.go @@ -0,0 +1,59 @@ +package assertions + +import ( + "encoding/json" + "fmt" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +type Serializer interface { + serialize(expected, actual interface{}, message string) string + serializeDetailed(expected, actual interface{}, message string) string +} + +type failureSerializer struct{} + +func (self *failureSerializer) serializeDetailed(expected, actual interface{}, message string) string { + view := self.format(expected, actual, message, "%#v") + serialized, err := json.Marshal(view) + if err != nil { + return message + } + return string(serialized) +} + +func (self *failureSerializer) serialize(expected, actual interface{}, message string) string { + view := self.format(expected, actual, message, "%+v") + serialized, err := json.Marshal(view) + if err != nil { + return message + } + return string(serialized) +} + +func (self *failureSerializer) format(expected, actual interface{}, message string, format string) reporting.FailureView { + return reporting.FailureView{ + Message: message, + Expected: fmt.Sprintf(format, expected), + Actual: fmt.Sprintf(format, actual), + } +} + +func newSerializer() *failureSerializer { + return &failureSerializer{} +} + +/////////////////////////////////////////////////////// + +// noopSerializer just gives back the original message. This is useful when we are using +// the assertions from a context other than the web UI, that requires the JSON structure +// provided by the failureSerializer. +type noopSerializer struct{} + +func (self *noopSerializer) serialize(expected, actual interface{}, message string) string { + return message +} +func (self *noopSerializer) serializeDetailed(expected, actual interface{}, message string) string { + return message +} diff --git a/vendor/github.com/smartystreets/assertions/serializer_test.go b/vendor/github.com/smartystreets/assertions/serializer_test.go new file mode 100644 index 0000000000..d82af72d28 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/serializer_test.go @@ -0,0 +1,38 @@ +package assertions + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +func TestSerializerCreatesSerializedVersionOfAssertionResult(t *testing.T) { + thing1 := Thing1{"Hi"} + thing2 := Thing2{"Bye"} + message := "Super-hip failure message." + serializer := newSerializer() + + actualResult := serializer.serialize(thing1, thing2, message) + + expectedResult, _ := json.Marshal(reporting.FailureView{ + Message: message, + Expected: fmt.Sprintf("%+v", thing1), + Actual: fmt.Sprintf("%+v", thing2), + }) + + if actualResult != string(expectedResult) { + t.Errorf("\nExpected: %s\nActual: %s", string(expectedResult), actualResult) + } + + actualResult = serializer.serializeDetailed(thing1, thing2, message) + expectedResult, _ = json.Marshal(reporting.FailureView{ + Message: message, + Expected: fmt.Sprintf("%#v", thing1), + Actual: fmt.Sprintf("%#v", thing2), + }) + if actualResult != string(expectedResult) { + t.Errorf("\nExpected: %s\nActual: %s", string(expectedResult), actualResult) + } +} diff --git a/vendor/github.com/smartystreets/assertions/strings.go b/vendor/github.com/smartystreets/assertions/strings.go new file mode 100644 index 0000000000..1b887b1191 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/strings.go @@ -0,0 +1,183 @@ +package assertions + +import ( + "fmt" + "reflect" + "strings" +) + +// ShouldStartWith receives exactly 2 string parameters and ensures that the first starts with the second. +func ShouldStartWith(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + value, valueIsString := actual.(string) + prefix, prefixIsString := expected[0].(string) + + if !valueIsString || !prefixIsString { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + return shouldStartWith(value, prefix) +} +func shouldStartWith(value, prefix string) string { + if !strings.HasPrefix(value, prefix) { + shortval := value + if len(shortval) > len(prefix) { + shortval = shortval[:len(prefix)] + "..." + } + return serializer.serialize(prefix, shortval, fmt.Sprintf(shouldHaveStartedWith, value, prefix)) + } + return success +} + +// ShouldNotStartWith receives exactly 2 string parameters and ensures that the first does not start with the second. +func ShouldNotStartWith(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + value, valueIsString := actual.(string) + prefix, prefixIsString := expected[0].(string) + + if !valueIsString || !prefixIsString { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + return shouldNotStartWith(value, prefix) +} +func shouldNotStartWith(value, prefix string) string { + if strings.HasPrefix(value, prefix) { + if value == "" { + value = "" + } + if prefix == "" { + prefix = "" + } + return fmt.Sprintf(shouldNotHaveStartedWith, value, prefix) + } + return success +} + +// ShouldEndWith receives exactly 2 string parameters and ensures that the first ends with the second. +func ShouldEndWith(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + value, valueIsString := actual.(string) + suffix, suffixIsString := expected[0].(string) + + if !valueIsString || !suffixIsString { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + return shouldEndWith(value, suffix) +} +func shouldEndWith(value, suffix string) string { + if !strings.HasSuffix(value, suffix) { + shortval := value + if len(shortval) > len(suffix) { + shortval = "..." + shortval[len(shortval)-len(suffix):] + } + return serializer.serialize(suffix, shortval, fmt.Sprintf(shouldHaveEndedWith, value, suffix)) + } + return success +} + +// ShouldEndWith receives exactly 2 string parameters and ensures that the first does not end with the second. +func ShouldNotEndWith(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + value, valueIsString := actual.(string) + suffix, suffixIsString := expected[0].(string) + + if !valueIsString || !suffixIsString { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + return shouldNotEndWith(value, suffix) +} +func shouldNotEndWith(value, suffix string) string { + if strings.HasSuffix(value, suffix) { + if value == "" { + value = "" + } + if suffix == "" { + suffix = "" + } + return fmt.Sprintf(shouldNotHaveEndedWith, value, suffix) + } + return success +} + +// ShouldContainSubstring receives exactly 2 string parameters and ensures that the first contains the second as a substring. +func ShouldContainSubstring(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + long, longOk := actual.(string) + short, shortOk := expected[0].(string) + + if !longOk || !shortOk { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + if !strings.Contains(long, short) { + return serializer.serialize(expected[0], actual, fmt.Sprintf(shouldHaveContainedSubstring, long, short)) + } + return success +} + +// ShouldNotContainSubstring receives exactly 2 string parameters and ensures that the first does NOT contain the second as a substring. +func ShouldNotContainSubstring(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + long, longOk := actual.(string) + short, shortOk := expected[0].(string) + + if !longOk || !shortOk { + return fmt.Sprintf(shouldBothBeStrings, reflect.TypeOf(actual), reflect.TypeOf(expected[0])) + } + + if strings.Contains(long, short) { + return fmt.Sprintf(shouldNotHaveContainedSubstring, long, short) + } + return success +} + +// ShouldBeBlank receives exactly 1 string parameter and ensures that it is equal to "". +func ShouldBeBlank(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + value, ok := actual.(string) + if !ok { + return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) + } + if value != "" { + return serializer.serialize("", value, fmt.Sprintf(shouldHaveBeenBlank, value)) + } + return success +} + +// ShouldNotBeBlank receives exactly 1 string parameter and ensures that it is equal to "". +func ShouldNotBeBlank(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + value, ok := actual.(string) + if !ok { + return fmt.Sprintf(shouldBeString, reflect.TypeOf(actual)) + } + if value == "" { + return shouldNotHaveBeenBlank + } + return success +} diff --git a/vendor/github.com/smartystreets/assertions/strings_test.go b/vendor/github.com/smartystreets/assertions/strings_test.go new file mode 100644 index 0000000000..83417332f6 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/strings_test.go @@ -0,0 +1,102 @@ +package assertions + +import "testing" + +func TestShouldStartWith(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so("", ShouldStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("", ShouldStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so("", ShouldStartWith, "")) + fail(t, so("", ShouldStartWith, "x"), "x||Expected '' to start with 'x' (but it didn't)!") + pass(t, so("abc", ShouldStartWith, "abc")) + fail(t, so("abc", ShouldStartWith, "abcd"), "abcd|abc|Expected 'abc' to start with 'abcd' (but it didn't)!") + + pass(t, so("superman", ShouldStartWith, "super")) + fail(t, so("superman", ShouldStartWith, "bat"), "bat|sup...|Expected 'superman' to start with 'bat' (but it didn't)!") + fail(t, so("superman", ShouldStartWith, "man"), "man|sup...|Expected 'superman' to start with 'man' (but it didn't)!") + + fail(t, so(1, ShouldStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") +} + +func TestShouldNotStartWith(t *testing.T) { + fail(t, so("", ShouldNotStartWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("", ShouldNotStartWith, "asdf", "asdf"), "This assertion requires exactly 1 comparison values (you provided 2).") + + fail(t, so("", ShouldNotStartWith, ""), "Expected '' NOT to start with '' (but it did)!") + fail(t, so("superman", ShouldNotStartWith, "super"), "Expected 'superman' NOT to start with 'super' (but it did)!") + pass(t, so("superman", ShouldNotStartWith, "bat")) + pass(t, so("superman", ShouldNotStartWith, "man")) + + fail(t, so(1, ShouldNotStartWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") +} + +func TestShouldEndWith(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so("", ShouldEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("", ShouldEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") + + pass(t, so("", ShouldEndWith, "")) + fail(t, so("", ShouldEndWith, "z"), "z||Expected '' to end with 'z' (but it didn't)!") + pass(t, so("xyz", ShouldEndWith, "xyz")) + fail(t, so("xyz", ShouldEndWith, "wxyz"), "wxyz|xyz|Expected 'xyz' to end with 'wxyz' (but it didn't)!") + + pass(t, so("superman", ShouldEndWith, "man")) + fail(t, so("superman", ShouldEndWith, "super"), "super|...erman|Expected 'superman' to end with 'super' (but it didn't)!") + fail(t, so("superman", ShouldEndWith, "blah"), "blah|...rman|Expected 'superman' to end with 'blah' (but it didn't)!") + + fail(t, so(1, ShouldEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") +} + +func TestShouldNotEndWith(t *testing.T) { + fail(t, so("", ShouldNotEndWith), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("", ShouldNotEndWith, "", ""), "This assertion requires exactly 1 comparison values (you provided 2).") + + fail(t, so("", ShouldNotEndWith, ""), "Expected '' NOT to end with '' (but it did)!") + fail(t, so("superman", ShouldNotEndWith, "man"), "Expected 'superman' NOT to end with 'man' (but it did)!") + pass(t, so("superman", ShouldNotEndWith, "super")) + + fail(t, so(1, ShouldNotEndWith, 2), "Both arguments to this assertion must be strings (you provided int and int).") +} + +func TestShouldContainSubstring(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so("asdf", ShouldContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("asdf", ShouldContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(123, ShouldContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") + + pass(t, so("asdf", ShouldContainSubstring, "sd")) + fail(t, so("qwer", ShouldContainSubstring, "sd"), "sd|qwer|Expected 'qwer' to contain substring 'sd' (but it didn't)!") +} + +func TestShouldNotContainSubstring(t *testing.T) { + fail(t, so("asdf", ShouldNotContainSubstring), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so("asdf", ShouldNotContainSubstring, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(123, ShouldNotContainSubstring, 23), "Both arguments to this assertion must be strings (you provided int and int).") + + pass(t, so("qwer", ShouldNotContainSubstring, "sd")) + fail(t, so("asdf", ShouldNotContainSubstring, "sd"), "Expected 'asdf' NOT to contain substring 'sd' (but it did)!") +} + +func TestShouldBeBlank(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so("", ShouldBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") + fail(t, so(1, ShouldBeBlank), "The argument to this assertion must be a string (you provided int).") + + fail(t, so("asdf", ShouldBeBlank), "|asdf|Expected 'asdf' to be blank (but it wasn't)!") + pass(t, so("", ShouldBeBlank)) +} + +func TestShouldNotBeBlank(t *testing.T) { + fail(t, so("", ShouldNotBeBlank, "adsf"), "This assertion requires exactly 0 comparison values (you provided 1).") + fail(t, so(1, ShouldNotBeBlank), "The argument to this assertion must be a string (you provided int).") + + fail(t, so("", ShouldNotBeBlank), "Expected value to NOT be blank (but it was)!") + pass(t, so("asdf", ShouldNotBeBlank)) +} diff --git a/vendor/github.com/smartystreets/assertions/time.go b/vendor/github.com/smartystreets/assertions/time.go new file mode 100644 index 0000000000..7e05026143 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/time.go @@ -0,0 +1,202 @@ +package assertions + +import ( + "fmt" + "time" +) + +// ShouldHappenBefore receives exactly 2 time.Time arguments and asserts that the first happens before the second. +func ShouldHappenBefore(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + expectedTime, secondOk := expected[0].(time.Time) + + if !firstOk || !secondOk { + return shouldUseTimes + } + + if !actualTime.Before(expectedTime) { + return fmt.Sprintf(shouldHaveHappenedBefore, actualTime, expectedTime, actualTime.Sub(expectedTime)) + } + + return success +} + +// ShouldHappenOnOrBefore receives exactly 2 time.Time arguments and asserts that the first happens on or before the second. +func ShouldHappenOnOrBefore(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + expectedTime, secondOk := expected[0].(time.Time) + + if !firstOk || !secondOk { + return shouldUseTimes + } + + if actualTime.Equal(expectedTime) { + return success + } + return ShouldHappenBefore(actualTime, expectedTime) +} + +// ShouldHappenAfter receives exactly 2 time.Time arguments and asserts that the first happens after the second. +func ShouldHappenAfter(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + expectedTime, secondOk := expected[0].(time.Time) + + if !firstOk || !secondOk { + return shouldUseTimes + } + if !actualTime.After(expectedTime) { + return fmt.Sprintf(shouldHaveHappenedAfter, actualTime, expectedTime, expectedTime.Sub(actualTime)) + } + return success +} + +// ShouldHappenOnOrAfter receives exactly 2 time.Time arguments and asserts that the first happens on or after the second. +func ShouldHappenOnOrAfter(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + expectedTime, secondOk := expected[0].(time.Time) + + if !firstOk || !secondOk { + return shouldUseTimes + } + if actualTime.Equal(expectedTime) { + return success + } + return ShouldHappenAfter(actualTime, expectedTime) +} + +// ShouldHappenBetween receives exactly 3 time.Time arguments and asserts that the first happens between (not on) the second and third. +func ShouldHappenBetween(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + min, secondOk := expected[0].(time.Time) + max, thirdOk := expected[1].(time.Time) + + if !firstOk || !secondOk || !thirdOk { + return shouldUseTimes + } + + if !actualTime.After(min) { + return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, min.Sub(actualTime)) + } + if !actualTime.Before(max) { + return fmt.Sprintf(shouldHaveHappenedBetween, actualTime, min, max, actualTime.Sub(max)) + } + return success +} + +// ShouldHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first happens between or on the second and third. +func ShouldHappenOnOrBetween(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + min, secondOk := expected[0].(time.Time) + max, thirdOk := expected[1].(time.Time) + + if !firstOk || !secondOk || !thirdOk { + return shouldUseTimes + } + if actualTime.Equal(min) || actualTime.Equal(max) { + return success + } + return ShouldHappenBetween(actualTime, min, max) +} + +// ShouldNotHappenOnOrBetween receives exactly 3 time.Time arguments and asserts that the first +// does NOT happen between or on the second or third. +func ShouldNotHappenOnOrBetween(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + min, secondOk := expected[0].(time.Time) + max, thirdOk := expected[1].(time.Time) + + if !firstOk || !secondOk || !thirdOk { + return shouldUseTimes + } + if actualTime.Equal(min) || actualTime.Equal(max) { + return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max) + } + if actualTime.After(min) && actualTime.Before(max) { + return fmt.Sprintf(shouldNotHaveHappenedOnOrBetween, actualTime, min, max) + } + return success +} + +// ShouldHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments) +// and asserts that the first time.Time happens within or on the duration specified relative to +// the other time.Time. +func ShouldHappenWithin(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + tolerance, secondOk := expected[0].(time.Duration) + threshold, thirdOk := expected[1].(time.Time) + + if !firstOk || !secondOk || !thirdOk { + return shouldUseDurationAndTime + } + + min := threshold.Add(-tolerance) + max := threshold.Add(tolerance) + return ShouldHappenOnOrBetween(actualTime, min, max) +} + +// ShouldNotHappenWithin receives a time.Time, a time.Duration, and a time.Time (3 arguments) +// and asserts that the first time.Time does NOT happen within or on the duration specified relative to +// the other time.Time. +func ShouldNotHappenWithin(actual interface{}, expected ...interface{}) string { + if fail := need(2, expected); fail != success { + return fail + } + actualTime, firstOk := actual.(time.Time) + tolerance, secondOk := expected[0].(time.Duration) + threshold, thirdOk := expected[1].(time.Time) + + if !firstOk || !secondOk || !thirdOk { + return shouldUseDurationAndTime + } + + min := threshold.Add(-tolerance) + max := threshold.Add(tolerance) + return ShouldNotHappenOnOrBetween(actualTime, min, max) +} + +// ShouldBeChronological receives a []time.Time slice and asserts that the are +// in chronological order starting with the first time.Time as the earliest. +func ShouldBeChronological(actual interface{}, expected ...interface{}) string { + if fail := need(0, expected); fail != success { + return fail + } + + times, ok := actual.([]time.Time) + if !ok { + return shouldUseTimeSlice + } + + var previous time.Time + for i, current := range times { + if i > 0 && current.Before(previous) { + return fmt.Sprintf(shouldHaveBeenChronological, + i, i-1, previous.String(), i, current.String()) + } + previous = current + } + return "" +} diff --git a/vendor/github.com/smartystreets/assertions/time_test.go b/vendor/github.com/smartystreets/assertions/time_test.go new file mode 100644 index 0000000000..f9dda8f8f3 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/time_test.go @@ -0,0 +1,159 @@ +package assertions + +import ( + "fmt" + "testing" + "time" +) + +func TestShouldHappenBefore(t *testing.T) { + fail(t, so(0, ShouldHappenBefore), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenBefore, 1), shouldUseTimes) + fail(t, so(0, ShouldHappenBefore, time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenBefore, 0), shouldUseTimes) + + fail(t, so(january3, ShouldHappenBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) + fail(t, so(january3, ShouldHappenBefore, january3), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '0' after)!", pretty(january3), pretty(january3))) + pass(t, so(january1, ShouldHappenBefore, january3)) +} + +func TestShouldHappenOnOrBefore(t *testing.T) { + fail(t, so(0, ShouldHappenOnOrBefore), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenOnOrBefore, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenOnOrBefore, 1), shouldUseTimes) + fail(t, so(0, ShouldHappenOnOrBefore, time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenOnOrBefore, 0), shouldUseTimes) + + fail(t, so(january3, ShouldHappenOnOrBefore, january1), fmt.Sprintf("Expected '%s' to happen before '%s' (it happened '48h0m0s' after)!", pretty(january3), pretty(january1))) + pass(t, so(january3, ShouldHappenOnOrBefore, january3)) + pass(t, so(january1, ShouldHappenOnOrBefore, january3)) +} + +func TestShouldHappenAfter(t *testing.T) { + fail(t, so(0, ShouldHappenAfter), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenAfter, 1), shouldUseTimes) + fail(t, so(0, ShouldHappenAfter, time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenAfter, 0), shouldUseTimes) + + fail(t, so(january1, ShouldHappenAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) + fail(t, so(january1, ShouldHappenAfter, january1), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '0' before)!", pretty(january1), pretty(january1))) + pass(t, so(january3, ShouldHappenAfter, january1)) +} + +func TestShouldHappenOnOrAfter(t *testing.T) { + fail(t, so(0, ShouldHappenOnOrAfter), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenOnOrAfter, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenOnOrAfter, 1), shouldUseTimes) + fail(t, so(0, ShouldHappenOnOrAfter, time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenOnOrAfter, 0), shouldUseTimes) + + fail(t, so(january1, ShouldHappenOnOrAfter, january2), fmt.Sprintf("Expected '%s' to happen after '%s' (it happened '24h0m0s' before)!", pretty(january1), pretty(january2))) + pass(t, so(january1, ShouldHappenOnOrAfter, january1)) + pass(t, so(january3, ShouldHappenOnOrAfter, january1)) +} + +func TestShouldHappenBetween(t *testing.T) { + fail(t, so(0, ShouldHappenBetween), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenBetween, 1, 2), shouldUseTimes) + fail(t, so(0, ShouldHappenBetween, time.Now(), time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenBetween, 0, time.Now()), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenBetween, time.Now(), 9), shouldUseTimes) + + fail(t, so(january1, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) + fail(t, so(january2, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january2), pretty(january2), pretty(january4))) + pass(t, so(january3, ShouldHappenBetween, january2, january4)) + fail(t, so(january4, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '0' outside threshold)!", pretty(january4), pretty(january2), pretty(january4))) + fail(t, so(january5, ShouldHappenBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) +} + +func TestShouldHappenOnOrBetween(t *testing.T) { + fail(t, so(0, ShouldHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenOnOrBetween, 1, time.Now()), shouldUseTimes) + fail(t, so(0, ShouldHappenOnOrBetween, time.Now(), 1), shouldUseTimes) + fail(t, so(time.Now(), ShouldHappenOnOrBetween, 0, 1), shouldUseTimes) + + fail(t, so(january1, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) + pass(t, so(january2, ShouldHappenOnOrBetween, january2, january4)) + pass(t, so(january3, ShouldHappenOnOrBetween, january2, january4)) + pass(t, so(january4, ShouldHappenOnOrBetween, january2, january4)) + fail(t, so(january5, ShouldHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) +} + +func TestShouldNotHappenOnOrBetween(t *testing.T) { + fail(t, so(0, ShouldNotHappenOnOrBetween), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(0, ShouldNotHappenOnOrBetween, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(0, ShouldNotHappenOnOrBetween, 1, time.Now()), shouldUseTimes) + fail(t, so(0, ShouldNotHappenOnOrBetween, time.Now(), 1), shouldUseTimes) + fail(t, so(time.Now(), ShouldNotHappenOnOrBetween, 0, 1), shouldUseTimes) + + pass(t, so(january1, ShouldNotHappenOnOrBetween, january2, january4)) + fail(t, so(january2, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) + fail(t, so(january3, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) + fail(t, so(january4, ShouldNotHappenOnOrBetween, january2, january4), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) + pass(t, so(january5, ShouldNotHappenOnOrBetween, january2, january4)) +} + +func TestShouldHappenWithin(t *testing.T) { + fail(t, so(0, ShouldHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(0, ShouldHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(0, ShouldHappenWithin, 1, 2), shouldUseDurationAndTime) + fail(t, so(0, ShouldHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) + fail(t, so(time.Now(), ShouldHappenWithin, 0, time.Now()), shouldUseDurationAndTime) + + fail(t, so(january1, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january1), pretty(january2), pretty(january4))) + pass(t, so(january2, ShouldHappenWithin, oneDay, january3)) + pass(t, so(january3, ShouldHappenWithin, oneDay, january3)) + pass(t, so(january4, ShouldHappenWithin, oneDay, january3)) + fail(t, so(january5, ShouldHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to happen between '%s' and '%s' (it happened '24h0m0s' outside threshold)!", pretty(january5), pretty(january2), pretty(january4))) +} + +func TestShouldNotHappenWithin(t *testing.T) { + fail(t, so(0, ShouldNotHappenWithin), "This assertion requires exactly 2 comparison values (you provided 0).") + fail(t, so(0, ShouldNotHappenWithin, 1, 2, 3), "This assertion requires exactly 2 comparison values (you provided 3).") + + fail(t, so(0, ShouldNotHappenWithin, 1, 2), shouldUseDurationAndTime) + fail(t, so(0, ShouldNotHappenWithin, oneDay, time.Now()), shouldUseDurationAndTime) + fail(t, so(time.Now(), ShouldNotHappenWithin, 0, time.Now()), shouldUseDurationAndTime) + + pass(t, so(january1, ShouldNotHappenWithin, oneDay, january3)) + fail(t, so(january2, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january2), pretty(january2), pretty(january4))) + fail(t, so(january3, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january3), pretty(january2), pretty(january4))) + fail(t, so(january4, ShouldNotHappenWithin, oneDay, january3), fmt.Sprintf("Expected '%s' to NOT happen on or between '%s' and '%s' (but it did)!", pretty(january4), pretty(january2), pretty(january4))) + pass(t, so(january5, ShouldNotHappenWithin, oneDay, january3)) +} + +func TestShouldBeChronological(t *testing.T) { + fail(t, so(0, ShouldBeChronological, 1, 2, 3), "This assertion requires exactly 0 comparison values (you provided 3).") + fail(t, so(0, ShouldBeChronological), shouldUseTimeSlice) + fail(t, so([]time.Time{january5, january1}, ShouldBeChronological), + "The 'Time' at index [1] should have happened after the previous one (but it didn't!):\n [0]: 2013-01-05 00:00:00 +0000 UTC\n [1]: 2013-01-01 00:00:00 +0000 UTC (see, it happened before!)") + + pass(t, so([]time.Time{january1, january2, january3, january4, january5}, ShouldBeChronological)) +} + +const layout = "2006-01-02 15:04" + +var january1, _ = time.Parse(layout, "2013-01-01 00:00") +var january2, _ = time.Parse(layout, "2013-01-02 00:00") +var january3, _ = time.Parse(layout, "2013-01-03 00:00") +var january4, _ = time.Parse(layout, "2013-01-04 00:00") +var january5, _ = time.Parse(layout, "2013-01-05 00:00") + +var oneDay, _ = time.ParseDuration("24h0m0s") +var twoDays, _ = time.ParseDuration("48h0m0s") + +func pretty(t time.Time) string { + return fmt.Sprintf("%v", t) +} diff --git a/vendor/github.com/smartystreets/assertions/type.go b/vendor/github.com/smartystreets/assertions/type.go new file mode 100644 index 0000000000..3fc00f68cd --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/type.go @@ -0,0 +1,112 @@ +package assertions + +import ( + "fmt" + "reflect" +) + +// ShouldHaveSameTypeAs receives exactly two parameters and compares their underlying types for equality. +func ShouldHaveSameTypeAs(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + first := reflect.TypeOf(actual) + second := reflect.TypeOf(expected[0]) + + if equal := ShouldEqual(first, second); equal != success { + return serializer.serialize(second, first, fmt.Sprintf(shouldHaveBeenA, actual, second, first)) + } + return success +} + +// ShouldNotHaveSameTypeAs receives exactly two parameters and compares their underlying types for inequality. +func ShouldNotHaveSameTypeAs(actual interface{}, expected ...interface{}) string { + if fail := need(1, expected); fail != success { + return fail + } + + first := reflect.TypeOf(actual) + second := reflect.TypeOf(expected[0]) + + if equal := ShouldEqual(first, second); equal == success { + return fmt.Sprintf(shouldNotHaveBeenA, actual, second) + } + return success +} + +// ShouldImplement receives exactly two parameters and ensures +// that the first implements the interface type of the second. +func ShouldImplement(actual interface{}, expectedList ...interface{}) string { + if fail := need(1, expectedList); fail != success { + return fail + } + + expected := expectedList[0] + if fail := ShouldBeNil(expected); fail != success { + return shouldCompareWithInterfacePointer + } + + if fail := ShouldNotBeNil(actual); fail != success { + return shouldNotBeNilActual + } + + var actualType reflect.Type + if reflect.TypeOf(actual).Kind() != reflect.Ptr { + actualType = reflect.PtrTo(reflect.TypeOf(actual)) + } else { + actualType = reflect.TypeOf(actual) + } + + expectedType := reflect.TypeOf(expected) + if fail := ShouldNotBeNil(expectedType); fail != success { + return shouldCompareWithInterfacePointer + } + + expectedInterface := expectedType.Elem() + + if actualType == nil { + return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actual) + } + + if !actualType.Implements(expectedInterface) { + return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actualType) + } + return success +} + +// ShouldNotImplement receives exactly two parameters and ensures +// that the first does NOT implement the interface type of the second. +func ShouldNotImplement(actual interface{}, expectedList ...interface{}) string { + if fail := need(1, expectedList); fail != success { + return fail + } + + expected := expectedList[0] + if fail := ShouldBeNil(expected); fail != success { + return shouldCompareWithInterfacePointer + } + + if fail := ShouldNotBeNil(actual); fail != success { + return shouldNotBeNilActual + } + + var actualType reflect.Type + if reflect.TypeOf(actual).Kind() != reflect.Ptr { + actualType = reflect.PtrTo(reflect.TypeOf(actual)) + } else { + actualType = reflect.TypeOf(actual) + } + + expectedType := reflect.TypeOf(expected) + if fail := ShouldNotBeNil(expectedType); fail != success { + return shouldCompareWithInterfacePointer + } + + expectedInterface := expectedType.Elem() + + if actualType.Implements(expectedInterface) { + return fmt.Sprintf(shouldNotHaveImplemented, actualType, expectedInterface) + } + return success +} diff --git a/vendor/github.com/smartystreets/assertions/type_test.go b/vendor/github.com/smartystreets/assertions/type_test.go new file mode 100644 index 0000000000..4b8d198467 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/type_test.go @@ -0,0 +1,76 @@ +package assertions + +import ( + "bytes" + "io" + "net/http" + "testing" +) + +func TestShouldHaveSameTypeAs(t *testing.T) { + serializer = newFakeSerializer() + + fail(t, so(1, ShouldHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(nil, ShouldHaveSameTypeAs, 0), "int||Expected '' to be: 'int' (but was: '')!") + fail(t, so(1, ShouldHaveSameTypeAs, "asdf"), "string|int|Expected '1' to be: 'string' (but was: 'int')!") + + pass(t, so(1, ShouldHaveSameTypeAs, 0)) + pass(t, so(nil, ShouldHaveSameTypeAs, nil)) +} + +func TestShouldNotHaveSameTypeAs(t *testing.T) { + fail(t, so(1, ShouldNotHaveSameTypeAs), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(1, ShouldNotHaveSameTypeAs, 1, 2, 3), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(1, ShouldNotHaveSameTypeAs, 0), "Expected '1' to NOT be: 'int' (but it was)!") + fail(t, so(nil, ShouldNotHaveSameTypeAs, nil), "Expected '' to NOT be: '' (but it was)!") + + pass(t, so(nil, ShouldNotHaveSameTypeAs, 0)) + pass(t, so(1, ShouldNotHaveSameTypeAs, "asdf")) +} + +func TestShouldImplement(t *testing.T) { + var ioReader *io.Reader = nil + var response http.Response = http.Response{} + var responsePtr *http.Response = new(http.Response) + var reader = bytes.NewBufferString("") + + fail(t, so(reader, ShouldImplement), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(reader, ShouldImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).") + fail(t, so(reader, ShouldImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(reader, ShouldImplement, "foo"), shouldCompareWithInterfacePointer) + fail(t, so(reader, ShouldImplement, 1), shouldCompareWithInterfacePointer) + fail(t, so(reader, ShouldImplement, nil), shouldCompareWithInterfacePointer) + + fail(t, so(nil, ShouldImplement, ioReader), shouldNotBeNilActual) + fail(t, so(1, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*int' does not implement the interface!") + + fail(t, so(response, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*http.Response' does not implement the interface!") + fail(t, so(responsePtr, ShouldImplement, ioReader), "Expected: 'io.Reader interface support'\nActual: '*http.Response' does not implement the interface!") + pass(t, so(reader, ShouldImplement, ioReader)) + pass(t, so(reader, ShouldImplement, (*io.Reader)(nil))) +} + +func TestShouldNotImplement(t *testing.T) { + var ioReader *io.Reader = nil + var response http.Response = http.Response{} + var responsePtr *http.Response = new(http.Response) + var reader io.Reader = bytes.NewBufferString("") + + fail(t, so(reader, ShouldNotImplement), "This assertion requires exactly 1 comparison values (you provided 0).") + fail(t, so(reader, ShouldNotImplement, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 2).") + fail(t, so(reader, ShouldNotImplement, ioReader, ioReader, ioReader), "This assertion requires exactly 1 comparison values (you provided 3).") + + fail(t, so(reader, ShouldNotImplement, "foo"), shouldCompareWithInterfacePointer) + fail(t, so(reader, ShouldNotImplement, 1), shouldCompareWithInterfacePointer) + fail(t, so(reader, ShouldNotImplement, nil), shouldCompareWithInterfacePointer) + + fail(t, so(reader, ShouldNotImplement, ioReader), "Expected '*bytes.Buffer'\nto NOT implement 'io.Reader' (but it did)!") + fail(t, so(nil, ShouldNotImplement, ioReader), shouldNotBeNilActual) + pass(t, so(1, ShouldNotImplement, ioReader)) + pass(t, so(response, ShouldNotImplement, ioReader)) + pass(t, so(responsePtr, ShouldNotImplement, ioReader)) +} diff --git a/vendor/github.com/smartystreets/assertions/utilities_for_test.go b/vendor/github.com/smartystreets/assertions/utilities_for_test.go new file mode 100644 index 0000000000..7243ebcb93 --- /dev/null +++ b/vendor/github.com/smartystreets/assertions/utilities_for_test.go @@ -0,0 +1,75 @@ +package assertions + +import ( + "fmt" + "path" + "runtime" + "strings" + "testing" +) + +func pass(t *testing.T, result string) { + if result != success { + _, file, line, _ := runtime.Caller(1) + base := path.Base(file) + t.Errorf("Expectation should have passed but failed (see %s: line %d): '%s'", base, line, result) + } +} + +func fail(t *testing.T, actual string, expected string) { + actual = format(actual) + expected = format(expected) + + if actual != expected { + if actual == "" { + actual = "(empty)" + } + _, file, line, _ := runtime.Caller(1) + base := path.Base(file) + t.Errorf("Expectation should have failed but passed (see %s: line %d). \nExpected: %s\nActual: %s\n", + base, line, expected, actual) + } +} +func format(message string) string { + message = strings.Replace(message, "\n", " ", -1) + for strings.Contains(message, " ") { + message = strings.Replace(message, " ", " ", -1) + } + return message +} + +type Thing1 struct { + a string +} +type Thing2 struct { + a string +} + +type Thinger interface { + Hi() +} + +type Thing struct{} + +func (self *Thing) Hi() {} + +type IntAlias int +type StringAlias string +type StringSliceAlias []string +type StringStringMapAlias map[string]string + +/******** FakeSerialzier ********/ + +type fakeSerializer struct{} + +func (self *fakeSerializer) serialize(expected, actual interface{}, message string) string { + return fmt.Sprintf("%v|%v|%s", expected, actual, message) +} + +func (self *fakeSerializer) serializeDetailed(expected, actual interface{}, message string) string { + return fmt.Sprintf("%v|%v|%s", expected, actual, message) +} + +func newFakeSerializer() *fakeSerializer { + return new(fakeSerializer) +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/assertions.go b/vendor/github.com/smartystreets/goconvey/convey/assertions.go new file mode 100644 index 0000000000..942c2d1ec1 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/assertions.go @@ -0,0 +1,67 @@ +package convey + +import "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions" + +var ( + ShouldEqual = assertions.ShouldEqual + ShouldNotEqual = assertions.ShouldNotEqual + ShouldAlmostEqual = assertions.ShouldAlmostEqual + ShouldNotAlmostEqual = assertions.ShouldNotAlmostEqual + ShouldResemble = assertions.ShouldResemble + ShouldNotResemble = assertions.ShouldNotResemble + ShouldPointTo = assertions.ShouldPointTo + ShouldNotPointTo = assertions.ShouldNotPointTo + ShouldBeNil = assertions.ShouldBeNil + ShouldNotBeNil = assertions.ShouldNotBeNil + ShouldBeTrue = assertions.ShouldBeTrue + ShouldBeFalse = assertions.ShouldBeFalse + ShouldBeZeroValue = assertions.ShouldBeZeroValue + + ShouldBeGreaterThan = assertions.ShouldBeGreaterThan + ShouldBeGreaterThanOrEqualTo = assertions.ShouldBeGreaterThanOrEqualTo + ShouldBeLessThan = assertions.ShouldBeLessThan + ShouldBeLessThanOrEqualTo = assertions.ShouldBeLessThanOrEqualTo + ShouldBeBetween = assertions.ShouldBeBetween + ShouldNotBeBetween = assertions.ShouldNotBeBetween + ShouldBeBetweenOrEqual = assertions.ShouldBeBetweenOrEqual + ShouldNotBeBetweenOrEqual = assertions.ShouldNotBeBetweenOrEqual + + ShouldContain = assertions.ShouldContain + ShouldNotContain = assertions.ShouldNotContain + ShouldContainKey = assertions.ShouldContainKey + ShouldNotContainKey = assertions.ShouldNotContainKey + ShouldBeIn = assertions.ShouldBeIn + ShouldNotBeIn = assertions.ShouldNotBeIn + ShouldBeEmpty = assertions.ShouldBeEmpty + ShouldNotBeEmpty = assertions.ShouldNotBeEmpty + + ShouldStartWith = assertions.ShouldStartWith + ShouldNotStartWith = assertions.ShouldNotStartWith + ShouldEndWith = assertions.ShouldEndWith + ShouldNotEndWith = assertions.ShouldNotEndWith + ShouldBeBlank = assertions.ShouldBeBlank + ShouldNotBeBlank = assertions.ShouldNotBeBlank + ShouldContainSubstring = assertions.ShouldContainSubstring + ShouldNotContainSubstring = assertions.ShouldNotContainSubstring + + ShouldPanic = assertions.ShouldPanic + ShouldNotPanic = assertions.ShouldNotPanic + ShouldPanicWith = assertions.ShouldPanicWith + ShouldNotPanicWith = assertions.ShouldNotPanicWith + + ShouldHaveSameTypeAs = assertions.ShouldHaveSameTypeAs + ShouldNotHaveSameTypeAs = assertions.ShouldNotHaveSameTypeAs + ShouldImplement = assertions.ShouldImplement + ShouldNotImplement = assertions.ShouldNotImplement + + ShouldHappenBefore = assertions.ShouldHappenBefore + ShouldHappenOnOrBefore = assertions.ShouldHappenOnOrBefore + ShouldHappenAfter = assertions.ShouldHappenAfter + ShouldHappenOnOrAfter = assertions.ShouldHappenOnOrAfter + ShouldHappenBetween = assertions.ShouldHappenBetween + ShouldHappenOnOrBetween = assertions.ShouldHappenOnOrBetween + ShouldNotHappenOnOrBetween = assertions.ShouldNotHappenOnOrBetween + ShouldHappenWithin = assertions.ShouldHappenWithin + ShouldNotHappenWithin = assertions.ShouldNotHappenWithin + ShouldBeChronological = assertions.ShouldBeChronological +) diff --git a/vendor/github.com/smartystreets/goconvey/convey/context.go b/vendor/github.com/smartystreets/goconvey/convey/context.go new file mode 100644 index 0000000000..f47da0f7e6 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/context.go @@ -0,0 +1,272 @@ +package convey + +import ( + "fmt" + + "github.com/scaleway/scaleway-cli/vendor/github.com/jtolds/gls" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +type conveyErr struct { + fmt string + params []interface{} +} + +func (e *conveyErr) Error() string { + return fmt.Sprintf(e.fmt, e.params...) +} + +func conveyPanic(fmt string, params ...interface{}) { + panic(&conveyErr{fmt, params}) +} + +const ( + missingGoTest = `Top-level calls to Convey(...) need a reference to the *testing.T. + Hint: Convey("description here", t, func() { /* notice that the second argument was the *testing.T (t)! */ }) ` + extraGoTest = `Only the top-level call to Convey(...) needs a reference to the *testing.T.` + noStackContext = "Convey operation made without context on goroutine stack.\n" + + "Hint: Perhaps you meant to use `Convey(..., func(c C){...})` ?" + differentConveySituations = "Different set of Convey statements on subsequent pass!\nDid not expect %#v." + multipleIdenticalConvey = "Multiple convey suites with identical names: %#v" +) + +const ( + failureHalt = "___FAILURE_HALT___" + + nodeKey = "node" +) + +///////////////////////////////// Stack Context ///////////////////////////////// + +func getCurrentContext() *context { + ctx, ok := ctxMgr.GetValue(nodeKey) + if ok { + return ctx.(*context) + } + return nil +} + +func mustGetCurrentContext() *context { + ctx := getCurrentContext() + if ctx == nil { + conveyPanic(noStackContext) + } + return ctx +} + +//////////////////////////////////// Context //////////////////////////////////// + +// context magically handles all coordination of Convey's and So assertions. +// +// It is tracked on the stack as goroutine-local-storage with the gls package, +// or explicitly if the user decides to call convey like: +// +// Convey(..., func(c C) { +// c.So(...) +// }) +// +// This implements the `C` interface. +type context struct { + reporter reporting.Reporter + + children map[string]*context + + resets []func() + + executedOnce bool + expectChildRun *bool + complete bool + + focus bool + failureMode FailureMode +} + +// rootConvey is the main entry point to a test suite. This is called when +// there's no context in the stack already, and items must contain a `t` object, +// or this panics. +func rootConvey(items ...interface{}) { + entry := discover(items) + + if entry.Test == nil { + conveyPanic(missingGoTest) + } + + expectChildRun := true + ctx := &context{ + reporter: buildReporter(), + + children: make(map[string]*context), + + expectChildRun: &expectChildRun, + + focus: entry.Focus, + failureMode: defaultFailureMode.combine(entry.FailMode), + } + ctxMgr.SetValues(gls.Values{nodeKey: ctx}, func() { + ctx.reporter.BeginStory(reporting.NewStoryReport(entry.Test)) + defer ctx.reporter.EndStory() + + for ctx.shouldVisit() { + ctx.conveyInner(entry.Situation, entry.Func) + expectChildRun = true + } + }) +} + +//////////////////////////////////// Methods //////////////////////////////////// + +func (ctx *context) SkipConvey(items ...interface{}) { + ctx.Convey(items, skipConvey) +} + +func (ctx *context) FocusConvey(items ...interface{}) { + ctx.Convey(items, focusConvey) +} + +func (ctx *context) Convey(items ...interface{}) { + entry := discover(items) + + // we're a branch, or leaf (on the wind) + if entry.Test != nil { + conveyPanic(extraGoTest) + } + if ctx.focus && !entry.Focus { + return + } + + var inner_ctx *context + if ctx.executedOnce { + var ok bool + inner_ctx, ok = ctx.children[entry.Situation] + if !ok { + conveyPanic(differentConveySituations, entry.Situation) + } + } else { + if _, ok := ctx.children[entry.Situation]; ok { + conveyPanic(multipleIdenticalConvey, entry.Situation) + } + inner_ctx = &context{ + reporter: ctx.reporter, + + children: make(map[string]*context), + + expectChildRun: ctx.expectChildRun, + + focus: entry.Focus, + failureMode: ctx.failureMode.combine(entry.FailMode), + } + ctx.children[entry.Situation] = inner_ctx + } + + if inner_ctx.shouldVisit() { + ctxMgr.SetValues(gls.Values{nodeKey: inner_ctx}, func() { + inner_ctx.conveyInner(entry.Situation, entry.Func) + }) + } +} + +func (ctx *context) SkipSo(stuff ...interface{}) { + ctx.assertionReport(reporting.NewSkipReport()) +} + +func (ctx *context) So(actual interface{}, assert assertion, expected ...interface{}) { + if result := assert(actual, expected...); result == assertionSuccess { + ctx.assertionReport(reporting.NewSuccessReport()) + } else { + ctx.assertionReport(reporting.NewFailureReport(result)) + } +} + +func (ctx *context) Reset(action func()) { + /* TODO: Failure mode configuration */ + ctx.resets = append(ctx.resets, action) +} + +func (ctx *context) Print(items ...interface{}) (int, error) { + fmt.Fprint(ctx.reporter, items...) + return fmt.Print(items...) +} + +func (ctx *context) Println(items ...interface{}) (int, error) { + fmt.Fprintln(ctx.reporter, items...) + return fmt.Println(items...) +} + +func (ctx *context) Printf(format string, items ...interface{}) (int, error) { + fmt.Fprintf(ctx.reporter, format, items...) + return fmt.Printf(format, items...) +} + +//////////////////////////////////// Private //////////////////////////////////// + +// shouldVisit returns true iff we should traverse down into a Convey. Note +// that just because we don't traverse a Convey this time, doesn't mean that +// we may not traverse it on a subsequent pass. +func (c *context) shouldVisit() bool { + return !c.complete && *c.expectChildRun +} + +// conveyInner is the function which actually executes the user's anonymous test +// function body. At this point, Convey or RootConvey has decided that this +// function should actually run. +func (ctx *context) conveyInner(situation string, f func(C)) { + // Record/Reset state for next time. + defer func() { + ctx.executedOnce = true + + // This is only needed at the leaves, but there's no harm in also setting it + // when returning from branch Convey's + *ctx.expectChildRun = false + }() + + // Set up+tear down our scope for the reporter + ctx.reporter.Enter(reporting.NewScopeReport(situation)) + defer ctx.reporter.Exit() + + // Recover from any panics in f, and assign the `complete` status for this + // node of the tree. + defer func() { + ctx.complete = true + if problem := recover(); problem != nil { + if problem, ok := problem.(*conveyErr); ok { + panic(problem) + } + if problem != failureHalt { + ctx.reporter.Report(reporting.NewErrorReport(problem)) + } + } else { + for _, child := range ctx.children { + if !child.complete { + ctx.complete = false + return + } + } + } + }() + + // Resets are registered as the `f` function executes, so nil them here. + // All resets are run in registration order (FIFO). + ctx.resets = []func(){} + defer func() { + for _, r := range ctx.resets { + // panics handled by the previous defer + r() + } + }() + + if f == nil { + // if f is nil, this was either a Convey(..., nil), or a SkipConvey + ctx.reporter.Report(reporting.NewSkipReport()) + } else { + f(ctx) + } +} + +// assertionReport is a helper for So and SkipSo which makes the report and +// then possibly panics, depending on the current context's failureMode. +func (ctx *context) assertionReport(r *reporting.AssertionResult) { + ctx.reporter.Report(r) + if r.Failure != "" && ctx.failureMode == FailureHalts { + panic(failureHalt) + } +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/convey.goconvey b/vendor/github.com/smartystreets/goconvey/convey/convey.goconvey new file mode 100644 index 0000000000..a2d9327dc9 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/convey.goconvey @@ -0,0 +1,4 @@ +#ignore +-timeout=1s +#-covermode=count +#-coverpkg=github.com/smartystreets/goconvey/convey,github.com/smartystreets/goconvey/convey/gotest,github.com/smartystreets/goconvey/convey/reporting \ No newline at end of file diff --git a/vendor/github.com/smartystreets/goconvey/convey/discovery.go b/vendor/github.com/smartystreets/goconvey/convey/discovery.go new file mode 100644 index 0000000000..eb8d4cb2ce --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/discovery.go @@ -0,0 +1,103 @@ +package convey + +type actionSpecifier uint8 + +const ( + noSpecifier actionSpecifier = iota + skipConvey + focusConvey +) + +type suite struct { + Situation string + Test t + Focus bool + Func func(C) // nil means skipped + FailMode FailureMode +} + +func newSuite(situation string, failureMode FailureMode, f func(C), test t, specifier actionSpecifier) *suite { + ret := &suite{ + Situation: situation, + Test: test, + Func: f, + FailMode: failureMode, + } + switch specifier { + case skipConvey: + ret.Func = nil + case focusConvey: + ret.Focus = true + } + return ret +} + +func discover(items []interface{}) *suite { + name, items := parseName(items) + test, items := parseGoTest(items) + failure, items := parseFailureMode(items) + action, items := parseAction(items) + specifier, items := parseSpecifier(items) + + if len(items) != 0 { + conveyPanic(parseError) + } + + return newSuite(name, failure, action, test, specifier) +} +func item(items []interface{}) interface{} { + if len(items) == 0 { + conveyPanic(parseError) + } + return items[0] +} +func parseName(items []interface{}) (string, []interface{}) { + if name, parsed := item(items).(string); parsed { + return name, items[1:] + } + conveyPanic(parseError) + panic("never get here") +} +func parseGoTest(items []interface{}) (t, []interface{}) { + if test, parsed := item(items).(t); parsed { + return test, items[1:] + } + return nil, items +} +func parseFailureMode(items []interface{}) (FailureMode, []interface{}) { + if mode, parsed := item(items).(FailureMode); parsed { + return mode, items[1:] + } + return FailureInherits, items +} +func parseAction(items []interface{}) (func(C), []interface{}) { + switch x := item(items).(type) { + case nil: + return nil, items[1:] + case func(C): + return x, items[1:] + case func(): + return func(C) { x() }, items[1:] + } + conveyPanic(parseError) + panic("never get here") +} +func parseSpecifier(items []interface{}) (actionSpecifier, []interface{}) { + if len(items) == 0 { + return noSpecifier, items + } + if spec, ok := items[0].(actionSpecifier); ok { + return spec, items[1:] + } + conveyPanic(parseError) + panic("never get here") +} + +// This interface allows us to pass the *testing.T struct +// throughout the internals of this package without ever +// having to import the "testing" package. +type t interface { + Fail() +} + +const parseError = "You must provide a name (string), then a *testing.T (if in outermost scope), an optional FailureMode, and then an action (func())." diff --git a/vendor/github.com/smartystreets/goconvey/convey/doc.go b/vendor/github.com/smartystreets/goconvey/convey/doc.go new file mode 100644 index 0000000000..7066bdbd4f --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/doc.go @@ -0,0 +1,218 @@ +// Package convey contains all of the public-facing entry points to this project. +// This means that it should never be required of the user to import any other +// packages from this project as they serve internal purposes. +package convey + +import "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" + +////////////////////////////////// suite ////////////////////////////////// + +// C is the Convey context which you can optionally obtain in your action +// by calling Convey like: +// +// Convey(..., func(c C) { +// ... +// }) +// +// See the documentation on Convey for more details. +// +// All methods in this context behave identically to the global functions of the +// same name in this package. +type C interface { + Convey(items ...interface{}) + SkipConvey(items ...interface{}) + FocusConvey(items ...interface{}) + + So(actual interface{}, assert assertion, expected ...interface{}) + SkipSo(stuff ...interface{}) + + Reset(action func()) + + Println(items ...interface{}) (int, error) + Print(items ...interface{}) (int, error) + Printf(format string, items ...interface{}) (int, error) +} + +// Convey is the method intended for use when declaring the scopes of +// a specification. Each scope has a description and a func() which may contain +// other calls to Convey(), Reset() or Should-style assertions. Convey calls can +// be nested as far as you see fit. +// +// IMPORTANT NOTE: The top-level Convey() within a Test method +// must conform to the following signature: +// +// Convey(description string, t *testing.T, action func()) +// +// All other calls should look like this (no need to pass in *testing.T): +// +// Convey(description string, action func()) +// +// Don't worry, goconvey will panic if you get it wrong so you can fix it. +// +// Additionally, you may explicitly obtain access to the Convey context by doing: +// +// Convey(description string, action func(c C)) +// +// You may need to do this if you want to pass the context through to a +// goroutine, or to close over the context in a handler to a library which +// calls your handler in a goroutine (httptest comes to mind). +// +// All Convey()-blocks also accept an optional parameter of FailureMode which sets +// how goconvey should treat failures for So()-assertions in the block and +// nested blocks. See the constants in this file for the available options. +// +// By default it will inherit from its parent block and the top-level blocks +// default to the FailureHalts setting. +// +// This parameter is inserted before the block itself: +// +// Convey(description string, t *testing.T, mode FailureMode, action func()) +// Convey(description string, mode FailureMode, action func()) +// +// See the examples package for, well, examples. +func Convey(items ...interface{}) { + if ctx := getCurrentContext(); ctx == nil { + rootConvey(items...) + } else { + ctx.Convey(items...) + } +} + +// SkipConvey is analagous to Convey except that the scope is not executed +// (which means that child scopes defined within this scope are not run either). +// The reporter will be notified that this step was skipped. +func SkipConvey(items ...interface{}) { + Convey(append(items, skipConvey)...) +} + +// FocusConvey is has the inverse effect of SkipConvey. If the top-level +// Convey is changed to `FocusConvey`, only nested scopes that are defined +// with FocusConvey will be run. The rest will be ignored completely. This +// is handy when debugging a large suite that runs a misbehaving function +// repeatedly as you can disable all but one of that function +// without swaths of `SkipConvey` calls, just a targeted chain of calls +// to FocusConvey. +func FocusConvey(items ...interface{}) { + Convey(append(items, focusConvey)...) +} + +// Reset registers a cleanup function to be run after each Convey() +// in the same scope. See the examples package for a simple use case. +func Reset(action func()) { + mustGetCurrentContext().Reset(action) +} + +/////////////////////////////////// Assertions /////////////////////////////////// + +// assertion is an alias for a function with a signature that the convey.So() +// method can handle. Any future or custom assertions should conform to this +// method signature. The return value should be an empty string if the assertion +// passes and a well-formed failure message if not. +type assertion func(actual interface{}, expected ...interface{}) string + +const assertionSuccess = "" + +// So is the means by which assertions are made against the system under test. +// The majority of exported names in the assertions package begin with the word +// 'Should' and describe how the first argument (actual) should compare with any +// of the final (expected) arguments. How many final arguments are accepted +// depends on the particular assertion that is passed in as the assert argument. +// See the examples package for use cases and the assertions package for +// documentation on specific assertion methods. A failing assertion will +// cause t.Fail() to be invoked--you should never call this method (or other +// failure-inducing methods) in your test code. Leave that to GoConvey. +func So(actual interface{}, assert assertion, expected ...interface{}) { + mustGetCurrentContext().So(actual, assert, expected...) +} + +// SkipSo is analagous to So except that the assertion that would have been passed +// to So is not executed and the reporter is notified that the assertion was skipped. +func SkipSo(stuff ...interface{}) { + mustGetCurrentContext().SkipSo() +} + +// FailureMode is a type which determines how the So() blocks should fail +// if their assertion fails. See constants further down for acceptable values +type FailureMode string + +const ( + + // FailureContinues is a failure mode which prevents failing + // So()-assertions from halting Convey-block execution, instead + // allowing the test to continue past failing So()-assertions. + FailureContinues FailureMode = "continue" + + // FailureHalts is the default setting for a top-level Convey()-block + // and will cause all failing So()-assertions to halt further execution + // in that test-arm and continue on to the next arm. + FailureHalts FailureMode = "halt" + + // FailureInherits is the default setting for failure-mode, it will + // default to the failure-mode of the parent block. You should never + // need to specify this mode in your tests.. + FailureInherits FailureMode = "inherits" +) + +func (f FailureMode) combine(other FailureMode) FailureMode { + if other == FailureInherits { + return f + } + return other +} + +var defaultFailureMode FailureMode = FailureHalts + +// SetDefaultFailureMode allows you to specify the default failure mode +// for all Convey blocks. It is meant to be used in an init function to +// allow the default mode to be changdd across all tests for an entire packgae +// but it can be used anywhere. +func SetDefaultFailureMode(mode FailureMode) { + if mode == FailureContinues || mode == FailureHalts { + defaultFailureMode = mode + } else { + panic("You may only use the constants named 'FailureContinues' and 'FailureHalts' as default failure modes.") + } +} + +//////////////////////////////////// Print functions //////////////////////////////////// + +// Print is analogous to fmt.Print (and it even calls fmt.Print). It ensures that +// output is aligned with the corresponding scopes in the web UI. +func Print(items ...interface{}) (written int, err error) { + return mustGetCurrentContext().Print(items...) +} + +// Print is analogous to fmt.Println (and it even calls fmt.Println). It ensures that +// output is aligned with the corresponding scopes in the web UI. +func Println(items ...interface{}) (written int, err error) { + return mustGetCurrentContext().Println(items...) +} + +// Print is analogous to fmt.Printf (and it even calls fmt.Printf). It ensures that +// output is aligned with the corresponding scopes in the web UI. +func Printf(format string, items ...interface{}) (written int, err error) { + return mustGetCurrentContext().Printf(format, items...) +} + +/////////////////////////////////////////////////////////////////////////////// + +// SuppressConsoleStatistics prevents automatic printing of console statistics. +// Calling PrintConsoleStatistics explicitly will force printing of statistics. +func SuppressConsoleStatistics() { + reporting.SuppressConsoleStatistics() +} + +// ConsoleStatistics may be called at any time to print assertion statistics. +// Generally, the best place to do this would be in a TestMain function, +// after all tests have been run. Something like this: +// +// func TestMain(m *testing.M) { +// convey.SuppressConsoleStatistics() +// result := m.Run() +// convey.PrintConsoleStatistics() +// os.Exit(result) +// } +// +func PrintConsoleStatistics() { + reporting.PrintConsoleStatistics() +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/focused_execution_test.go b/vendor/github.com/smartystreets/goconvey/convey/focused_execution_test.go new file mode 100644 index 0000000000..294e32fa17 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/focused_execution_test.go @@ -0,0 +1,72 @@ +package convey + +import "testing" + +func TestFocusOnlyAtTopLevel(t *testing.T) { + output := prepare() + + FocusConvey("hi", t, func() { + output += "done" + }) + + expectEqual(t, "done", output) +} + +func TestFocus(t *testing.T) { + output := prepare() + + FocusConvey("hi", t, func() { + output += "1" + + Convey("bye", func() { + output += "2" + }) + }) + + expectEqual(t, "1", output) +} + +func TestNestedFocus(t *testing.T) { + output := prepare() + + FocusConvey("hi", t, func() { + output += "1" + + Convey("This shouldn't run", func() { + output += "boink!" + }) + + FocusConvey("This should run", func() { + output += "2" + + FocusConvey("The should run too", func() { + output += "3" + + }) + + Convey("The should NOT run", func() { + output += "blah blah blah!" + }) + }) + }) + + expectEqual(t, "123", output) +} + +func TestForgotTopLevelFocus(t *testing.T) { + output := prepare() + + Convey("1", t, func() { + output += "1" + + FocusConvey("This will be run because the top-level lacks Focus", func() { + output += "2" + }) + + Convey("3", func() { + output += "3" + }) + }) + + expectEqual(t, "1213", output) +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/gotest/doc_test.go b/vendor/github.com/smartystreets/goconvey/convey/gotest/doc_test.go new file mode 100644 index 0000000000..1b6406be99 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/gotest/doc_test.go @@ -0,0 +1 @@ +package gotest diff --git a/vendor/github.com/smartystreets/goconvey/convey/gotest/utils.go b/vendor/github.com/smartystreets/goconvey/convey/gotest/utils.go new file mode 100644 index 0000000000..2855761fab --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/gotest/utils.go @@ -0,0 +1,37 @@ +// Package gotest contains internal functionality. Although this package +// contains one or more exported names it is not intended for public +// consumption. See the examples package for how to use this project. +package gotest + +import ( + "fmt" + "runtime" + "strings" +) + +func FormatExternalFileAndLine() string { + file, line, _ := ResolveExternalCaller() + if line == -1 { + return "" // panic? + } + return fmt.Sprintf("%s:%d", file, line) +} + +func ResolveExternalCaller() (file string, line int, name string) { + var caller_id uintptr + callers := runtime.Callers(0, callStack) + + for x := 0; x < callers; x++ { + caller_id, file, line, _ = runtime.Caller(x) + if strings.HasSuffix(file, "_test.go") || strings.HasSuffix(file, "_tests.go") { + name = runtime.FuncForPC(caller_id).Name() + return + } + } + file, line, name = "", -1, "" + return // panic? +} + +const maxStackDepth = 100 // This had better be enough... + +var callStack []uintptr = make([]uintptr, maxStackDepth, maxStackDepth) diff --git a/vendor/github.com/smartystreets/goconvey/convey/init.go b/vendor/github.com/smartystreets/goconvey/convey/init.go new file mode 100644 index 0000000000..1afb61de90 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/init.go @@ -0,0 +1,76 @@ +package convey + +import ( + "flag" + "os" + + "github.com/scaleway/scaleway-cli/vendor/github.com/jtolds/gls" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/assertions" + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +func init() { + assertions.GoConveyMode(true) + + declareFlags() + + ctxMgr = gls.NewContextManager() +} + +func declareFlags() { + flag.BoolVar(&json, "json", false, "When true, emits results in JSON blocks. Default: 'false'") + flag.BoolVar(&silent, "silent", false, "When true, all output from GoConvey is suppressed.") + flag.BoolVar(&story, "story", false, "When true, emits story output, otherwise emits dot output. When not provided, this flag mirros the value of the '-test.v' flag") + + if noStoryFlagProvided() { + story = verboseEnabled + } + + // FYI: flag.Parse() is called from the testing package. +} + +func noStoryFlagProvided() bool { + return !story && !storyDisabled +} + +func buildReporter() reporting.Reporter { + switch { + case testReporter != nil: + return testReporter + case json: + return reporting.BuildJsonReporter() + case silent: + return reporting.BuildSilentReporter() + case story: + return reporting.BuildStoryReporter() + default: + return reporting.BuildDotReporter() + } +} + +var ( + ctxMgr *gls.ContextManager + + // only set by internal tests + testReporter reporting.Reporter +) + +var ( + json bool + silent bool + story bool + + verboseEnabled = flagFound("-test.v=true") + storyDisabled = flagFound("-story=false") +) + +// flagFound parses the command line args manually for flags defined in other +// packages. Like the '-v' flag from the "testing" package, for instance. +func flagFound(flagValue string) bool { + for _, arg := range os.Args { + if arg == flagValue { + return true + } + } + return false +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/isolated_execution_test.go b/vendor/github.com/smartystreets/goconvey/convey/isolated_execution_test.go new file mode 100644 index 0000000000..7e22b3caa5 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/isolated_execution_test.go @@ -0,0 +1,774 @@ +package convey + +import ( + "strconv" + "testing" + "time" +) + +func TestSingleScope(t *testing.T) { + output := prepare() + + Convey("hi", t, func() { + output += "done" + }) + + expectEqual(t, "done", output) +} + +func TestSingleScopeWithMultipleConveys(t *testing.T) { + output := prepare() + + Convey("1", t, func() { + output += "1" + }) + + Convey("2", t, func() { + output += "2" + }) + + expectEqual(t, "12", output) +} + +func TestNestedScopes(t *testing.T) { + output := prepare() + + Convey("a", t, func() { + output += "a " + + Convey("bb", func() { + output += "bb " + + Convey("ccc", func() { + output += "ccc | " + }) + }) + }) + + expectEqual(t, "a bb ccc | ", output) +} + +func TestNestedScopesWithIsolatedExecution(t *testing.T) { + output := prepare() + + Convey("a", t, func() { + output += "a " + + Convey("aa", func() { + output += "aa " + + Convey("aaa", func() { + output += "aaa | " + }) + + Convey("aaa1", func() { + output += "aaa1 | " + }) + }) + + Convey("ab", func() { + output += "ab " + + Convey("abb", func() { + output += "abb | " + }) + }) + }) + + expectEqual(t, "a aa aaa | a aa aaa1 | a ab abb | ", output) +} + +func TestSingleScopeWithConveyAndNestedReset(t *testing.T) { + output := prepare() + + Convey("1", t, func() { + output += "1" + + Reset(func() { + output += "a" + }) + }) + + expectEqual(t, "1a", output) +} + +func TestPanicingReset(t *testing.T) { + output := prepare() + + Convey("1", t, func() { + output += "1" + + Reset(func() { + panic("nooo") + }) + + Convey("runs since the reset hasn't yet", func() { + output += "a" + }) + + Convey("but this doesnt", func() { + output += "nope" + }) + }) + + expectEqual(t, "1a", output) +} + +func TestSingleScopeWithMultipleRegistrationsAndReset(t *testing.T) { + output := prepare() + + Convey("reset after each nested convey", t, func() { + Convey("first output", func() { + output += "1" + }) + + Convey("second output", func() { + output += "2" + }) + + Reset(func() { + output += "a" + }) + }) + + expectEqual(t, "1a2a", output) +} + +func TestSingleScopeWithMultipleRegistrationsAndMultipleResets(t *testing.T) { + output := prepare() + + Convey("each reset is run at end of each nested convey", t, func() { + Convey("1", func() { + output += "1" + }) + + Convey("2", func() { + output += "2" + }) + + Reset(func() { + output += "a" + }) + + Reset(func() { + output += "b" + }) + }) + + expectEqual(t, "1ab2ab", output) +} + +func Test_Failure_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) { + output := prepare() + + Convey("This step fails", t, func() { + So(1, ShouldEqual, 2) + + Convey("this should NOT be executed", func() { + output += "a" + }) + }) + + expectEqual(t, "", output) +} + +func Test_Panic_AtHigherLevelScopePreventsChildScopesFromRunning(t *testing.T) { + output := prepare() + + Convey("This step panics", t, func() { + Convey("this happens, because the panic didn't happen yet", func() { + output += "1" + }) + + output += "a" + + Convey("this should NOT be executed", func() { + output += "2" + }) + + output += "b" + + panic("Hi") + + output += "nope" + }) + + expectEqual(t, "1ab", output) +} + +func Test_Panic_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) { + output := prepare() + + Convey("This is the parent", t, func() { + Convey("This step panics", func() { + panic("Hi") + output += "1" + }) + + Convey("This sibling should execute", func() { + output += "2" + }) + }) + + expectEqual(t, "2", output) +} + +func Test_Failure_InChildScopeDoes_NOT_PreventExecutionOfSiblingScopes(t *testing.T) { + output := prepare() + + Convey("This is the parent", t, func() { + Convey("This step fails", func() { + So(1, ShouldEqual, 2) + output += "1" + }) + + Convey("This sibling should execute", func() { + output += "2" + }) + }) + + expectEqual(t, "2", output) +} + +func TestResetsAreAlwaysExecutedAfterScope_Panics(t *testing.T) { + output := prepare() + + Convey("This is the parent", t, func() { + Convey("This step panics", func() { + panic("Hi") + output += "1" + }) + + Convey("This sibling step does not panic", func() { + output += "a" + + Reset(func() { + output += "b" + }) + }) + + Reset(func() { + output += "2" + }) + }) + + expectEqual(t, "2ab2", output) +} + +func TestResetsAreAlwaysExecutedAfterScope_Failures(t *testing.T) { + output := prepare() + + Convey("This is the parent", t, func() { + Convey("This step fails", func() { + So(1, ShouldEqual, 2) + output += "1" + }) + + Convey("This sibling step does not fail", func() { + output += "a" + + Reset(func() { + output += "b" + }) + }) + + Reset(func() { + output += "2" + }) + }) + + expectEqual(t, "2ab2", output) +} + +func TestSkipTopLevel(t *testing.T) { + output := prepare() + + SkipConvey("hi", t, func() { + output += "This shouldn't be executed!" + }) + + expectEqual(t, "", output) +} + +func TestSkipNestedLevel(t *testing.T) { + output := prepare() + + Convey("hi", t, func() { + output += "yes" + + SkipConvey("bye", func() { + output += "no" + }) + }) + + expectEqual(t, "yes", output) +} + +func TestSkipNestedLevelSkipsAllChildLevels(t *testing.T) { + output := prepare() + + Convey("hi", t, func() { + output += "yes" + + SkipConvey("bye", func() { + output += "no" + + Convey("byebye", func() { + output += "no-no" + }) + }) + }) + + expectEqual(t, "yes", output) +} + +func TestIterativeConveys(t *testing.T) { + output := prepare() + + Convey("Test", t, func() { + for x := 0; x < 10; x++ { + y := strconv.Itoa(x) + + Convey(y, func() { + output += y + }) + } + }) + + expectEqual(t, "0123456789", output) +} + +func TestClosureVariables(t *testing.T) { + output := prepare() + + i := 0 + + Convey("A", t, func() { + i = i + 1 + j := i + + output += "A" + strconv.Itoa(i) + " " + + Convey("B", func() { + k := j + j = j + 1 + + output += "B" + strconv.Itoa(k) + " " + + Convey("C", func() { + output += "C" + strconv.Itoa(k) + strconv.Itoa(j) + " " + }) + + Convey("D", func() { + output += "D" + strconv.Itoa(k) + strconv.Itoa(j) + " " + }) + }) + + Convey("C", func() { + output += "C" + strconv.Itoa(j) + " " + }) + }) + + output += "D" + strconv.Itoa(i) + " " + + expectEqual(t, "A1 B1 C12 A2 B2 D23 A3 C3 D3 ", output) +} + +func TestClosureVariablesWithReset(t *testing.T) { + output := prepare() + + i := 0 + + Convey("A", t, func() { + i = i + 1 + j := i + + output += "A" + strconv.Itoa(i) + " " + + Reset(func() { + output += "R" + strconv.Itoa(i) + strconv.Itoa(j) + " " + }) + + Convey("B", func() { + output += "B" + strconv.Itoa(j) + " " + }) + + Convey("C", func() { + output += "C" + strconv.Itoa(j) + " " + }) + }) + + output += "D" + strconv.Itoa(i) + " " + + expectEqual(t, "A1 B1 R11 A2 C2 R22 D2 ", output) +} + +func TestWrappedSimple(t *testing.T) { + prepare() + output := resetTestString{""} + + Convey("A", t, func() { + func() { + output.output += "A " + + Convey("B", func() { + output.output += "B " + + Convey("C", func() { + output.output += "C " + }) + + }) + + Convey("D", func() { + output.output += "D " + }) + }() + }) + + expectEqual(t, "A B C A D ", output.output) +} + +type resetTestString struct { + output string +} + +func addReset(o *resetTestString, f func()) func() { + return func() { + Reset(func() { + o.output += "R " + }) + + f() + } +} + +func TestWrappedReset(t *testing.T) { + prepare() + output := resetTestString{""} + + Convey("A", t, addReset(&output, func() { + output.output += "A " + + Convey("B", func() { + output.output += "B " + }) + + Convey("C", func() { + output.output += "C " + }) + })) + + expectEqual(t, "A B R A C R ", output.output) +} + +func TestWrappedReset2(t *testing.T) { + prepare() + output := resetTestString{""} + + Convey("A", t, func() { + Reset(func() { + output.output += "R " + }) + + func() { + output.output += "A " + + Convey("B", func() { + output.output += "B " + + Convey("C", func() { + output.output += "C " + }) + }) + + Convey("D", func() { + output.output += "D " + }) + }() + }) + + expectEqual(t, "A B C R A D R ", output.output) +} + +func TestInfiniteLoopWithTrailingFail(t *testing.T) { + done := make(chan int) + + go func() { + Convey("This fails", t, func() { + Convey("and this is run", func() { + So(true, ShouldEqual, true) + }) + + /* And this prevents the whole block to be marked as run */ + So(false, ShouldEqual, true) + }) + + done <- 1 + }() + + select { + case <-done: + return + case <-time.After(1 * time.Millisecond): + t.Fail() + } +} + +func TestOutermostResetInvokedForGrandchildren(t *testing.T) { + output := prepare() + + Convey("A", t, func() { + output += "A " + + Reset(func() { + output += "rA " + }) + + Convey("B", func() { + output += "B " + + Reset(func() { + output += "rB " + }) + + Convey("C", func() { + output += "C " + + Reset(func() { + output += "rC " + }) + }) + + Convey("D", func() { + output += "D " + + Reset(func() { + output += "rD " + }) + }) + }) + }) + + expectEqual(t, "A B C rC rB rA A B D rD rB rA ", output) +} + +func TestFailureOption(t *testing.T) { + output := prepare() + + Convey("A", t, FailureHalts, func() { + output += "A " + So(true, ShouldEqual, true) + output += "B " + So(false, ShouldEqual, true) + output += "C " + }) + + expectEqual(t, "A B ", output) +} + +func TestFailureOption2(t *testing.T) { + output := prepare() + + Convey("A", t, func() { + output += "A " + So(true, ShouldEqual, true) + output += "B " + So(false, ShouldEqual, true) + output += "C " + }) + + expectEqual(t, "A B ", output) +} + +func TestFailureOption3(t *testing.T) { + output := prepare() + + Convey("A", t, FailureContinues, func() { + output += "A " + So(true, ShouldEqual, true) + output += "B " + So(false, ShouldEqual, true) + output += "C " + }) + + expectEqual(t, "A B C ", output) +} + +func TestFailureOptionInherit(t *testing.T) { + output := prepare() + + Convey("A", t, FailureContinues, func() { + output += "A1 " + So(false, ShouldEqual, true) + output += "A2 " + + Convey("B", func() { + output += "B1 " + So(true, ShouldEqual, true) + output += "B2 " + So(false, ShouldEqual, true) + output += "B3 " + }) + }) + + expectEqual(t, "A1 A2 B1 B2 B3 ", output) +} + +func TestFailureOptionInherit2(t *testing.T) { + output := prepare() + + Convey("A", t, FailureHalts, func() { + output += "A1 " + So(false, ShouldEqual, true) + output += "A2 " + + Convey("B", func() { + output += "A1 " + So(true, ShouldEqual, true) + output += "A2 " + So(false, ShouldEqual, true) + output += "A3 " + }) + }) + + expectEqual(t, "A1 ", output) +} + +func TestFailureOptionInherit3(t *testing.T) { + output := prepare() + + Convey("A", t, FailureHalts, func() { + output += "A1 " + So(true, ShouldEqual, true) + output += "A2 " + + Convey("B", func() { + output += "B1 " + So(true, ShouldEqual, true) + output += "B2 " + So(false, ShouldEqual, true) + output += "B3 " + }) + }) + + expectEqual(t, "A1 A2 B1 B2 ", output) +} + +func TestFailureOptionNestedOverride(t *testing.T) { + output := prepare() + + Convey("A", t, FailureContinues, func() { + output += "A " + So(false, ShouldEqual, true) + output += "B " + + Convey("C", FailureHalts, func() { + output += "C " + So(true, ShouldEqual, true) + output += "D " + So(false, ShouldEqual, true) + output += "E " + }) + }) + + expectEqual(t, "A B C D ", output) +} + +func TestFailureOptionNestedOverride2(t *testing.T) { + output := prepare() + + Convey("A", t, FailureHalts, func() { + output += "A " + So(true, ShouldEqual, true) + output += "B " + + Convey("C", FailureContinues, func() { + output += "C " + So(true, ShouldEqual, true) + output += "D " + So(false, ShouldEqual, true) + output += "E " + }) + }) + + expectEqual(t, "A B C D E ", output) +} + +func TestMultipleInvocationInheritance(t *testing.T) { + output := prepare() + + Convey("A", t, FailureHalts, func() { + output += "A1 " + So(true, ShouldEqual, true) + output += "A2 " + + Convey("B", FailureContinues, func() { + output += "B1 " + So(true, ShouldEqual, true) + output += "B2 " + So(false, ShouldEqual, true) + output += "B3 " + }) + + Convey("C", func() { + output += "C1 " + So(true, ShouldEqual, true) + output += "C2 " + So(false, ShouldEqual, true) + output += "C3 " + }) + }) + + expectEqual(t, "A1 A2 B1 B2 B3 A1 A2 C1 C2 ", output) +} + +func TestMultipleInvocationInheritance2(t *testing.T) { + output := prepare() + + Convey("A", t, FailureContinues, func() { + output += "A1 " + So(true, ShouldEqual, true) + output += "A2 " + So(false, ShouldEqual, true) + output += "A3 " + + Convey("B", FailureHalts, func() { + output += "B1 " + So(true, ShouldEqual, true) + output += "B2 " + So(false, ShouldEqual, true) + output += "B3 " + }) + + Convey("C", func() { + output += "C1 " + So(true, ShouldEqual, true) + output += "C2 " + So(false, ShouldEqual, true) + output += "C3 " + }) + }) + + expectEqual(t, "A1 A2 A3 B1 B2 A1 A2 A3 C1 C2 C3 ", output) +} + +func TestSetDefaultFailureMode(t *testing.T) { + output := prepare() + + SetDefaultFailureMode(FailureContinues) // the default is normally FailureHalts + defer SetDefaultFailureMode(FailureHalts) + + Convey("A", t, func() { + output += "A1 " + So(true, ShouldBeFalse) + output += "A2 " + }) + + expectEqual(t, "A1 A2 ", output) +} + +func prepare() string { + testReporter = newNilReporter() + return "" +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/nilReporter.go b/vendor/github.com/smartystreets/goconvey/convey/nilReporter.go new file mode 100644 index 0000000000..c8c991127b --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/nilReporter.go @@ -0,0 +1,15 @@ +package convey + +import ( + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +type nilReporter struct{} + +func (self *nilReporter) BeginStory(story *reporting.StoryReport) {} +func (self *nilReporter) Enter(scope *reporting.ScopeReport) {} +func (self *nilReporter) Report(report *reporting.AssertionResult) {} +func (self *nilReporter) Exit() {} +func (self *nilReporter) EndStory() {} +func (self *nilReporter) Write(p []byte) (int, error) { return len(p), nil } +func newNilReporter() *nilReporter { return &nilReporter{} } diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go new file mode 100644 index 0000000000..7bf67dbb2b --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go @@ -0,0 +1,16 @@ +package reporting + +import ( + "fmt" + "io" +) + +type console struct{} + +func (self *console) Write(p []byte) (n int, err error) { + return fmt.Print(string(p)) +} + +func NewConsole() io.Writer { + return new(console) +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go new file mode 100644 index 0000000000..a37d001946 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go @@ -0,0 +1,5 @@ +// Package reporting contains internal functionality related +// to console reporting and output. Although this package has +// exported names is not intended for public consumption. See the +// examples package for how to use this project. +package reporting diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go new file mode 100644 index 0000000000..47d57c6b0d --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go @@ -0,0 +1,40 @@ +package reporting + +import "fmt" + +type dot struct{ out *Printer } + +func (self *dot) BeginStory(story *StoryReport) {} + +func (self *dot) Enter(scope *ScopeReport) {} + +func (self *dot) Report(report *AssertionResult) { + if report.Error != nil { + fmt.Print(redColor) + self.out.Insert(dotError) + } else if report.Failure != "" { + fmt.Print(yellowColor) + self.out.Insert(dotFailure) + } else if report.Skipped { + fmt.Print(yellowColor) + self.out.Insert(dotSkip) + } else { + fmt.Print(greenColor) + self.out.Insert(dotSuccess) + } + fmt.Print(resetColor) +} + +func (self *dot) Exit() {} + +func (self *dot) EndStory() {} + +func (self *dot) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewDotReporter(out *Printer) *dot { + self := new(dot) + self.out = out + return self +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/dot_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot_test.go new file mode 100644 index 0000000000..a8d20d46f0 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot_test.go @@ -0,0 +1,40 @@ +package reporting + +import ( + "errors" + "testing" +) + +func TestDotReporterAssertionPrinting(t *testing.T) { + monochrome() + file := newMemoryFile() + printer := NewPrinter(file) + reporter := NewDotReporter(printer) + + reporter.Report(NewSuccessReport()) + reporter.Report(NewFailureReport("failed")) + reporter.Report(NewErrorReport(errors.New("error"))) + reporter.Report(NewSkipReport()) + + expected := dotSuccess + dotFailure + dotError + dotSkip + + if file.buffer != expected { + t.Errorf("\nExpected: '%s'\nActual: '%s'", expected, file.buffer) + } +} + +func TestDotReporterOnlyReportsAssertions(t *testing.T) { + monochrome() + file := newMemoryFile() + printer := NewPrinter(file) + reporter := NewDotReporter(printer) + + reporter.BeginStory(nil) + reporter.Enter(nil) + reporter.Exit() + reporter.EndStory() + + if file.buffer != "" { + t.Errorf("\nExpected: '(blank)'\nActual: '%s'", file.buffer) + } +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go new file mode 100644 index 0000000000..c396e16b17 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go @@ -0,0 +1,33 @@ +package reporting + +type gotestReporter struct{ test T } + +func (self *gotestReporter) BeginStory(story *StoryReport) { + self.test = story.Test +} + +func (self *gotestReporter) Enter(scope *ScopeReport) {} + +func (self *gotestReporter) Report(r *AssertionResult) { + if !passed(r) { + self.test.Fail() + } +} + +func (self *gotestReporter) Exit() {} + +func (self *gotestReporter) EndStory() { + self.test = nil +} + +func (self *gotestReporter) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewGoTestReporter() *gotestReporter { + return new(gotestReporter) +} + +func passed(r *AssertionResult) bool { + return r.Error == nil && r.Failure == "" +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go new file mode 100644 index 0000000000..fda189458e --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest_test.go @@ -0,0 +1,66 @@ +package reporting + +import "testing" + +func TestReporterReceivesSuccessfulReport(t *testing.T) { + reporter := NewGoTestReporter() + test := new(fakeTest) + reporter.BeginStory(NewStoryReport(test)) + reporter.Report(NewSuccessReport()) + + if test.failed { + t.Errorf("Should have have marked test as failed--the report reflected success.") + } +} + +func TestReporterReceivesFailureReport(t *testing.T) { + reporter := NewGoTestReporter() + test := new(fakeTest) + reporter.BeginStory(NewStoryReport(test)) + reporter.Report(NewFailureReport("This is a failure.")) + + if !test.failed { + t.Errorf("Test should have been marked as failed (but it wasn't).") + } +} + +func TestReporterReceivesErrorReport(t *testing.T) { + reporter := NewGoTestReporter() + test := new(fakeTest) + reporter.BeginStory(NewStoryReport(test)) + reporter.Report(NewErrorReport("This is an error.")) + + if !test.failed { + t.Errorf("Test should have been marked as failed (but it wasn't).") + } +} + +func TestReporterIsResetAtTheEndOfTheStory(t *testing.T) { + defer catch(t) + reporter := NewGoTestReporter() + test := new(fakeTest) + reporter.BeginStory(NewStoryReport(test)) + reporter.EndStory() + + reporter.Report(NewSuccessReport()) +} + +func TestReporterNoopMethods(t *testing.T) { + reporter := NewGoTestReporter() + reporter.Enter(NewScopeReport("title")) + reporter.Exit() +} + +func catch(t *testing.T) { + if r := recover(); r != nil { + t.Log("Getting to this point means we've passed (because we caught a panic appropriately).") + } +} + +type fakeTest struct { + failed bool +} + +func (self *fakeTest) Fail() { + self.failed = true +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go new file mode 100644 index 0000000000..44a133259f --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go @@ -0,0 +1,97 @@ +package reporting + +import ( + "fmt" + "os" + "runtime" + "strings" +) + +func init() { + if !isXterm() { + monochrome() + } + + if runtime.GOOS == "windows" { + success, failure, error_ = dotSuccess, dotFailure, dotError + } +} + +func BuildJsonReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewJsonReporter(out)) +} +func BuildDotReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewDotReporter(out), + NewProblemReporter(out), + consoleStatistics) +} +func BuildStoryReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewStoryReporter(out), + NewProblemReporter(out), + consoleStatistics) +} +func BuildSilentReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewProblemReporter(out)) +} + +var ( + newline = "\n" + success = "✔" + failure = "✘" + error_ = "🔥" + skip = "âš " + dotSuccess = "." + dotFailure = "x" + dotError = "E" + dotSkip = "S" + errorTemplate = "* %s \nLine %d: - %v \n%s\n" + failureTemplate = "* %s \nLine %d:\n%s\n" +) + +var ( + greenColor = "\033[32m" + yellowColor = "\033[33m" + redColor = "\033[31m" + resetColor = "\033[0m" +) + +var consoleStatistics = NewStatisticsReporter(NewPrinter(NewConsole())) + +func SuppressConsoleStatistics() { consoleStatistics.Suppress() } +func PrintConsoleStatistics() { consoleStatistics.PrintSummary() } + +// QuiteMode disables all console output symbols. This is only meant to be used +// for tests that are internal to goconvey where the output is distracting or +// otherwise not needed in the test output. +func QuietMode() { + success, failure, error_, skip, dotSuccess, dotFailure, dotError, dotSkip = "", "", "", "", "", "", "", "" +} + +func monochrome() { + greenColor, yellowColor, redColor, resetColor = "", "", "", "" +} + +func isXterm() bool { + env := fmt.Sprintf("%v", os.Environ()) + return strings.Contains(env, " TERM=isXterm") || + strings.Contains(env, " TERM=xterm") +} + +// This interface allows us to pass the *testing.T struct +// throughout the internals of this tool without ever +// having to import the "testing" package. +type T interface { + Fail() +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go new file mode 100644 index 0000000000..f8526979f8 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go @@ -0,0 +1,88 @@ +// TODO: under unit test + +package reporting + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" +) + +type JsonReporter struct { + out *Printer + currentKey []string + current *ScopeResult + index map[string]*ScopeResult + scopes []*ScopeResult +} + +func (self *JsonReporter) depth() int { return len(self.currentKey) } + +func (self *JsonReporter) BeginStory(story *StoryReport) {} + +func (self *JsonReporter) Enter(scope *ScopeReport) { + self.currentKey = append(self.currentKey, scope.Title) + ID := strings.Join(self.currentKey, "|") + if _, found := self.index[ID]; !found { + next := newScopeResult(scope.Title, self.depth(), scope.File, scope.Line) + self.scopes = append(self.scopes, next) + self.index[ID] = next + } + self.current = self.index[ID] +} + +func (self *JsonReporter) Report(report *AssertionResult) { + self.current.Assertions = append(self.current.Assertions, report) +} + +func (self *JsonReporter) Exit() { + self.currentKey = self.currentKey[:len(self.currentKey)-1] +} + +func (self *JsonReporter) EndStory() { + self.report() + self.reset() +} +func (self *JsonReporter) report() { + scopes := []string{} + for _, scope := range self.scopes { + serialized, err := json.Marshal(scope) + if err != nil { + self.out.Println(jsonMarshalFailure) + panic(err) + } + var buffer bytes.Buffer + json.Indent(&buffer, serialized, "", " ") + scopes = append(scopes, buffer.String()) + } + self.out.Print(fmt.Sprintf("%s\n%s,\n%s\n", OpenJson, strings.Join(scopes, ","), CloseJson)) +} +func (self *JsonReporter) reset() { + self.scopes = []*ScopeResult{} + self.index = map[string]*ScopeResult{} + self.currentKey = nil +} + +func (self *JsonReporter) Write(content []byte) (written int, err error) { + self.current.Output += string(content) + return len(content), nil +} + +func NewJsonReporter(out *Printer) *JsonReporter { + self := new(JsonReporter) + self.out = out + self.reset() + return self +} + +const OpenJson = ">->->OPEN-JSON->->->" // "⌦" +const CloseJson = "<-<-<-CLOSE-JSON<-<-<" // "⌫" +const jsonMarshalFailure = ` + +GOCONVEY_JSON_MARSHALL_FAILURE: There was an error when attempting to convert test results to JSON. +Please file a bug report and reference the code that caused this failure if possible. + +Here's the panic: + +` diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go new file mode 100644 index 0000000000..6d4a879c40 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go @@ -0,0 +1,57 @@ +package reporting + +import ( + "fmt" + "io" + "strings" +) + +type Printer struct { + out io.Writer + prefix string +} + +func (self *Printer) Println(message string, values ...interface{}) { + formatted := self.format(message, values...) + newline + self.out.Write([]byte(formatted)) +} + +func (self *Printer) Print(message string, values ...interface{}) { + formatted := self.format(message, values...) + self.out.Write([]byte(formatted)) +} + +func (self *Printer) Insert(text string) { + self.out.Write([]byte(text)) +} + +func (self *Printer) format(message string, values ...interface{}) string { + var formatted string + if len(values) == 0 { + formatted = self.prefix + message + } else { + formatted = self.prefix + fmt.Sprintf(message, values...) + } + indented := strings.Replace(formatted, newline, newline+self.prefix, -1) + return strings.TrimRight(indented, space) +} + +func (self *Printer) Indent() { + self.prefix += pad +} + +func (self *Printer) Dedent() { + if len(self.prefix) >= padLength { + self.prefix = self.prefix[:len(self.prefix)-padLength] + } +} + +func NewPrinter(out io.Writer) *Printer { + self := new(Printer) + self.out = out + return self +} + +const space = " " +const pad = space + space +const padLength = len(pad) diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/printer_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer_test.go new file mode 100644 index 0000000000..94202d5ac9 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer_test.go @@ -0,0 +1,181 @@ +package reporting + +import "testing" + +func TestPrint(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "Hello, World!" + + printer.Print(expected) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintFormat(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + template := "Hi, %s" + name := "Ralph" + expected := "Hi, Ralph" + + printer.Print(template, name) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintPreservesEncodedStrings(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "= -> %3D" + printer.Print(expected) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintln(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "Hello, World!" + + printer.Println(expected) + + if file.buffer != expected+"\n" { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintlnFormat(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + template := "Hi, %s" + name := "Ralph" + expected := "Hi, Ralph\n" + + printer.Println(template, name) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintlnPreservesEncodedStrings(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "= -> %3D" + printer.Println(expected) + + if file.buffer != expected+"\n" { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintIndented(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const message = "Hello, World!\nGoodbye, World!" + const expected = " Hello, World!\n Goodbye, World!" + + printer.Indent() + printer.Print(message) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintDedented(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "Hello, World!\nGoodbye, World!" + + printer.Indent() + printer.Dedent() + printer.Print(expected) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintlnIndented(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const message = "Hello, World!\nGoodbye, World!" + const expected = " Hello, World!\n Goodbye, World!\n" + + printer.Indent() + printer.Println(message) + + if file.buffer != expected { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestPrintlnDedented(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + const expected = "Hello, World!\nGoodbye, World!" + + printer.Indent() + printer.Dedent() + printer.Println(expected) + + if file.buffer != expected+"\n" { + t.Errorf("Expected '%s' to equal '%s'.", expected, file.buffer) + } +} + +func TestDedentTooFarShouldNotPanic(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Error("Should not have panicked!") + } + }() + file := newMemoryFile() + printer := NewPrinter(file) + + printer.Dedent() + + t.Log("Getting to this point without panicking means we passed.") +} + +func TestInsert(t *testing.T) { + file := newMemoryFile() + printer := NewPrinter(file) + + printer.Indent() + printer.Print("Hi") + printer.Insert(" there") + printer.Dedent() + + expected := " Hi there" + if file.buffer != expected { + t.Errorf("Should have written '%s' but instead wrote '%s'.", expected, file.buffer) + } +} + +////////////////// memoryFile //////////////////// + +type memoryFile struct { + buffer string +} + +func (self *memoryFile) Write(p []byte) (n int, err error) { + self.buffer += string(p) + return len(p), nil +} + +func (self *memoryFile) String() string { + return self.buffer +} + +func newMemoryFile() *memoryFile { + return new(memoryFile) +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go new file mode 100644 index 0000000000..c610ba8869 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go @@ -0,0 +1,68 @@ +package reporting + +import "fmt" + +type problem struct { + out *Printer + errors []*AssertionResult + failures []*AssertionResult +} + +func (self *problem) BeginStory(story *StoryReport) {} + +func (self *problem) Enter(scope *ScopeReport) {} + +func (self *problem) Report(report *AssertionResult) { + if report.Error != nil { + self.errors = append(self.errors, report) + } else if report.Failure != "" { + self.failures = append(self.failures, report) + } +} + +func (self *problem) Exit() {} + +func (self *problem) EndStory() { + self.show(self.showErrors, redColor) + self.show(self.showFailures, yellowColor) + self.prepareForNextStory() +} +func (self *problem) show(display func(), color string) { + fmt.Print(color) + display() + fmt.Print(resetColor) + self.out.Dedent() +} +func (self *problem) showErrors() { + for i, e := range self.errors { + if i == 0 { + self.out.Println("\nErrors:\n") + self.out.Indent() + } + self.out.Println(errorTemplate, e.File, e.Line, e.Error, e.StackTrace) + } +} +func (self *problem) showFailures() { + for i, f := range self.failures { + if i == 0 { + self.out.Println("\nFailures:\n") + self.out.Indent() + } + self.out.Println(failureTemplate, f.File, f.Line, f.Failure) + } +} + +func (self *problem) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewProblemReporter(out *Printer) *problem { + self := new(problem) + self.out = out + self.prepareForNextStory() + return self +} +func (self *problem) prepareForNextStory() { + self.errors = []*AssertionResult{} + self.failures = []*AssertionResult{} +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/problems_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems_test.go new file mode 100644 index 0000000000..92f0ca35cc --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems_test.go @@ -0,0 +1,51 @@ +package reporting + +import ( + "strings" + "testing" +) + +func TestNoopProblemReporterActions(t *testing.T) { + file, reporter := setup() + reporter.BeginStory(nil) + reporter.Enter(nil) + reporter.Exit() + expected := "" + actual := file.String() + if expected != actual { + t.Errorf("Expected: '(blank)'\nActual: '%s'", actual) + } +} + +func TestReporterPrintsFailuresAndErrorsAtTheEndOfTheStory(t *testing.T) { + file, reporter := setup() + reporter.Report(NewFailureReport("failed")) + reporter.Report(NewErrorReport("error")) + reporter.Report(NewSuccessReport()) + reporter.EndStory() + + result := file.String() + if !strings.Contains(result, "Errors:\n") { + t.Errorf("Expected errors, found none.") + } + if !strings.Contains(result, "Failures:\n") { + t.Errorf("Expected failures, found none.") + } + + // Each stack trace looks like: `* /path/to/file.go`, so look for `* `. + // With go 1.4+ there is a line in some stack traces that looks like this: + // `testing.(*M).Run(0x2082d60a0, 0x25b7c0)` + // So we can't just look for "*" anymore. + problemCount := strings.Count(result, "* ") + if problemCount != 2 { + t.Errorf("Expected one failure and one error (total of 2 '*' characters). Got %d", problemCount) + } +} + +func setup() (file *memoryFile, reporter *problem) { + monochrome() + file = newMemoryFile() + printer := NewPrinter(file) + reporter = NewProblemReporter(printer) + return +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go new file mode 100644 index 0000000000..cce6c5e438 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go @@ -0,0 +1,39 @@ +package reporting + +import "io" + +type Reporter interface { + BeginStory(story *StoryReport) + Enter(scope *ScopeReport) + Report(r *AssertionResult) + Exit() + EndStory() + io.Writer +} + +type reporters struct{ collection []Reporter } + +func (self *reporters) BeginStory(s *StoryReport) { self.foreach(func(r Reporter) { r.BeginStory(s) }) } +func (self *reporters) Enter(s *ScopeReport) { self.foreach(func(r Reporter) { r.Enter(s) }) } +func (self *reporters) Report(a *AssertionResult) { self.foreach(func(r Reporter) { r.Report(a) }) } +func (self *reporters) Exit() { self.foreach(func(r Reporter) { r.Exit() }) } +func (self *reporters) EndStory() { self.foreach(func(r Reporter) { r.EndStory() }) } + +func (self *reporters) Write(contents []byte) (written int, err error) { + self.foreach(func(r Reporter) { + written, err = r.Write(contents) + }) + return written, err +} + +func (self *reporters) foreach(action func(Reporter)) { + for _, r := range self.collection { + action(r) + } +} + +func NewReporters(collection ...Reporter) *reporters { + self := new(reporters) + self.collection = collection + return self +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go new file mode 100644 index 0000000000..4e5caf63b2 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter_test.go @@ -0,0 +1,94 @@ +package reporting + +import ( + "runtime" + "testing" +) + +func TestEachNestedReporterReceivesTheCallFromTheContainingReporter(t *testing.T) { + fake1 := newFakeReporter() + fake2 := newFakeReporter() + reporter := NewReporters(fake1, fake2) + + reporter.BeginStory(nil) + assertTrue(t, fake1.begun) + assertTrue(t, fake2.begun) + + reporter.Enter(NewScopeReport("scope")) + assertTrue(t, fake1.entered) + assertTrue(t, fake2.entered) + + reporter.Report(NewSuccessReport()) + assertTrue(t, fake1.reported) + assertTrue(t, fake2.reported) + + reporter.Exit() + assertTrue(t, fake1.exited) + assertTrue(t, fake2.exited) + + reporter.EndStory() + assertTrue(t, fake1.ended) + assertTrue(t, fake2.ended) + + content := []byte("hi") + written, err := reporter.Write(content) + assertTrue(t, fake1.written) + assertTrue(t, fake2.written) + assertEqual(t, written, len(content)) + assertNil(t, err) + +} + +func assertTrue(t *testing.T, value bool) { + if !value { + _, _, line, _ := runtime.Caller(1) + t.Errorf("Value should have been true (but was false). See line %d", line) + } +} + +func assertEqual(t *testing.T, expected, actual int) { + if actual != expected { + _, _, line, _ := runtime.Caller(1) + t.Errorf("Value should have been %d (but was %d). See line %d", expected, actual, line) + } +} + +func assertNil(t *testing.T, err error) { + if err != nil { + _, _, line, _ := runtime.Caller(1) + t.Errorf("Error should have been (but wasn't). See line %d", err, line) + } +} + +type fakeReporter struct { + begun bool + entered bool + reported bool + exited bool + ended bool + written bool +} + +func newFakeReporter() *fakeReporter { + return &fakeReporter{} +} + +func (self *fakeReporter) BeginStory(story *StoryReport) { + self.begun = true +} +func (self *fakeReporter) Enter(scope *ScopeReport) { + self.entered = true +} +func (self *fakeReporter) Report(report *AssertionResult) { + self.reported = true +} +func (self *fakeReporter) Exit() { + self.exited = true +} +func (self *fakeReporter) EndStory() { + self.ended = true +} +func (self *fakeReporter) Write(content []byte) (int, error) { + self.written = true + return len(content), nil +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey new file mode 100644 index 0000000000..79982854b5 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey @@ -0,0 +1,2 @@ +#ignore +-timeout=1s diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go new file mode 100644 index 0000000000..43066a0ff8 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go @@ -0,0 +1,177 @@ +package reporting + +import ( + "encoding/json" + "fmt" + "runtime" + "strings" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/gotest" +) + +////////////////// ScopeReport //////////////////// + +type ScopeReport struct { + Title string + File string + Line int +} + +func NewScopeReport(title string) *ScopeReport { + file, line, _ := gotest.ResolveExternalCaller() + self := new(ScopeReport) + self.Title = title + self.File = file + self.Line = line + return self +} + +////////////////// ScopeResult //////////////////// + +type ScopeResult struct { + Title string + File string + Line int + Depth int + Assertions []*AssertionResult + Output string +} + +func newScopeResult(title string, depth int, file string, line int) *ScopeResult { + self := new(ScopeResult) + self.Title = title + self.Depth = depth + self.File = file + self.Line = line + self.Assertions = []*AssertionResult{} + return self +} + +/////////////////// StoryReport ///////////////////// + +type StoryReport struct { + Test T + Name string + File string + Line int +} + +func NewStoryReport(test T) *StoryReport { + file, line, name := gotest.ResolveExternalCaller() + name = removePackagePath(name) + self := new(StoryReport) + self.Test = test + self.Name = name + self.File = file + self.Line = line + return self +} + +// name comes in looking like "github.com/smartystreets/goconvey/examples.TestName". +// We only want the stuff after the last '.', which is the name of the test function. +func removePackagePath(name string) string { + parts := strings.Split(name, ".") + return parts[len(parts)-1] +} + +/////////////////// FailureView //////////////////////// + +type FailureView struct { + Message string + Expected string + Actual string +} + +////////////////////AssertionResult ////////////////////// + +type AssertionResult struct { + File string + Line int + Expected string + Actual string + Failure string + Error interface{} + StackTrace string + Skipped bool +} + +func NewFailureReport(failure string) *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = stackTrace() + parseFailure(failure, report) + return report +} +func parseFailure(failure string, report *AssertionResult) { + view := new(FailureView) + err := json.Unmarshal([]byte(failure), view) + if err == nil { + report.Failure = view.Message + report.Expected = view.Expected + report.Actual = view.Actual + } else { + report.Failure = failure + } +} +func NewErrorReport(err interface{}) *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = fullStackTrace() + report.Error = fmt.Sprintf("%v", err) + return report +} +func NewSuccessReport() *AssertionResult { + return new(AssertionResult) +} +func NewSkipReport() *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = fullStackTrace() + report.Skipped = true + return report +} + +func caller() (file string, line int) { + file, line, _ = gotest.ResolveExternalCaller() + return +} + +func stackTrace() string { + buffer := make([]byte, 1024*64) + n := runtime.Stack(buffer, false) + return removeInternalEntries(string(buffer[:n])) +} +func fullStackTrace() string { + buffer := make([]byte, 1024*64) + n := runtime.Stack(buffer, true) + return removeInternalEntries(string(buffer[:n])) +} +func removeInternalEntries(stack string) string { + lines := strings.Split(stack, newline) + filtered := []string{} + for _, line := range lines { + if !isExternal(line) { + filtered = append(filtered, line) + } + } + return strings.Join(filtered, newline) +} +func isExternal(line string) bool { + for _, p := range internalPackages { + if strings.Contains(line, p) { + return true + } + } + return false +} + +// NOTE: any new packages that host goconvey packages will need to be added here! +// An alternative is to scan the goconvey directory and then exclude stuff like +// the examples package but that's nasty too. +var internalPackages = []string{ + "goconvey/assertions", + "goconvey/convey", + "goconvey/execution", + "goconvey/gotest", + "goconvey/reporting", +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go new file mode 100644 index 0000000000..28e1d2071d --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go @@ -0,0 +1,89 @@ +package reporting + +import "fmt" + +func (self *statistics) BeginStory(story *StoryReport) {} + +func (self *statistics) Enter(scope *ScopeReport) {} + +func (self *statistics) Report(report *AssertionResult) { + if !self.failing && report.Failure != "" { + self.failing = true + } + if !self.erroring && report.Error != nil { + self.erroring = true + } + if report.Skipped { + self.skipped += 1 + } else { + self.total++ + } +} + +func (self *statistics) Exit() {} + +func (self *statistics) EndStory() { + if !self.suppressed { + self.PrintSummary() + } +} + +func (self *statistics) Suppress() { + self.suppressed = true +} + +func (self *statistics) PrintSummary() { + self.reportAssertions() + self.reportSkippedSections() + self.completeReport() +} +func (self *statistics) reportAssertions() { + self.decideColor() + self.out.Print("\n%d total %s", self.total, plural("assertion", self.total)) +} +func (self *statistics) decideColor() { + if self.failing && !self.erroring { + fmt.Print(yellowColor) + } else if self.erroring { + fmt.Print(redColor) + } else { + fmt.Print(greenColor) + } +} +func (self *statistics) reportSkippedSections() { + if self.skipped > 0 { + fmt.Print(yellowColor) + self.out.Print(" (one or more sections skipped)") + } +} +func (self *statistics) completeReport() { + fmt.Print(resetColor) + self.out.Print("\n") + self.out.Print("\n") +} + +func (self *statistics) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewStatisticsReporter(out *Printer) *statistics { + self := statistics{} + self.out = out + return &self +} + +type statistics struct { + out *Printer + total int + failing bool + erroring bool + skipped int + suppressed bool +} + +func plural(word string, count int) string { + if count == 1 { + return word + } + return word + "s" +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go new file mode 100644 index 0000000000..9e73c971f8 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go @@ -0,0 +1,73 @@ +// TODO: in order for this reporter to be completely honest +// we need to retrofit to be more like the json reporter such that: +// 1. it maintains ScopeResult collections, which count assertions +// 2. it reports only after EndStory(), so that all tick marks +// are placed near the appropriate title. +// 3. Under unit test + +package reporting + +import ( + "fmt" + "strings" +) + +type story struct { + out *Printer + titlesById map[string]string + currentKey []string +} + +func (self *story) BeginStory(story *StoryReport) {} + +func (self *story) Enter(scope *ScopeReport) { + self.out.Indent() + + self.currentKey = append(self.currentKey, scope.Title) + ID := strings.Join(self.currentKey, "|") + + if _, found := self.titlesById[ID]; !found { + self.out.Println("") + self.out.Print(scope.Title) + self.out.Insert(" ") + self.titlesById[ID] = scope.Title + } +} + +func (self *story) Report(report *AssertionResult) { + if report.Error != nil { + fmt.Print(redColor) + self.out.Insert(error_) + } else if report.Failure != "" { + fmt.Print(yellowColor) + self.out.Insert(failure) + } else if report.Skipped { + fmt.Print(yellowColor) + self.out.Insert(skip) + } else { + fmt.Print(greenColor) + self.out.Insert(success) + } + fmt.Print(resetColor) +} + +func (self *story) Exit() { + self.out.Dedent() + self.currentKey = self.currentKey[:len(self.currentKey)-1] +} + +func (self *story) EndStory() { + self.titlesById = make(map[string]string) + self.out.Println("\n") +} + +func (self *story) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewStoryReporter(out *Printer) *story { + self := new(story) + self.out = out + self.titlesById = make(map[string]string) + return self +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go b/vendor/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go new file mode 100644 index 0000000000..b42ea3f130 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting_hooks_test.go @@ -0,0 +1,317 @@ +package convey + +import ( + "fmt" + "net/http" + "net/http/httptest" + "path" + "runtime" + "strconv" + "strings" + "testing" + + "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey/reporting" +) + +func TestSingleScopeReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + So(1, ShouldEqual, 1) + }) + + expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory()) +} + +func TestNestedScopeReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + Convey("B", func() { + So(1, ShouldEqual, 1) + }) + }) + + expectEqual(t, "Begin|A|B|Success|Exit|Exit|End", myReporter.wholeStory()) +} + +func TestFailureReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + So(1, ShouldBeNil) + }) + + expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory()) +} + +func TestFirstFailureEndsScopeExecution(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + So(1, ShouldBeNil) + So(nil, ShouldBeNil) + }) + + expectEqual(t, "Begin|A|Failure|Exit|End", myReporter.wholeStory()) +} + +func TestComparisonFailureDeserializedAndReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + So("hi", ShouldEqual, "bye") + }) + + expectEqual(t, "Begin|A|Failure(bye/hi)|Exit|End", myReporter.wholeStory()) +} + +func TestNestedFailureReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + Convey("B", func() { + So(2, ShouldBeNil) + }) + }) + + expectEqual(t, "Begin|A|B|Failure|Exit|Exit|End", myReporter.wholeStory()) +} + +func TestSuccessAndFailureReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + So(nil, ShouldBeNil) + So(1, ShouldBeNil) + }) + + expectEqual(t, "Begin|A|Success|Failure|Exit|End", myReporter.wholeStory()) +} + +func TestIncompleteActionReportedAsSkipped(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + Convey("B", nil) + }) + + expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) +} + +func TestSkippedConveyReportedAsSkipped(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + SkipConvey("B", func() { + So(1, ShouldEqual, 1) + }) + }) + + expectEqual(t, "Begin|A|B|Skipped|Exit|Exit|End", myReporter.wholeStory()) +} + +func TestMultipleSkipsAreReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + Convey("0", func() { + So(nil, ShouldBeNil) + }) + + SkipConvey("1", func() {}) + SkipConvey("2", func() {}) + + Convey("3", nil) + Convey("4", nil) + + Convey("5", func() { + So(nil, ShouldBeNil) + }) + }) + + expected := "Begin" + + "|A|0|Success|Exit|Exit" + + "|A|1|Skipped|Exit|Exit" + + "|A|2|Skipped|Exit|Exit" + + "|A|3|Skipped|Exit|Exit" + + "|A|4|Skipped|Exit|Exit" + + "|A|5|Success|Exit|Exit" + + "|End" + + expectEqual(t, expected, myReporter.wholeStory()) +} + +func TestSkippedAssertionIsNotReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + SkipSo(1, ShouldEqual, 1) + }) + + expectEqual(t, "Begin|A|Skipped|Exit|End", myReporter.wholeStory()) +} + +func TestMultipleSkippedAssertionsAreNotReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + SkipSo(1, ShouldEqual, 1) + So(1, ShouldEqual, 1) + SkipSo(1, ShouldEqual, 1) + }) + + expectEqual(t, "Begin|A|Skipped|Success|Skipped|Exit|End", myReporter.wholeStory()) +} + +func TestErrorByManualPanicReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + panic("Gopher alert!") + }) + + expectEqual(t, "Begin|A|Error|Exit|End", myReporter.wholeStory()) +} + +func TestIterativeConveysReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + for x := 0; x < 3; x++ { + Convey(strconv.Itoa(x), func() { + So(x, ShouldEqual, x) + }) + } + }) + + expectEqual(t, "Begin|A|0|Success|Exit|Exit|A|1|Success|Exit|Exit|A|2|Success|Exit|Exit|End", myReporter.wholeStory()) +} + +func TestNestedIterativeConveysReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func() { + for x := 0; x < 3; x++ { + Convey(strconv.Itoa(x), func() { + for y := 0; y < 3; y++ { + Convey("< "+strconv.Itoa(y), func() { + So(x, ShouldBeLessThan, y) + }) + } + }) + } + }) + + expectEqual(t, ("Begin|" + + "A|0|< 0|Failure|Exit|Exit|Exit|" + + "A|0|< 1|Success|Exit|Exit|Exit|" + + "A|0|< 2|Success|Exit|Exit|Exit|" + + "A|1|< 0|Failure|Exit|Exit|Exit|" + + "A|1|< 1|Failure|Exit|Exit|Exit|" + + "A|1|< 2|Success|Exit|Exit|Exit|" + + "A|2|< 0|Failure|Exit|Exit|Exit|" + + "A|2|< 1|Failure|Exit|Exit|Exit|" + + "A|2|< 2|Failure|Exit|Exit|Exit|" + + "End"), myReporter.wholeStory()) +} + +func TestEmbeddedAssertionReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + Convey("A", test, func(c C) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + c.So(r.FormValue("msg"), ShouldEqual, "ping") + })) + http.DefaultClient.Get(ts.URL + "?msg=ping") + }) + + expectEqual(t, "Begin|A|Success|Exit|End", myReporter.wholeStory()) +} + +func TestEmbeddedContextHelperReported(t *testing.T) { + myReporter, test := setupFakeReporter() + + helper := func(c C) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + c.Convey("Embedded", func() { + So(r.FormValue("msg"), ShouldEqual, "ping") + }) + }) + } + + Convey("A", test, func(c C) { + ts := httptest.NewServer(helper(c)) + http.DefaultClient.Get(ts.URL + "?msg=ping") + }) + + expectEqual(t, "Begin|A|Embedded|Success|Exit|Exit|End", myReporter.wholeStory()) +} + +func expectEqual(t *testing.T, expected interface{}, actual interface{}) { + if expected != actual { + _, file, line, _ := runtime.Caller(1) + t.Errorf("Expected '%v' to be '%v' but it wasn't. See '%s' at line %d.", + actual, expected, path.Base(file), line) + } +} + +func setupFakeReporter() (*fakeReporter, *fakeGoTest) { + myReporter := new(fakeReporter) + myReporter.calls = []string{} + testReporter = myReporter + return myReporter, new(fakeGoTest) +} + +type fakeReporter struct { + calls []string +} + +func (self *fakeReporter) BeginStory(story *reporting.StoryReport) { + self.calls = append(self.calls, "Begin") +} + +func (self *fakeReporter) Enter(scope *reporting.ScopeReport) { + self.calls = append(self.calls, scope.Title) +} + +func (self *fakeReporter) Report(report *reporting.AssertionResult) { + if report.Error != nil { + self.calls = append(self.calls, "Error") + } else if report.Failure != "" { + message := "Failure" + if report.Expected != "" || report.Actual != "" { + message += fmt.Sprintf("(%s/%s)", report.Expected, report.Actual) + } + self.calls = append(self.calls, message) + } else if report.Skipped { + self.calls = append(self.calls, "Skipped") + } else { + self.calls = append(self.calls, "Success") + } +} + +func (self *fakeReporter) Exit() { + self.calls = append(self.calls, "Exit") +} + +func (self *fakeReporter) EndStory() { + self.calls = append(self.calls, "End") +} + +func (self *fakeReporter) Write(content []byte) (int, error) { + return len(content), nil // no-op +} + +func (self *fakeReporter) wholeStory() string { + return strings.Join(self.calls, "|") +} + +//////////////////////////////// + +type fakeGoTest struct{} + +func (self *fakeGoTest) Fail() {} +func (self *fakeGoTest) Fatalf(format string, args ...interface{}) {} + +var test t = new(fakeGoTest) diff --git a/vendor/github.com/smartystreets/goconvey/convey/story_conventions_test.go b/vendor/github.com/smartystreets/goconvey/convey/story_conventions_test.go new file mode 100644 index 0000000000..ff3a4e6e7a --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/story_conventions_test.go @@ -0,0 +1,184 @@ +package convey + +import ( + "reflect" + "testing" +) + +func expectPanic(t *testing.T, f string) interface{} { + r := recover() + if r != nil { + if cp, ok := r.(*conveyErr); ok { + if cp.fmt != f { + t.Error("Incorrect panic message.") + } + } else { + t.Errorf("Incorrect panic type. %s", reflect.TypeOf(r)) + } + } else { + t.Error("Expected panic but none occured") + } + return r +} + +func TestMissingTopLevelGoTestReferenceCausesPanic(t *testing.T) { + output := map[string]bool{} + + defer expectEqual(t, false, output["good"]) + defer expectPanic(t, missingGoTest) + + Convey("Hi", func() { + output["bad"] = true // this shouldn't happen + }) +} + +func requireGoTestReference(t *testing.T) { + err := recover() + if err == nil { + t.Error("We should have recovered a panic here (because of a missing *testing.T reference)!") + } else { + expectEqual(t, missingGoTest, err) + } +} + +func TestMissingTopLevelGoTestReferenceAfterGoodExample(t *testing.T) { + output := map[string]bool{} + + defer func() { + expectEqual(t, true, output["good"]) + expectEqual(t, false, output["bad"]) + }() + defer expectPanic(t, missingGoTest) + + Convey("Good example", t, func() { + output["good"] = true + }) + + Convey("Bad example", func() { + output["bad"] = true // shouldn't happen + }) +} + +func TestExtraReferencePanics(t *testing.T) { + output := map[string]bool{} + + defer expectEqual(t, false, output["bad"]) + defer expectPanic(t, extraGoTest) + + Convey("Good example", t, func() { + Convey("Bad example - passing in *testing.T a second time!", t, func() { + output["bad"] = true // shouldn't happen + }) + }) +} + +func TestParseRegistrationMissingRequiredElements(t *testing.T) { + defer expectPanic(t, parseError) + + Convey() +} + +func TestParseRegistration_MissingNameString(t *testing.T) { + defer expectPanic(t, parseError) + + Convey(func() {}) +} + +func TestParseRegistration_MissingActionFunc(t *testing.T) { + defer expectPanic(t, parseError) + + Convey("Hi there", 12345) +} + +func TestFailureModeNoContext(t *testing.T) { + Convey("Foo", t, func() { + done := make(chan int, 1) + go func() { + defer func() { done <- 1 }() + defer expectPanic(t, noStackContext) + So(len("I have no context"), ShouldBeGreaterThan, 0) + }() + <-done + }) +} + +func TestFailureModeDuplicateSuite(t *testing.T) { + Convey("cool", t, func() { + defer expectPanic(t, multipleIdenticalConvey) + + Convey("dup", nil) + Convey("dup", nil) + }) +} + +func TestFailureModeIndeterminentSuiteNames(t *testing.T) { + defer expectPanic(t, differentConveySituations) + + name := "bob" + Convey("cool", t, func() { + for i := 0; i < 3; i++ { + Convey(name, func() {}) + name += "bob" + } + }) +} + +func TestFailureModeNestedIndeterminentSuiteNames(t *testing.T) { + defer expectPanic(t, differentConveySituations) + + name := "bob" + Convey("cool", t, func() { + Convey("inner", func() { + for i := 0; i < 3; i++ { + Convey(name, func() {}) + name += "bob" + } + }) + }) +} + +func TestFailureModeParameterButMissing(t *testing.T) { + defer expectPanic(t, parseError) + + prepare() + + Convey("Foobar", t, FailureHalts) +} + +func TestFailureModeParameterWithAction(t *testing.T) { + prepare() + + Convey("Foobar", t, FailureHalts, func() {}) +} + +func TestExtraConveyParameters(t *testing.T) { + defer expectPanic(t, parseError) + + prepare() + + Convey("Foobar", t, FailureHalts, func() {}, "This is not supposed to be here") +} + +func TestExtraConveyParameters2(t *testing.T) { + defer expectPanic(t, parseError) + + prepare() + + Convey("Foobar", t, func() {}, "This is not supposed to be here") +} + +func TestExtraConveyParameters3(t *testing.T) { + defer expectPanic(t, parseError) + + output := prepare() + + Convey("A", t, func() { + output += "A " + + Convey("B", func() { + output += "B " + }, "This is not supposed to be here") + }) + + expectEqual(t, "A ", output) +} diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go new file mode 100644 index 0000000000..05ff742e9b --- /dev/null +++ b/vendor/golang.org/x/net/context/context.go @@ -0,0 +1,447 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package context defines the Context type, which carries deadlines, +// cancelation signals, and other request-scoped values across API boundaries +// and between processes. +// +// Incoming requests to a server should create a Context, and outgoing calls to +// servers should accept a Context. The chain of function calls between must +// propagate the Context, optionally replacing it with a modified copy created +// using WithDeadline, WithTimeout, WithCancel, or WithValue. +// +// Programs that use Contexts should follow these rules to keep interfaces +// consistent across packages and enable static analysis tools to check context +// propagation: +// +// Do not store Contexts inside a struct type; instead, pass a Context +// explicitly to each function that needs it. The Context should be the first +// parameter, typically named ctx: +// +// func DoSomething(ctx context.Context, arg Arg) error { +// // ... use ctx ... +// } +// +// Do not pass a nil Context, even if a function permits it. Pass context.TODO +// if you are unsure about which Context to use. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +// +// The same Context may be passed to functions running in different goroutines; +// Contexts are safe for simultaneous use by multiple goroutines. +// +// See http://blog.golang.org/context for example code for a server that uses +// Contexts. +package context // import "github.com/scaleway/scaleway-cli/vendor/golang.org/x/net/context" + +import ( + "errors" + "fmt" + "sync" + "time" +) + +// A Context carries a deadline, a cancelation signal, and other values across +// API boundaries. +// +// Context's methods may be called by multiple goroutines simultaneously. +type Context interface { + // Deadline returns the time when work done on behalf of this context + // should be canceled. Deadline returns ok==false when no deadline is + // set. Successive calls to Deadline return the same results. + Deadline() (deadline time.Time, ok bool) + + // Done returns a channel that's closed when work done on behalf of this + // context should be canceled. Done may return nil if this context can + // never be canceled. Successive calls to Done return the same value. + // + // WithCancel arranges for Done to be closed when cancel is called; + // WithDeadline arranges for Done to be closed when the deadline + // expires; WithTimeout arranges for Done to be closed when the timeout + // elapses. + // + // Done is provided for use in select statements: + // + // // Stream generates values with DoSomething and sends them to out + // // until DoSomething returns an error or ctx.Done is closed. + // func Stream(ctx context.Context, out <-chan Value) error { + // for { + // v, err := DoSomething(ctx) + // if err != nil { + // return err + // } + // select { + // case <-ctx.Done(): + // return ctx.Err() + // case out <- v: + // } + // } + // } + // + // See http://blog.golang.org/pipelines for more examples of how to use + // a Done channel for cancelation. + Done() <-chan struct{} + + // Err returns a non-nil error value after Done is closed. Err returns + // Canceled if the context was canceled or DeadlineExceeded if the + // context's deadline passed. No other values for Err are defined. + // After Done is closed, successive calls to Err return the same value. + Err() error + + // Value returns the value associated with this context for key, or nil + // if no value is associated with key. Successive calls to Value with + // the same key returns the same result. + // + // Use context values only for request-scoped data that transits + // processes and API boundaries, not for passing optional parameters to + // functions. + // + // A key identifies a specific value in a Context. Functions that wish + // to store values in Context typically allocate a key in a global + // variable then use that key as the argument to context.WithValue and + // Context.Value. A key can be any type that supports equality; + // packages should define keys as an unexported type to avoid + // collisions. + // + // Packages that define a Context key should provide type-safe accessors + // for the values stores using that key: + // + // // Package user defines a User type that's stored in Contexts. + // package user + // + // import "golang.org/x/net/context" + // + // // User is the type of value stored in the Contexts. + // type User struct {...} + // + // // key is an unexported type for keys defined in this package. + // // This prevents collisions with keys defined in other packages. + // type key int + // + // // userKey is the key for user.User values in Contexts. It is + // // unexported; clients use user.NewContext and user.FromContext + // // instead of using this key directly. + // var userKey key = 0 + // + // // NewContext returns a new Context that carries value u. + // func NewContext(ctx context.Context, u *User) context.Context { + // return context.WithValue(ctx, userKey, u) + // } + // + // // FromContext returns the User value stored in ctx, if any. + // func FromContext(ctx context.Context) (*User, bool) { + // u, ok := ctx.Value(userKey).(*User) + // return u, ok + // } + Value(key interface{}) interface{} +} + +// Canceled is the error returned by Context.Err when the context is canceled. +var Canceled = errors.New("context canceled") + +// DeadlineExceeded is the error returned by Context.Err when the context's +// deadline passes. +var DeadlineExceeded = errors.New("context deadline exceeded") + +// An emptyCtx is never canceled, has no values, and has no deadline. It is not +// struct{}, since vars of this type must have distinct addresses. +type emptyCtx int + +func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { + return +} + +func (*emptyCtx) Done() <-chan struct{} { + return nil +} + +func (*emptyCtx) Err() error { + return nil +} + +func (*emptyCtx) Value(key interface{}) interface{} { + return nil +} + +func (e *emptyCtx) String() string { + switch e { + case background: + return "context.Background" + case todo: + return "context.TODO" + } + return "unknown empty Context" +} + +var ( + background = new(emptyCtx) + todo = new(emptyCtx) +) + +// Background returns a non-nil, empty Context. It is never canceled, has no +// values, and has no deadline. It is typically used by the main function, +// initialization, and tests, and as the top-level Context for incoming +// requests. +func Background() Context { + return background +} + +// TODO returns a non-nil, empty Context. Code should use context.TODO when +// it's unclear which Context to use or it's is not yet available (because the +// surrounding function has not yet been extended to accept a Context +// parameter). TODO is recognized by static analysis tools that determine +// whether Contexts are propagated correctly in a program. +func TODO() Context { + return todo +} + +// A CancelFunc tells an operation to abandon its work. +// A CancelFunc does not wait for the work to stop. +// After the first call, subsequent calls to a CancelFunc do nothing. +type CancelFunc func() + +// WithCancel returns a copy of parent with a new Done channel. The returned +// context's Done channel is closed when the returned cancel function is called +// or when the parent context's Done channel is closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { + c := newCancelCtx(parent) + propagateCancel(parent, &c) + return &c, func() { c.cancel(true, Canceled) } +} + +// newCancelCtx returns an initialized cancelCtx. +func newCancelCtx(parent Context) cancelCtx { + return cancelCtx{ + Context: parent, + done: make(chan struct{}), + } +} + +// propagateCancel arranges for child to be canceled when parent is. +func propagateCancel(parent Context, child canceler) { + if parent.Done() == nil { + return // parent is never canceled + } + if p, ok := parentCancelCtx(parent); ok { + p.mu.Lock() + if p.err != nil { + // parent has already been canceled + child.cancel(false, p.err) + } else { + if p.children == nil { + p.children = make(map[canceler]bool) + } + p.children[child] = true + } + p.mu.Unlock() + } else { + go func() { + select { + case <-parent.Done(): + child.cancel(false, parent.Err()) + case <-child.Done(): + } + }() + } +} + +// parentCancelCtx follows a chain of parent references until it finds a +// *cancelCtx. This function understands how each of the concrete types in this +// package represents its parent. +func parentCancelCtx(parent Context) (*cancelCtx, bool) { + for { + switch c := parent.(type) { + case *cancelCtx: + return c, true + case *timerCtx: + return &c.cancelCtx, true + case *valueCtx: + parent = c.Context + default: + return nil, false + } + } +} + +// removeChild removes a context from its parent. +func removeChild(parent Context, child canceler) { + p, ok := parentCancelCtx(parent) + if !ok { + return + } + p.mu.Lock() + if p.children != nil { + delete(p.children, child) + } + p.mu.Unlock() +} + +// A canceler is a context type that can be canceled directly. The +// implementations are *cancelCtx and *timerCtx. +type canceler interface { + cancel(removeFromParent bool, err error) + Done() <-chan struct{} +} + +// A cancelCtx can be canceled. When canceled, it also cancels any children +// that implement canceler. +type cancelCtx struct { + Context + + done chan struct{} // closed by the first cancel call. + + mu sync.Mutex + children map[canceler]bool // set to nil by the first cancel call + err error // set to non-nil by the first cancel call +} + +func (c *cancelCtx) Done() <-chan struct{} { + return c.done +} + +func (c *cancelCtx) Err() error { + c.mu.Lock() + defer c.mu.Unlock() + return c.err +} + +func (c *cancelCtx) String() string { + return fmt.Sprintf("%v.WithCancel", c.Context) +} + +// cancel closes c.done, cancels each of c's children, and, if +// removeFromParent is true, removes c from its parent's children. +func (c *cancelCtx) cancel(removeFromParent bool, err error) { + if err == nil { + panic("context: internal error: missing cancel error") + } + c.mu.Lock() + if c.err != nil { + c.mu.Unlock() + return // already canceled + } + c.err = err + close(c.done) + for child := range c.children { + // NOTE: acquiring the child's lock while holding parent's lock. + child.cancel(false, err) + } + c.children = nil + c.mu.Unlock() + + if removeFromParent { + removeChild(c.Context, c) + } +} + +// WithDeadline returns a copy of the parent context with the deadline adjusted +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// context's Done channel is closed when the deadline expires, when the returned +// cancel function is called, or when the parent context's Done channel is +// closed, whichever happens first. +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete. +func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { + if cur, ok := parent.Deadline(); ok && cur.Before(deadline) { + // The current deadline is already sooner than the new one. + return WithCancel(parent) + } + c := &timerCtx{ + cancelCtx: newCancelCtx(parent), + deadline: deadline, + } + propagateCancel(parent, c) + d := deadline.Sub(time.Now()) + if d <= 0 { + c.cancel(true, DeadlineExceeded) // deadline has already passed + return c, func() { c.cancel(true, Canceled) } + } + c.mu.Lock() + defer c.mu.Unlock() + if c.err == nil { + c.timer = time.AfterFunc(d, func() { + c.cancel(true, DeadlineExceeded) + }) + } + return c, func() { c.cancel(true, Canceled) } +} + +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then +// delegating to cancelCtx.cancel. +type timerCtx struct { + cancelCtx + timer *time.Timer // Under cancelCtx.mu. + + deadline time.Time +} + +func (c *timerCtx) Deadline() (deadline time.Time, ok bool) { + return c.deadline, true +} + +func (c *timerCtx) String() string { + return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now())) +} + +func (c *timerCtx) cancel(removeFromParent bool, err error) { + c.cancelCtx.cancel(false, err) + if removeFromParent { + // Remove this timerCtx from its parent cancelCtx's children. + removeChild(c.cancelCtx.Context, c) + } + c.mu.Lock() + if c.timer != nil { + c.timer.Stop() + c.timer = nil + } + c.mu.Unlock() +} + +// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). +// +// Canceling this context releases resources associated with it, so code should +// call cancel as soon as the operations running in this Context complete: +// +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } +func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { + return WithDeadline(parent, time.Now().Add(timeout)) +} + +// WithValue returns a copy of parent in which the value associated with key is +// val. +// +// Use context Values only for request-scoped data that transits processes and +// APIs, not for passing optional parameters to functions. +func WithValue(parent Context, key interface{}, val interface{}) Context { + return &valueCtx{parent, key, val} +} + +// A valueCtx carries a key-value pair. It implements Value for that key and +// delegates all other calls to the embedded Context. +type valueCtx struct { + Context + key, val interface{} +} + +func (c *valueCtx) String() string { + return fmt.Sprintf("%v.WithValue(%#v, %#v)", c.Context, c.key, c.val) +} + +func (c *valueCtx) Value(key interface{}) interface{} { + if c.key == key { + return c.val + } + return c.Context.Value(key) +} diff --git a/vendor/golang.org/x/net/context/context_test.go b/vendor/golang.org/x/net/context/context_test.go new file mode 100644 index 0000000000..e64afa64c6 --- /dev/null +++ b/vendor/golang.org/x/net/context/context_test.go @@ -0,0 +1,575 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package context + +import ( + "fmt" + "math/rand" + "runtime" + "strings" + "sync" + "testing" + "time" +) + +// otherContext is a Context that's not one of the types defined in context.go. +// This lets us test code paths that differ based on the underlying type of the +// Context. +type otherContext struct { + Context +} + +func TestBackground(t *testing.T) { + c := Background() + if c == nil { + t.Fatalf("Background returned nil") + } + select { + case x := <-c.Done(): + t.Errorf("<-c.Done() == %v want nothing (it should block)", x) + default: + } + if got, want := fmt.Sprint(c), "context.Background"; got != want { + t.Errorf("Background().String() = %q want %q", got, want) + } +} + +func TestTODO(t *testing.T) { + c := TODO() + if c == nil { + t.Fatalf("TODO returned nil") + } + select { + case x := <-c.Done(): + t.Errorf("<-c.Done() == %v want nothing (it should block)", x) + default: + } + if got, want := fmt.Sprint(c), "context.TODO"; got != want { + t.Errorf("TODO().String() = %q want %q", got, want) + } +} + +func TestWithCancel(t *testing.T) { + c1, cancel := WithCancel(Background()) + + if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want { + t.Errorf("c1.String() = %q want %q", got, want) + } + + o := otherContext{c1} + c2, _ := WithCancel(o) + contexts := []Context{c1, o, c2} + + for i, c := range contexts { + if d := c.Done(); d == nil { + t.Errorf("c[%d].Done() == %v want non-nil", i, d) + } + if e := c.Err(); e != nil { + t.Errorf("c[%d].Err() == %v want nil", i, e) + } + + select { + case x := <-c.Done(): + t.Errorf("<-c.Done() == %v want nothing (it should block)", x) + default: + } + } + + cancel() + time.Sleep(100 * time.Millisecond) // let cancelation propagate + + for i, c := range contexts { + select { + case <-c.Done(): + default: + t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i) + } + if e := c.Err(); e != Canceled { + t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled) + } + } +} + +func TestParentFinishesChild(t *testing.T) { + // Context tree: + // parent -> cancelChild + // parent -> valueChild -> timerChild + parent, cancel := WithCancel(Background()) + cancelChild, stop := WithCancel(parent) + defer stop() + valueChild := WithValue(parent, "key", "value") + timerChild, stop := WithTimeout(valueChild, 10000*time.Hour) + defer stop() + + select { + case x := <-parent.Done(): + t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) + case x := <-cancelChild.Done(): + t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x) + case x := <-timerChild.Done(): + t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x) + case x := <-valueChild.Done(): + t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x) + default: + } + + // The parent's children should contain the two cancelable children. + pc := parent.(*cancelCtx) + cc := cancelChild.(*cancelCtx) + tc := timerChild.(*timerCtx) + pc.mu.Lock() + if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] { + t.Errorf("bad linkage: pc.children = %v, want %v and %v", + pc.children, cc, tc) + } + pc.mu.Unlock() + + if p, ok := parentCancelCtx(cc.Context); !ok || p != pc { + t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc) + } + if p, ok := parentCancelCtx(tc.Context); !ok || p != pc { + t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc) + } + + cancel() + + pc.mu.Lock() + if len(pc.children) != 0 { + t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children) + } + pc.mu.Unlock() + + // parent and children should all be finished. + check := func(ctx Context, name string) { + select { + case <-ctx.Done(): + default: + t.Errorf("<-%s.Done() blocked, but shouldn't have", name) + } + if e := ctx.Err(); e != Canceled { + t.Errorf("%s.Err() == %v want %v", name, e, Canceled) + } + } + check(parent, "parent") + check(cancelChild, "cancelChild") + check(valueChild, "valueChild") + check(timerChild, "timerChild") + + // WithCancel should return a canceled context on a canceled parent. + precanceledChild := WithValue(parent, "key", "value") + select { + case <-precanceledChild.Done(): + default: + t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have") + } + if e := precanceledChild.Err(); e != Canceled { + t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled) + } +} + +func TestChildFinishesFirst(t *testing.T) { + cancelable, stop := WithCancel(Background()) + defer stop() + for _, parent := range []Context{Background(), cancelable} { + child, cancel := WithCancel(parent) + + select { + case x := <-parent.Done(): + t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) + case x := <-child.Done(): + t.Errorf("<-child.Done() == %v want nothing (it should block)", x) + default: + } + + cc := child.(*cancelCtx) + pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background() + if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) { + t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok) + } + + if pcok { + pc.mu.Lock() + if len(pc.children) != 1 || !pc.children[cc] { + t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc) + } + pc.mu.Unlock() + } + + cancel() + + if pcok { + pc.mu.Lock() + if len(pc.children) != 0 { + t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children) + } + pc.mu.Unlock() + } + + // child should be finished. + select { + case <-child.Done(): + default: + t.Errorf("<-child.Done() blocked, but shouldn't have") + } + if e := child.Err(); e != Canceled { + t.Errorf("child.Err() == %v want %v", e, Canceled) + } + + // parent should not be finished. + select { + case x := <-parent.Done(): + t.Errorf("<-parent.Done() == %v want nothing (it should block)", x) + default: + } + if e := parent.Err(); e != nil { + t.Errorf("parent.Err() == %v want nil", e) + } + } +} + +func testDeadline(c Context, wait time.Duration, t *testing.T) { + select { + case <-time.After(wait): + t.Fatalf("context should have timed out") + case <-c.Done(): + } + if e := c.Err(); e != DeadlineExceeded { + t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded) + } +} + +func TestDeadline(t *testing.T) { + c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) + if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { + t.Errorf("c.String() = %q want prefix %q", got, prefix) + } + testDeadline(c, 200*time.Millisecond, t) + + c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) + o := otherContext{c} + testDeadline(o, 200*time.Millisecond, t) + + c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond)) + o = otherContext{c} + c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond)) + testDeadline(c, 200*time.Millisecond, t) +} + +func TestTimeout(t *testing.T) { + c, _ := WithTimeout(Background(), 100*time.Millisecond) + if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) { + t.Errorf("c.String() = %q want prefix %q", got, prefix) + } + testDeadline(c, 200*time.Millisecond, t) + + c, _ = WithTimeout(Background(), 100*time.Millisecond) + o := otherContext{c} + testDeadline(o, 200*time.Millisecond, t) + + c, _ = WithTimeout(Background(), 100*time.Millisecond) + o = otherContext{c} + c, _ = WithTimeout(o, 300*time.Millisecond) + testDeadline(c, 200*time.Millisecond, t) +} + +func TestCanceledTimeout(t *testing.T) { + c, _ := WithTimeout(Background(), 200*time.Millisecond) + o := otherContext{c} + c, cancel := WithTimeout(o, 400*time.Millisecond) + cancel() + time.Sleep(100 * time.Millisecond) // let cancelation propagate + select { + case <-c.Done(): + default: + t.Errorf("<-c.Done() blocked, but shouldn't have") + } + if e := c.Err(); e != Canceled { + t.Errorf("c.Err() == %v want %v", e, Canceled) + } +} + +type key1 int +type key2 int + +var k1 = key1(1) +var k2 = key2(1) // same int as k1, different type +var k3 = key2(3) // same type as k2, different int + +func TestValues(t *testing.T) { + check := func(c Context, nm, v1, v2, v3 string) { + if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 { + t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0) + } + if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 { + t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0) + } + if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 { + t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0) + } + } + + c0 := Background() + check(c0, "c0", "", "", "") + + c1 := WithValue(Background(), k1, "c1k1") + check(c1, "c1", "c1k1", "", "") + + if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want { + t.Errorf("c.String() = %q want %q", got, want) + } + + c2 := WithValue(c1, k2, "c2k2") + check(c2, "c2", "c1k1", "c2k2", "") + + c3 := WithValue(c2, k3, "c3k3") + check(c3, "c2", "c1k1", "c2k2", "c3k3") + + c4 := WithValue(c3, k1, nil) + check(c4, "c4", "", "c2k2", "c3k3") + + o0 := otherContext{Background()} + check(o0, "o0", "", "", "") + + o1 := otherContext{WithValue(Background(), k1, "c1k1")} + check(o1, "o1", "c1k1", "", "") + + o2 := WithValue(o1, k2, "o2k2") + check(o2, "o2", "c1k1", "o2k2", "") + + o3 := otherContext{c4} + check(o3, "o3", "", "c2k2", "c3k3") + + o4 := WithValue(o3, k3, nil) + check(o4, "o4", "", "c2k2", "") +} + +func TestAllocs(t *testing.T) { + bg := Background() + for _, test := range []struct { + desc string + f func() + limit float64 + gccgoLimit float64 + }{ + { + desc: "Background()", + f: func() { Background() }, + limit: 0, + gccgoLimit: 0, + }, + { + desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1), + f: func() { + c := WithValue(bg, k1, nil) + c.Value(k1) + }, + limit: 3, + gccgoLimit: 3, + }, + { + desc: "WithTimeout(bg, 15*time.Millisecond)", + f: func() { + c, _ := WithTimeout(bg, 15*time.Millisecond) + <-c.Done() + }, + limit: 8, + gccgoLimit: 15, + }, + { + desc: "WithCancel(bg)", + f: func() { + c, cancel := WithCancel(bg) + cancel() + <-c.Done() + }, + limit: 5, + gccgoLimit: 8, + }, + { + desc: "WithTimeout(bg, 100*time.Millisecond)", + f: func() { + c, cancel := WithTimeout(bg, 100*time.Millisecond) + cancel() + <-c.Done() + }, + limit: 8, + gccgoLimit: 25, + }, + } { + limit := test.limit + if runtime.Compiler == "gccgo" { + // gccgo does not yet do escape analysis. + // TOOD(iant): Remove this when gccgo does do escape analysis. + limit = test.gccgoLimit + } + if n := testing.AllocsPerRun(100, test.f); n > limit { + t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit)) + } + } +} + +func TestSimultaneousCancels(t *testing.T) { + root, cancel := WithCancel(Background()) + m := map[Context]CancelFunc{root: cancel} + q := []Context{root} + // Create a tree of contexts. + for len(q) != 0 && len(m) < 100 { + parent := q[0] + q = q[1:] + for i := 0; i < 4; i++ { + ctx, cancel := WithCancel(parent) + m[ctx] = cancel + q = append(q, ctx) + } + } + // Start all the cancels in a random order. + var wg sync.WaitGroup + wg.Add(len(m)) + for _, cancel := range m { + go func(cancel CancelFunc) { + cancel() + wg.Done() + }(cancel) + } + // Wait on all the contexts in a random order. + for ctx := range m { + select { + case <-ctx.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n]) + } + } + // Wait for all the cancel functions to return. + done := make(chan struct{}) + go func() { + wg.Wait() + close(done) + }() + select { + case <-done: + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n]) + } +} + +func TestInterlockedCancels(t *testing.T) { + parent, cancelParent := WithCancel(Background()) + child, cancelChild := WithCancel(parent) + go func() { + parent.Done() + cancelChild() + }() + cancelParent() + select { + case <-child.Done(): + case <-time.After(1 * time.Second): + buf := make([]byte, 10<<10) + n := runtime.Stack(buf, true) + t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n]) + } +} + +func TestLayersCancel(t *testing.T) { + testLayers(t, time.Now().UnixNano(), false) +} + +func TestLayersTimeout(t *testing.T) { + testLayers(t, time.Now().UnixNano(), true) +} + +func testLayers(t *testing.T, seed int64, testTimeout bool) { + rand.Seed(seed) + errorf := func(format string, a ...interface{}) { + t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...) + } + const ( + timeout = 200 * time.Millisecond + minLayers = 30 + ) + type value int + var ( + vals []*value + cancels []CancelFunc + numTimers int + ctx = Background() + ) + for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ { + switch rand.Intn(3) { + case 0: + v := new(value) + ctx = WithValue(ctx, v, v) + vals = append(vals, v) + case 1: + var cancel CancelFunc + ctx, cancel = WithCancel(ctx) + cancels = append(cancels, cancel) + case 2: + var cancel CancelFunc + ctx, cancel = WithTimeout(ctx, timeout) + cancels = append(cancels, cancel) + numTimers++ + } + } + checkValues := func(when string) { + for _, key := range vals { + if val := ctx.Value(key).(*value); key != val { + errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key) + } + } + } + select { + case <-ctx.Done(): + errorf("ctx should not be canceled yet") + default: + } + if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) { + t.Errorf("ctx.String() = %q want prefix %q", s, prefix) + } + t.Log(ctx) + checkValues("before cancel") + if testTimeout { + select { + case <-ctx.Done(): + case <-time.After(timeout + timeout/10): + errorf("ctx should have timed out") + } + checkValues("after timeout") + } else { + cancel := cancels[rand.Intn(len(cancels))] + cancel() + select { + case <-ctx.Done(): + default: + errorf("ctx should be canceled") + } + checkValues("after cancel") + } +} + +func TestCancelRemoves(t *testing.T) { + checkChildren := func(when string, ctx Context, want int) { + if got := len(ctx.(*cancelCtx).children); got != want { + t.Errorf("%s: context has %d children, want %d", when, got, want) + } + } + + ctx, _ := WithCancel(Background()) + checkChildren("after creation", ctx, 0) + _, cancel := WithCancel(ctx) + checkChildren("with WithCancel child ", ctx, 1) + cancel() + checkChildren("after cancelling WithCancel child", ctx, 0) + + ctx, _ = WithCancel(Background()) + checkChildren("after creation", ctx, 0) + _, cancel = WithTimeout(ctx, 60*time.Minute) + checkChildren("with WithTimeout child ", ctx, 1) + cancel() + checkChildren("after cancelling WithTimeout child", ctx, 0) +} diff --git a/vendor/golang.org/x/net/context/withtimeout_test.go b/vendor/golang.org/x/net/context/withtimeout_test.go new file mode 100644 index 0000000000..4e710a52c8 --- /dev/null +++ b/vendor/golang.org/x/net/context/withtimeout_test.go @@ -0,0 +1,26 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package context_test + +import ( + "fmt" + "time" + + "github.com/scaleway/scaleway-cli/vendor/golang.org/x/net/context" +) + +func ExampleWithTimeout() { + // Pass a context with a timeout to tell a blocking function that it + // should abandon its work after the timeout elapses. + ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond) + select { + case <-time.After(200 * time.Millisecond): + fmt.Println("overslept") + case <-ctx.Done(): + fmt.Println(ctx.Err()) // prints "context deadline exceeded" + } + // Output: + // context deadline exceeded +} From 8654b622f60beab5680ccecfbc15ed933e2eb2ed Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 16:14:15 +0200 Subject: [PATCH 08/10] Refactored cli.Commands to return an error instead of panicing --- cmd/scw/main.go | 5 ++++- pkg/cli/attach.go | 14 ++++---------- pkg/cli/command.go | 2 +- pkg/cli/commit.go | 14 ++++---------- pkg/cli/cp.go | 13 +++---------- pkg/cli/create.go | 8 ++------ pkg/cli/events.go | 14 ++++---------- pkg/cli/exec.go | 14 ++++---------- pkg/cli/help.go | 5 +++-- pkg/cli/history.go | 12 +++--------- pkg/cli/images.go | 12 +++--------- pkg/cli/info.go | 12 +++--------- pkg/cli/inspect.go | 13 +++---------- pkg/cli/kill.go | 13 +++---------- pkg/cli/login.go | 14 ++++---------- pkg/cli/logout.go | 12 +++--------- pkg/cli/logs.go | 13 +++---------- pkg/cli/port.go | 13 +++---------- pkg/cli/ps.go | 14 ++++---------- pkg/cli/rename.go | 13 +++---------- pkg/cli/restart.go | 13 +++---------- pkg/cli/rm.go | 13 +++---------- pkg/cli/rmi.go | 12 +++--------- pkg/cli/run.go | 19 +++++++------------ pkg/cli/search.go | 13 +++---------- pkg/cli/start.go | 13 +++---------- pkg/cli/stop.go | 13 +++---------- pkg/cli/tag.go | 12 +++--------- pkg/cli/top.go | 13 +++---------- pkg/cli/version.go | 12 +++--------- pkg/cli/wait.go | 13 +++---------- pkg/cli/x_completion.go | 4 +++- pkg/cli/x_flushcache.go | 4 +++- pkg/cli/x_patch.go | 4 +++- 34 files changed, 110 insertions(+), 278 deletions(-) diff --git a/cmd/scw/main.go b/cmd/scw/main.go index 087613aadf..53502aa334 100644 --- a/cmd/scw/main.go +++ b/cmd/scw/main.go @@ -120,7 +120,10 @@ func main() { } cmd.API = api } - cmd.Exec(cmd, cmd.Flag.Args()) + err = cmd.Exec(cmd, cmd.Flag.Args()) + if err != nil { + log.Fatalf("Cannot execute '%s': %v", cmd.Name(), err) + } if cmd.API != nil { cmd.API.Sync() } diff --git a/pkg/cli/attach.go b/pkg/cli/attach.go index fc47dff5f2..fdcfc2205f 100644 --- a/pkg/cli/attach.go +++ b/pkg/cli/attach.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdAttach = &Command{ - Exec: cmdExecAttach, + Exec: runAttach, UsageLine: "attach [OPTIONS] SERVER", Description: "Attach to a server serial console", Help: "Attach to a running server serial console.", @@ -30,7 +27,7 @@ func init() { var attachHelp bool // -h, --help flag var attachNoStdin bool // --no-stdin flag -func cmdExecAttach(cmd *Command, rawArgs []string) { +func runAttach(cmd *Command, rawArgs []string) error { if attachHelp { cmd.PrintUsage() } @@ -43,8 +40,5 @@ func cmdExecAttach(cmd *Command, rawArgs []string) { Server: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunAttach(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'attach': %v", err) - } + return commands.RunAttach(ctx, args) } diff --git a/pkg/cli/command.go b/pkg/cli/command.go index 68910f7831..13e5d8c318 100644 --- a/pkg/cli/command.go +++ b/pkg/cli/command.go @@ -22,7 +22,7 @@ import ( // Command contains everything needed by the cli main loop to calls the workflow, display help and usage, and the context type Command struct { // Exec executes the command - Exec func(cmd *Command, args []string) + Exec func(cmd *Command, args []string) error // Usage is the one-line usage message. UsageLine string diff --git a/pkg/cli/commit.go b/pkg/cli/commit.go index e946feaba2..a1c4a96e33 100644 --- a/pkg/cli/commit.go +++ b/pkg/cli/commit.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdCommit = &Command{ - Exec: cmdExecCommit, + Exec: runCommit, UsageLine: "commit [OPTIONS] SERVER [NAME]", Description: "Create a new snapshot from a server's volume", Help: "Create a new snapshot from a server's volume.", @@ -29,7 +26,7 @@ func init() { var commitVolume int // -v, --volume flag var commitHelp bool // -h, --help flag -func cmdExecCommit(cmd *Command, rawArgs []string) { +func runCommit(cmd *Command, rawArgs []string) error { if commitHelp { cmd.PrintUsage() } @@ -47,8 +44,5 @@ func cmdExecCommit(cmd *Command, rawArgs []string) { } ctx := cmd.GetContext(rawArgs) - err := commands.RunCommit(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'commit': %v", err) - } + return commands.RunCommit(ctx, args) } diff --git a/pkg/cli/cp.go b/pkg/cli/cp.go index f51db23c12..3dc226f2b8 100644 --- a/pkg/cli/cp.go +++ b/pkg/cli/cp.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdCp = &Command{ Exec: runCp, @@ -40,7 +37,7 @@ func init() { var cpHelp bool // -h, --help flag var cpGateway string // -g, --gateway flag -func runCp(cmd *Command, rawArgs []string) { +func runCp(cmd *Command, rawArgs []string) error { if cpHelp { cmd.PrintUsage() } @@ -54,9 +51,5 @@ func runCp(cmd *Command, rawArgs []string) { Destination: rawArgs[1], } ctx := cmd.GetContext(rawArgs) - err := commands.RunCp(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'cp': %v", err) - } - + return commands.RunCp(ctx, args) } diff --git a/pkg/cli/create.go b/pkg/cli/create.go index 6b4fdb9519..65dd30a2c4 100644 --- a/pkg/cli/create.go +++ b/pkg/cli/create.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" ) var cmdCreate = &Command{ @@ -43,7 +42,7 @@ var createVolume string // -v, --volume flag var createHelp bool // -h, --help flag var createTmpSSHKey bool // --tmp-ssh-key flag -func runCreate(cmd *Command, rawArgs []string) { +func runCreate(cmd *Command, rawArgs []string) error { if createHelp { cmd.PrintUsage() } @@ -65,8 +64,5 @@ func runCreate(cmd *Command, rawArgs []string) { args.Volumes = strings.Split(runCreateVolume, " ") } ctx := cmd.GetContext(rawArgs) - err := commands.RunCreate(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'create': %v", err) - } + return commands.RunCreate(ctx, args) } diff --git a/pkg/cli/events.go b/pkg/cli/events.go index 79b54a6959..11c5719476 100644 --- a/pkg/cli/events.go +++ b/pkg/cli/events.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdEvents = &Command{ - Exec: cmdExecEvents, + Exec: runEvents, UsageLine: "events [OPTIONS]", Description: "Get real time events from the API", Help: "Get real time events from the API.", @@ -23,7 +20,7 @@ func init() { // Flags var eventsHelp bool // -h, --help flag -func cmdExecEvents(cmd *Command, rawArgs []string) { +func runEvents(cmd *Command, rawArgs []string) error { if eventsHelp { cmd.PrintUsage() } @@ -33,8 +30,5 @@ func cmdExecEvents(cmd *Command, rawArgs []string) { args := commands.EventsArgs{} ctx := cmd.GetContext(rawArgs) - err := commands.RunEvents(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'events': %v", err) - } + return commands.RunEvents(ctx, args) } diff --git a/pkg/cli/exec.go b/pkg/cli/exec.go index 76eeaae79c..d93bd6ef2f 100644 --- a/pkg/cli/exec.go +++ b/pkg/cli/exec.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdExec = &Command{ - Exec: cmdExecExec, + Exec: runExec, UsageLine: "exec [OPTIONS] SERVER [COMMAND] [ARGS...]", Description: "Run a command on a running server", Help: "Run a command on a running server.", @@ -41,7 +38,7 @@ var execTimeout float64 // -T flag var execHelp bool // -h, --help flag var execGateway string // -g, --gateway flag -func cmdExecExec(cmd *Command, rawArgs []string) { +func runExec(cmd *Command, rawArgs []string) error { if execHelp { cmd.PrintUsage() } @@ -57,8 +54,5 @@ func cmdExecExec(cmd *Command, rawArgs []string) { Command: rawArgs[1:], } ctx := cmd.GetContext(rawArgs) - err := commands.RunExec(ctx, args) - if err != nil { - logrus.Fatalf("Cannot exec 'exec': %v", err) - } + return commands.RunExec(ctx, args) } diff --git a/pkg/cli/help.go b/pkg/cli/help.go index a1c1e18f3f..c6494e09aa 100644 --- a/pkg/cli/help.go +++ b/pkg/cli/help.go @@ -53,7 +53,7 @@ Commands: Run 'scw COMMAND --help' for more information on a command. ` -func runHelp(cmd *Command, args []string) { +func runHelp(cmd *Command, args []string) error { if waitHelp { cmd.PrintUsage() } @@ -73,7 +73,8 @@ func runHelp(cmd *Command, args []string) { t := template.New("top") template.Must(t.Parse(helpTemplate)) if err := t.Execute(os.Stdout, Commands); err != nil { - panic(err) + return err } } + return nil } diff --git a/pkg/cli/history.go b/pkg/cli/history.go index 3f0e808720..2e752eb309 100644 --- a/pkg/cli/history.go +++ b/pkg/cli/history.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdHistory = &Command{ Exec: runHistory, @@ -27,7 +24,7 @@ var historyNoTrunc bool // --no-trunc flag var historyQuiet bool // -q, --quiet flag var historyHelp bool // -h, --help flag -func runHistory(cmd *Command, rawArgs []string) { +func runHistory(cmd *Command, rawArgs []string) error { if historyHelp { cmd.PrintUsage() } @@ -41,8 +38,5 @@ func runHistory(cmd *Command, rawArgs []string) { Image: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunHistory(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'history': %v", err) - } + return commands.RunHistory(ctx, args) } diff --git a/pkg/cli/images.go b/pkg/cli/images.go index f26b1bf3b6..45859c694a 100644 --- a/pkg/cli/images.go +++ b/pkg/cli/images.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdImages = &Command{ Exec: runImages, @@ -29,7 +26,7 @@ var imagesQ bool // -q flag var imagesNoTrunc bool // -no-trunc flag var imagesHelp bool // -h, --help flag -func runImages(cmd *Command, rawArgs []string) { +func runImages(cmd *Command, rawArgs []string) error { if imagesHelp { cmd.PrintUsage() } @@ -43,8 +40,5 @@ func runImages(cmd *Command, rawArgs []string) { NoTrunc: imagesNoTrunc, } ctx := cmd.GetContext(rawArgs) - err := commands.RunImages(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'images': %v", err) - } + return commands.RunImages(ctx, args) } diff --git a/pkg/cli/info.go b/pkg/cli/info.go index 74b9e207ee..db3a38785a 100644 --- a/pkg/cli/info.go +++ b/pkg/cli/info.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdInfo = &Command{ Exec: runInfo, @@ -23,7 +20,7 @@ func init() { // Flags var infoHelp bool // -h, --help flag -func runInfo(cmd *Command, rawArgs []string) { +func runInfo(cmd *Command, rawArgs []string) error { if infoHelp { cmd.PrintUsage() } @@ -33,8 +30,5 @@ func runInfo(cmd *Command, rawArgs []string) { args := commands.InfoArgs{} ctx := cmd.GetContext(rawArgs) - err := commands.RunInfo(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'info': %v", err) - } + return commands.RunInfo(ctx, args) } diff --git a/pkg/cli/inspect.go b/pkg/cli/inspect.go index 0c5cba302e..14c8de0745 100644 --- a/pkg/cli/inspect.go +++ b/pkg/cli/inspect.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdInspect = &Command{ Exec: runInspect, @@ -45,7 +41,7 @@ var inspectFormat string // -f, --format flag var inspectBrowser bool // -b, --browser flag var inspectHelp bool // -h, --help flag -func runInspect(cmd *Command, rawArgs []string) { +func runInspect(cmd *Command, rawArgs []string) error { if inspectHelp { cmd.PrintUsage() } @@ -59,8 +55,5 @@ func runInspect(cmd *Command, rawArgs []string) { Identifiers: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunInspect(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'inspect': %v", err) - } + return commands.RunInspect(ctx, args) } diff --git a/pkg/cli/kill.go b/pkg/cli/kill.go index a5d181e465..a4c1fb441f 100644 --- a/pkg/cli/kill.go +++ b/pkg/cli/kill.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdKill = &Command{ Exec: runKill, @@ -27,7 +23,7 @@ func init() { var killHelp bool // -h, --help flag var killGateway string // -g, --gateway flag -func runKill(cmd *Command, rawArgs []string) { +func runKill(cmd *Command, rawArgs []string) error { if killHelp { cmd.PrintUsage() } @@ -40,8 +36,5 @@ func runKill(cmd *Command, rawArgs []string) { Server: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunKill(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'kill': %v", err) - } + return commands.RunKill(ctx, args) } diff --git a/pkg/cli/login.go b/pkg/cli/login.go index 8cbe1bd6e2..bf76d93f00 100644 --- a/pkg/cli/login.go +++ b/pkg/cli/login.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - log "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdLogin = &Command{ - Exec: cmdExecLogin, + Exec: runLogin, UsageLine: "login [OPTIONS]", Description: "Log in to Scaleway API", Help: `Generates a configuration file in '/home/$USER/.scwrc' @@ -32,7 +29,7 @@ var organization string // -o flag var token string // -t flag var loginHelp bool // -h, --help flag -func cmdExecLogin(cmd *Command, rawArgs []string) { +func runLogin(cmd *Command, rawArgs []string) error { if loginHelp { cmd.PrintUsage() } @@ -45,8 +42,5 @@ func cmdExecLogin(cmd *Command, rawArgs []string) { Token: token, } ctx := cmd.GetContext(rawArgs) - err := commands.RunLogin(ctx, args) - if err != nil { - log.Fatalf("Cannot execute 'login': %v", err) - } + return commands.RunLogin(ctx, args) } diff --git a/pkg/cli/logout.go b/pkg/cli/logout.go index e8d0160a7a..4f045bd212 100644 --- a/pkg/cli/logout.go +++ b/pkg/cli/logout.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdLogout = &Command{ Exec: runLogout, @@ -23,7 +20,7 @@ func init() { // FLags var logoutHelp bool // -h, --help flag -func runLogout(cmd *Command, rawArgs []string) { +func runLogout(cmd *Command, rawArgs []string) error { if logoutHelp { cmd.PrintUsage() } @@ -33,8 +30,5 @@ func runLogout(cmd *Command, rawArgs []string) { args := commands.LogoutArgs{} ctx := cmd.GetContext(rawArgs) - err := commands.RunLogout(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'logout': %v", err) - } + return commands.RunLogout(ctx, args) } diff --git a/pkg/cli/logs.go b/pkg/cli/logs.go index a89091c10b..c18e657cb1 100644 --- a/pkg/cli/logs.go +++ b/pkg/cli/logs.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdLogs = &Command{ Exec: runLogs, @@ -26,7 +22,7 @@ func init() { var logsHelp bool // -h, --help flag var logsGateway string // -g, --gateway flag -func runLogs(cmd *Command, rawArgs []string) { +func runLogs(cmd *Command, rawArgs []string) error { if logsHelp { cmd.PrintUsage() } @@ -39,8 +35,5 @@ func runLogs(cmd *Command, rawArgs []string) { Server: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunLogs(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'logs': %v", err) - } + return commands.RunLogs(ctx, args) } diff --git a/pkg/cli/port.go b/pkg/cli/port.go index e7bf460330..dd5c18f1c1 100644 --- a/pkg/cli/port.go +++ b/pkg/cli/port.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdPort = &Command{ Exec: runPort, @@ -26,7 +22,7 @@ func init() { var portHelp bool // -h, --help flag var portGateway string // -g, --gateway flag -func runPort(cmd *Command, rawArgs []string) { +func runPort(cmd *Command, rawArgs []string) error { if portHelp { cmd.PrintUsage() } @@ -39,8 +35,5 @@ func runPort(cmd *Command, rawArgs []string) { Server: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunPort(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'port': %v", err) - } + return commands.RunPort(ctx, args) } diff --git a/pkg/cli/ps.go b/pkg/cli/ps.go index 91066164fe..396ef331cc 100644 --- a/pkg/cli/ps.go +++ b/pkg/cli/ps.go @@ -4,13 +4,10 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdPs = &Command{ - Exec: cmdExecPs, + Exec: runPs, UsageLine: "ps [OPTIONS]", Description: "List servers", Help: "List servers. By default, only running servers are displayed.", @@ -33,7 +30,7 @@ var psNoTrunc bool // -no-trunc flag var psN int // -n flag var psHelp bool // -h, --help flag -func cmdExecPs(cmd *Command, rawArgs []string) { +func runPs(cmd *Command, rawArgs []string) error { if psHelp { cmd.PrintUsage() } @@ -49,8 +46,5 @@ func cmdExecPs(cmd *Command, rawArgs []string) { NLast: psN, } ctx := cmd.GetContext(rawArgs) - err := commands.RunPs(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'ps': %v", err) - } + return commands.RunPs(ctx, args) } diff --git a/pkg/cli/rename.go b/pkg/cli/rename.go index 8aa6a6978e..49c0280cb3 100644 --- a/pkg/cli/rename.go +++ b/pkg/cli/rename.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdRename = &Command{ Exec: runRename, @@ -24,7 +20,7 @@ func init() { // Flags var renameHelp bool // -h, --help flag -func runRename(cmd *Command, rawArgs []string) { +func runRename(cmd *Command, rawArgs []string) error { if renameHelp { cmd.PrintUsage() } @@ -37,8 +33,5 @@ func runRename(cmd *Command, rawArgs []string) { NewName: rawArgs[1], } ctx := cmd.GetContext(rawArgs) - err := commands.RunRename(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'rename': %v", err) - } + return commands.RunRename(ctx, args) } diff --git a/pkg/cli/restart.go b/pkg/cli/restart.go index ba045b6fee..4c100932ff 100644 --- a/pkg/cli/restart.go +++ b/pkg/cli/restart.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdRestart = &Command{ Exec: runRestart, @@ -23,7 +20,7 @@ func init() { // Flags var restartHelp bool // -h, --help flag -func runRestart(cmd *Command, rawArgs []string) { +func runRestart(cmd *Command, rawArgs []string) error { if restartHelp { cmd.PrintUsage() } @@ -35,9 +32,5 @@ func runRestart(cmd *Command, rawArgs []string) { Servers: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunRestart(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'restart': %v", err) - } - + return commands.RunRestart(ctx, args) } diff --git a/pkg/cli/rm.go b/pkg/cli/rm.go index 0a420614ce..9375c17e4e 100644 --- a/pkg/cli/rm.go +++ b/pkg/cli/rm.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdRm = &Command{ Exec: runRm, @@ -28,7 +25,7 @@ func init() { // Flags var rmHelp bool // -h, --help flag -func runRm(cmd *Command, rawArgs []string) { +func runRm(cmd *Command, rawArgs []string) error { if rmHelp { cmd.PrintUsage() } @@ -40,9 +37,5 @@ func runRm(cmd *Command, rawArgs []string) { Servers: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunRm(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'rm': %v", err) - } - + return commands.RunRm(ctx, args) } diff --git a/pkg/cli/rmi.go b/pkg/cli/rmi.go index 2c7375ec92..6c0f04e784 100644 --- a/pkg/cli/rmi.go +++ b/pkg/cli/rmi.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdRmi = &Command{ Exec: runRmi, @@ -27,7 +24,7 @@ func init() { // Flags var rmiHelp bool // -h, --help flag -func runRmi(cmd *Command, rawArgs []string) { +func runRmi(cmd *Command, rawArgs []string) error { if rmiHelp { cmd.PrintUsage() } @@ -39,8 +36,5 @@ func runRmi(cmd *Command, rawArgs []string) { Images: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunRmi(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'rmi': %v", err) - } + return commands.RunRmi(ctx, args) } diff --git a/pkg/cli/run.go b/pkg/cli/run.go index d8c1fb0755..4966990f7d 100644 --- a/pkg/cli/run.go +++ b/pkg/cli/run.go @@ -5,11 +5,9 @@ package cli import ( + "fmt" "strings" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - log "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - "github.com/scaleway/scaleway-cli/pkg/commands" ) @@ -58,7 +56,7 @@ var runDetachFlag bool // -d, --detach flag var runGateway string // -g, --gateway flag var runTmpSSHKey bool // --tmp-ssh-key flag -func runRun(cmd *Command, rawArgs []string) { +func runRun(cmd *Command, rawArgs []string) error { if runHelpFlag { cmd.PrintUsage() } @@ -66,16 +64,16 @@ func runRun(cmd *Command, rawArgs []string) { cmd.PrintShortUsage() } if runAttachFlag && len(rawArgs) > 1 { - log.Fatalf("Conflicting options: -a and COMMAND") + return fmt.Errorf("conflicting options: -a and COMMAND") } if runAttachFlag && runDetachFlag { - log.Fatalf("Conflicting options: -a and -d") + return fmt.Errorf("conflicting options: -a and -d") } if runDetachFlag && len(rawArgs) > 1 { - log.Fatalf("Conflicting options: -d and COMMAND") + return fmt.Errorf("conflicting options: -d and COMMAND") } if runAutoRemove && runDetachFlag { - log.Fatalf("Conflicting options: --attach and --rm") + return fmt.Errorf("conflicting options: --detach and --rm") } args := commands.RunArgs{ @@ -99,8 +97,5 @@ func runRun(cmd *Command, rawArgs []string) { args.Volumes = strings.Split(runCreateVolume, " ") } ctx := cmd.GetContext(rawArgs) - err := commands.Run(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'run': %v", err) - } + return commands.Run(ctx, args) } diff --git a/pkg/cli/search.go b/pkg/cli/search.go index af832965c6..a3502df9e7 100644 --- a/pkg/cli/search.go +++ b/pkg/cli/search.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdSearch = &Command{ Exec: runSearch, @@ -26,7 +22,7 @@ func init() { var searchNoTrunc bool // --no-trunc flag var searchHelp bool // -h, --help flag -func runSearch(cmd *Command, rawArgs []string) { +func runSearch(cmd *Command, rawArgs []string) error { if searchHelp { cmd.PrintUsage() } @@ -39,8 +35,5 @@ func runSearch(cmd *Command, rawArgs []string) { NoTrunc: searchNoTrunc, } ctx := cmd.GetContext(rawArgs) - err := commands.RunSearch(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'search': %v", err) - } + return commands.RunSearch(ctx, args) } diff --git a/pkg/cli/start.go b/pkg/cli/start.go index ddb536ddf6..6f4a9c0e59 100644 --- a/pkg/cli/start.go +++ b/pkg/cli/start.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdStart = &Command{ Exec: runStart, @@ -28,7 +24,7 @@ var startW bool // -w flag var startTimeout float64 // -T flag var startHelp bool // -h, --help flag -func runStart(cmd *Command, rawArgs []string) { +func runStart(cmd *Command, rawArgs []string) error { if startHelp { cmd.PrintUsage() } @@ -42,8 +38,5 @@ func runStart(cmd *Command, rawArgs []string) { Wait: startW, } ctx := cmd.GetContext(rawArgs) - err := commands.RunStart(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'start': %v", err) - } + return commands.RunStart(ctx, args) } diff --git a/pkg/cli/stop.go b/pkg/cli/stop.go index 226cdc8cd5..2e8c896e01 100644 --- a/pkg/cli/stop.go +++ b/pkg/cli/stop.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdStop = &Command{ Exec: runStop, @@ -36,7 +32,7 @@ var stopT bool // -t flag var stopHelp bool // -h, --help flag var stopW bool // -w, --wait flat -func runStop(cmd *Command, rawArgs []string) { +func runStop(cmd *Command, rawArgs []string) error { if stopHelp { cmd.PrintUsage() } @@ -50,8 +46,5 @@ func runStop(cmd *Command, rawArgs []string) { Servers: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunStop(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'stop': %v", err) - } + return commands.RunStop(ctx, args) } diff --git a/pkg/cli/tag.go b/pkg/cli/tag.go index 3c655694c9..1be7732edb 100644 --- a/pkg/cli/tag.go +++ b/pkg/cli/tag.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdTag = &Command{ Exec: runTag, @@ -23,7 +20,7 @@ func init() { // Flags var tagHelp bool // -h, --help flag -func runTag(cmd *Command, rawArgs []string) { +func runTag(cmd *Command, rawArgs []string) error { if tagHelp { cmd.PrintUsage() } @@ -36,8 +33,5 @@ func runTag(cmd *Command, rawArgs []string) { Name: rawArgs[1], } ctx := cmd.GetContext(rawArgs) - err := commands.RunTag(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'tag': %v", err) - } + return commands.RunTag(ctx, args) } diff --git a/pkg/cli/top.go b/pkg/cli/top.go index 992e3c4114..849a327456 100644 --- a/pkg/cli/top.go +++ b/pkg/cli/top.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdTop = &Command{ Exec: runTop, @@ -26,7 +22,7 @@ func init() { var topHelp bool // -h, --help flag var topGateway string // -g, --gateway flag -func runTop(cmd *Command, rawArgs []string) { +func runTop(cmd *Command, rawArgs []string) error { if topHelp { cmd.PrintUsage() } @@ -39,8 +35,5 @@ func runTop(cmd *Command, rawArgs []string) { Server: rawArgs[0], } ctx := cmd.GetContext(rawArgs) - err := commands.RunTop(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'top': %v", err) - } + return commands.RunTop(ctx, args) } diff --git a/pkg/cli/version.go b/pkg/cli/version.go index 994af346ea..3b1e5e579e 100644 --- a/pkg/cli/version.go +++ b/pkg/cli/version.go @@ -4,10 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/pkg/commands" - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdVersion = &Command{ Exec: runVersion, @@ -23,7 +20,7 @@ func init() { // Flags var versionHelp bool // -h, --help flag -func runVersion(cmd *Command, rawArgs []string) { +func runVersion(cmd *Command, rawArgs []string) error { if versionHelp { cmd.PrintUsage() } @@ -33,8 +30,5 @@ func runVersion(cmd *Command, rawArgs []string) { args := commands.VersionArgs{} ctx := cmd.GetContext(rawArgs) - err := commands.Version(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'version': %v", err) - } + return commands.Version(ctx, args) } diff --git a/pkg/cli/wait.go b/pkg/cli/wait.go index 7086bf909d..e2e5f94eeb 100644 --- a/pkg/cli/wait.go +++ b/pkg/cli/wait.go @@ -4,11 +4,7 @@ package cli -import ( - "github.com/scaleway/scaleway-cli/vendor/github.com/Sirupsen/logrus" - - "github.com/scaleway/scaleway-cli/pkg/commands" -) +import "github.com/scaleway/scaleway-cli/pkg/commands" var cmdWait = &Command{ Exec: runWait, @@ -24,7 +20,7 @@ func init() { // Flags var waitHelp bool // -h, --help flag -func runWait(cmd *Command, rawArgs []string) { +func runWait(cmd *Command, rawArgs []string) error { if waitHelp { cmd.PrintUsage() } @@ -36,8 +32,5 @@ func runWait(cmd *Command, rawArgs []string) { Servers: rawArgs, } ctx := cmd.GetContext(rawArgs) - err := commands.RunWait(ctx, args) - if err != nil { - logrus.Fatalf("Cannot execute 'wait': %v", err) - } + return commands.RunWait(ctx, args) } diff --git a/pkg/cli/x_completion.go b/pkg/cli/x_completion.go index 7133e26112..081300e6d5 100644 --- a/pkg/cli/x_completion.go +++ b/pkg/cli/x_completion.go @@ -51,7 +51,7 @@ func wordifyName(name string, kind string) string { return ret } -func runCompletion(cmd *Command, args []string) { +func runCompletion(cmd *Command, args []string) error { if completionHelp { cmd.PrintUsage() } @@ -110,4 +110,6 @@ func runCompletion(cmd *Command, args []string) { sort.Strings(elements) fmt.Println(strings.Join(utils.RemoveDuplicates(elements), "\n")) + + return nil } diff --git a/pkg/cli/x_flushcache.go b/pkg/cli/x_flushcache.go index 87a280377b..cbb318c840 100644 --- a/pkg/cli/x_flushcache.go +++ b/pkg/cli/x_flushcache.go @@ -25,7 +25,7 @@ func init() { // Flags var flushCacheHelp bool // -h, --help flag -func runFlushCache(cmd *Command, args []string) { +func runFlushCache(cmd *Command, args []string) error { if flushCacheHelp { cmd.PrintUsage() } @@ -39,4 +39,6 @@ func runFlushCache(cmd *Command, args []string) { } fmt.Println("Cache flushed") + + return nil } diff --git a/pkg/cli/x_patch.go b/pkg/cli/x_patch.go index 670c315438..aa3e391cdf 100644 --- a/pkg/cli/x_patch.go +++ b/pkg/cli/x_patch.go @@ -32,7 +32,7 @@ func init() { // Flags var patchHelp bool // -h, --help flag -func runPatch(cmd *Command, args []string) { +func runPatch(cmd *Command, args []string) error { if patchHelp { cmd.PrintUsage() } @@ -104,4 +104,6 @@ func runPatch(cmd *Command, args []string) { log.Fatalf("_patch not implemented for this kind of object") } fmt.Println(ident.Identifier) + + return nil } From 9aeaaec67f5c7860c65d1d7a6cb2c53af6f0be1d Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Fri, 14 Aug 2015 16:14:40 +0200 Subject: [PATCH 09/10] Basic testing for 'run' command --- pkg/cli/run_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 pkg/cli/run_test.go diff --git a/pkg/cli/run_test.go b/pkg/cli/run_test.go new file mode 100644 index 0000000000..0a9b667f1b --- /dev/null +++ b/pkg/cli/run_test.go @@ -0,0 +1,32 @@ +package cli + +import ( + "fmt" + "testing" + + . "github.com/scaleway/scaleway-cli/vendor/github.com/smartystreets/goconvey/convey" +) + +func TestRunRun(t *testing.T) { + Convey("Testing runRun", t, func() { + cmdRun.Flag.Parse([]string{"-a", "-d"}) + rawArgs := []string{"my-server"} + So(runRun(cmdRun, rawArgs), ShouldResemble, fmt.Errorf("conflicting options: -a and -d")) + runAttachFlag = false + runDetachFlag = false + + cmdRun.Flag.Parse([]string{"-a"}) + rawArgs = []string{"my-server", "my-command"} + So(runRun(cmdRun, rawArgs), ShouldResemble, fmt.Errorf("conflicting options: -a and COMMAND")) + runAttachFlag = false + + cmdRun.Flag.Parse([]string{"-d"}) + rawArgs = []string{"my-server", "my-command"} + So(runRun(cmdRun, rawArgs), ShouldResemble, fmt.Errorf("conflicting options: -d and COMMAND")) + runDetachFlag = false + + cmdRun.Flag.Parse([]string{"-d", "--rm"}) + rawArgs = []string{"my-server"} + So(runRun(cmdRun, rawArgs), ShouldResemble, fmt.Errorf("conflicting options: --detach and --rm")) + }) +} From 83fe0ff824e6edf2b8134419ba931bb600531d65 Mon Sep 17 00:00:00 2001 From: Manfred Touron Date: Mon, 17 Aug 2015 14:57:05 +0200 Subject: [PATCH 10/10] Testing GeneratingAnSSHKey --- pkg/utils/utils_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index 4cc5acb6ea..3fffbcd7d3 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -1,6 +1,9 @@ package utils import ( + "io/ioutil" + "os" + "path/filepath" "sort" "strings" "testing" @@ -84,3 +87,28 @@ func TestGetConfigFilePath(t *testing.T) { So(strings.Contains(configPath, homedir), ShouldBeTrue) }) } + +func TestGeneratingAnSSHKey(t *testing.T) { + Convey("Testing GeneratingAnSSHKey()", t, func() { + streams := SpawnRedirection{ + Stdout: os.Stdout, + Stderr: os.Stderr, + Stdin: os.Stdin, + } + + tmpDir, err := ioutil.TempDir("/tmp", "scaleway-test") + So(err, ShouldBeNil) + + tmpFile, err := ioutil.TempFile(tmpDir, "ssh-key") + So(err, ShouldBeNil) + + err = os.Remove(tmpFile.Name()) + So(err, ShouldBeNil) + + filePath, err := GeneratingAnSSHKey(streams, tmpDir, filepath.Base(tmpFile.Name())) + So(err, ShouldBeNil) + So(filePath, ShouldEqual, tmpFile.Name()) + + os.Remove(tmpFile.Name()) + }) +}