├── .gitignore ├── Godeps ├── Godeps.json └── Readme ├── Procfile ├── README.md ├── db └── migrations │ ├── 2014-11-17-18-04-create-match-requests.sql │ ├── 2014-11-17-18-08-create-participants.sql │ └── 2014-11-17-18-09-create-results.sql ├── domain └── domain.go ├── go.mod ├── go.sum ├── handlers.go ├── handlers_test.go ├── io ├── io.go ├── io_suite_test.go └── io_test.go ├── main.go ├── manifest.yml ├── pong_matcher_go_suite_test.go └── vendor ├── github.com ├── coopernurse │ └── gorp │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── dialect.go │ │ ├── errors.go │ │ ├── gorp.go │ │ └── test_all.sh ├── go-sql-driver │ └── mysql │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── AUTHORS │ │ ├── CHANGELOG.md │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── appengine.go │ │ ├── buffer.go │ │ ├── collations.go │ │ ├── connection.go │ │ ├── const.go │ │ ├── driver.go │ │ ├── errors.go │ │ ├── infile.go │ │ ├── packets.go │ │ ├── result.go │ │ ├── rows.go │ │ ├── statement.go │ │ ├── transaction.go │ │ └── utils.go ├── gorilla │ ├── context │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── context.go │ │ └── doc.go │ └── mux │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── mux.go │ │ ├── regexp.go │ │ └── route.go ├── nu7hatch │ └── gouuid │ │ ├── .gitignore │ │ ├── COPYING │ │ ├── README.md │ │ └── uuid.go ├── onsi │ ├── ginkgo │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── config │ │ │ └── config.go │ │ ├── ginkgo_dsl.go │ │ ├── internal │ │ │ ├── codelocation │ │ │ │ └── code_location.go │ │ │ ├── containernode │ │ │ │ └── container_node.go │ │ │ ├── failer │ │ │ │ └── failer.go │ │ │ ├── leafnodes │ │ │ │ ├── benchmarker.go │ │ │ │ ├── interfaces.go │ │ │ │ ├── it_node.go │ │ │ │ ├── measure_node.go │ │ │ │ ├── runner.go │ │ │ │ ├── setup_nodes.go │ │ │ │ ├── suite_nodes.go │ │ │ │ ├── synchronized_after_suite_node.go │ │ │ │ └── synchronized_before_suite_node.go │ │ │ ├── remote │ │ │ │ ├── aggregator.go │ │ │ │ ├── forwarding_reporter.go │ │ │ │ ├── output_interceptor.go │ │ │ │ ├── output_interceptor_unix.go │ │ │ │ ├── output_interceptor_win.go │ │ │ │ └── server.go │ │ │ ├── spec │ │ │ │ ├── index_computer.go │ │ │ │ ├── spec.go │ │ │ │ └── specs.go │ │ │ ├── specrunner │ │ │ │ ├── random_id.go │ │ │ │ └── spec_runner.go │ │ │ ├── suite │ │ │ │ └── suite.go │ │ │ ├── testingtproxy │ │ │ │ └── testing_t_proxy.go │ │ │ └── writer │ │ │ │ ├── fake_writer.go │ │ │ │ └── writer.go │ │ ├── reporters │ │ │ ├── default_reporter.go │ │ │ ├── fake_reporter.go │ │ │ ├── junit_reporter.go │ │ │ ├── reporter.go │ │ │ ├── stenographer │ │ │ │ ├── console_logging.go │ │ │ │ ├── fake_stenographer.go │ │ │ │ └── stenographer.go │ │ │ └── teamcity_reporter.go │ │ └── types │ │ │ ├── code_location.go │ │ │ ├── synchronization.go │ │ │ └── types.go │ └── gomega │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── format │ │ └── format.go │ │ ├── gomega_dsl.go │ │ ├── internal │ │ ├── assertion │ │ │ └── assertion.go │ │ ├── asyncassertion │ │ │ └── async_assertion.go │ │ └── testingtsupport │ │ │ └── testing_t_support.go │ │ ├── matchers.go │ │ ├── matchers │ │ ├── assignable_to_type_of_matcher.go │ │ ├── be_closed_matcher.go │ │ ├── be_empty_matcher.go │ │ ├── be_equivalent_to_matcher.go │ │ ├── be_false_matcher.go │ │ ├── be_nil_matcher.go │ │ ├── be_numerically_matcher.go │ │ ├── be_sent_matcher.go │ │ ├── be_temporally_matcher.go │ │ ├── be_true_matcher.go │ │ ├── be_zero_matcher.go │ │ ├── consist_of.go │ │ ├── contain_element_matcher.go │ │ ├── contain_substring_matcher.go │ │ ├── equal_matcher.go │ │ ├── have_key_matcher.go │ │ ├── have_key_with_value_matcher.go │ │ ├── have_len_matcher.go │ │ ├── have_occurred_matcher.go │ │ ├── have_prefix_matcher.go │ │ ├── have_suffix_matcher.go │ │ ├── match_error_matcher.go │ │ ├── match_json_matcher.go │ │ ├── match_regexp_matcher.go │ │ ├── panic_matcher.go │ │ ├── receive_matcher.go │ │ ├── succeed_matcher.go │ │ ├── support │ │ │ └── goraph │ │ │ │ ├── bipartitegraph │ │ │ │ ├── bipartitegraph.go │ │ │ │ └── bipartitegraphmatching.go │ │ │ │ ├── edge │ │ │ │ └── edge.go │ │ │ │ ├── node │ │ │ │ └── node.go │ │ │ │ └── util │ │ │ │ └── util.go │ │ └── type_support.go │ │ └── types │ │ └── types.go └── rubenv │ └── sql-migrate │ ├── .gitignore │ ├── .travis.yml │ ├── README.md │ ├── doc.go │ ├── migrate.go │ └── sqlparse │ ├── README.md │ └── sqlparse.go ├── gopkg.in └── guregu │ └── null.v2 │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── bool.go │ ├── float.go │ ├── int.go │ └── string.go └── modules.txt /.gitignore: -------------------------------------------------------------------------------- 1 | main 2 | tags 3 | pong_matcher_go 4 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: pong_matcher_go 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CF example app: ping-pong matching server 2 | 3 | This is an app to match ping-pong players with each other. It's currently an 4 | API only, so you have to use `curl` to interact with it. 5 | 6 | It has an [acceptance test suite][acceptance-test] you might like to look at. 7 | 8 | **Note**: We highly recommend that you use the latest versions of any software required by this sample application. 9 | 10 | ## Running on [Pivotal Web Services][pws] 11 | 12 | Log in. 13 | 14 | ```bash 15 | cf login -a https://api.run.pivotal.io 16 | ``` 17 | 18 | Target your org / space. An empty space is recommended, to avoid naming collisions. 19 | 20 | ```bash 21 | cf target -o myorg -s myspace 22 | ``` 23 | 24 | Sign up for a cleardb instance. 25 | 26 | ```bash 27 | cf create-service cleardb spark mysql 28 | ``` 29 | 30 | Push the app. Its manifest assumes you called your ClearDB instance 'mysql'. 31 | 32 | ```bash 33 | cf push -n mysubdomain 34 | ``` 35 | 36 | Export the test host 37 | 38 | ```bash 39 | export HOST=http://mysubdomain.cfapps.io 40 | ``` 41 | 42 | Now follow the [interaction instructions](#interaction-instructions). 43 | 44 | ## Running locally 45 | 46 | The following assumes you have a working, recent version of Go installed, and 47 | you have a properly set-up Go workspace. 48 | 49 | The minimum required set-up for a Go workspace is a directory structured as shown below: 50 | 51 | ``` 52 | |- 53 | |-src 54 | |-bin 55 | |-pkg 56 | ``` 57 | 58 | Also, ensure that you set your GOPATH environment variable using your workspace name: `export GOPATH=$HOME/.../`. 59 | 60 | 1. Install and start MySQL: 61 | 62 | ```bash 63 | brew install mysql 64 | mysql.server start 65 | mysql -u root 66 | ``` 67 | 68 | 1. Create a database user and table in the MySQL REPL you just opened: 69 | 70 | ```sql 71 | CREATE USER 'gopong'@'localhost' IDENTIFIED BY 'gopong'; 72 | CREATE DATABASE pong_matcher_go_development; 73 | GRANT ALL ON pong_matcher_go_development.* TO 'gopong'@'localhost'; 74 | exit 75 | ``` 76 | 1. Install and start the application server: 77 | 78 | ```bash 79 | go get github.com/cloudfoundry-samples/pong_matcher_go 80 | cd $GOPATH/src/github.com/cloudfoundry-samples/pong_matcher_go 81 | go install 82 | $GOPATH/bin/pong_matcher_go 83 | ``` 84 | 85 | 1. Export the test host in another shell, where you can then run the interactions: 86 | 87 | ```bash 88 | export HOST=http://localhost:3000 89 | ``` 90 | 91 | Now follow the [interaction instructions](#interaction-instructions). 92 | 93 | ## Interaction instructions 94 | 95 | Start by clearing the database from any previous tests. 96 | You should get a 200. 97 | 98 | ```bash 99 | curl -v -X DELETE $HOST/all 100 | ``` 101 | 102 | Then request a match, providing both a request ID and player ID. Again, you 103 | should get a 200. 104 | 105 | ```bash 106 | curl -v -H "Content-Type: application/json" -X PUT $HOST/match_requests/firstrequest -d '{"player": "andrew"}' 107 | ``` 108 | 109 | Now pretend to be someone else requesting a match: 110 | 111 | ```bash 112 | curl -v -H "Content-Type: application/json" -X PUT $HOST/match_requests/secondrequest -d '{"player": "navratilova"}' 113 | ``` 114 | 115 | Let's check on the status of our first match request: 116 | 117 | ```bash 118 | curl -v -X GET $HOST/match_requests/firstrequest 119 | ``` 120 | 121 | The bottom of the output should show you the match_id. You'll need this in the 122 | next step. 123 | 124 | Now pretend that you've got back to your desk and need to enter the result: 125 | 126 | ```bash 127 | curl -v -H "Content-Type: application/json" -X POST $HOST/results -d ' 128 | { 129 | "match_id":"thematchidyoureceived", 130 | "winner":"andrew", 131 | "loser":"navratilova" 132 | }' 133 | ``` 134 | 135 | You should get a 201 Created response. 136 | 137 | Future requests with different player IDs should not cause a match with someone 138 | who has already played. The program is not yet useful enough to 139 | allow pairs who've already played to play again. 140 | 141 | [acceptance-test]:https://github.com/cloudfoundry-samples/pong_matcher_acceptance 142 | [pws]:https://run.pivotal.io 143 | -------------------------------------------------------------------------------- /db/migrations/2014-11-17-18-04-create-match-requests.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | CREATE TABLE `match_requests` ( 3 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 4 | `uuid` varchar(255) DEFAULT NULL, 5 | `requester_id` varchar(255) DEFAULT NULL, 6 | PRIMARY KEY (`id`) 7 | ); 8 | 9 | -- +migrate Down 10 | DROP TABLE match_requests; 11 | -------------------------------------------------------------------------------- /db/migrations/2014-11-17-18-08-create-participants.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | CREATE TABLE `participants` ( 3 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 4 | `match_id` varchar(255) DEFAULT NULL, 5 | `match_request_uuid` varchar(255) DEFAULT NULL, 6 | `player_id` varchar(255) DEFAULT NULL, 7 | `opponent_id` varchar(255) DEFAULT NULL, 8 | PRIMARY KEY (`id`), 9 | UNIQUE KEY `match_request_uuid` (`match_request_uuid`) 10 | ); 11 | 12 | -- +migrate Down 13 | DROP TABLE participants; 14 | -------------------------------------------------------------------------------- /db/migrations/2014-11-17-18-09-create-results.sql: -------------------------------------------------------------------------------- 1 | -- +migrate Up 2 | CREATE TABLE `results` ( 3 | `id` bigint(20) NOT NULL AUTO_INCREMENT, 4 | `match_id` varchar(255) DEFAULT NULL, 5 | `winner` varchar(255) DEFAULT NULL, 6 | `loser` varchar(255) DEFAULT NULL, 7 | PRIMARY KEY (`id`) 8 | ); 9 | 10 | -- +migrate Down 11 | DROP TABLE `results`; 12 | -------------------------------------------------------------------------------- /domain/domain.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "gopkg.in/guregu/null.v2" 5 | ) 6 | 7 | type MatchRequest struct { 8 | Id int64 `json:"-" db:"id"` 9 | Uuid string `json:"id" db:"uuid"` 10 | RequesterId string `json:"player" db:"requester_id"` 11 | MatchId null.String `json:"match_id" db:"-"` 12 | } 13 | 14 | type Participant struct { 15 | Id int64 `db:"id"` 16 | MatchId string `db:"match_id"` 17 | MatchRequestUuid string `db:"match_request_uuid"` 18 | PlayerId string `db:"player_id"` 19 | OpponentId string `db:"opponent_id"` 20 | } 21 | 22 | type Match struct { 23 | Id string `json:"id"` 24 | MatchRequest1Id string `json:"match_request_1_id"` 25 | MatchRequest2Id string `json:"match_request_2_id"` 26 | } 27 | 28 | type Result struct { 29 | Id int64 `json:"-" db:"id"` 30 | MatchId string `json:"match_id" db:"match_id"` 31 | Winner string `json:"winner" db:"winner"` 32 | Loser string `json:"loser" db:"loser"` 33 | } 34 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cloudfoundry-samples/pong_matcher_go 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/coopernurse/gorp v1.6.2-0.20140906144417-5d19ebd22fdc 7 | github.com/go-sql-driver/mysql v1.2.1-0.20140926190841-954375029540 8 | github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 // indirect 9 | github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e 10 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d 11 | github.com/onsi/ginkgo v1.1.1-0.20141113002505-9c7cbc493e1b 12 | github.com/onsi/gomega v0.0.0-20141104003221-2cd6d99ccf3a 13 | github.com/rubenv/sql-migrate v0.0.0-20141001072755-09d124bf5f0e 14 | gopkg.in/guregu/null.v2 v2.1.1 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/coopernurse/gorp v1.6.2-0.20140906144417-5d19ebd22fdc h1:c2qJk01aA2kLGbNZMHgYitY7sGTmIAEqhHKz84zcax4= 2 | github.com/coopernurse/gorp v1.6.2-0.20140906144417-5d19ebd22fdc/go.mod h1:wkfIkQktc4uuBo0kLNE8tMMN9okbsTa2orfZvBaL9F8= 3 | github.com/go-sql-driver/mysql v1.2.1-0.20140926190841-954375029540 h1:gIPaR0uO9daNQjRvOU5x9HlVqZcjngcm0vLu28pgQl4= 4 | github.com/go-sql-driver/mysql v1.2.1-0.20140926190841-954375029540/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 5 | github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 h1:yCHB2BCyFu0V6ChUHb8sF2VodD5B0PAgPDoCxBE7ICQ= 6 | github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= 7 | github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e h1:nH09qCdJVZxw0nRVfm14xjXkw2puLyLPN56n4u+vTC0= 8 | github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 9 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= 10 | github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= 11 | github.com/onsi/ginkgo v1.1.1-0.20141113002505-9c7cbc493e1b h1:8z+1kxoxAuyMs1oxHg6faxPsqZyoKKR2ptP6ZFSvy3A= 12 | github.com/onsi/ginkgo v1.1.1-0.20141113002505-9c7cbc493e1b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 13 | github.com/onsi/gomega v0.0.0-20141104003221-2cd6d99ccf3a h1:mbIYHraLYMrrbspRyuWS+xZ7GyvAN9iTBkAksQxF9WU= 14 | github.com/onsi/gomega v0.0.0-20141104003221-2cd6d99ccf3a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 15 | github.com/rubenv/sql-migrate v0.0.0-20141001072755-09d124bf5f0e h1:BMW8GU++Ophax0ZK+PBLwIaAM2cj2ndW9e84utHPOfg= 16 | github.com/rubenv/sql-migrate v0.0.0-20141001072755-09d124bf5f0e/go.mod h1:WS0rl9eEliYI8DPnr3TOwz4439pay+qNgzJoVya/DmY= 17 | gopkg.in/guregu/null.v2 v2.1.1 h1:VZG6Tc5BeHlfx3WDQ4YogWUtL71q0C4l6wn+skQ13Ak= 18 | gopkg.in/guregu/null.v2 v2.1.1/go.mod h1:XORrx8tyS5ZDcyUboCIxQtta/Aujk/6pfWrn9Xe33mU= 19 | -------------------------------------------------------------------------------- /handlers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/gorilla/mux" 6 | "log" 7 | "net/http" 8 | 9 | "github.com/cloudfoundry-samples/pong_matcher_go/domain" 10 | ) 11 | 12 | type MatchRequestPersister func(domain.MatchRequest) error 13 | type MatchRequestRetriever func(string) (bool, domain.MatchRequest, error) 14 | type MatchRetriever func(string) (bool, domain.Match) 15 | type ResultPersister func(domain.Result) error 16 | type Wiper func() error 17 | 18 | func AllHandler(wipe Wiper) http.HandlerFunc { 19 | return func(w http.ResponseWriter, r *http.Request) { 20 | if err := wipe(); err != nil { 21 | w.WriteHeader(500) 22 | } 23 | } 24 | } 25 | 26 | func CreateMatchRequestHandler(persist MatchRequestPersister) http.HandlerFunc { 27 | return func(w http.ResponseWriter, r *http.Request) { 28 | var matchRequest domain.MatchRequest 29 | decoder := json.NewDecoder(r.Body) 30 | if err := decoder.Decode(&matchRequest); err != nil { 31 | w.WriteHeader(400) 32 | return 33 | } 34 | 35 | matchRequest.Uuid = mux.Vars(r)["uuid"] 36 | 37 | if err := persist(matchRequest); err != nil { 38 | w.WriteHeader(500) 39 | return 40 | } 41 | 42 | w.Header().Set("Content-Type", "application/json") 43 | w.WriteHeader(200) 44 | } 45 | } 46 | 47 | func GetMatchRequestHandler(retrieve MatchRequestRetriever) http.HandlerFunc { 48 | return func(w http.ResponseWriter, r *http.Request) { 49 | found, matchRequest, err := retrieve(mux.Vars(r)["uuid"]) 50 | 51 | if err != nil { 52 | w.WriteHeader(500) 53 | return 54 | } 55 | 56 | if found { 57 | js, err := json.Marshal(matchRequest) 58 | if err != nil { 59 | log.Fatalln("Error writing JSON:", err) 60 | } 61 | 62 | w.Header().Set("Content-Type", "application/json") 63 | w.WriteHeader(200) 64 | w.Write(js) 65 | } else { 66 | w.WriteHeader(404) 67 | } 68 | } 69 | } 70 | 71 | func MatchHandler(retrieve MatchRetriever) http.HandlerFunc { 72 | return func(w http.ResponseWriter, r *http.Request) { 73 | if found, match := retrieve(mux.Vars(r)["uuid"]); found { 74 | js, err := json.Marshal(match) 75 | if err != nil { 76 | log.Fatalln("Error writing JSON:", err) 77 | } 78 | w.WriteHeader(200) 79 | w.Write(js) 80 | } else { 81 | w.WriteHeader(404) 82 | } 83 | } 84 | } 85 | 86 | func ResultsHandler(persist ResultPersister) http.HandlerFunc { 87 | return func(w http.ResponseWriter, r *http.Request) { 88 | var result domain.Result 89 | decoder := json.NewDecoder(r.Body) 90 | if err := decoder.Decode(&result); err != nil { 91 | w.WriteHeader(400) 92 | return 93 | } 94 | if err := persist(result); err != nil { 95 | w.WriteHeader(500) 96 | } else { 97 | w.WriteHeader(201) 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /io/io_suite_test.go: -------------------------------------------------------------------------------- 1 | package io_test 2 | 3 | import ( 4 | . "github.com/cloudfoundry-samples/pong_matcher_go/io" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | 9 | "testing" 10 | ) 11 | 12 | func TestPongMatcherGoIo(t *testing.T) { 13 | RegisterFailHandler(Fail) 14 | RunSpecs(t, "PongMatcherGo IO Suite") 15 | } 16 | 17 | var _ = BeforeSuite(func() { 18 | createTestDb() 19 | }) 20 | 21 | func createTestDb() { 22 | databaseUrl := "mysql2://gopong:gopong@127.0.0.1:3306/pong_matcher_go_test" 23 | InitDb(MigratedDbMap(databaseUrl, "../db/migrations")) 24 | } 25 | -------------------------------------------------------------------------------- /io/io_test.go: -------------------------------------------------------------------------------- 1 | package io_test 2 | 3 | import ( 4 | . "github.com/cloudfoundry-samples/pong_matcher_go/io" 5 | . "github.com/cloudfoundry-samples/pong_matcher_go/domain" 6 | 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | ) 10 | 11 | var _ = Describe("IO:", func() { 12 | BeforeEach(func() { 13 | DeleteAll() 14 | }) 15 | 16 | Describe("getting a match", func() { 17 | Context("with an empty database", func() { 18 | It("informs the caller that no match was found", func() { 19 | success, _ := GetMatch("nonexistentUUID") 20 | Expect(success).To(Equal(false)) 21 | }) 22 | }) 23 | }) 24 | 25 | Describe("entering a result", func() { 26 | It("returns a nil error on success", func() { 27 | err := PersistResult(Result{}) 28 | Expect(err).To(BeNil()) 29 | }) 30 | 31 | It("removes match_id from match request (pending rename of match_id)", func() { 32 | err := PersistMatchRequest(MatchRequest{Uuid: "foo", RequesterId: "andrew"}) 33 | Expect(err).To(BeNil()) 34 | 35 | err = PersistMatchRequest(MatchRequest{Uuid: "bar", RequesterId: "india"}) 36 | Expect(err).To(BeNil()) 37 | 38 | _, matchRequest, err := GetMatchRequest("foo") 39 | 40 | err = PersistResult(Result{MatchId: matchRequest.MatchId.String}) 41 | Expect(err).To(BeNil()) 42 | 43 | _, matchRequest, err = GetMatchRequest("foo") 44 | Expect(err).To(BeNil()) 45 | Expect(matchRequest.MatchId.Valid).To(BeFalse()) 46 | }) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gorilla/mux" 6 | "log" 7 | "net/http" 8 | "os" 9 | 10 | "github.com/cloudfoundry-samples/pong_matcher_go/io" 11 | ) 12 | 13 | func main() { 14 | databaseUrl := os.Getenv("DATABASE_URL") 15 | if databaseUrl == "" { 16 | databaseUrl = "mysql2://gopong:gopong@127.0.0.1:3306/pong_matcher_go_development?reconnect=true" 17 | } 18 | 19 | io.InitDb(io.MigratedDbMap(databaseUrl, "db/migrations")) 20 | defer io.CloseDb() 21 | 22 | router := mux.NewRouter() 23 | 24 | router. 25 | HandleFunc("/all", AllHandler(io.DeleteAll)). 26 | Methods("DELETE") 27 | router. 28 | HandleFunc("/match_requests/{uuid}", CreateMatchRequestHandler(io.PersistMatchRequest)). 29 | Methods("PUT") 30 | router. 31 | HandleFunc("/match_requests/{uuid}", GetMatchRequestHandler(io.GetMatchRequest)). 32 | Methods("GET") 33 | router. 34 | HandleFunc("/matches/{uuid}", MatchHandler(io.GetMatch)). 35 | Methods("GET") 36 | router. 37 | HandleFunc("/results", ResultsHandler(io.PersistResult)). 38 | Methods("POST") 39 | 40 | if err := http.ListenAndServe(fmt.Sprintf(":%v", getPort()), router); err != nil { 41 | log.Fatalln(err) 42 | } 43 | } 44 | 45 | func getPort() string { 46 | if configuredPort := os.Getenv("PORT"); configuredPort == "" { 47 | return "3000" 48 | } else { 49 | return configuredPort 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: gopong 4 | memory: 256M 5 | instances: 1 6 | services: 7 | - mysql 8 | 9 | -------------------------------------------------------------------------------- /pong_matcher_go_suite_test.go: -------------------------------------------------------------------------------- 1 | package main_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "testing" 8 | ) 9 | 10 | func TestPongMatcherGo(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "PongMatcherGo Suite") 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/.gitignore: -------------------------------------------------------------------------------- 1 | _test 2 | _testmain.go 3 | _obj 4 | *~ 5 | *.6 6 | 6.out 7 | gorptest.bin 8 | tmp 9 | -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1 4 | - tip 5 | 6 | services: 7 | - mysql 8 | - postgres 9 | - sqlite3 10 | 11 | before_script: 12 | - mysql -e "CREATE DATABASE gorptest;" 13 | - mysql -u root -e "GRANT ALL ON gorptest.* TO gorptest@localhost IDENTIFIED BY 'gorptest'" 14 | - psql -c "CREATE DATABASE gorptest;" -U postgres 15 | - psql -c "CREATE USER "gorptest" WITH SUPERUSER PASSWORD 'gorptest';" -U postgres 16 | - go get github.com/lib/pq 17 | - go get github.com/mattn/go-sqlite3 18 | - go get github.com/ziutek/mymysql/godrv 19 | - go get github.com/go-sql-driver/mysql 20 | 21 | script: ./test_all.sh 22 | -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012 James Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/Makefile: -------------------------------------------------------------------------------- 1 | include $(GOROOT)/src/Make.inc 2 | 3 | TARG = github.com/coopernurse/gorp 4 | GOFILES = gorp.go dialect.go 5 | 6 | include $(GOROOT)/src/Make.pkg -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/errors.go: -------------------------------------------------------------------------------- 1 | package gorp 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // A non-fatal error, when a select query returns columns that do not exist 8 | // as fields in the struct it is being mapped to 9 | type NoFieldInTypeError struct { 10 | TypeName string 11 | MissingColNames []string 12 | } 13 | 14 | func (err *NoFieldInTypeError) Error() string { 15 | return fmt.Sprintf("gorp: No fields %+v in type %s", err.MissingColNames, err.TypeName) 16 | } 17 | 18 | // returns true if the error is non-fatal (ie, we shouldn't immediately return) 19 | func NonFatalError(err error) bool { 20 | switch err.(type) { 21 | case *NoFieldInTypeError: 22 | return true 23 | default: 24 | return false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/coopernurse/gorp/test_all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # on macs, you may need to: 4 | # export GOBUILDFLAG=-ldflags -linkmode=external 5 | 6 | set -e 7 | 8 | export GORP_TEST_DSN=gorptest/gorptest/gorptest 9 | export GORP_TEST_DIALECT=mysql 10 | go test $GOBUILDFLAG . 11 | 12 | export GORP_TEST_DSN=gorptest:gorptest@/gorptest 13 | export GORP_TEST_DIALECT=gomysql 14 | go test $GOBUILDFLAG . 15 | 16 | export GORP_TEST_DSN="user=gorptest password=gorptest dbname=gorptest sslmode=disable" 17 | export GORP_TEST_DIALECT=postgres 18 | go test $GOBUILDFLAG . 19 | 20 | export GORP_TEST_DSN=/tmp/gorptest.bin 21 | export GORP_TEST_DIALECT=sqlite 22 | go test $GOBUILDFLAG . 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1 4 | - 1.2 5 | - 1.3 6 | - tip 7 | 8 | before_script: 9 | - mysql -e 'create database gotest;' 10 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Go-MySQL-Driver authors for copyright purposes. 2 | 3 | # If you are submitting a patch, please add your name or the name of the 4 | # organization which holds the copyright to this list in alphabetical order. 5 | 6 | # Names should be added to this file as 7 | # Name 8 | # The email address is not required for organizations. 9 | # Please keep the list sorted. 10 | 11 | 12 | # Individual Persons 13 | 14 | Aaron Hopkins 15 | Arne Hormann 16 | Carlos Nieto 17 | DisposaBoy 18 | Frederick Mayle 19 | Gustavo Kristic 20 | Hanno Braun 21 | Henri Yandell 22 | James Harr 23 | Jian Zhen 24 | Julien Schmidt 25 | Leonardo YongUk Kim 26 | Lucas Liu 27 | Luke Scott 28 | Michael Woolnough 29 | Nicola Peduzzi 30 | Xiaobing Jiang 31 | Xiuming Chen 32 | 33 | # Organizations 34 | 35 | Barracuda Networks, Inc. 36 | Google Inc. 37 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## HEAD 2 | 3 | Changes: 4 | 5 | - Use decimals field from MySQL to format time types 6 | 7 | Bugfixes: 8 | 9 | - Enable microsecond resolution on TIME, DATETIME and TIMESTAMP 10 | 11 | 12 | ## Version 1.2 (2014-06-03) 13 | 14 | Changes: 15 | 16 | - We switched back to a "rolling release". `go get` installs the current master branch again 17 | - Version v1 of the driver will not be maintained anymore. Go 1.0 is no longer supported by this driver 18 | - Exported errors to allow easy checking from application code 19 | - Enabled TCP Keepalives on TCP connections 20 | - Optimized INFILE handling (better buffer size calculation, lazy init, ...) 21 | - The DSN parser also checks for a missing separating slash 22 | - Faster binary date / datetime to string formatting 23 | - Also exported the MySQLWarning type 24 | - mysqlConn.Close returns the first error encountered instead of ignoring all errors 25 | - writePacket() automatically writes the packet size to the header 26 | - readPacket() uses an iterative approach instead of the recursive approach to merge splitted packets 27 | 28 | New Features: 29 | 30 | - `RegisterDial` allows the usage of a custom dial function to establish the network connection 31 | - Setting the connection collation is possible with the `collation` DSN parameter. This parameter should be preferred over the `charset` parameter 32 | - Logging of critical errors is configurable with `SetLogger` 33 | - Google CloudSQL support 34 | 35 | Bugfixes: 36 | 37 | - Allow more than 32 parameters in prepared statements 38 | - Various old_password fixes 39 | - Fixed TestConcurrent test to pass Go's race detection 40 | - Fixed appendLengthEncodedInteger for large numbers 41 | - Renamed readLengthEnodedString to readLengthEncodedString and skipLengthEnodedString to skipLengthEncodedString (fixed typo) 42 | 43 | 44 | ## Version 1.1 (2013-11-02) 45 | 46 | Changes: 47 | 48 | - Go-MySQL-Driver now requires Go 1.1 49 | - Connections now use the collation `utf8_general_ci` by default. Adding `&charset=UTF8` to the DSN should not be necessary anymore 50 | - Made closing rows and connections error tolerant. This allows for example deferring rows.Close() without checking for errors 51 | - `[]byte(nil)` is now treated as a NULL value. Before, it was treated like an empty string / `[]byte("")` 52 | - DSN parameter values must now be url.QueryEscape'ed. This allows text values to contain special characters, such as '&'. 53 | - Use the IO buffer also for writing. This results in zero allocations (by the driver) for most queries 54 | - Optimized the buffer for reading 55 | - stmt.Query now caches column metadata 56 | - New Logo 57 | - Changed the copyright header to include all contributors 58 | - Improved the LOAD INFILE documentation 59 | - The driver struct is now exported to make the driver directly accessible 60 | - Refactored the driver tests 61 | - Added more benchmarks and moved all to a separate file 62 | - Other small refactoring 63 | 64 | New Features: 65 | 66 | - Added *old_passwords* support: Required in some cases, but must be enabled by adding `allowOldPasswords=true` to the DSN since it is insecure 67 | - Added a `clientFoundRows` parameter: Return the number of matching rows instead of the number of rows changed on UPDATEs 68 | - Added TLS/SSL support: Use a TLS/SSL encrypted connection to the server. Custom TLS configs can be registered and used 69 | 70 | Bugfixes: 71 | 72 | - Fixed MySQL 4.1 support: MySQL 4.1 sends packets with lengths which differ from the specification 73 | - Convert to DB timezone when inserting `time.Time` 74 | - Splitted packets (more than 16MB) are now merged correctly 75 | - Fixed false positive `io.EOF` errors when the data was fully read 76 | - Avoid panics on reuse of closed connections 77 | - Fixed empty string producing false nil values 78 | - Fixed sign byte for positive TIME fields 79 | 80 | 81 | ## Version 1.0 (2013-05-14) 82 | 83 | Initial Release 84 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | ## Reporting Issues 4 | 5 | Before creating a new Issue, please check first if a similar Issue [already exists](https://github.com/go-sql-driver/mysql/issues?state=open) or was [recently closed](https://github.com/go-sql-driver/mysql/issues?direction=desc&page=1&sort=updated&state=closed). 6 | 7 | Please provide the following minimum information: 8 | * Your Go-MySQL-Driver version (or git SHA) 9 | * Your Go version (run `go version` in your console) 10 | * A detailed issue description 11 | * Error Log if present 12 | * If possible, a short example 13 | 14 | 15 | ## Contributing Code 16 | 17 | By contributing to this project, you share your code under the Mozilla Public License 2, as specified in the LICENSE file. 18 | Don't forget to add yourself to the AUTHORS file. 19 | 20 | ### Pull Requests Checklist 21 | 22 | Please check the following points before submitting your pull request: 23 | - [x] Code compiles correctly 24 | - [x] Created tests, if possible 25 | - [x] All tests pass 26 | - [x] Extended the README / documentation, if necessary 27 | - [x] Added yourself to the AUTHORS file 28 | 29 | ### Code Review 30 | 31 | Everyone is invited to review and comment on pull requests. 32 | If it looks fine to you, comment with "LGTM" (Looks good to me). 33 | 34 | If changes are required, notice the reviewers with "PTAL" (Please take another look) after committing the fixes. 35 | 36 | Before merging the Pull Request, at least one [team member](https://github.com/go-sql-driver?tab=members) must have commented with "LGTM". 37 | 38 | ## Development Ideas 39 | 40 | If you are looking for ideas for code contributions, please check our [Development Ideas](https://github.com/go-sql-driver/mysql/wiki/Development-Ideas) Wiki page. 41 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/appengine.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | // +build appengine 10 | 11 | package mysql 12 | 13 | import ( 14 | "appengine/cloudsql" 15 | ) 16 | 17 | func init() { 18 | RegisterDial("cloudsql", cloudsql.Dial) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/buffer.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import "io" 12 | 13 | const defaultBufSize = 4096 14 | 15 | // A buffer which is used for both reading and writing. 16 | // This is possible since communication on each connection is synchronous. 17 | // In other words, we can't write and read simultaneously on the same connection. 18 | // The buffer is similar to bufio.Reader / Writer but zero-copy-ish 19 | // Also highly optimized for this particular use case. 20 | type buffer struct { 21 | buf []byte 22 | rd io.Reader 23 | idx int 24 | length int 25 | } 26 | 27 | func newBuffer(rd io.Reader) buffer { 28 | var b [defaultBufSize]byte 29 | return buffer{ 30 | buf: b[:], 31 | rd: rd, 32 | } 33 | } 34 | 35 | // fill reads into the buffer until at least _need_ bytes are in it 36 | func (b *buffer) fill(need int) error { 37 | n := b.length 38 | 39 | // move existing data to the beginning 40 | if n > 0 && b.idx > 0 { 41 | copy(b.buf[0:n], b.buf[b.idx:]) 42 | } 43 | 44 | // grow buffer if necessary 45 | // TODO: let the buffer shrink again at some point 46 | // Maybe keep the org buf slice and swap back? 47 | if need > len(b.buf) { 48 | // Round up to the next multiple of the default size 49 | newBuf := make([]byte, ((need/defaultBufSize)+1)*defaultBufSize) 50 | copy(newBuf, b.buf) 51 | b.buf = newBuf 52 | } 53 | 54 | b.idx = 0 55 | 56 | for { 57 | nn, err := b.rd.Read(b.buf[n:]) 58 | n += nn 59 | 60 | switch err { 61 | case nil: 62 | if n < need { 63 | continue 64 | } 65 | b.length = n 66 | return nil 67 | 68 | case io.EOF: 69 | if n >= need { 70 | b.length = n 71 | return nil 72 | } 73 | return io.ErrUnexpectedEOF 74 | 75 | default: 76 | return err 77 | } 78 | } 79 | } 80 | 81 | // returns next N bytes from buffer. 82 | // The returned slice is only guaranteed to be valid until the next read 83 | func (b *buffer) readNext(need int) ([]byte, error) { 84 | if b.length < need { 85 | // refill 86 | if err := b.fill(need); err != nil { 87 | return nil, err 88 | } 89 | } 90 | 91 | offset := b.idx 92 | b.idx += need 93 | b.length -= need 94 | return b.buf[offset:b.idx], nil 95 | } 96 | 97 | // returns a buffer with the requested size. 98 | // If possible, a slice from the existing buffer is returned. 99 | // Otherwise a bigger buffer is made. 100 | // Only one buffer (total) can be used at a time. 101 | func (b *buffer) takeBuffer(length int) []byte { 102 | if b.length > 0 { 103 | return nil 104 | } 105 | 106 | // test (cheap) general case first 107 | if length <= defaultBufSize || length <= cap(b.buf) { 108 | return b.buf[:length] 109 | } 110 | 111 | if length < maxPacketSize { 112 | b.buf = make([]byte, length) 113 | return b.buf 114 | } 115 | return make([]byte, length) 116 | } 117 | 118 | // shortcut which can be used if the requested buffer is guaranteed to be 119 | // smaller than defaultBufSize 120 | // Only one buffer (total) can be used at a time. 121 | func (b *buffer) takeSmallBuffer(length int) []byte { 122 | if b.length == 0 { 123 | return b.buf[:length] 124 | } 125 | return nil 126 | } 127 | 128 | // takeCompleteBuffer returns the complete existing buffer. 129 | // This can be used if the necessary buffer size is unknown. 130 | // Only one buffer (total) can be used at a time. 131 | func (b *buffer) takeCompleteBuffer() []byte { 132 | if b.length == 0 { 133 | return b.buf 134 | } 135 | return nil 136 | } 137 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/const.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | const ( 12 | minProtocolVersion byte = 10 13 | maxPacketSize = 1<<24 - 1 14 | timeFormat = "2006-01-02 15:04:05.999999" 15 | ) 16 | 17 | // MySQL constants documentation: 18 | // http://dev.mysql.com/doc/internals/en/client-server-protocol.html 19 | 20 | const ( 21 | iOK byte = 0x00 22 | iLocalInFile byte = 0xfb 23 | iEOF byte = 0xfe 24 | iERR byte = 0xff 25 | ) 26 | 27 | type clientFlag uint32 28 | 29 | const ( 30 | clientLongPassword clientFlag = 1 << iota 31 | clientFoundRows 32 | clientLongFlag 33 | clientConnectWithDB 34 | clientNoSchema 35 | clientCompress 36 | clientODBC 37 | clientLocalFiles 38 | clientIgnoreSpace 39 | clientProtocol41 40 | clientInteractive 41 | clientSSL 42 | clientIgnoreSIGPIPE 43 | clientTransactions 44 | clientReserved 45 | clientSecureConn 46 | clientMultiStatements 47 | clientMultiResults 48 | ) 49 | 50 | const ( 51 | comQuit byte = iota + 1 52 | comInitDB 53 | comQuery 54 | comFieldList 55 | comCreateDB 56 | comDropDB 57 | comRefresh 58 | comShutdown 59 | comStatistics 60 | comProcessInfo 61 | comConnect 62 | comProcessKill 63 | comDebug 64 | comPing 65 | comTime 66 | comDelayedInsert 67 | comChangeUser 68 | comBinlogDump 69 | comTableDump 70 | comConnectOut 71 | comRegiserSlave 72 | comStmtPrepare 73 | comStmtExecute 74 | comStmtSendLongData 75 | comStmtClose 76 | comStmtReset 77 | comSetOption 78 | comStmtFetch 79 | ) 80 | 81 | const ( 82 | fieldTypeDecimal byte = iota 83 | fieldTypeTiny 84 | fieldTypeShort 85 | fieldTypeLong 86 | fieldTypeFloat 87 | fieldTypeDouble 88 | fieldTypeNULL 89 | fieldTypeTimestamp 90 | fieldTypeLongLong 91 | fieldTypeInt24 92 | fieldTypeDate 93 | fieldTypeTime 94 | fieldTypeDateTime 95 | fieldTypeYear 96 | fieldTypeNewDate 97 | fieldTypeVarChar 98 | fieldTypeBit 99 | ) 100 | const ( 101 | fieldTypeNewDecimal byte = iota + 0xf6 102 | fieldTypeEnum 103 | fieldTypeSet 104 | fieldTypeTinyBLOB 105 | fieldTypeMediumBLOB 106 | fieldTypeLongBLOB 107 | fieldTypeBLOB 108 | fieldTypeVarString 109 | fieldTypeString 110 | fieldTypeGeometry 111 | ) 112 | 113 | type fieldFlag uint16 114 | 115 | const ( 116 | flagNotNULL fieldFlag = 1 << iota 117 | flagPriKey 118 | flagUniqueKey 119 | flagMultipleKey 120 | flagBLOB 121 | flagUnsigned 122 | flagZeroFill 123 | flagBinary 124 | flagEnum 125 | flagAutoIncrement 126 | flagTimestamp 127 | flagSet 128 | flagUnknown1 129 | flagUnknown2 130 | flagUnknown3 131 | flagUnknown4 132 | ) 133 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/driver.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 2 | // 3 | // This Source Code Form is subject to the terms of the Mozilla Public 4 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 | // You can obtain one at http://mozilla.org/MPL/2.0/. 6 | 7 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 8 | // 9 | // The driver should be used via the database/sql package: 10 | // 11 | // import "database/sql" 12 | // import _ "github.com/go-sql-driver/mysql" 13 | // 14 | // db, err := sql.Open("mysql", "user:password@/dbname") 15 | // 16 | // See https://github.com/go-sql-driver/mysql#usage for details 17 | package mysql 18 | 19 | import ( 20 | "database/sql" 21 | "database/sql/driver" 22 | "net" 23 | ) 24 | 25 | // This struct is exported to make the driver directly accessible. 26 | // In general the driver is used via the database/sql package. 27 | type MySQLDriver struct{} 28 | 29 | // DialFunc is a function which can be used to establish the network connection. 30 | // Custom dial functions must be registered with RegisterDial 31 | type DialFunc func(addr string) (net.Conn, error) 32 | 33 | var dials map[string]DialFunc 34 | 35 | // RegisterDial registers a custom dial function. It can then be used by the 36 | // network address mynet(addr), where mynet is the registered new network. 37 | // addr is passed as a parameter to the dial function. 38 | func RegisterDial(net string, dial DialFunc) { 39 | if dials == nil { 40 | dials = make(map[string]DialFunc) 41 | } 42 | dials[net] = dial 43 | } 44 | 45 | // Open new Connection. 46 | // See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how 47 | // the DSN string is formated 48 | func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { 49 | var err error 50 | 51 | // New mysqlConn 52 | mc := &mysqlConn{ 53 | maxPacketAllowed: maxPacketSize, 54 | maxWriteSize: maxPacketSize - 1, 55 | } 56 | mc.cfg, err = parseDSN(dsn) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | // Connect to Server 62 | if dial, ok := dials[mc.cfg.net]; ok { 63 | mc.netConn, err = dial(mc.cfg.addr) 64 | } else { 65 | nd := net.Dialer{Timeout: mc.cfg.timeout} 66 | mc.netConn, err = nd.Dial(mc.cfg.net, mc.cfg.addr) 67 | } 68 | if err != nil { 69 | return nil, err 70 | } 71 | 72 | // Enable TCP Keepalives on TCP connections 73 | if tc, ok := mc.netConn.(*net.TCPConn); ok { 74 | if err := tc.SetKeepAlive(true); err != nil { 75 | mc.Close() 76 | return nil, err 77 | } 78 | } 79 | 80 | mc.buf = newBuffer(mc.netConn) 81 | 82 | // Reading Handshake Initialization Packet 83 | cipher, err := mc.readInitPacket() 84 | if err != nil { 85 | mc.Close() 86 | return nil, err 87 | } 88 | 89 | // Send Client Authentication Packet 90 | if err = mc.writeAuthPacket(cipher); err != nil { 91 | mc.Close() 92 | return nil, err 93 | } 94 | 95 | // Read Result Packet 96 | err = mc.readResultOK() 97 | if err != nil { 98 | // Retry with old authentication method, if allowed 99 | if mc.cfg != nil && mc.cfg.allowOldPasswords && err == ErrOldPassword { 100 | if err = mc.writeOldAuthPacket(cipher); err != nil { 101 | mc.Close() 102 | return nil, err 103 | } 104 | if err = mc.readResultOK(); err != nil { 105 | mc.Close() 106 | return nil, err 107 | } 108 | } else { 109 | mc.Close() 110 | return nil, err 111 | } 112 | 113 | } 114 | 115 | // Get max allowed packet size 116 | maxap, err := mc.getSystemVar("max_allowed_packet") 117 | if err != nil { 118 | mc.Close() 119 | return nil, err 120 | } 121 | mc.maxPacketAllowed = stringToInt(maxap) - 1 122 | if mc.maxPacketAllowed < maxPacketSize { 123 | mc.maxWriteSize = mc.maxPacketAllowed 124 | } 125 | 126 | // Handle DSN Params 127 | err = mc.handleParams() 128 | if err != nil { 129 | mc.Close() 130 | return nil, err 131 | } 132 | 133 | return mc, nil 134 | } 135 | 136 | func init() { 137 | sql.Register("mysql", &MySQLDriver{}) 138 | } 139 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/errors.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "errors" 14 | "fmt" 15 | "io" 16 | "log" 17 | "os" 18 | ) 19 | 20 | // Various errors the driver might return. Can change between driver versions. 21 | var ( 22 | ErrInvalidConn = errors.New("Invalid Connection") 23 | ErrMalformPkt = errors.New("Malformed Packet") 24 | ErrNoTLS = errors.New("TLS encryption requested but server does not support TLS") 25 | ErrOldPassword = errors.New("This server only supports the insecure old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords") 26 | ErrOldProtocol = errors.New("MySQL-Server does not support required Protocol 41+") 27 | ErrPktSync = errors.New("Commands out of sync. You can't run this command now") 28 | ErrPktSyncMul = errors.New("Commands out of sync. Did you run multiple statements at once?") 29 | ErrPktTooLarge = errors.New("Packet for query is too large. You can change this value on the server by adjusting the 'max_allowed_packet' variable.") 30 | ErrBusyBuffer = errors.New("Busy buffer") 31 | ) 32 | 33 | var errLog Logger = log.New(os.Stderr, "[MySQL] ", log.Ldate|log.Ltime|log.Lshortfile) 34 | 35 | // Logger is used to log critical error messages. 36 | type Logger interface { 37 | Print(v ...interface{}) 38 | } 39 | 40 | // SetLogger is used to set the logger for critical errors. 41 | // The initial logger is os.Stderr. 42 | func SetLogger(logger Logger) error { 43 | if logger == nil { 44 | return errors.New("logger is nil") 45 | } 46 | errLog = logger 47 | return nil 48 | } 49 | 50 | // MySQLError is an error type which represents a single MySQL error 51 | type MySQLError struct { 52 | Number uint16 53 | Message string 54 | } 55 | 56 | func (me *MySQLError) Error() string { 57 | return fmt.Sprintf("Error %d: %s", me.Number, me.Message) 58 | } 59 | 60 | // MySQLWarnings is an error type which represents a group of one or more MySQL 61 | // warnings 62 | type MySQLWarnings []MySQLWarning 63 | 64 | func (mws MySQLWarnings) Error() string { 65 | var msg string 66 | for i, warning := range mws { 67 | if i > 0 { 68 | msg += "\r\n" 69 | } 70 | msg += fmt.Sprintf( 71 | "%s %s: %s", 72 | warning.Level, 73 | warning.Code, 74 | warning.Message, 75 | ) 76 | } 77 | return msg 78 | } 79 | 80 | // MySQLWarning is an error type which represents a single MySQL warning. 81 | // Warnings are returned in groups only. See MySQLWarnings 82 | type MySQLWarning struct { 83 | Level string 84 | Code string 85 | Message string 86 | } 87 | 88 | func (mc *mysqlConn) getWarnings() (err error) { 89 | rows, err := mc.Query("SHOW WARNINGS", nil) 90 | if err != nil { 91 | return 92 | } 93 | 94 | var warnings = MySQLWarnings{} 95 | var values = make([]driver.Value, 3) 96 | 97 | for { 98 | err = rows.Next(values) 99 | switch err { 100 | case nil: 101 | warning := MySQLWarning{} 102 | 103 | if raw, ok := values[0].([]byte); ok { 104 | warning.Level = string(raw) 105 | } else { 106 | warning.Level = fmt.Sprintf("%s", values[0]) 107 | } 108 | if raw, ok := values[1].([]byte); ok { 109 | warning.Code = string(raw) 110 | } else { 111 | warning.Code = fmt.Sprintf("%s", values[1]) 112 | } 113 | if raw, ok := values[2].([]byte); ok { 114 | warning.Message = string(raw) 115 | } else { 116 | warning.Message = fmt.Sprintf("%s", values[0]) 117 | } 118 | 119 | warnings = append(warnings, warning) 120 | 121 | case io.EOF: 122 | return warnings 123 | 124 | default: 125 | rows.Close() 126 | return 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/infile.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "fmt" 13 | "io" 14 | "os" 15 | "strings" 16 | ) 17 | 18 | var ( 19 | fileRegister map[string]bool 20 | readerRegister map[string]func() io.Reader 21 | ) 22 | 23 | // RegisterLocalFile adds the given file to the file whitelist, 24 | // so that it can be used by "LOAD DATA LOCAL INFILE ". 25 | // Alternatively you can allow the use of all local files with 26 | // the DSN parameter 'allowAllFiles=true' 27 | // 28 | // filePath := "/home/gopher/data.csv" 29 | // mysql.RegisterLocalFile(filePath) 30 | // err := db.Exec("LOAD DATA LOCAL INFILE '" + filePath + "' INTO TABLE foo") 31 | // if err != nil { 32 | // ... 33 | // 34 | func RegisterLocalFile(filePath string) { 35 | // lazy map init 36 | if fileRegister == nil { 37 | fileRegister = make(map[string]bool) 38 | } 39 | 40 | fileRegister[strings.Trim(filePath, `"`)] = true 41 | } 42 | 43 | // DeregisterLocalFile removes the given filepath from the whitelist. 44 | func DeregisterLocalFile(filePath string) { 45 | delete(fileRegister, strings.Trim(filePath, `"`)) 46 | } 47 | 48 | // RegisterReaderHandler registers a handler function which is used 49 | // to receive a io.Reader. 50 | // The Reader can be used by "LOAD DATA LOCAL INFILE Reader::". 51 | // If the handler returns a io.ReadCloser Close() is called when the 52 | // request is finished. 53 | // 54 | // mysql.RegisterReaderHandler("data", func() io.Reader { 55 | // var csvReader io.Reader // Some Reader that returns CSV data 56 | // ... // Open Reader here 57 | // return csvReader 58 | // }) 59 | // err := db.Exec("LOAD DATA LOCAL INFILE 'Reader::data' INTO TABLE foo") 60 | // if err != nil { 61 | // ... 62 | // 63 | func RegisterReaderHandler(name string, handler func() io.Reader) { 64 | // lazy map init 65 | if readerRegister == nil { 66 | readerRegister = make(map[string]func() io.Reader) 67 | } 68 | 69 | readerRegister[name] = handler 70 | } 71 | 72 | // DeregisterReaderHandler removes the ReaderHandler function with 73 | // the given name from the registry. 74 | func DeregisterReaderHandler(name string) { 75 | delete(readerRegister, name) 76 | } 77 | 78 | func deferredClose(err *error, closer io.Closer) { 79 | closeErr := closer.Close() 80 | if *err == nil { 81 | *err = closeErr 82 | } 83 | } 84 | 85 | func (mc *mysqlConn) handleInFileRequest(name string) (err error) { 86 | var rdr io.Reader 87 | var data []byte 88 | 89 | if strings.HasPrefix(name, "Reader::") { // io.Reader 90 | name = name[8:] 91 | if handler, inMap := readerRegister[name]; inMap { 92 | rdr = handler() 93 | if rdr != nil { 94 | data = make([]byte, 4+mc.maxWriteSize) 95 | 96 | if cl, ok := rdr.(io.Closer); ok { 97 | defer deferredClose(&err, cl) 98 | } 99 | } else { 100 | err = fmt.Errorf("Reader '%s' is ", name) 101 | } 102 | } else { 103 | err = fmt.Errorf("Reader '%s' is not registered", name) 104 | } 105 | } else { // File 106 | name = strings.Trim(name, `"`) 107 | if mc.cfg.allowAllFiles || fileRegister[name] { 108 | var file *os.File 109 | var fi os.FileInfo 110 | 111 | if file, err = os.Open(name); err == nil { 112 | defer deferredClose(&err, file) 113 | 114 | // get file size 115 | if fi, err = file.Stat(); err == nil { 116 | rdr = file 117 | if fileSize := int(fi.Size()); fileSize <= mc.maxWriteSize { 118 | data = make([]byte, 4+fileSize) 119 | } else if fileSize <= mc.maxPacketAllowed { 120 | data = make([]byte, 4+mc.maxWriteSize) 121 | } else { 122 | err = fmt.Errorf("Local File '%s' too large: Size: %d, Max: %d", name, fileSize, mc.maxPacketAllowed) 123 | } 124 | } 125 | } 126 | } else { 127 | err = fmt.Errorf("Local File '%s' is not registered. Use the DSN parameter 'allowAllFiles=true' to allow all files", name) 128 | } 129 | } 130 | 131 | // send content packets 132 | if err == nil { 133 | var n int 134 | for err == nil { 135 | n, err = rdr.Read(data[4:]) 136 | if n > 0 { 137 | if ioErr := mc.writePacket(data[:4+n]); ioErr != nil { 138 | return ioErr 139 | } 140 | } 141 | } 142 | if err == io.EOF { 143 | err = nil 144 | } 145 | } 146 | 147 | // send empty packet (termination) 148 | if data == nil { 149 | data = make([]byte, 4) 150 | } 151 | if ioErr := mc.writePacket(data[:4]); ioErr != nil { 152 | return ioErr 153 | } 154 | 155 | // read OK packet 156 | if err == nil { 157 | return mc.readResultOK() 158 | } else { 159 | mc.readPacket() 160 | } 161 | return err 162 | } 163 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/result.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlResult struct { 12 | affectedRows int64 13 | insertId int64 14 | } 15 | 16 | func (res *mysqlResult) LastInsertId() (int64, error) { 17 | return res.insertId, nil 18 | } 19 | 20 | func (res *mysqlResult) RowsAffected() (int64, error) { 21 | return res.affectedRows, nil 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/rows.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | "io" 14 | ) 15 | 16 | type mysqlField struct { 17 | name string 18 | flags fieldFlag 19 | fieldType byte 20 | decimals byte 21 | } 22 | 23 | type mysqlRows struct { 24 | mc *mysqlConn 25 | columns []mysqlField 26 | } 27 | 28 | type binaryRows struct { 29 | mysqlRows 30 | } 31 | 32 | type textRows struct { 33 | mysqlRows 34 | } 35 | 36 | type emptyRows struct{} 37 | 38 | func (rows *mysqlRows) Columns() []string { 39 | columns := make([]string, len(rows.columns)) 40 | for i := range columns { 41 | columns[i] = rows.columns[i].name 42 | } 43 | return columns 44 | } 45 | 46 | func (rows *mysqlRows) Close() error { 47 | mc := rows.mc 48 | if mc == nil { 49 | return nil 50 | } 51 | if mc.netConn == nil { 52 | return ErrInvalidConn 53 | } 54 | 55 | // Remove unread packets from stream 56 | err := mc.readUntilEOF() 57 | rows.mc = nil 58 | return err 59 | } 60 | 61 | func (rows *binaryRows) Next(dest []driver.Value) error { 62 | if mc := rows.mc; mc != nil { 63 | if mc.netConn == nil { 64 | return ErrInvalidConn 65 | } 66 | 67 | // Fetch next row from stream 68 | if err := rows.readRow(dest); err != io.EOF { 69 | return err 70 | } 71 | rows.mc = nil 72 | } 73 | return io.EOF 74 | } 75 | 76 | func (rows *textRows) Next(dest []driver.Value) error { 77 | if mc := rows.mc; mc != nil { 78 | if mc.netConn == nil { 79 | return ErrInvalidConn 80 | } 81 | 82 | // Fetch next row from stream 83 | if err := rows.readRow(dest); err != io.EOF { 84 | return err 85 | } 86 | rows.mc = nil 87 | } 88 | return io.EOF 89 | } 90 | 91 | func (rows emptyRows) Columns() []string { 92 | return nil 93 | } 94 | 95 | func (rows emptyRows) Close() error { 96 | return nil 97 | } 98 | 99 | func (rows emptyRows) Next(dest []driver.Value) error { 100 | return io.EOF 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/statement.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | import ( 12 | "database/sql/driver" 13 | ) 14 | 15 | type mysqlStmt struct { 16 | mc *mysqlConn 17 | id uint32 18 | paramCount int 19 | columns []mysqlField // cached from the first query 20 | } 21 | 22 | func (stmt *mysqlStmt) Close() error { 23 | if stmt.mc == nil || stmt.mc.netConn == nil { 24 | errLog.Print(ErrInvalidConn) 25 | return driver.ErrBadConn 26 | } 27 | 28 | err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id) 29 | stmt.mc = nil 30 | return err 31 | } 32 | 33 | func (stmt *mysqlStmt) NumInput() int { 34 | return stmt.paramCount 35 | } 36 | 37 | func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { 38 | if stmt.mc.netConn == nil { 39 | errLog.Print(ErrInvalidConn) 40 | return nil, driver.ErrBadConn 41 | } 42 | // Send command 43 | err := stmt.writeExecutePacket(args) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | mc := stmt.mc 49 | 50 | mc.affectedRows = 0 51 | mc.insertId = 0 52 | 53 | // Read Result 54 | resLen, err := mc.readResultSetHeaderPacket() 55 | if err == nil { 56 | if resLen > 0 { 57 | // Columns 58 | err = mc.readUntilEOF() 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | // Rows 64 | err = mc.readUntilEOF() 65 | } 66 | if err == nil { 67 | return &mysqlResult{ 68 | affectedRows: int64(mc.affectedRows), 69 | insertId: int64(mc.insertId), 70 | }, nil 71 | } 72 | } 73 | 74 | return nil, err 75 | } 76 | 77 | func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { 78 | if stmt.mc.netConn == nil { 79 | errLog.Print(ErrInvalidConn) 80 | return nil, driver.ErrBadConn 81 | } 82 | // Send command 83 | err := stmt.writeExecutePacket(args) 84 | if err != nil { 85 | return nil, err 86 | } 87 | 88 | mc := stmt.mc 89 | 90 | // Read Result 91 | resLen, err := mc.readResultSetHeaderPacket() 92 | if err != nil { 93 | return nil, err 94 | } 95 | 96 | rows := new(binaryRows) 97 | rows.mc = mc 98 | 99 | if resLen > 0 { 100 | // Columns 101 | // If not cached, read them and cache them 102 | if stmt.columns == nil { 103 | rows.columns, err = mc.readColumns(resLen) 104 | stmt.columns = rows.columns 105 | } else { 106 | rows.columns = stmt.columns 107 | err = mc.readUntilEOF() 108 | } 109 | } 110 | 111 | return rows, err 112 | } 113 | -------------------------------------------------------------------------------- /vendor/github.com/go-sql-driver/mysql/transaction.go: -------------------------------------------------------------------------------- 1 | // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 | // 3 | // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 | // 5 | // This Source Code Form is subject to the terms of the Mozilla Public 6 | // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 | // You can obtain one at http://mozilla.org/MPL/2.0/. 8 | 9 | package mysql 10 | 11 | type mysqlTx struct { 12 | mc *mysqlConn 13 | } 14 | 15 | func (tx *mysqlTx) Commit() (err error) { 16 | if tx.mc == nil || tx.mc.netConn == nil { 17 | return ErrInvalidConn 18 | } 19 | err = tx.mc.exec("COMMIT") 20 | tx.mc = nil 21 | return 22 | } 23 | 24 | func (tx *mysqlTx) Rollback() (err error) { 25 | if tx.mc == nil || tx.mc.netConn == nil { 26 | return ErrInvalidConn 27 | } 28 | err = tx.mc.exec("ROLLBACK") 29 | tx.mc = nil 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.0 5 | - 1.1 6 | - 1.2 7 | - tip 8 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/README.md: -------------------------------------------------------------------------------- 1 | context 2 | ======= 3 | [![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) 4 | 5 | gorilla/context is a general purpose registry for global request variables. 6 | 7 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/context 8 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package context 6 | 7 | import ( 8 | "net/http" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | var ( 14 | mutex sync.RWMutex 15 | data = make(map[*http.Request]map[interface{}]interface{}) 16 | datat = make(map[*http.Request]int64) 17 | ) 18 | 19 | // Set stores a value for a given key in a given request. 20 | func Set(r *http.Request, key, val interface{}) { 21 | mutex.Lock() 22 | if data[r] == nil { 23 | data[r] = make(map[interface{}]interface{}) 24 | datat[r] = time.Now().Unix() 25 | } 26 | data[r][key] = val 27 | mutex.Unlock() 28 | } 29 | 30 | // Get returns a value stored for a given key in a given request. 31 | func Get(r *http.Request, key interface{}) interface{} { 32 | mutex.RLock() 33 | if ctx := data[r]; ctx != nil { 34 | value := ctx[key] 35 | mutex.RUnlock() 36 | return value 37 | } 38 | mutex.RUnlock() 39 | return nil 40 | } 41 | 42 | // GetOk returns stored value and presence state like multi-value return of map access. 43 | func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 | mutex.RLock() 45 | if _, ok := data[r]; ok { 46 | value, ok := data[r][key] 47 | mutex.RUnlock() 48 | return value, ok 49 | } 50 | mutex.RUnlock() 51 | return nil, false 52 | } 53 | 54 | // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 | func GetAll(r *http.Request) map[interface{}]interface{} { 56 | mutex.RLock() 57 | if context, ok := data[r]; ok { 58 | result := make(map[interface{}]interface{}, len(context)) 59 | for k, v := range context { 60 | result[k] = v 61 | } 62 | mutex.RUnlock() 63 | return result 64 | } 65 | mutex.RUnlock() 66 | return nil 67 | } 68 | 69 | // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 | // the request was registered. 71 | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 | mutex.RLock() 73 | context, ok := data[r] 74 | result := make(map[interface{}]interface{}, len(context)) 75 | for k, v := range context { 76 | result[k] = v 77 | } 78 | mutex.RUnlock() 79 | return result, ok 80 | } 81 | 82 | // Delete removes a value stored for a given key in a given request. 83 | func Delete(r *http.Request, key interface{}) { 84 | mutex.Lock() 85 | if data[r] != nil { 86 | delete(data[r], key) 87 | } 88 | mutex.Unlock() 89 | } 90 | 91 | // Clear removes all values stored for a given request. 92 | // 93 | // This is usually called by a handler wrapper to clean up request 94 | // variables at the end of a request lifetime. See ClearHandler(). 95 | func Clear(r *http.Request) { 96 | mutex.Lock() 97 | clear(r) 98 | mutex.Unlock() 99 | } 100 | 101 | // clear is Clear without the lock. 102 | func clear(r *http.Request) { 103 | delete(data, r) 104 | delete(datat, r) 105 | } 106 | 107 | // Purge removes request data stored for longer than maxAge, in seconds. 108 | // It returns the amount of requests removed. 109 | // 110 | // If maxAge <= 0, all request data is removed. 111 | // 112 | // This is only used for sanity check: in case context cleaning was not 113 | // properly set some request data can be kept forever, consuming an increasing 114 | // amount of memory. In case this is detected, Purge() must be called 115 | // periodically until the problem is fixed. 116 | func Purge(maxAge int) int { 117 | mutex.Lock() 118 | count := 0 119 | if maxAge <= 0 { 120 | count = len(data) 121 | data = make(map[*http.Request]map[interface{}]interface{}) 122 | datat = make(map[*http.Request]int64) 123 | } else { 124 | min := time.Now().Unix() - int64(maxAge) 125 | for r := range data { 126 | if datat[r] < min { 127 | clear(r) 128 | count++ 129 | } 130 | } 131 | } 132 | mutex.Unlock() 133 | return count 134 | } 135 | 136 | // ClearHandler wraps an http.Handler and clears request values at the end 137 | // of a request lifetime. 138 | func ClearHandler(h http.Handler) http.Handler { 139 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 | defer Clear(r) 141 | h.ServeHTTP(w, r) 142 | }) 143 | } 144 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/context/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Gorilla Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package context stores values shared during a request lifetime. 7 | 8 | For example, a router can set variables extracted from the URL and later 9 | application handlers can access those values, or it can be used to store 10 | sessions values to be saved at the end of a request. There are several 11 | others common uses. 12 | 13 | The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: 14 | 15 | http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 16 | 17 | Here's the basic usage: first define the keys that you will need. The key 18 | type is interface{} so a key can be of any type that supports equality. 19 | Here we define a key using a custom int type to avoid name collisions: 20 | 21 | package foo 22 | 23 | import ( 24 | "github.com/gorilla/context" 25 | ) 26 | 27 | type key int 28 | 29 | const MyKey key = 0 30 | 31 | Then set a variable. Variables are bound to an http.Request object, so you 32 | need a request instance to set a value: 33 | 34 | context.Set(r, MyKey, "bar") 35 | 36 | The application can later access the variable using the same key you provided: 37 | 38 | func MyHandler(w http.ResponseWriter, r *http.Request) { 39 | // val is "bar". 40 | val := context.Get(r, foo.MyKey) 41 | 42 | // returns ("bar", true) 43 | val, ok := context.GetOk(r, foo.MyKey) 44 | // ... 45 | } 46 | 47 | And that's all about the basic usage. We discuss some other ideas below. 48 | 49 | Any type can be stored in the context. To enforce a given type, make the key 50 | private and wrap Get() and Set() to accept and return values of a specific 51 | type: 52 | 53 | type key int 54 | 55 | const mykey key = 0 56 | 57 | // GetMyKey returns a value for this package from the request values. 58 | func GetMyKey(r *http.Request) SomeType { 59 | if rv := context.Get(r, mykey); rv != nil { 60 | return rv.(SomeType) 61 | } 62 | return nil 63 | } 64 | 65 | // SetMyKey sets a value for this package in the request values. 66 | func SetMyKey(r *http.Request, val SomeType) { 67 | context.Set(r, mykey, val) 68 | } 69 | 70 | Variables must be cleared at the end of a request, to remove all values 71 | that were stored. This can be done in an http.Handler, after a request was 72 | served. Just call Clear() passing the request: 73 | 74 | context.Clear(r) 75 | 76 | ...or use ClearHandler(), which conveniently wraps an http.Handler to clear 77 | variables at the end of a request lifetime. 78 | 79 | The Routers from the packages gorilla/mux and gorilla/pat call Clear() 80 | so if you are using either of them you don't need to clear the context manually. 81 | */ 82 | package context 83 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.0 5 | - 1.1 6 | - 1.2 7 | - tip 8 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Rodrigo Moraes. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/gorilla/mux/README.md: -------------------------------------------------------------------------------- 1 | mux 2 | === 3 | [![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux) 4 | 5 | gorilla/mux is a powerful URL router and dispatcher. 6 | 7 | Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux 8 | -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/.gitignore: -------------------------------------------------------------------------------- 1 | _obj 2 | _test 3 | *.6 4 | *.out 5 | _testmain.go 6 | \#* 7 | .\#* 8 | *.log 9 | _cgo* 10 | *.o 11 | *.a 12 | -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Krzysztof Kowalik 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /vendor/github.com/nu7hatch/gouuid/README.md: -------------------------------------------------------------------------------- 1 | # Pure Go UUID implementation 2 | 3 | This package provides immutable UUID structs and the functions 4 | NewV3, NewV4, NewV5 and Parse() for generating versions 3, 4 5 | and 5 UUIDs as specified in [RFC 4122](http://www.ietf.org/rfc/rfc4122.txt). 6 | 7 | ## Installation 8 | 9 | Use the `go` tool: 10 | 11 | $ go get github.com/nu7hatch/gouuid 12 | 13 | ## Usage 14 | 15 | See [documentation and examples](http://godoc.org/github.com/nu7hatch/gouuid) 16 | for more information. 17 | 18 | ## Copyright 19 | 20 | Copyright (C) 2011 by Krzysztof Kowalik . See [COPYING](https://github.com/nu7hatch/gouuid/tree/master/COPYING) 21 | file for details. 22 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | TODO 3 | tmp/**/* 4 | *.coverprofile -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.3 4 | 5 | install: 6 | - go get -v ./... 7 | - go get code.google.com/p/go.tools/cmd/cover 8 | - go get github.com/onsi/gomega 9 | - go install github.com/onsi/ginkgo/ginkgo 10 | - export PATH=$PATH:$HOME/gopath/bin 11 | 12 | script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --failOnPending --randomizeSuites --race 13 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014 Onsi Fakhouri 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/codelocation/code_location.go: -------------------------------------------------------------------------------- 1 | package codelocation 2 | 3 | import ( 4 | "regexp" 5 | "runtime" 6 | "runtime/debug" 7 | "strings" 8 | 9 | "github.com/onsi/ginkgo/types" 10 | ) 11 | 12 | func New(skip int) types.CodeLocation { 13 | _, file, line, _ := runtime.Caller(skip + 1) 14 | stackTrace := PruneStack(string(debug.Stack()), skip) 15 | return types.CodeLocation{FileName: file, LineNumber: line, FullStackTrace: stackTrace} 16 | } 17 | 18 | func PruneStack(fullStackTrace string, skip int) string { 19 | stack := strings.Split(fullStackTrace, "\n") 20 | if len(stack) > 2*(skip+1) { 21 | stack = stack[2*(skip+1):] 22 | } 23 | prunedStack := []string{} 24 | re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`) 25 | for i := 0; i < len(stack)/2; i++ { 26 | if !re.Match([]byte(stack[i*2])) { 27 | prunedStack = append(prunedStack, stack[i*2]) 28 | prunedStack = append(prunedStack, stack[i*2+1]) 29 | } 30 | } 31 | return strings.Join(prunedStack, "\n") 32 | } 33 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/containernode/container_node.go: -------------------------------------------------------------------------------- 1 | package containernode 2 | 3 | import ( 4 | "math/rand" 5 | "sort" 6 | 7 | "github.com/onsi/ginkgo/internal/leafnodes" 8 | "github.com/onsi/ginkgo/types" 9 | ) 10 | 11 | type subjectOrContainerNode struct { 12 | containerNode *ContainerNode 13 | subjectNode leafnodes.SubjectNode 14 | } 15 | 16 | func (n subjectOrContainerNode) text() string { 17 | if n.containerNode != nil { 18 | return n.containerNode.Text() 19 | } else { 20 | return n.subjectNode.Text() 21 | } 22 | } 23 | 24 | type CollatedNodes struct { 25 | Containers []*ContainerNode 26 | Subject leafnodes.SubjectNode 27 | } 28 | 29 | type ContainerNode struct { 30 | text string 31 | flag types.FlagType 32 | codeLocation types.CodeLocation 33 | 34 | setupNodes []leafnodes.BasicNode 35 | subjectAndContainerNodes []subjectOrContainerNode 36 | } 37 | 38 | func New(text string, flag types.FlagType, codeLocation types.CodeLocation) *ContainerNode { 39 | return &ContainerNode{ 40 | text: text, 41 | flag: flag, 42 | codeLocation: codeLocation, 43 | } 44 | } 45 | 46 | func (container *ContainerNode) Shuffle(r *rand.Rand) { 47 | sort.Sort(container) 48 | permutation := r.Perm(len(container.subjectAndContainerNodes)) 49 | shuffledNodes := make([]subjectOrContainerNode, len(container.subjectAndContainerNodes)) 50 | for i, j := range permutation { 51 | shuffledNodes[i] = container.subjectAndContainerNodes[j] 52 | } 53 | container.subjectAndContainerNodes = shuffledNodes 54 | } 55 | 56 | func (node *ContainerNode) BackPropagateProgrammaticFocus() bool { 57 | if node.flag == types.FlagTypePending { 58 | return false 59 | } 60 | 61 | shouldUnfocus := false 62 | for _, subjectOrContainerNode := range node.subjectAndContainerNodes { 63 | if subjectOrContainerNode.containerNode != nil { 64 | shouldUnfocus = subjectOrContainerNode.containerNode.BackPropagateProgrammaticFocus() || shouldUnfocus 65 | } else { 66 | shouldUnfocus = (subjectOrContainerNode.subjectNode.Flag() == types.FlagTypeFocused) || shouldUnfocus 67 | } 68 | } 69 | 70 | if shouldUnfocus { 71 | if node.flag == types.FlagTypeFocused { 72 | node.flag = types.FlagTypeNone 73 | } 74 | return true 75 | } 76 | 77 | return node.flag == types.FlagTypeFocused 78 | } 79 | 80 | func (node *ContainerNode) Collate() []CollatedNodes { 81 | return node.collate([]*ContainerNode{}) 82 | } 83 | 84 | func (node *ContainerNode) collate(enclosingContainers []*ContainerNode) []CollatedNodes { 85 | collated := make([]CollatedNodes, 0) 86 | 87 | containers := make([]*ContainerNode, len(enclosingContainers)) 88 | copy(containers, enclosingContainers) 89 | containers = append(containers, node) 90 | 91 | for _, subjectOrContainer := range node.subjectAndContainerNodes { 92 | if subjectOrContainer.containerNode != nil { 93 | collated = append(collated, subjectOrContainer.containerNode.collate(containers)...) 94 | } else { 95 | collated = append(collated, CollatedNodes{ 96 | Containers: containers, 97 | Subject: subjectOrContainer.subjectNode, 98 | }) 99 | } 100 | } 101 | 102 | return collated 103 | } 104 | 105 | func (node *ContainerNode) PushContainerNode(container *ContainerNode) { 106 | node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{containerNode: container}) 107 | } 108 | 109 | func (node *ContainerNode) PushSubjectNode(subject leafnodes.SubjectNode) { 110 | node.subjectAndContainerNodes = append(node.subjectAndContainerNodes, subjectOrContainerNode{subjectNode: subject}) 111 | } 112 | 113 | func (node *ContainerNode) PushSetupNode(setupNode leafnodes.BasicNode) { 114 | node.setupNodes = append(node.setupNodes, setupNode) 115 | } 116 | 117 | func (node *ContainerNode) SetupNodesOfType(nodeType types.SpecComponentType) []leafnodes.BasicNode { 118 | nodes := []leafnodes.BasicNode{} 119 | for _, setupNode := range node.setupNodes { 120 | if setupNode.Type() == nodeType { 121 | nodes = append(nodes, setupNode) 122 | } 123 | } 124 | return nodes 125 | } 126 | 127 | func (node *ContainerNode) Text() string { 128 | return node.text 129 | } 130 | 131 | func (node *ContainerNode) CodeLocation() types.CodeLocation { 132 | return node.codeLocation 133 | } 134 | 135 | func (node *ContainerNode) Flag() types.FlagType { 136 | return node.flag 137 | } 138 | 139 | //sort.Interface 140 | 141 | func (node *ContainerNode) Len() int { 142 | return len(node.subjectAndContainerNodes) 143 | } 144 | 145 | func (node *ContainerNode) Less(i, j int) bool { 146 | return node.subjectAndContainerNodes[i].text() < node.subjectAndContainerNodes[j].text() 147 | } 148 | 149 | func (node *ContainerNode) Swap(i, j int) { 150 | node.subjectAndContainerNodes[i], node.subjectAndContainerNodes[j] = node.subjectAndContainerNodes[j], node.subjectAndContainerNodes[i] 151 | } 152 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/failer/failer.go: -------------------------------------------------------------------------------- 1 | package failer 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/types" 5 | "sync" 6 | ) 7 | 8 | type Failer struct { 9 | lock *sync.Mutex 10 | failure types.SpecFailure 11 | state types.SpecState 12 | } 13 | 14 | func New() *Failer { 15 | return &Failer{ 16 | lock: &sync.Mutex{}, 17 | state: types.SpecStatePassed, 18 | } 19 | } 20 | 21 | func (f *Failer) Panic(location types.CodeLocation, forwardedPanic interface{}) { 22 | f.lock.Lock() 23 | defer f.lock.Unlock() 24 | 25 | if f.state == types.SpecStatePassed { 26 | f.state = types.SpecStatePanicked 27 | f.failure = types.SpecFailure{ 28 | Message: "Test Panicked", 29 | Location: location, 30 | ForwardedPanic: forwardedPanic, 31 | } 32 | } 33 | } 34 | 35 | func (f *Failer) Timeout(location types.CodeLocation) { 36 | f.lock.Lock() 37 | defer f.lock.Unlock() 38 | 39 | if f.state == types.SpecStatePassed { 40 | f.state = types.SpecStateTimedOut 41 | f.failure = types.SpecFailure{ 42 | Message: "Timed out", 43 | Location: location, 44 | } 45 | } 46 | } 47 | 48 | func (f *Failer) Fail(message string, location types.CodeLocation) { 49 | f.lock.Lock() 50 | defer f.lock.Unlock() 51 | 52 | if f.state == types.SpecStatePassed { 53 | f.state = types.SpecStateFailed 54 | f.failure = types.SpecFailure{ 55 | Message: message, 56 | Location: location, 57 | } 58 | } 59 | } 60 | 61 | func (f *Failer) Drain(componentType types.SpecComponentType, componentIndex int, componentCodeLocation types.CodeLocation) (types.SpecFailure, types.SpecState) { 62 | f.lock.Lock() 63 | defer f.lock.Unlock() 64 | 65 | failure := f.failure 66 | outcome := f.state 67 | if outcome != types.SpecStatePassed { 68 | failure.ComponentType = componentType 69 | failure.ComponentIndex = componentIndex 70 | failure.ComponentCodeLocation = componentCodeLocation 71 | } 72 | 73 | f.state = types.SpecStatePassed 74 | f.failure = types.SpecFailure{} 75 | 76 | return failure, outcome 77 | } 78 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/benchmarker.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "math" 5 | "time" 6 | 7 | "github.com/onsi/ginkgo/types" 8 | ) 9 | 10 | type benchmarker struct { 11 | measurements map[string]*types.SpecMeasurement 12 | orderCounter int 13 | } 14 | 15 | func newBenchmarker() *benchmarker { 16 | return &benchmarker{ 17 | measurements: make(map[string]*types.SpecMeasurement, 0), 18 | } 19 | } 20 | 21 | func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration) { 22 | t := time.Now() 23 | body() 24 | elapsedTime = time.Since(t) 25 | 26 | measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", info...) 27 | measurement.Results = append(measurement.Results, elapsedTime.Seconds()) 28 | 29 | return 30 | } 31 | 32 | func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) { 33 | measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", info...) 34 | measurement.Results = append(measurement.Results, value) 35 | } 36 | 37 | func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, info ...interface{}) *types.SpecMeasurement { 38 | measurement, ok := b.measurements[name] 39 | if !ok { 40 | var computedInfo interface{} 41 | computedInfo = nil 42 | if len(info) > 0 { 43 | computedInfo = info[0] 44 | } 45 | measurement = &types.SpecMeasurement{ 46 | Name: name, 47 | Info: computedInfo, 48 | Order: b.orderCounter, 49 | SmallestLabel: smallestLabel, 50 | LargestLabel: largestLabel, 51 | AverageLabel: averageLabel, 52 | Units: units, 53 | Results: make([]float64, 0), 54 | } 55 | b.measurements[name] = measurement 56 | b.orderCounter++ 57 | } 58 | 59 | return measurement 60 | } 61 | 62 | func (b *benchmarker) measurementsReport() map[string]*types.SpecMeasurement { 63 | for _, measurement := range b.measurements { 64 | measurement.Smallest = math.MaxFloat64 65 | measurement.Largest = -math.MaxFloat64 66 | sum := float64(0) 67 | sumOfSquares := float64(0) 68 | 69 | for _, result := range measurement.Results { 70 | if result > measurement.Largest { 71 | measurement.Largest = result 72 | } 73 | if result < measurement.Smallest { 74 | measurement.Smallest = result 75 | } 76 | sum += result 77 | sumOfSquares += result * result 78 | } 79 | 80 | n := float64(len(measurement.Results)) 81 | measurement.Average = sum / n 82 | measurement.StdDeviation = math.Sqrt(sumOfSquares/n - (sum/n)*(sum/n)) 83 | } 84 | 85 | return b.measurements 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/interfaces.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/types" 5 | ) 6 | 7 | type BasicNode interface { 8 | Type() types.SpecComponentType 9 | Run() (types.SpecState, types.SpecFailure) 10 | CodeLocation() types.CodeLocation 11 | } 12 | 13 | type SubjectNode interface { 14 | BasicNode 15 | 16 | Text() string 17 | Flag() types.FlagType 18 | Samples() int 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/it_node.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/internal/failer" 5 | "github.com/onsi/ginkgo/types" 6 | "time" 7 | ) 8 | 9 | type ItNode struct { 10 | runner *runner 11 | 12 | flag types.FlagType 13 | text string 14 | } 15 | 16 | func NewItNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *ItNode { 17 | return &ItNode{ 18 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeIt, componentIndex), 19 | flag: flag, 20 | text: text, 21 | } 22 | } 23 | 24 | func (node *ItNode) Run() (outcome types.SpecState, failure types.SpecFailure) { 25 | return node.runner.run() 26 | } 27 | 28 | func (node *ItNode) Type() types.SpecComponentType { 29 | return types.SpecComponentTypeIt 30 | } 31 | 32 | func (node *ItNode) Text() string { 33 | return node.text 34 | } 35 | 36 | func (node *ItNode) Flag() types.FlagType { 37 | return node.flag 38 | } 39 | 40 | func (node *ItNode) CodeLocation() types.CodeLocation { 41 | return node.runner.codeLocation 42 | } 43 | 44 | func (node *ItNode) Samples() int { 45 | return 1 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/measure_node.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/internal/failer" 5 | "github.com/onsi/ginkgo/types" 6 | "reflect" 7 | ) 8 | 9 | type MeasureNode struct { 10 | runner *runner 11 | 12 | text string 13 | flag types.FlagType 14 | samples int 15 | benchmarker *benchmarker 16 | } 17 | 18 | func NewMeasureNode(text string, body interface{}, flag types.FlagType, codeLocation types.CodeLocation, samples int, failer *failer.Failer, componentIndex int) *MeasureNode { 19 | benchmarker := newBenchmarker() 20 | 21 | wrappedBody := func() { 22 | reflect.ValueOf(body).Call([]reflect.Value{reflect.ValueOf(benchmarker)}) 23 | } 24 | 25 | return &MeasureNode{ 26 | runner: newRunner(wrappedBody, codeLocation, 0, failer, types.SpecComponentTypeMeasure, componentIndex), 27 | 28 | text: text, 29 | flag: flag, 30 | samples: samples, 31 | benchmarker: benchmarker, 32 | } 33 | } 34 | 35 | func (node *MeasureNode) Run() (outcome types.SpecState, failure types.SpecFailure) { 36 | return node.runner.run() 37 | } 38 | 39 | func (node *MeasureNode) MeasurementsReport() map[string]*types.SpecMeasurement { 40 | return node.benchmarker.measurementsReport() 41 | } 42 | 43 | func (node *MeasureNode) Type() types.SpecComponentType { 44 | return types.SpecComponentTypeMeasure 45 | } 46 | 47 | func (node *MeasureNode) Text() string { 48 | return node.text 49 | } 50 | 51 | func (node *MeasureNode) Flag() types.FlagType { 52 | return node.flag 53 | } 54 | 55 | func (node *MeasureNode) CodeLocation() types.CodeLocation { 56 | return node.runner.codeLocation 57 | } 58 | 59 | func (node *MeasureNode) Samples() int { 60 | return node.samples 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/runner.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/ginkgo/internal/codelocation" 6 | "github.com/onsi/ginkgo/internal/failer" 7 | "github.com/onsi/ginkgo/types" 8 | "reflect" 9 | "time" 10 | ) 11 | 12 | type runner struct { 13 | isAsync bool 14 | asyncFunc func(chan<- interface{}) 15 | syncFunc func() 16 | codeLocation types.CodeLocation 17 | timeoutThreshold time.Duration 18 | nodeType types.SpecComponentType 19 | componentIndex int 20 | failer *failer.Failer 21 | } 22 | 23 | func newRunner(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, nodeType types.SpecComponentType, componentIndex int) *runner { 24 | bodyType := reflect.TypeOf(body) 25 | if bodyType.Kind() != reflect.Func { 26 | panic(fmt.Sprintf("Expected a function but got something else at %v", codeLocation)) 27 | } 28 | 29 | runner := &runner{ 30 | codeLocation: codeLocation, 31 | timeoutThreshold: timeout, 32 | failer: failer, 33 | nodeType: nodeType, 34 | componentIndex: componentIndex, 35 | } 36 | 37 | switch bodyType.NumIn() { 38 | case 0: 39 | runner.syncFunc = body.(func()) 40 | return runner 41 | case 1: 42 | if !(bodyType.In(0).Kind() == reflect.Chan && bodyType.In(0).Elem().Kind() == reflect.Interface) { 43 | panic(fmt.Sprintf("Must pass a Done channel to function at %v", codeLocation)) 44 | } 45 | 46 | wrappedBody := func(done chan<- interface{}) { 47 | bodyValue := reflect.ValueOf(body) 48 | bodyValue.Call([]reflect.Value{reflect.ValueOf(done)}) 49 | } 50 | 51 | runner.isAsync = true 52 | runner.asyncFunc = wrappedBody 53 | return runner 54 | } 55 | 56 | panic(fmt.Sprintf("Too many arguments to function at %v", codeLocation)) 57 | } 58 | 59 | func (r *runner) run() (outcome types.SpecState, failure types.SpecFailure) { 60 | if r.isAsync { 61 | return r.runAsync() 62 | } else { 63 | return r.runSync() 64 | } 65 | } 66 | 67 | func (r *runner) runAsync() (outcome types.SpecState, failure types.SpecFailure) { 68 | done := make(chan interface{}, 1) 69 | 70 | go func() { 71 | defer func() { 72 | if e := recover(); e != nil { 73 | r.failer.Panic(codelocation.New(2), e) 74 | select { 75 | case <-done: 76 | break 77 | default: 78 | close(done) 79 | } 80 | } 81 | }() 82 | 83 | r.asyncFunc(done) 84 | }() 85 | 86 | select { 87 | case <-done: 88 | case <-time.After(r.timeoutThreshold): 89 | r.failer.Timeout(r.codeLocation) 90 | } 91 | 92 | failure, outcome = r.failer.Drain(r.nodeType, r.componentIndex, r.codeLocation) 93 | return 94 | } 95 | func (r *runner) runSync() (outcome types.SpecState, failure types.SpecFailure) { 96 | defer func() { 97 | if e := recover(); e != nil { 98 | r.failer.Panic(codelocation.New(2), e) 99 | } 100 | 101 | failure, outcome = r.failer.Drain(r.nodeType, r.componentIndex, r.codeLocation) 102 | }() 103 | 104 | r.syncFunc() 105 | 106 | return 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/setup_nodes.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/internal/failer" 5 | "github.com/onsi/ginkgo/types" 6 | "time" 7 | ) 8 | 9 | type SetupNode struct { 10 | runner *runner 11 | } 12 | 13 | func (node *SetupNode) Run() (outcome types.SpecState, failure types.SpecFailure) { 14 | return node.runner.run() 15 | } 16 | 17 | func (node *SetupNode) Type() types.SpecComponentType { 18 | return node.runner.nodeType 19 | } 20 | 21 | func (node *SetupNode) CodeLocation() types.CodeLocation { 22 | return node.runner.codeLocation 23 | } 24 | 25 | func NewBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode { 26 | return &SetupNode{ 27 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeBeforeEach, componentIndex), 28 | } 29 | } 30 | 31 | func NewAfterEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode { 32 | return &SetupNode{ 33 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeAfterEach, componentIndex), 34 | } 35 | } 36 | 37 | func NewJustBeforeEachNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer, componentIndex int) *SetupNode { 38 | return &SetupNode{ 39 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeJustBeforeEach, componentIndex), 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/suite_nodes.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/internal/failer" 5 | "github.com/onsi/ginkgo/types" 6 | "time" 7 | ) 8 | 9 | type SuiteNode interface { 10 | Run(parallelNode int, parallelTotal int, syncHost string) bool 11 | Passed() bool 12 | Summary() *types.SetupSummary 13 | } 14 | 15 | type simpleSuiteNode struct { 16 | runner *runner 17 | outcome types.SpecState 18 | failure types.SpecFailure 19 | runTime time.Duration 20 | } 21 | 22 | func (node *simpleSuiteNode) Run(parallelNode int, parallelTotal int, syncHost string) bool { 23 | t := time.Now() 24 | node.outcome, node.failure = node.runner.run() 25 | node.runTime = time.Since(t) 26 | 27 | return node.outcome == types.SpecStatePassed 28 | } 29 | 30 | func (node *simpleSuiteNode) Passed() bool { 31 | return node.outcome == types.SpecStatePassed 32 | } 33 | 34 | func (node *simpleSuiteNode) Summary() *types.SetupSummary { 35 | return &types.SetupSummary{ 36 | ComponentType: node.runner.nodeType, 37 | CodeLocation: node.runner.codeLocation, 38 | State: node.outcome, 39 | RunTime: node.runTime, 40 | Failure: node.failure, 41 | } 42 | } 43 | 44 | func NewBeforeSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode { 45 | return &simpleSuiteNode{ 46 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeBeforeSuite, 0), 47 | } 48 | } 49 | 50 | func NewAfterSuiteNode(body interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode { 51 | return &simpleSuiteNode{ 52 | runner: newRunner(body, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0), 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/leafnodes/synchronized_after_suite_node.go: -------------------------------------------------------------------------------- 1 | package leafnodes 2 | 3 | import ( 4 | "encoding/json" 5 | "github.com/onsi/ginkgo/internal/failer" 6 | "github.com/onsi/ginkgo/types" 7 | "io/ioutil" 8 | "net/http" 9 | "time" 10 | ) 11 | 12 | type synchronizedAfterSuiteNode struct { 13 | runnerA *runner 14 | runnerB *runner 15 | 16 | outcome types.SpecState 17 | failure types.SpecFailure 18 | runTime time.Duration 19 | } 20 | 21 | func NewSynchronizedAfterSuiteNode(bodyA interface{}, bodyB interface{}, codeLocation types.CodeLocation, timeout time.Duration, failer *failer.Failer) SuiteNode { 22 | return &synchronizedAfterSuiteNode{ 23 | runnerA: newRunner(bodyA, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0), 24 | runnerB: newRunner(bodyB, codeLocation, timeout, failer, types.SpecComponentTypeAfterSuite, 0), 25 | } 26 | } 27 | 28 | func (node *synchronizedAfterSuiteNode) Run(parallelNode int, parallelTotal int, syncHost string) bool { 29 | node.outcome, node.failure = node.runnerA.run() 30 | 31 | if parallelNode == 1 { 32 | if parallelTotal > 1 { 33 | node.waitUntilOtherNodesAreDone(syncHost) 34 | } 35 | 36 | outcome, failure := node.runnerB.run() 37 | 38 | if node.outcome == types.SpecStatePassed { 39 | node.outcome, node.failure = outcome, failure 40 | } 41 | } 42 | 43 | return node.outcome == types.SpecStatePassed 44 | } 45 | 46 | func (node *synchronizedAfterSuiteNode) Passed() bool { 47 | return node.outcome == types.SpecStatePassed 48 | } 49 | 50 | func (node *synchronizedAfterSuiteNode) Summary() *types.SetupSummary { 51 | return &types.SetupSummary{ 52 | ComponentType: node.runnerA.nodeType, 53 | CodeLocation: node.runnerA.codeLocation, 54 | State: node.outcome, 55 | RunTime: node.runTime, 56 | Failure: node.failure, 57 | } 58 | } 59 | 60 | func (node *synchronizedAfterSuiteNode) waitUntilOtherNodesAreDone(syncHost string) { 61 | for { 62 | if node.canRun(syncHost) { 63 | return 64 | } 65 | 66 | time.Sleep(50 * time.Millisecond) 67 | } 68 | } 69 | 70 | func (node *synchronizedAfterSuiteNode) canRun(syncHost string) bool { 71 | resp, err := http.Get(syncHost + "/RemoteAfterSuiteData") 72 | if err != nil || resp.StatusCode != http.StatusOK { 73 | return false 74 | } 75 | 76 | body, err := ioutil.ReadAll(resp.Body) 77 | if err != nil { 78 | return false 79 | } 80 | resp.Body.Close() 81 | 82 | afterSuiteData := types.RemoteAfterSuiteData{} 83 | err = json.Unmarshal(body, &afterSuiteData) 84 | if err != nil { 85 | return false 86 | } 87 | 88 | return afterSuiteData.CanRun 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/remote/forwarding_reporter.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io" 7 | "net/http" 8 | 9 | "github.com/onsi/ginkgo/config" 10 | "github.com/onsi/ginkgo/types" 11 | ) 12 | 13 | //An interface to net/http's client to allow the injection of fakes under test 14 | type Poster interface { 15 | Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error) 16 | } 17 | 18 | /* 19 | The ForwardingReporter is a Ginkgo reporter that forwards information to 20 | a Ginkgo remote server. 21 | 22 | When streaming parallel test output, this repoter is automatically installed by Ginkgo. 23 | 24 | This is accomplished by passing in the GINKGO_REMOTE_REPORTING_SERVER environment variable to `go test`, the Ginkgo test runner 25 | detects this environment variable (which should contain the host of the server) and automatically installs a ForwardingReporter 26 | in place of Ginkgo's DefaultReporter. 27 | */ 28 | 29 | type ForwardingReporter struct { 30 | serverHost string 31 | poster Poster 32 | outputInterceptor OutputInterceptor 33 | } 34 | 35 | func NewForwardingReporter(serverHost string, poster Poster, outputInterceptor OutputInterceptor) *ForwardingReporter { 36 | return &ForwardingReporter{ 37 | serverHost: serverHost, 38 | poster: poster, 39 | outputInterceptor: outputInterceptor, 40 | } 41 | } 42 | 43 | func (reporter *ForwardingReporter) post(path string, data interface{}) { 44 | encoded, _ := json.Marshal(data) 45 | buffer := bytes.NewBuffer(encoded) 46 | reporter.poster.Post(reporter.serverHost+path, "application/json", buffer) 47 | } 48 | 49 | func (reporter *ForwardingReporter) SpecSuiteWillBegin(conf config.GinkgoConfigType, summary *types.SuiteSummary) { 50 | data := struct { 51 | Config config.GinkgoConfigType `json:"config"` 52 | Summary *types.SuiteSummary `json:"suite-summary"` 53 | }{ 54 | conf, 55 | summary, 56 | } 57 | 58 | reporter.outputInterceptor.StartInterceptingOutput() 59 | reporter.post("/SpecSuiteWillBegin", data) 60 | } 61 | 62 | func (reporter *ForwardingReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) { 63 | output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput() 64 | reporter.outputInterceptor.StartInterceptingOutput() 65 | setupSummary.CapturedOutput = output 66 | reporter.post("/BeforeSuiteDidRun", setupSummary) 67 | } 68 | 69 | func (reporter *ForwardingReporter) SpecWillRun(specSummary *types.SpecSummary) { 70 | reporter.post("/SpecWillRun", specSummary) 71 | } 72 | 73 | func (reporter *ForwardingReporter) SpecDidComplete(specSummary *types.SpecSummary) { 74 | output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput() 75 | reporter.outputInterceptor.StartInterceptingOutput() 76 | specSummary.CapturedOutput = output 77 | reporter.post("/SpecDidComplete", specSummary) 78 | } 79 | 80 | func (reporter *ForwardingReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) { 81 | output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput() 82 | reporter.outputInterceptor.StartInterceptingOutput() 83 | setupSummary.CapturedOutput = output 84 | reporter.post("/AfterSuiteDidRun", setupSummary) 85 | } 86 | 87 | func (reporter *ForwardingReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) { 88 | reporter.outputInterceptor.StopInterceptingAndReturnOutput() 89 | reporter.post("/SpecSuiteDidEnd", summary) 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | /* 4 | The OutputInterceptor is used by the ForwardingReporter to 5 | intercept and capture all stdin and stderr output during a test run. 6 | */ 7 | type OutputInterceptor interface { 8 | StartInterceptingOutput() error 9 | StopInterceptingAndReturnOutput() (string, error) 10 | } 11 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_unix.go: -------------------------------------------------------------------------------- 1 | // +build freebsd openbsd netbsd dragonfly darwin linux 2 | 3 | package remote 4 | 5 | import ( 6 | "errors" 7 | "io/ioutil" 8 | "os" 9 | "syscall" 10 | ) 11 | 12 | func NewOutputInterceptor() OutputInterceptor { 13 | return &outputInterceptor{} 14 | } 15 | 16 | type outputInterceptor struct { 17 | stdoutPlaceholder *os.File 18 | stderrPlaceholder *os.File 19 | redirectFile *os.File 20 | intercepting bool 21 | } 22 | 23 | func (interceptor *outputInterceptor) StartInterceptingOutput() error { 24 | if interceptor.intercepting { 25 | return errors.New("Already intercepting output!") 26 | } 27 | interceptor.intercepting = true 28 | 29 | var err error 30 | 31 | interceptor.redirectFile, err = ioutil.TempFile("", "ginkgo-output") 32 | if err != nil { 33 | return err 34 | } 35 | 36 | interceptor.stdoutPlaceholder, err = ioutil.TempFile("", "ginkgo-output") 37 | if err != nil { 38 | return err 39 | } 40 | 41 | interceptor.stderrPlaceholder, err = ioutil.TempFile("", "ginkgo-output") 42 | if err != nil { 43 | return err 44 | } 45 | 46 | syscall.Dup2(1, int(interceptor.stdoutPlaceholder.Fd())) 47 | syscall.Dup2(2, int(interceptor.stderrPlaceholder.Fd())) 48 | 49 | syscall.Dup2(int(interceptor.redirectFile.Fd()), 1) 50 | syscall.Dup2(int(interceptor.redirectFile.Fd()), 2) 51 | 52 | return nil 53 | } 54 | 55 | func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) { 56 | if !interceptor.intercepting { 57 | return "", errors.New("Not intercepting output!") 58 | } 59 | 60 | syscall.Dup2(int(interceptor.stdoutPlaceholder.Fd()), 1) 61 | syscall.Dup2(int(interceptor.stderrPlaceholder.Fd()), 2) 62 | 63 | for _, f := range []*os.File{interceptor.redirectFile, interceptor.stdoutPlaceholder, interceptor.stderrPlaceholder} { 64 | f.Close() 65 | } 66 | 67 | output, err := ioutil.ReadFile(interceptor.redirectFile.Name()) 68 | 69 | for _, f := range []*os.File{interceptor.redirectFile, interceptor.stdoutPlaceholder, interceptor.stderrPlaceholder} { 70 | os.Remove(f.Name()) 71 | } 72 | 73 | interceptor.intercepting = false 74 | 75 | return string(output), err 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/remote/output_interceptor_win.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package remote 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | func NewOutputInterceptor() OutputInterceptor { 10 | return &outputInterceptor{} 11 | } 12 | 13 | type outputInterceptor struct { 14 | intercepting bool 15 | } 16 | 17 | func (interceptor *outputInterceptor) StartInterceptingOutput() error { 18 | if interceptor.intercepting { 19 | return errors.New("Already intercepting output!") 20 | } 21 | interceptor.intercepting = true 22 | 23 | // not working on windows... 24 | 25 | return nil 26 | } 27 | 28 | func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) { 29 | // not working on windows... 30 | interceptor.intercepting = false 31 | 32 | return "", nil 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/spec/index_computer.go: -------------------------------------------------------------------------------- 1 | package spec 2 | 3 | func ParallelizedIndexRange(length int, parallelTotal int, parallelNode int) (startIndex int, count int) { 4 | if length == 0 { 5 | return 0, 0 6 | } 7 | 8 | // We have more nodes than tests. Trivial case. 9 | if parallelTotal >= length { 10 | if parallelNode > length { 11 | return 0, 0 12 | } else { 13 | return parallelNode - 1, 1 14 | } 15 | } 16 | 17 | // This is the minimum amount of tests that a node will be required to run 18 | minTestsPerNode := length / parallelTotal 19 | 20 | // This is the maximum amount of tests that a node will be required to run 21 | // The algorithm guarantees that this would be equal to at least the minimum amount 22 | // and at most one more 23 | maxTestsPerNode := minTestsPerNode 24 | if length%parallelTotal != 0 { 25 | maxTestsPerNode++ 26 | } 27 | 28 | // Number of nodes that will have to run the maximum amount of tests per node 29 | numMaxLoadNodes := length % parallelTotal 30 | 31 | // Number of nodes that precede the current node and will have to run the maximum amount of tests per node 32 | var numPrecedingMaxLoadNodes int 33 | if parallelNode > numMaxLoadNodes { 34 | numPrecedingMaxLoadNodes = numMaxLoadNodes 35 | } else { 36 | numPrecedingMaxLoadNodes = parallelNode - 1 37 | } 38 | 39 | // Number of nodes that precede the current node and will have to run the minimum amount of tests per node 40 | var numPrecedingMinLoadNodes int 41 | if parallelNode <= numMaxLoadNodes { 42 | numPrecedingMinLoadNodes = 0 43 | } else { 44 | numPrecedingMinLoadNodes = parallelNode - numMaxLoadNodes - 1 45 | } 46 | 47 | // Evaluate the test start index and number of tests to run 48 | startIndex = numPrecedingMaxLoadNodes*maxTestsPerNode + numPrecedingMinLoadNodes*minTestsPerNode 49 | if parallelNode > numMaxLoadNodes { 50 | count = minTestsPerNode 51 | } else { 52 | count = maxTestsPerNode 53 | } 54 | return 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/spec/specs.go: -------------------------------------------------------------------------------- 1 | package spec 2 | 3 | import ( 4 | "math/rand" 5 | "regexp" 6 | "sort" 7 | ) 8 | 9 | type Specs struct { 10 | specs []*Spec 11 | numberOfOriginalSpecs int 12 | hasProgrammaticFocus bool 13 | } 14 | 15 | func NewSpecs(specs []*Spec) *Specs { 16 | return &Specs{ 17 | specs: specs, 18 | numberOfOriginalSpecs: len(specs), 19 | } 20 | } 21 | 22 | func (e *Specs) Specs() []*Spec { 23 | return e.specs 24 | } 25 | 26 | func (e *Specs) NumberOfOriginalSpecs() int { 27 | return e.numberOfOriginalSpecs 28 | } 29 | 30 | func (e *Specs) HasProgrammaticFocus() bool { 31 | return e.hasProgrammaticFocus 32 | } 33 | 34 | func (e *Specs) Shuffle(r *rand.Rand) { 35 | sort.Sort(e) 36 | permutation := r.Perm(len(e.specs)) 37 | shuffledSpecs := make([]*Spec, len(e.specs)) 38 | for i, j := range permutation { 39 | shuffledSpecs[i] = e.specs[j] 40 | } 41 | e.specs = shuffledSpecs 42 | } 43 | 44 | func (e *Specs) ApplyFocus(description string, focusString string, skipString string) { 45 | if focusString == "" && skipString == "" { 46 | e.applyProgrammaticFocus() 47 | } else { 48 | e.applyRegExpFocus(description, focusString, skipString) 49 | } 50 | } 51 | 52 | func (e *Specs) applyProgrammaticFocus() { 53 | e.hasProgrammaticFocus = false 54 | for _, spec := range e.specs { 55 | if spec.Focused() { 56 | e.hasProgrammaticFocus = true 57 | break 58 | } 59 | } 60 | 61 | if e.hasProgrammaticFocus { 62 | for _, spec := range e.specs { 63 | if !spec.Focused() { 64 | spec.Skip() 65 | } 66 | } 67 | } 68 | } 69 | 70 | func (e *Specs) applyRegExpFocus(description string, focusString string, skipString string) { 71 | for _, spec := range e.specs { 72 | matchesFocus := true 73 | matchesSkip := false 74 | 75 | toMatch := []byte(description + " " + spec.ConcatenatedString()) 76 | 77 | if focusString != "" { 78 | focusFilter := regexp.MustCompile(focusString) 79 | matchesFocus = focusFilter.Match([]byte(toMatch)) 80 | } 81 | 82 | if skipString != "" { 83 | skipFilter := regexp.MustCompile(skipString) 84 | matchesSkip = skipFilter.Match([]byte(toMatch)) 85 | } 86 | 87 | if !matchesFocus || matchesSkip { 88 | spec.Skip() 89 | } 90 | } 91 | } 92 | 93 | func (e *Specs) SkipMeasurements() { 94 | for _, spec := range e.specs { 95 | if spec.IsMeasurement() { 96 | spec.Skip() 97 | } 98 | } 99 | } 100 | 101 | func (e *Specs) TrimForParallelization(total int, node int) { 102 | startIndex, count := ParallelizedIndexRange(len(e.specs), total, node) 103 | if count == 0 { 104 | e.specs = make([]*Spec, 0) 105 | } else { 106 | e.specs = e.specs[startIndex : startIndex+count] 107 | } 108 | } 109 | 110 | //sort.Interface 111 | 112 | func (e *Specs) Len() int { 113 | return len(e.specs) 114 | } 115 | 116 | func (e *Specs) Less(i, j int) bool { 117 | return e.specs[i].ConcatenatedString() < e.specs[j].ConcatenatedString() 118 | } 119 | 120 | func (e *Specs) Swap(i, j int) { 121 | e.specs[i], e.specs[j] = e.specs[j], e.specs[i] 122 | } 123 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/specrunner/random_id.go: -------------------------------------------------------------------------------- 1 | package specrunner 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | ) 7 | 8 | func randomID() string { 9 | b := make([]byte, 8) 10 | _, err := rand.Read(b) 11 | if err != nil { 12 | return "" 13 | } 14 | return fmt.Sprintf("%x-%x-%x-%x", b[0:2], b[2:4], b[4:6], b[6:8]) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/testingtproxy/testing_t_proxy.go: -------------------------------------------------------------------------------- 1 | package testingtproxy 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | type failFunc func(message string, callerSkip ...int) 9 | 10 | func New(writer io.Writer, fail failFunc, offset int) *ginkgoTestingTProxy { 11 | return &ginkgoTestingTProxy{ 12 | fail: fail, 13 | offset: offset, 14 | writer: writer, 15 | } 16 | } 17 | 18 | type ginkgoTestingTProxy struct { 19 | fail failFunc 20 | offset int 21 | writer io.Writer 22 | } 23 | 24 | func (t *ginkgoTestingTProxy) Error(args ...interface{}) { 25 | t.fail(fmt.Sprintln(args...), t.offset) 26 | } 27 | 28 | func (t *ginkgoTestingTProxy) Errorf(format string, args ...interface{}) { 29 | t.fail(fmt.Sprintf(format, args...), t.offset) 30 | } 31 | 32 | func (t *ginkgoTestingTProxy) Fail() { 33 | t.fail("failed", t.offset) 34 | } 35 | 36 | func (t *ginkgoTestingTProxy) FailNow() { 37 | t.fail("failed", t.offset) 38 | } 39 | 40 | func (t *ginkgoTestingTProxy) Fatal(args ...interface{}) { 41 | t.fail(fmt.Sprintln(args...), t.offset) 42 | } 43 | 44 | func (t *ginkgoTestingTProxy) Fatalf(format string, args ...interface{}) { 45 | t.fail(fmt.Sprintf(format, args...), t.offset) 46 | } 47 | 48 | func (t *ginkgoTestingTProxy) Log(args ...interface{}) { 49 | fmt.Fprintln(t.writer, args...) 50 | } 51 | 52 | func (t *ginkgoTestingTProxy) Logf(format string, args ...interface{}) { 53 | fmt.Fprintf(t.writer, format, args...) 54 | } 55 | 56 | func (t *ginkgoTestingTProxy) Failed() bool { 57 | return false 58 | } 59 | 60 | func (t *ginkgoTestingTProxy) Parallel() { 61 | } 62 | 63 | func (t *ginkgoTestingTProxy) Skip(args ...interface{}) { 64 | fmt.Println(args...) 65 | } 66 | 67 | func (t *ginkgoTestingTProxy) Skipf(format string, args ...interface{}) { 68 | fmt.Printf(format, args...) 69 | } 70 | 71 | func (t *ginkgoTestingTProxy) SkipNow() { 72 | } 73 | 74 | func (t *ginkgoTestingTProxy) Skipped() bool { 75 | return false 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/writer/fake_writer.go: -------------------------------------------------------------------------------- 1 | package writer 2 | 3 | type FakeGinkgoWriter struct { 4 | EventStream []string 5 | } 6 | 7 | func NewFake() *FakeGinkgoWriter { 8 | return &FakeGinkgoWriter{ 9 | EventStream: []string{}, 10 | } 11 | } 12 | 13 | func (writer *FakeGinkgoWriter) AddEvent(event string) { 14 | writer.EventStream = append(writer.EventStream, event) 15 | } 16 | 17 | func (writer *FakeGinkgoWriter) Truncate() { 18 | writer.EventStream = append(writer.EventStream, "TRUNCATE") 19 | } 20 | 21 | func (writer *FakeGinkgoWriter) DumpOut() { 22 | writer.EventStream = append(writer.EventStream, "DUMP") 23 | } 24 | 25 | func (writer *FakeGinkgoWriter) DumpOutWithHeader(header string) { 26 | writer.EventStream = append(writer.EventStream, "DUMP_WITH_HEADER: "+header) 27 | } 28 | 29 | func (writer *FakeGinkgoWriter) Write(data []byte) (n int, err error) { 30 | return 0, nil 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/internal/writer/writer.go: -------------------------------------------------------------------------------- 1 | package writer 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "sync" 7 | ) 8 | 9 | type WriterInterface interface { 10 | io.Writer 11 | 12 | Truncate() 13 | DumpOut() 14 | DumpOutWithHeader(header string) 15 | } 16 | 17 | type Writer struct { 18 | buffer *bytes.Buffer 19 | outWriter io.Writer 20 | lock *sync.Mutex 21 | stream bool 22 | } 23 | 24 | func New(outWriter io.Writer) *Writer { 25 | return &Writer{ 26 | buffer: &bytes.Buffer{}, 27 | lock: &sync.Mutex{}, 28 | outWriter: outWriter, 29 | stream: true, 30 | } 31 | } 32 | 33 | func (w *Writer) SetStream(stream bool) { 34 | w.lock.Lock() 35 | defer w.lock.Unlock() 36 | w.stream = stream 37 | } 38 | 39 | func (w *Writer) Write(b []byte) (n int, err error) { 40 | w.lock.Lock() 41 | defer w.lock.Unlock() 42 | 43 | if w.stream { 44 | return w.outWriter.Write(b) 45 | } else { 46 | return w.buffer.Write(b) 47 | } 48 | } 49 | 50 | func (w *Writer) Truncate() { 51 | w.lock.Lock() 52 | defer w.lock.Unlock() 53 | w.buffer.Reset() 54 | } 55 | 56 | func (w *Writer) DumpOut() { 57 | w.lock.Lock() 58 | defer w.lock.Unlock() 59 | if !w.stream { 60 | w.buffer.WriteTo(w.outWriter) 61 | } 62 | } 63 | 64 | func (w *Writer) DumpOutWithHeader(header string) { 65 | w.lock.Lock() 66 | defer w.lock.Unlock() 67 | if !w.stream && w.buffer.Len() > 0 { 68 | w.outWriter.Write([]byte(header)) 69 | w.buffer.WriteTo(w.outWriter) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/reporters/default_reporter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Ginkgo's Default Reporter 3 | 4 | A number of command line flags are available to tweak Ginkgo's default output. 5 | 6 | These are documented [here](http://onsi.github.io/ginkgo/#running_tests) 7 | */ 8 | package reporters 9 | 10 | import ( 11 | "github.com/onsi/ginkgo/config" 12 | "github.com/onsi/ginkgo/reporters/stenographer" 13 | "github.com/onsi/ginkgo/types" 14 | ) 15 | 16 | type DefaultReporter struct { 17 | config config.DefaultReporterConfigType 18 | stenographer stenographer.Stenographer 19 | specSummaries []*types.SpecSummary 20 | } 21 | 22 | func NewDefaultReporter(config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *DefaultReporter { 23 | return &DefaultReporter{ 24 | config: config, 25 | stenographer: stenographer, 26 | } 27 | } 28 | 29 | func (reporter *DefaultReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) { 30 | reporter.stenographer.AnnounceSuite(summary.SuiteDescription, config.RandomSeed, config.RandomizeAllSpecs, reporter.config.Succinct) 31 | if config.ParallelTotal > 1 { 32 | reporter.stenographer.AnnounceParallelRun(config.ParallelNode, config.ParallelTotal, summary.NumberOfTotalSpecs, summary.NumberOfSpecsBeforeParallelization, reporter.config.Succinct) 33 | } 34 | reporter.stenographer.AnnounceNumberOfSpecs(summary.NumberOfSpecsThatWillBeRun, summary.NumberOfTotalSpecs, reporter.config.Succinct) 35 | } 36 | 37 | func (reporter *DefaultReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) { 38 | if setupSummary.State != types.SpecStatePassed { 39 | reporter.stenographer.AnnounceBeforeSuiteFailure(setupSummary, reporter.config.Succinct, reporter.config.FullTrace) 40 | } 41 | } 42 | 43 | func (reporter *DefaultReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) { 44 | if setupSummary.State != types.SpecStatePassed { 45 | reporter.stenographer.AnnounceAfterSuiteFailure(setupSummary, reporter.config.Succinct, reporter.config.FullTrace) 46 | } 47 | } 48 | 49 | func (reporter *DefaultReporter) SpecWillRun(specSummary *types.SpecSummary) { 50 | if reporter.config.Verbose && !reporter.config.Succinct && specSummary.State != types.SpecStatePending && specSummary.State != types.SpecStateSkipped { 51 | reporter.stenographer.AnnounceSpecWillRun(specSummary) 52 | } 53 | } 54 | 55 | func (reporter *DefaultReporter) SpecDidComplete(specSummary *types.SpecSummary) { 56 | switch specSummary.State { 57 | case types.SpecStatePassed: 58 | if specSummary.IsMeasurement { 59 | reporter.stenographer.AnnounceSuccesfulMeasurement(specSummary, reporter.config.Succinct) 60 | } else if specSummary.RunTime.Seconds() >= reporter.config.SlowSpecThreshold { 61 | reporter.stenographer.AnnounceSuccesfulSlowSpec(specSummary, reporter.config.Succinct) 62 | } else { 63 | reporter.stenographer.AnnounceSuccesfulSpec(specSummary) 64 | } 65 | case types.SpecStatePending: 66 | reporter.stenographer.AnnouncePendingSpec(specSummary, reporter.config.NoisyPendings && !reporter.config.Succinct) 67 | case types.SpecStateSkipped: 68 | reporter.stenographer.AnnounceSkippedSpec(specSummary) 69 | case types.SpecStateTimedOut: 70 | reporter.stenographer.AnnounceSpecTimedOut(specSummary, reporter.config.Succinct, reporter.config.FullTrace) 71 | case types.SpecStatePanicked: 72 | reporter.stenographer.AnnounceSpecPanicked(specSummary, reporter.config.Succinct, reporter.config.FullTrace) 73 | case types.SpecStateFailed: 74 | reporter.stenographer.AnnounceSpecFailed(specSummary, reporter.config.Succinct, reporter.config.FullTrace) 75 | } 76 | 77 | reporter.specSummaries = append(reporter.specSummaries, specSummary) 78 | } 79 | 80 | func (reporter *DefaultReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) { 81 | reporter.stenographer.SummarizeFailures(reporter.specSummaries) 82 | reporter.stenographer.AnnounceSpecRunCompletion(summary, reporter.config.Succinct) 83 | } 84 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/reporters/fake_reporter.go: -------------------------------------------------------------------------------- 1 | package reporters 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/config" 5 | "github.com/onsi/ginkgo/types" 6 | ) 7 | 8 | //FakeReporter is useful for testing purposes 9 | type FakeReporter struct { 10 | Config config.GinkgoConfigType 11 | 12 | BeginSummary *types.SuiteSummary 13 | BeforeSuiteSummary *types.SetupSummary 14 | SpecWillRunSummaries []*types.SpecSummary 15 | SpecSummaries []*types.SpecSummary 16 | AfterSuiteSummary *types.SetupSummary 17 | EndSummary *types.SuiteSummary 18 | 19 | SpecWillRunStub func(specSummary *types.SpecSummary) 20 | SpecDidCompleteStub func(specSummary *types.SpecSummary) 21 | } 22 | 23 | func NewFakeReporter() *FakeReporter { 24 | return &FakeReporter{ 25 | SpecWillRunSummaries: make([]*types.SpecSummary, 0), 26 | SpecSummaries: make([]*types.SpecSummary, 0), 27 | } 28 | } 29 | 30 | func (fakeR *FakeReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) { 31 | fakeR.Config = config 32 | fakeR.BeginSummary = summary 33 | } 34 | 35 | func (fakeR *FakeReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) { 36 | fakeR.BeforeSuiteSummary = setupSummary 37 | } 38 | 39 | func (fakeR *FakeReporter) SpecWillRun(specSummary *types.SpecSummary) { 40 | if fakeR.SpecWillRunStub != nil { 41 | fakeR.SpecWillRunStub(specSummary) 42 | } 43 | fakeR.SpecWillRunSummaries = append(fakeR.SpecWillRunSummaries, specSummary) 44 | } 45 | 46 | func (fakeR *FakeReporter) SpecDidComplete(specSummary *types.SpecSummary) { 47 | if fakeR.SpecDidCompleteStub != nil { 48 | fakeR.SpecDidCompleteStub(specSummary) 49 | } 50 | fakeR.SpecSummaries = append(fakeR.SpecSummaries, specSummary) 51 | } 52 | 53 | func (fakeR *FakeReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) { 54 | fakeR.AfterSuiteSummary = setupSummary 55 | } 56 | 57 | func (fakeR *FakeReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) { 58 | fakeR.EndSummary = summary 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/reporters/reporter.go: -------------------------------------------------------------------------------- 1 | package reporters 2 | 3 | import ( 4 | "github.com/onsi/ginkgo/config" 5 | "github.com/onsi/ginkgo/types" 6 | ) 7 | 8 | type Reporter interface { 9 | SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) 10 | BeforeSuiteDidRun(setupSummary *types.SetupSummary) 11 | SpecWillRun(specSummary *types.SpecSummary) 12 | SpecDidComplete(specSummary *types.SpecSummary) 13 | AfterSuiteDidRun(setupSummary *types.SetupSummary) 14 | SpecSuiteDidEnd(summary *types.SuiteSummary) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/reporters/stenographer/console_logging.go: -------------------------------------------------------------------------------- 1 | package stenographer 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func (s *consoleStenographer) colorize(colorCode string, format string, args ...interface{}) string { 9 | var out string 10 | 11 | if len(args) > 0 { 12 | out = fmt.Sprintf(format, args...) 13 | } else { 14 | out = format 15 | } 16 | 17 | if s.color { 18 | return fmt.Sprintf("%s%s%s", colorCode, out, defaultStyle) 19 | } else { 20 | return out 21 | } 22 | } 23 | 24 | func (s *consoleStenographer) printBanner(text string, bannerCharacter string) { 25 | fmt.Println(text) 26 | fmt.Println(strings.Repeat(bannerCharacter, len(text))) 27 | } 28 | 29 | func (s *consoleStenographer) printNewLine() { 30 | fmt.Println("") 31 | } 32 | 33 | func (s *consoleStenographer) printDelimiter() { 34 | fmt.Println(s.colorize(grayColor, "%s", strings.Repeat("-", 30))) 35 | } 36 | 37 | func (s *consoleStenographer) print(indentation int, format string, args ...interface{}) { 38 | fmt.Print(s.indent(indentation, format, args...)) 39 | } 40 | 41 | func (s *consoleStenographer) println(indentation int, format string, args ...interface{}) { 42 | fmt.Println(s.indent(indentation, format, args...)) 43 | } 44 | 45 | func (s *consoleStenographer) indent(indentation int, format string, args ...interface{}) string { 46 | var text string 47 | 48 | if len(args) > 0 { 49 | text = fmt.Sprintf(format, args...) 50 | } else { 51 | text = format 52 | } 53 | 54 | stringArray := strings.Split(text, "\n") 55 | padding := "" 56 | if indentation >= 0 { 57 | padding = strings.Repeat(" ", indentation) 58 | } 59 | for i, s := range stringArray { 60 | stringArray[i] = fmt.Sprintf("%s%s", padding, s) 61 | } 62 | 63 | return strings.Join(stringArray, "\n") 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/reporters/teamcity_reporter.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | TeamCity Reporter for Ginkgo 4 | 5 | Makes use of TeamCity's support for Service Messages 6 | http://confluence.jetbrains.com/display/TCD7/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingTests 7 | */ 8 | 9 | package reporters 10 | 11 | import ( 12 | "fmt" 13 | "github.com/onsi/ginkgo/config" 14 | "github.com/onsi/ginkgo/types" 15 | "io" 16 | "strings" 17 | ) 18 | 19 | const ( 20 | messageId = "##teamcity" 21 | ) 22 | 23 | type TeamCityReporter struct { 24 | writer io.Writer 25 | testSuiteName string 26 | } 27 | 28 | func NewTeamCityReporter(writer io.Writer) *TeamCityReporter { 29 | return &TeamCityReporter{ 30 | writer: writer, 31 | } 32 | } 33 | 34 | func (reporter *TeamCityReporter) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) { 35 | reporter.testSuiteName = escape(summary.SuiteDescription) 36 | fmt.Fprintf(reporter.writer, "%s[testSuiteStarted name='%s']", messageId, reporter.testSuiteName) 37 | } 38 | 39 | func (reporter *TeamCityReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) { 40 | reporter.handleSetupSummary("BeforeSuite", setupSummary) 41 | } 42 | 43 | func (reporter *TeamCityReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) { 44 | reporter.handleSetupSummary("AfterSuite", setupSummary) 45 | } 46 | 47 | func (reporter *TeamCityReporter) handleSetupSummary(name string, setupSummary *types.SetupSummary) { 48 | if setupSummary.State != types.SpecStatePassed { 49 | testName := escape(name) 50 | fmt.Fprintf(reporter.writer, "%s[testStarted name='%s']", messageId, testName) 51 | message := escape(setupSummary.Failure.ComponentCodeLocation.String()) 52 | details := escape(setupSummary.Failure.Message) 53 | fmt.Fprintf(reporter.writer, "%s[testFailed name='%s' message='%s' details='%s']", messageId, testName, message, details) 54 | durationInMilliseconds := setupSummary.RunTime.Seconds() * 1000 55 | fmt.Fprintf(reporter.writer, "%s[testFinished name='%s' duration='%v']", messageId, testName, durationInMilliseconds) 56 | } 57 | } 58 | 59 | func (reporter *TeamCityReporter) SpecWillRun(specSummary *types.SpecSummary) { 60 | testName := escape(strings.Join(specSummary.ComponentTexts[1:], " ")) 61 | fmt.Fprintf(reporter.writer, "%s[testStarted name='%s']", messageId, testName) 62 | } 63 | 64 | func (reporter *TeamCityReporter) SpecDidComplete(specSummary *types.SpecSummary) { 65 | testName := escape(strings.Join(specSummary.ComponentTexts[1:], " ")) 66 | 67 | if specSummary.State == types.SpecStateFailed || specSummary.State == types.SpecStateTimedOut || specSummary.State == types.SpecStatePanicked { 68 | message := escape(specSummary.Failure.ComponentCodeLocation.String()) 69 | details := escape(specSummary.Failure.Message) 70 | fmt.Fprintf(reporter.writer, "%s[testFailed name='%s' message='%s' details='%s']", messageId, testName, message, details) 71 | } 72 | if specSummary.State == types.SpecStateSkipped || specSummary.State == types.SpecStatePending { 73 | fmt.Fprintf(reporter.writer, "%s[testIgnored name='%s']", messageId, testName) 74 | } 75 | 76 | durationInMilliseconds := specSummary.RunTime.Seconds() * 1000 77 | fmt.Fprintf(reporter.writer, "%s[testFinished name='%s' duration='%v']", messageId, testName, durationInMilliseconds) 78 | } 79 | 80 | func (reporter *TeamCityReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) { 81 | fmt.Fprintf(reporter.writer, "%s[testSuiteFinished name='%s']", messageId, reporter.testSuiteName) 82 | } 83 | 84 | func escape(output string) string { 85 | output = strings.Replace(output, "|", "||", -1) 86 | output = strings.Replace(output, "'", "|'", -1) 87 | output = strings.Replace(output, "\n", "|n", -1) 88 | output = strings.Replace(output, "\r", "|r", -1) 89 | output = strings.Replace(output, "[", "|[", -1) 90 | output = strings.Replace(output, "]", "|]", -1) 91 | return output 92 | } 93 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/types/code_location.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type CodeLocation struct { 8 | FileName string 9 | LineNumber int 10 | FullStackTrace string 11 | } 12 | 13 | func (codeLocation CodeLocation) String() string { 14 | return fmt.Sprintf("%s:%d", codeLocation.FileName, codeLocation.LineNumber) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/types/synchronization.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | type RemoteBeforeSuiteState int 8 | 9 | const ( 10 | RemoteBeforeSuiteStateInvalid RemoteBeforeSuiteState = iota 11 | 12 | RemoteBeforeSuiteStatePending 13 | RemoteBeforeSuiteStatePassed 14 | RemoteBeforeSuiteStateFailed 15 | RemoteBeforeSuiteStateDisappeared 16 | ) 17 | 18 | type RemoteBeforeSuiteData struct { 19 | Data []byte 20 | State RemoteBeforeSuiteState 21 | } 22 | 23 | func (r RemoteBeforeSuiteData) ToJSON() []byte { 24 | data, _ := json.Marshal(r) 25 | return data 26 | } 27 | 28 | type RemoteAfterSuiteData struct { 29 | CanRun bool 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/ginkgo/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | const GINKGO_FOCUS_EXIT_CODE = 197 8 | 9 | type SuiteSummary struct { 10 | SuiteDescription string 11 | SuiteSucceeded bool 12 | SuiteID string 13 | 14 | NumberOfSpecsBeforeParallelization int 15 | NumberOfTotalSpecs int 16 | NumberOfSpecsThatWillBeRun int 17 | NumberOfPendingSpecs int 18 | NumberOfSkippedSpecs int 19 | NumberOfPassedSpecs int 20 | NumberOfFailedSpecs int 21 | RunTime time.Duration 22 | } 23 | 24 | type SpecSummary struct { 25 | ComponentTexts []string 26 | ComponentCodeLocations []CodeLocation 27 | 28 | State SpecState 29 | RunTime time.Duration 30 | Failure SpecFailure 31 | IsMeasurement bool 32 | NumberOfSamples int 33 | Measurements map[string]*SpecMeasurement 34 | 35 | CapturedOutput string 36 | SuiteID string 37 | } 38 | 39 | func (s SpecSummary) HasFailureState() bool { 40 | return s.State == SpecStateTimedOut || s.State == SpecStatePanicked || s.State == SpecStateFailed 41 | } 42 | 43 | func (s SpecSummary) TimedOut() bool { 44 | return s.State == SpecStateTimedOut 45 | } 46 | 47 | func (s SpecSummary) Panicked() bool { 48 | return s.State == SpecStatePanicked 49 | } 50 | 51 | func (s SpecSummary) Failed() bool { 52 | return s.State == SpecStateFailed 53 | } 54 | 55 | func (s SpecSummary) Passed() bool { 56 | return s.State == SpecStatePassed 57 | } 58 | 59 | func (s SpecSummary) Skipped() bool { 60 | return s.State == SpecStateSkipped 61 | } 62 | 63 | func (s SpecSummary) Pending() bool { 64 | return s.State == SpecStatePending 65 | } 66 | 67 | type SetupSummary struct { 68 | ComponentType SpecComponentType 69 | CodeLocation CodeLocation 70 | 71 | State SpecState 72 | RunTime time.Duration 73 | Failure SpecFailure 74 | 75 | CapturedOutput string 76 | SuiteID string 77 | } 78 | 79 | type SpecFailure struct { 80 | Message string 81 | Location CodeLocation 82 | ForwardedPanic interface{} 83 | 84 | ComponentIndex int 85 | ComponentType SpecComponentType 86 | ComponentCodeLocation CodeLocation 87 | } 88 | 89 | type SpecMeasurement struct { 90 | Name string 91 | Info interface{} 92 | Order int 93 | 94 | Results []float64 95 | 96 | Smallest float64 97 | Largest float64 98 | Average float64 99 | StdDeviation float64 100 | 101 | SmallestLabel string 102 | LargestLabel string 103 | AverageLabel string 104 | Units string 105 | } 106 | 107 | type SpecState uint 108 | 109 | const ( 110 | SpecStateInvalid SpecState = iota 111 | 112 | SpecStatePending 113 | SpecStateSkipped 114 | SpecStatePassed 115 | SpecStateFailed 116 | SpecStatePanicked 117 | SpecStateTimedOut 118 | ) 119 | 120 | type SpecComponentType uint 121 | 122 | const ( 123 | SpecComponentTypeInvalid SpecComponentType = iota 124 | 125 | SpecComponentTypeContainer 126 | SpecComponentTypeBeforeSuite 127 | SpecComponentTypeAfterSuite 128 | SpecComponentTypeBeforeEach 129 | SpecComponentTypeJustBeforeEach 130 | SpecComponentTypeAfterEach 131 | SpecComponentTypeIt 132 | SpecComponentTypeMeasure 133 | ) 134 | 135 | type FlagType uint 136 | 137 | const ( 138 | FlagTypeNone FlagType = iota 139 | FlagTypeFocused 140 | FlagTypePending 141 | ) 142 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.test 3 | . 4 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.3 4 | 5 | install: 6 | - go get -v ./... 7 | - go get github.com/onsi/ginkgo 8 | - go install github.com/onsi/ginkgo/ginkgo 9 | 10 | script: $HOME/gopath/bin/ginkgo -r --randomizeAllSpecs --failOnPending --randomizeSuites --race 11 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## HEAD 2 | 3 | Improvements: 4 | 5 | - Added `BeSent` which attempts to send a value down a channel and fails if the attempt blocks. Can be paired with `Eventually` to safely send a value down a channel with a timeout. 6 | - `Ω`, `Expect`, `Eventually`, and `Consistently` now immediately `panic` if there is no registered fail handler. This is always a mistake that can hide failing tests. 7 | - `Receive()` no longer errors when passed a closed channel, it's perfectly fine to attempt to read from a closed channel so Ω(c).Should(Receive()) always fails and Ω(c).ShoudlNot(Receive()) always passes with a closed channel. 8 | - Added `HavePrefix` and `HaveSuffix` matchers. 9 | - `ghttp` can now handle concurrent requests. 10 | - Added `Succeed` which allows one to write `Ω(MyFunction()).Should(Succeed())`. 11 | 12 | ## 1.0 (8/2/2014) 13 | 14 | No changes. Dropping "beta" from the version number. 15 | 16 | ## 1.0.0-beta (7/8/2014) 17 | Breaking Changes: 18 | 19 | - Changed OmegaMatcher interface. Instead of having `Match` return failure messages, two new methods `FailureMessage` and `NegatedFailureMessage` are called instead. 20 | - Moved and renamed OmegaFailHandler to types.GomegaFailHandler and OmegaMatcher to types.GomegaMatcher. Any references to OmegaMatcher in any custom matchers will need to be changed to point to types.GomegaMatcher 21 | 22 | New Test-Support Features: 23 | 24 | - `ghttp`: supports testing http clients 25 | - Provides a flexible fake http server 26 | - Provides a collection of chainable http handlers that perform assertions. 27 | - `gbytes`: supports making ordered assertions against streams of data 28 | - Provides a `gbytes.Buffer` 29 | - Provides a `Say` matcher to perform ordered assertions against output data 30 | - `gexec`: supports testing external processes 31 | - Provides support for building Go binaries 32 | - Wraps and starts `exec.Cmd` commands 33 | - Makes it easy to assert against stdout and stderr 34 | - Makes it easy to send signals and wait for processes to exit 35 | - Provides an `Exit` matcher to assert against exit code. 36 | 37 | DSL Changes: 38 | 39 | - `Eventually` and `Consistently` can accept `time.Duration` interval and polling inputs. 40 | - The default timeouts for `Eventually` and `Consistently` are now configurable. 41 | 42 | New Matchers: 43 | 44 | - `ConsistOf`: order-independent assertion against the elements of an array/slice or keys of a map. 45 | - `BeTemporally`: like `BeNumerically` but for `time.Time` 46 | - `HaveKeyWithValue`: asserts a map has a given key with the given value. 47 | 48 | Updated Matchers: 49 | 50 | - `Receive` matcher can take a matcher as an argument and passes only if the channel under test receives an objet that satisfies the passed-in matcher. 51 | - Matchers that implement `MatchMayChangeInTheFuture(actual interface{}) bool` can inform `Eventually` and/or `Consistently` when a match has no chance of changing status in the future. For example, `Receive` returns `false` when a channel is closed. 52 | 53 | Misc: 54 | 55 | - Start using semantic versioning 56 | - Start maintaining changelog 57 | 58 | Major refactor: 59 | 60 | - Pull out Gomega's internal to `internal` 61 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2014 Onsi Fakhouri 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/README.md: -------------------------------------------------------------------------------- 1 | ![Gomega: Ginkgo's Preferred Matcher Library](http://onsi.github.io/gomega/images/gomega.png) 2 | 3 | [![Build Status](https://travis-ci.org/onsi/gomega.png)](https://travis-ci.org/onsi/gomega) 4 | 5 | Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers). 6 | 7 | To discuss Gomega and get updates, join the [google group](https://groups.google.com/d/forum/ginkgo-and-gomega). 8 | 9 | ## [Ginkgo](http://github.com/onsi/ginkgo): a BDD Testing Framework for Golang 10 | 11 | Learn more about Ginkgo [here](http://onsi.github.io/ginkgo/) 12 | 13 | ## License 14 | 15 | Gomega is MIT-Licensed 16 | 17 | The `ConsistOf` matcher uses [goraph](https://github.com/amitkgupta/goraph) which is embedded in the source to simplify distribution. goraph has an MIT license. 18 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/internal/assertion/assertion.go: -------------------------------------------------------------------------------- 1 | package assertion 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/onsi/gomega/types" 8 | ) 9 | 10 | type Assertion struct { 11 | actualInput interface{} 12 | fail types.GomegaFailHandler 13 | offset int 14 | extra []interface{} 15 | } 16 | 17 | func New(actualInput interface{}, fail types.GomegaFailHandler, offset int, extra ...interface{}) *Assertion { 18 | return &Assertion{ 19 | actualInput: actualInput, 20 | fail: fail, 21 | offset: offset, 22 | extra: extra, 23 | } 24 | } 25 | 26 | func (assertion *Assertion) Should(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { 27 | return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) 28 | } 29 | 30 | func (assertion *Assertion) ShouldNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { 31 | return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) 32 | } 33 | 34 | func (assertion *Assertion) To(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { 35 | return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, true, optionalDescription...) 36 | } 37 | 38 | func (assertion *Assertion) ToNot(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { 39 | return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) 40 | } 41 | 42 | func (assertion *Assertion) NotTo(matcher types.GomegaMatcher, optionalDescription ...interface{}) bool { 43 | return assertion.vetExtras(optionalDescription...) && assertion.match(matcher, false, optionalDescription...) 44 | } 45 | 46 | func (assertion *Assertion) buildDescription(optionalDescription ...interface{}) string { 47 | switch len(optionalDescription) { 48 | case 0: 49 | return "" 50 | default: 51 | return fmt.Sprintf(optionalDescription[0].(string), optionalDescription[1:]...) + "\n" 52 | } 53 | } 54 | 55 | func (assertion *Assertion) match(matcher types.GomegaMatcher, desiredMatch bool, optionalDescription ...interface{}) bool { 56 | matches, err := matcher.Match(assertion.actualInput) 57 | description := assertion.buildDescription(optionalDescription...) 58 | if err != nil { 59 | assertion.fail(description+err.Error(), 2+assertion.offset) 60 | return false 61 | } 62 | if matches != desiredMatch { 63 | var message string 64 | if desiredMatch { 65 | message = matcher.FailureMessage(assertion.actualInput) 66 | } else { 67 | message = matcher.NegatedFailureMessage(assertion.actualInput) 68 | } 69 | assertion.fail(description+message, 2+assertion.offset) 70 | return false 71 | } 72 | 73 | return true 74 | } 75 | 76 | func (assertion *Assertion) vetExtras(optionalDescription ...interface{}) bool { 77 | success, message := vetExtras(assertion.extra) 78 | if success { 79 | return true 80 | } 81 | 82 | description := assertion.buildDescription(optionalDescription...) 83 | assertion.fail(description+message, 2+assertion.offset) 84 | return false 85 | } 86 | 87 | func vetExtras(extras []interface{}) (bool, string) { 88 | for i, extra := range extras { 89 | if extra != nil { 90 | zeroValue := reflect.Zero(reflect.TypeOf(extra)).Interface() 91 | if !reflect.DeepEqual(zeroValue, extra) { 92 | message := fmt.Sprintf("Unexpected non-nil/non-zero extra argument at index %d:\n\t<%T>: %#v", i+1, extra, extra) 93 | return false, message 94 | } 95 | } 96 | } 97 | return true, "" 98 | } 99 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/internal/testingtsupport/testing_t_support.go: -------------------------------------------------------------------------------- 1 | package testingtsupport 2 | 3 | import ( 4 | "regexp" 5 | "runtime/debug" 6 | "strings" 7 | 8 | "github.com/onsi/gomega/types" 9 | ) 10 | 11 | type gomegaTestingT interface { 12 | Errorf(format string, args ...interface{}) 13 | } 14 | 15 | func BuildTestingTGomegaFailHandler(t gomegaTestingT) types.GomegaFailHandler { 16 | return func(message string, callerSkip ...int) { 17 | skip := 1 18 | if len(callerSkip) > 0 { 19 | skip = callerSkip[0] 20 | } 21 | stackTrace := pruneStack(string(debug.Stack()), skip) 22 | t.Errorf("\n%s\n%s", stackTrace, message) 23 | } 24 | } 25 | 26 | func pruneStack(fullStackTrace string, skip int) string { 27 | stack := strings.Split(fullStackTrace, "\n") 28 | if len(stack) > 2*(skip+1) { 29 | stack = stack[2*(skip+1):] 30 | } 31 | prunedStack := []string{} 32 | re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`) 33 | for i := 0; i < len(stack)/2; i++ { 34 | if !re.Match([]byte(stack[i*2])) { 35 | prunedStack = append(prunedStack, stack[i*2]) 36 | prunedStack = append(prunedStack, stack[i*2+1]) 37 | } 38 | } 39 | return strings.Join(prunedStack, "\n") 40 | } 41 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/assignable_to_type_of_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type AssignableToTypeOfMatcher struct { 10 | Expected interface{} 11 | } 12 | 13 | func (matcher *AssignableToTypeOfMatcher) Match(actual interface{}) (success bool, err error) { 14 | if actual == nil || matcher.Expected == nil { 15 | return false, fmt.Errorf("Refusing to compare to .") 16 | } 17 | 18 | actualType := reflect.TypeOf(actual) 19 | expectedType := reflect.TypeOf(matcher.Expected) 20 | 21 | return actualType.AssignableTo(expectedType), nil 22 | } 23 | 24 | func (matcher *AssignableToTypeOfMatcher) FailureMessage(actual interface{}) string { 25 | return format.Message(actual, fmt.Sprintf("to be assignable to the type: %T", matcher.Expected)) 26 | } 27 | 28 | func (matcher *AssignableToTypeOfMatcher) NegatedFailureMessage(actual interface{}) string { 29 | return format.Message(actual, fmt.Sprintf("not to be assignable to the type: %T", matcher.Expected)) 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_closed_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type BeClosedMatcher struct { 10 | } 11 | 12 | func (matcher *BeClosedMatcher) Match(actual interface{}) (success bool, err error) { 13 | if !isChan(actual) { 14 | return false, fmt.Errorf("BeClosed matcher expects a channel. Got:\n%s", format.Object(actual, 1)) 15 | } 16 | 17 | channelType := reflect.TypeOf(actual) 18 | channelValue := reflect.ValueOf(actual) 19 | 20 | if channelType.ChanDir() == reflect.SendDir { 21 | return false, fmt.Errorf("BeClosed matcher cannot determine if a send-only channel is closed or open. Got:\n%s", format.Object(actual, 1)) 22 | } 23 | 24 | winnerIndex, _, open := reflect.Select([]reflect.SelectCase{ 25 | reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue}, 26 | reflect.SelectCase{Dir: reflect.SelectDefault}, 27 | }) 28 | 29 | var closed bool 30 | if winnerIndex == 0 { 31 | closed = !open 32 | } else if winnerIndex == 1 { 33 | closed = false 34 | } 35 | 36 | return closed, nil 37 | } 38 | 39 | func (matcher *BeClosedMatcher) FailureMessage(actual interface{}) (message string) { 40 | return format.Message(actual, "to be closed") 41 | } 42 | 43 | func (matcher *BeClosedMatcher) NegatedFailureMessage(actual interface{}) (message string) { 44 | return format.Message(actual, "to be open") 45 | } 46 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_empty_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type BeEmptyMatcher struct { 9 | } 10 | 11 | func (matcher *BeEmptyMatcher) Match(actual interface{}) (success bool, err error) { 12 | length, ok := lengthOf(actual) 13 | if !ok { 14 | return false, fmt.Errorf("BeEmpty matcher expects a string/array/map/channel/slice. Got:\n%s", format.Object(actual, 1)) 15 | } 16 | 17 | return length == 0, nil 18 | } 19 | 20 | func (matcher *BeEmptyMatcher) FailureMessage(actual interface{}) (message string) { 21 | return format.Message(actual, "to be empty") 22 | } 23 | 24 | func (matcher *BeEmptyMatcher) NegatedFailureMessage(actual interface{}) (message string) { 25 | return format.Message(actual, "not to be empty") 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_equivalent_to_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type BeEquivalentToMatcher struct { 10 | Expected interface{} 11 | } 12 | 13 | func (matcher *BeEquivalentToMatcher) Match(actual interface{}) (success bool, err error) { 14 | if actual == nil && matcher.Expected == nil { 15 | return false, fmt.Errorf("Both actual and expected must not be nil.") 16 | } 17 | 18 | convertedActual := actual 19 | 20 | if actual != nil && matcher.Expected != nil && reflect.TypeOf(actual).ConvertibleTo(reflect.TypeOf(matcher.Expected)) { 21 | convertedActual = reflect.ValueOf(actual).Convert(reflect.TypeOf(matcher.Expected)).Interface() 22 | } 23 | 24 | return reflect.DeepEqual(convertedActual, matcher.Expected), nil 25 | } 26 | 27 | func (matcher *BeEquivalentToMatcher) FailureMessage(actual interface{}) (message string) { 28 | return format.Message(actual, "to be equivalent to", matcher.Expected) 29 | } 30 | 31 | func (matcher *BeEquivalentToMatcher) NegatedFailureMessage(actual interface{}) (message string) { 32 | return format.Message(actual, "not to be equivalent to", matcher.Expected) 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_false_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type BeFalseMatcher struct { 9 | } 10 | 11 | func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err error) { 12 | if !isBool(actual) { 13 | return false, fmt.Errorf("Expected a boolean. Got:\n%s", format.Object(actual, 1)) 14 | } 15 | 16 | return actual == false, nil 17 | } 18 | 19 | func (matcher *BeFalseMatcher) FailureMessage(actual interface{}) (message string) { 20 | return format.Message(actual, "to be false") 21 | } 22 | 23 | func (matcher *BeFalseMatcher) NegatedFailureMessage(actual interface{}) (message string) { 24 | return format.Message(actual, "not to be false") 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_nil_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import "github.com/onsi/gomega/format" 4 | 5 | type BeNilMatcher struct { 6 | } 7 | 8 | func (matcher *BeNilMatcher) Match(actual interface{}) (success bool, err error) { 9 | return isNil(actual), nil 10 | } 11 | 12 | func (matcher *BeNilMatcher) FailureMessage(actual interface{}) (message string) { 13 | return format.Message(actual, "to be nil") 14 | } 15 | 16 | func (matcher *BeNilMatcher) NegatedFailureMessage(actual interface{}) (message string) { 17 | return format.Message(actual, "not to be nil") 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_numerically_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "math" 7 | ) 8 | 9 | type BeNumericallyMatcher struct { 10 | Comparator string 11 | CompareTo []interface{} 12 | } 13 | 14 | func (matcher *BeNumericallyMatcher) FailureMessage(actual interface{}) (message string) { 15 | return format.Message(actual, fmt.Sprintf("to be %s", matcher.Comparator), matcher.CompareTo[0]) 16 | } 17 | 18 | func (matcher *BeNumericallyMatcher) NegatedFailureMessage(actual interface{}) (message string) { 19 | return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Comparator), matcher.CompareTo[0]) 20 | } 21 | 22 | func (matcher *BeNumericallyMatcher) Match(actual interface{}) (success bool, err error) { 23 | if len(matcher.CompareTo) == 0 || len(matcher.CompareTo) > 2 { 24 | return false, fmt.Errorf("BeNumerically requires 1 or 2 CompareTo arguments. Got:\n%s", format.Object(matcher.CompareTo, 1)) 25 | } 26 | if !isNumber(actual) { 27 | return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(actual, 1)) 28 | } 29 | if !isNumber(matcher.CompareTo[0]) { 30 | return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) 31 | } 32 | if len(matcher.CompareTo) == 2 && !isNumber(matcher.CompareTo[1]) { 33 | return false, fmt.Errorf("Expected a number. Got:\n%s", format.Object(matcher.CompareTo[0], 1)) 34 | } 35 | 36 | switch matcher.Comparator { 37 | case "==", "~", ">", ">=", "<", "<=": 38 | default: 39 | return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator) 40 | } 41 | 42 | if isFloat(actual) || isFloat(matcher.CompareTo[0]) { 43 | var secondOperand float64 = 1e-8 44 | if len(matcher.CompareTo) == 2 { 45 | secondOperand = toFloat(matcher.CompareTo[1]) 46 | } 47 | success = matcher.matchFloats(toFloat(actual), toFloat(matcher.CompareTo[0]), secondOperand) 48 | } else if isInteger(actual) { 49 | var secondOperand int64 = 0 50 | if len(matcher.CompareTo) == 2 { 51 | secondOperand = toInteger(matcher.CompareTo[1]) 52 | } 53 | success = matcher.matchIntegers(toInteger(actual), toInteger(matcher.CompareTo[0]), secondOperand) 54 | } else if isUnsignedInteger(actual) { 55 | var secondOperand uint64 = 0 56 | if len(matcher.CompareTo) == 2 { 57 | secondOperand = toUnsignedInteger(matcher.CompareTo[1]) 58 | } 59 | success = matcher.matchUnsignedIntegers(toUnsignedInteger(actual), toUnsignedInteger(matcher.CompareTo[0]), secondOperand) 60 | } else { 61 | return false, fmt.Errorf("Failed to compare:\n%s\n%s:\n%s", format.Object(actual, 1), matcher.Comparator, format.Object(matcher.CompareTo[0], 1)) 62 | } 63 | 64 | return success, nil 65 | } 66 | 67 | func (matcher *BeNumericallyMatcher) matchIntegers(actual, compareTo, threshold int64) (success bool) { 68 | switch matcher.Comparator { 69 | case "==", "~": 70 | diff := actual - compareTo 71 | return -threshold <= diff && diff <= threshold 72 | case ">": 73 | return (actual > compareTo) 74 | case ">=": 75 | return (actual >= compareTo) 76 | case "<": 77 | return (actual < compareTo) 78 | case "<=": 79 | return (actual <= compareTo) 80 | } 81 | return false 82 | } 83 | 84 | func (matcher *BeNumericallyMatcher) matchUnsignedIntegers(actual, compareTo, threshold uint64) (success bool) { 85 | switch matcher.Comparator { 86 | case "==", "~": 87 | if actual < compareTo { 88 | actual, compareTo = compareTo, actual 89 | } 90 | return actual-compareTo <= threshold 91 | case ">": 92 | return (actual > compareTo) 93 | case ">=": 94 | return (actual >= compareTo) 95 | case "<": 96 | return (actual < compareTo) 97 | case "<=": 98 | return (actual <= compareTo) 99 | } 100 | return false 101 | } 102 | 103 | func (matcher *BeNumericallyMatcher) matchFloats(actual, compareTo, threshold float64) (success bool) { 104 | switch matcher.Comparator { 105 | case "~": 106 | return math.Abs(actual-compareTo) <= threshold 107 | case "==": 108 | return (actual == compareTo) 109 | case ">": 110 | return (actual > compareTo) 111 | case ">=": 112 | return (actual >= compareTo) 113 | case "<": 114 | return (actual < compareTo) 115 | case "<=": 116 | return (actual <= compareTo) 117 | } 118 | return false 119 | } 120 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_sent_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/onsi/gomega/format" 8 | ) 9 | 10 | type BeSentMatcher struct { 11 | Arg interface{} 12 | channelClosed bool 13 | } 14 | 15 | func (matcher *BeSentMatcher) Match(actual interface{}) (success bool, err error) { 16 | if !isChan(actual) { 17 | return false, fmt.Errorf("BeSent expects a channel. Got:\n%s", format.Object(actual, 1)) 18 | } 19 | 20 | channelType := reflect.TypeOf(actual) 21 | channelValue := reflect.ValueOf(actual) 22 | 23 | if channelType.ChanDir() == reflect.RecvDir { 24 | return false, fmt.Errorf("BeSent matcher cannot be passed a receive-only channel. Got:\n%s", format.Object(actual, 1)) 25 | } 26 | 27 | argType := reflect.TypeOf(matcher.Arg) 28 | assignable := argType.AssignableTo(channelType.Elem()) 29 | 30 | if !assignable { 31 | return false, fmt.Errorf("Cannot pass:\n%s to the channel:\n%s\nThe types don't match.", format.Object(matcher.Arg, 1), format.Object(actual, 1)) 32 | } 33 | 34 | argValue := reflect.ValueOf(matcher.Arg) 35 | 36 | defer func() { 37 | if e := recover(); e != nil { 38 | success = false 39 | err = fmt.Errorf("Cannot send to a closed channel") 40 | matcher.channelClosed = true 41 | } 42 | }() 43 | 44 | winnerIndex, _, _ := reflect.Select([]reflect.SelectCase{ 45 | reflect.SelectCase{Dir: reflect.SelectSend, Chan: channelValue, Send: argValue}, 46 | reflect.SelectCase{Dir: reflect.SelectDefault}, 47 | }) 48 | 49 | var didSend bool 50 | if winnerIndex == 0 { 51 | didSend = true 52 | } 53 | 54 | return didSend, nil 55 | } 56 | 57 | func (matcher *BeSentMatcher) FailureMessage(actual interface{}) (message string) { 58 | return format.Message(actual, "to send:", matcher.Arg) 59 | } 60 | 61 | func (matcher *BeSentMatcher) NegatedFailureMessage(actual interface{}) (message string) { 62 | return format.Message(actual, "not to send:", matcher.Arg) 63 | } 64 | 65 | func (matcher *BeSentMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { 66 | if !isChan(actual) { 67 | return false 68 | } 69 | 70 | return !matcher.channelClosed 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_temporally_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "time" 7 | ) 8 | 9 | type BeTemporallyMatcher struct { 10 | Comparator string 11 | CompareTo time.Time 12 | Threshold []time.Duration 13 | } 14 | 15 | func (matcher *BeTemporallyMatcher) FailureMessage(actual interface{}) (message string) { 16 | return format.Message(actual, fmt.Sprintf("to be %s", matcher.Comparator), matcher.CompareTo) 17 | } 18 | 19 | func (matcher *BeTemporallyMatcher) NegatedFailureMessage(actual interface{}) (message string) { 20 | return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Comparator), matcher.CompareTo) 21 | } 22 | 23 | func (matcher *BeTemporallyMatcher) Match(actual interface{}) (bool, error) { 24 | // predicate to test for time.Time type 25 | isTime := func(t interface{}) bool { 26 | _, ok := t.(time.Time) 27 | return ok 28 | } 29 | 30 | if !isTime(actual) { 31 | return false, fmt.Errorf("Expected a time.Time. Got:\n%s", format.Object(actual, 1)) 32 | } 33 | 34 | switch matcher.Comparator { 35 | case "==", "~", ">", ">=", "<", "<=": 36 | default: 37 | return false, fmt.Errorf("Unknown comparator: %s", matcher.Comparator) 38 | } 39 | 40 | var threshold = time.Millisecond 41 | if len(matcher.Threshold) == 1 { 42 | threshold = matcher.Threshold[0] 43 | } 44 | 45 | return matcher.matchTimes(actual.(time.Time), matcher.CompareTo, threshold), nil 46 | } 47 | 48 | func (matcher *BeTemporallyMatcher) matchTimes(actual, compareTo time.Time, threshold time.Duration) (success bool) { 49 | switch matcher.Comparator { 50 | case "==": 51 | return actual.Equal(compareTo) 52 | case "~": 53 | diff := actual.Sub(compareTo) 54 | return -threshold <= diff && diff <= threshold 55 | case ">": 56 | return actual.After(compareTo) 57 | case ">=": 58 | return !actual.Before(compareTo) 59 | case "<": 60 | return actual.Before(compareTo) 61 | case "<=": 62 | return !actual.After(compareTo) 63 | } 64 | return false 65 | } 66 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_true_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type BeTrueMatcher struct { 9 | } 10 | 11 | func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) { 12 | if !isBool(actual) { 13 | return false, fmt.Errorf("Expected a boolean. Got:\n%s", format.Object(actual, 1)) 14 | } 15 | 16 | return actual.(bool), nil 17 | } 18 | 19 | func (matcher *BeTrueMatcher) FailureMessage(actual interface{}) (message string) { 20 | return format.Message(actual, "to be true") 21 | } 22 | 23 | func (matcher *BeTrueMatcher) NegatedFailureMessage(actual interface{}) (message string) { 24 | return format.Message(actual, "not to be true") 25 | } 26 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/be_zero_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "github.com/onsi/gomega/format" 5 | "reflect" 6 | ) 7 | 8 | type BeZeroMatcher struct { 9 | } 10 | 11 | func (matcher *BeZeroMatcher) Match(actual interface{}) (success bool, err error) { 12 | if actual == nil { 13 | return true, nil 14 | } 15 | zeroValue := reflect.Zero(reflect.TypeOf(actual)).Interface() 16 | 17 | return reflect.DeepEqual(zeroValue, actual), nil 18 | 19 | } 20 | 21 | func (matcher *BeZeroMatcher) FailureMessage(actual interface{}) (message string) { 22 | return format.Message(actual, "to be zero-valued") 23 | } 24 | 25 | func (matcher *BeZeroMatcher) NegatedFailureMessage(actual interface{}) (message string) { 26 | return format.Message(actual, "not to be zero-valued") 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/consist_of.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/onsi/gomega/format" 8 | "github.com/onsi/gomega/matchers/support/goraph/bipartitegraph" 9 | ) 10 | 11 | type ConsistOfMatcher struct { 12 | Elements []interface{} 13 | } 14 | 15 | func (matcher *ConsistOfMatcher) Match(actual interface{}) (success bool, err error) { 16 | if !isArrayOrSlice(actual) && !isMap(actual) { 17 | return false, fmt.Errorf("ConsistOf matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1)) 18 | } 19 | 20 | elements := matcher.Elements 21 | if len(matcher.Elements) == 1 && isArrayOrSlice(matcher.Elements[0]) { 22 | elements = []interface{}{} 23 | value := reflect.ValueOf(matcher.Elements[0]) 24 | for i := 0; i < value.Len(); i++ { 25 | elements = append(elements, value.Index(i).Interface()) 26 | } 27 | } 28 | 29 | matchers := []interface{}{} 30 | for _, element := range elements { 31 | matcher, isMatcher := element.(omegaMatcher) 32 | if !isMatcher { 33 | matcher = &EqualMatcher{Expected: element} 34 | } 35 | matchers = append(matchers, matcher) 36 | } 37 | 38 | values := matcher.valuesOf(actual) 39 | 40 | if len(values) != len(matchers) { 41 | return false, nil 42 | } 43 | 44 | neighbours := func(v, m interface{}) (bool, error) { 45 | match, err := m.(omegaMatcher).Match(v) 46 | return match && err == nil, nil 47 | } 48 | 49 | bipartiteGraph, err := bipartitegraph.NewBipartiteGraph(values, matchers, neighbours) 50 | if err != nil { 51 | return false, err 52 | } 53 | 54 | return len(bipartiteGraph.LargestMatching()) == len(values), nil 55 | } 56 | 57 | func (matcher *ConsistOfMatcher) valuesOf(actual interface{}) []interface{} { 58 | value := reflect.ValueOf(actual) 59 | values := []interface{}{} 60 | if isMap(actual) { 61 | keys := value.MapKeys() 62 | for i := 0; i < value.Len(); i++ { 63 | values = append(values, value.MapIndex(keys[i]).Interface()) 64 | } 65 | } else { 66 | for i := 0; i < value.Len(); i++ { 67 | values = append(values, value.Index(i).Interface()) 68 | } 69 | } 70 | 71 | return values 72 | } 73 | 74 | func (matcher *ConsistOfMatcher) FailureMessage(actual interface{}) (message string) { 75 | return format.Message(actual, "to consist of", matcher.Elements) 76 | } 77 | 78 | func (matcher *ConsistOfMatcher) NegatedFailureMessage(actual interface{}) (message string) { 79 | return format.Message(actual, "not to consist of", matcher.Elements) 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/contain_element_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type ContainElementMatcher struct { 10 | Element interface{} 11 | } 12 | 13 | func (matcher *ContainElementMatcher) Match(actual interface{}) (success bool, err error) { 14 | if !isArrayOrSlice(actual) && !isMap(actual) { 15 | return false, fmt.Errorf("ContainElement matcher expects an array/slice/map. Got:\n%s", format.Object(actual, 1)) 16 | } 17 | 18 | elemMatcher, elementIsMatcher := matcher.Element.(omegaMatcher) 19 | if !elementIsMatcher { 20 | elemMatcher = &EqualMatcher{Expected: matcher.Element} 21 | } 22 | 23 | value := reflect.ValueOf(actual) 24 | var keys []reflect.Value 25 | if isMap(actual) { 26 | keys = value.MapKeys() 27 | } 28 | for i := 0; i < value.Len(); i++ { 29 | var success bool 30 | var err error 31 | if isMap(actual) { 32 | success, err = elemMatcher.Match(value.MapIndex(keys[i]).Interface()) 33 | } else { 34 | success, err = elemMatcher.Match(value.Index(i).Interface()) 35 | } 36 | if err != nil { 37 | return false, fmt.Errorf("ContainElement's element matcher failed with:\n\t%s", err.Error()) 38 | } 39 | if success { 40 | return true, nil 41 | } 42 | } 43 | 44 | return false, nil 45 | } 46 | 47 | func (matcher *ContainElementMatcher) FailureMessage(actual interface{}) (message string) { 48 | return format.Message(actual, "to contain element matching", matcher.Element) 49 | } 50 | 51 | func (matcher *ContainElementMatcher) NegatedFailureMessage(actual interface{}) (message string) { 52 | return format.Message(actual, "not to contain element matching", matcher.Element) 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/contain_substring_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "strings" 7 | ) 8 | 9 | type ContainSubstringMatcher struct { 10 | Substr string 11 | Args []interface{} 12 | } 13 | 14 | func (matcher *ContainSubstringMatcher) Match(actual interface{}) (success bool, err error) { 15 | actualString, ok := toString(actual) 16 | if !ok { 17 | return false, fmt.Errorf("ContainSubstring matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1)) 18 | } 19 | 20 | return strings.Contains(actualString, matcher.stringToMatch()), nil 21 | } 22 | 23 | func (matcher *ContainSubstringMatcher) stringToMatch() string { 24 | stringToMatch := matcher.Substr 25 | if len(matcher.Args) > 0 { 26 | stringToMatch = fmt.Sprintf(matcher.Substr, matcher.Args...) 27 | } 28 | return stringToMatch 29 | } 30 | 31 | func (matcher *ContainSubstringMatcher) FailureMessage(actual interface{}) (message string) { 32 | return format.Message(actual, "to contain substring", matcher.stringToMatch()) 33 | } 34 | 35 | func (matcher *ContainSubstringMatcher) NegatedFailureMessage(actual interface{}) (message string) { 36 | return format.Message(actual, "not to contain substring", matcher.stringToMatch()) 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/equal_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type EqualMatcher struct { 10 | Expected interface{} 11 | } 12 | 13 | func (matcher *EqualMatcher) Match(actual interface{}) (success bool, err error) { 14 | if actual == nil && matcher.Expected == nil { 15 | return false, fmt.Errorf("Refusing to compare to .") 16 | } 17 | return reflect.DeepEqual(actual, matcher.Expected), nil 18 | } 19 | 20 | func (matcher *EqualMatcher) FailureMessage(actual interface{}) (message string) { 21 | return format.Message(actual, "to equal", matcher.Expected) 22 | } 23 | 24 | func (matcher *EqualMatcher) NegatedFailureMessage(actual interface{}) (message string) { 25 | return format.Message(actual, "not to equal", matcher.Expected) 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_key_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type HaveKeyMatcher struct { 10 | Key interface{} 11 | } 12 | 13 | func (matcher *HaveKeyMatcher) Match(actual interface{}) (success bool, err error) { 14 | if !isMap(actual) { 15 | return false, fmt.Errorf("HaveKey matcher expects a map. Got:%s", format.Object(actual, 1)) 16 | } 17 | 18 | keyMatcher, keyIsMatcher := matcher.Key.(omegaMatcher) 19 | if !keyIsMatcher { 20 | keyMatcher = &EqualMatcher{Expected: matcher.Key} 21 | } 22 | 23 | keys := reflect.ValueOf(actual).MapKeys() 24 | for i := 0; i < len(keys); i++ { 25 | success, err := keyMatcher.Match(keys[i].Interface()) 26 | if err != nil { 27 | return false, fmt.Errorf("HaveKey's key matcher failed with:\n%s%s", format.Indent, err.Error()) 28 | } 29 | if success { 30 | return true, nil 31 | } 32 | } 33 | 34 | return false, nil 35 | } 36 | 37 | func (matcher *HaveKeyMatcher) FailureMessage(actual interface{}) (message string) { 38 | switch matcher.Key.(type) { 39 | case omegaMatcher: 40 | return format.Message(actual, "to have key matching", matcher.Key) 41 | default: 42 | return format.Message(actual, "to have key", matcher.Key) 43 | } 44 | } 45 | 46 | func (matcher *HaveKeyMatcher) NegatedFailureMessage(actual interface{}) (message string) { 47 | switch matcher.Key.(type) { 48 | case omegaMatcher: 49 | return format.Message(actual, "not to have key matching", matcher.Key) 50 | default: 51 | return format.Message(actual, "not to have key", matcher.Key) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_key_with_value_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type HaveKeyWithValueMatcher struct { 10 | Key interface{} 11 | Value interface{} 12 | } 13 | 14 | func (matcher *HaveKeyWithValueMatcher) Match(actual interface{}) (success bool, err error) { 15 | if !isMap(actual) { 16 | return false, fmt.Errorf("HaveKeyWithValue matcher expects a map. Got:%s", format.Object(actual, 1)) 17 | } 18 | 19 | keyMatcher, keyIsMatcher := matcher.Key.(omegaMatcher) 20 | if !keyIsMatcher { 21 | keyMatcher = &EqualMatcher{Expected: matcher.Key} 22 | } 23 | 24 | valueMatcher, valueIsMatcher := matcher.Value.(omegaMatcher) 25 | if !valueIsMatcher { 26 | valueMatcher = &EqualMatcher{Expected: matcher.Value} 27 | } 28 | 29 | keys := reflect.ValueOf(actual).MapKeys() 30 | for i := 0; i < len(keys); i++ { 31 | success, err := keyMatcher.Match(keys[i].Interface()) 32 | if err != nil { 33 | return false, fmt.Errorf("HaveKeyWithValue's key matcher failed with:\n%s%s", format.Indent, err.Error()) 34 | } 35 | if success { 36 | actualValue := reflect.ValueOf(actual).MapIndex(keys[i]) 37 | success, err := valueMatcher.Match(actualValue.Interface()) 38 | if err != nil { 39 | return false, fmt.Errorf("HaveKeyWithValue's value matcher failed with:\n%s%s", format.Indent, err.Error()) 40 | } 41 | return success, nil 42 | } 43 | } 44 | 45 | return false, nil 46 | } 47 | 48 | func (matcher *HaveKeyWithValueMatcher) FailureMessage(actual interface{}) (message string) { 49 | str := "to have {key: value}" 50 | if _, ok := matcher.Key.(omegaMatcher); ok { 51 | str += " matching" 52 | } else if _, ok := matcher.Value.(omegaMatcher); ok { 53 | str += " matching" 54 | } 55 | 56 | expect := make(map[interface{}]interface{}, 1) 57 | expect[matcher.Key] = matcher.Value 58 | return format.Message(actual, str, expect) 59 | } 60 | 61 | func (matcher *HaveKeyWithValueMatcher) NegatedFailureMessage(actual interface{}) (message string) { 62 | kStr := "not to have key" 63 | if _, ok := matcher.Key.(omegaMatcher); ok { 64 | kStr = "not to have key matching" 65 | } 66 | 67 | vStr := "or that key's value not be" 68 | if _, ok := matcher.Value.(omegaMatcher); ok { 69 | vStr = "or to have that key's value not matching" 70 | } 71 | 72 | return format.Message(actual, kStr, matcher.Key, vStr, matcher.Value) 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_len_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type HaveLenMatcher struct { 9 | Count int 10 | } 11 | 12 | func (matcher *HaveLenMatcher) Match(actual interface{}) (success bool, err error) { 13 | length, ok := lengthOf(actual) 14 | if !ok { 15 | return false, fmt.Errorf("HaveLen matcher expects a string/array/map/channel/slice. Got:\n%s", format.Object(actual, 1)) 16 | } 17 | 18 | return length == matcher.Count, nil 19 | } 20 | 21 | func (matcher *HaveLenMatcher) FailureMessage(actual interface{}) (message string) { 22 | return fmt.Sprintf("Expected\n%s\nto have length %d", format.Object(actual, 1), matcher.Count) 23 | } 24 | 25 | func (matcher *HaveLenMatcher) NegatedFailureMessage(actual interface{}) (message string) { 26 | return fmt.Sprintf("Expected\n%s\nnot to have length %d", format.Object(actual, 1), matcher.Count) 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_occurred_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type HaveOccurredMatcher struct { 9 | } 10 | 11 | func (matcher *HaveOccurredMatcher) Match(actual interface{}) (success bool, err error) { 12 | if actual == nil { 13 | return false, nil 14 | } 15 | 16 | if isError(actual) { 17 | return true, nil 18 | } 19 | 20 | return false, fmt.Errorf("Expected an error. Got:\n%s", format.Object(actual, 1)) 21 | } 22 | 23 | func (matcher *HaveOccurredMatcher) FailureMessage(actual interface{}) (message string) { 24 | return fmt.Sprintf("Expected an error to have occured. Got:\n%s", format.Object(actual, 1)) 25 | } 26 | 27 | func (matcher *HaveOccurredMatcher) NegatedFailureMessage(actual interface{}) (message string) { 28 | return fmt.Sprintf("Expected error:\n%s\n%s\n%s", format.Object(actual, 1), format.IndentString(actual.(error).Error(), 1), "not to have occurred") 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_prefix_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type HavePrefixMatcher struct { 9 | Prefix string 10 | Args []interface{} 11 | } 12 | 13 | func (matcher *HavePrefixMatcher) Match(actual interface{}) (success bool, err error) { 14 | actualString, ok := toString(actual) 15 | if !ok { 16 | return false, fmt.Errorf("HavePrefix matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1)) 17 | } 18 | prefix := matcher.prefix() 19 | return len(actualString) >= len(prefix) && actualString[0:len(prefix)] == prefix, nil 20 | } 21 | 22 | func (matcher *HavePrefixMatcher) prefix() string { 23 | if len(matcher.Args) > 0 { 24 | return fmt.Sprintf(matcher.Prefix, matcher.Args...) 25 | } 26 | return matcher.Prefix 27 | } 28 | 29 | func (matcher *HavePrefixMatcher) FailureMessage(actual interface{}) (message string) { 30 | return format.Message(actual, "to have prefix", matcher.prefix()) 31 | } 32 | 33 | func (matcher *HavePrefixMatcher) NegatedFailureMessage(actual interface{}) (message string) { 34 | return format.Message(actual, "not to have prefix", matcher.prefix()) 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/have_suffix_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | ) 7 | 8 | type HaveSuffixMatcher struct { 9 | Suffix string 10 | Args []interface{} 11 | } 12 | 13 | func (matcher *HaveSuffixMatcher) Match(actual interface{}) (success bool, err error) { 14 | actualString, ok := toString(actual) 15 | if !ok { 16 | return false, fmt.Errorf("HaveSuffix matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1)) 17 | } 18 | suffix := matcher.suffix() 19 | return len(actualString) >= len(suffix) && actualString[len(actualString) - len(suffix):] == suffix, nil 20 | } 21 | 22 | func (matcher *HaveSuffixMatcher) suffix() string { 23 | if len(matcher.Args) > 0 { 24 | return fmt.Sprintf(matcher.Suffix, matcher.Args...) 25 | } 26 | return matcher.Suffix 27 | } 28 | 29 | func (matcher *HaveSuffixMatcher) FailureMessage(actual interface{}) (message string) { 30 | return format.Message(actual, "to have suffix", matcher.suffix()) 31 | } 32 | 33 | func (matcher *HaveSuffixMatcher) NegatedFailureMessage(actual interface{}) (message string) { 34 | return format.Message(actual, "not to have suffix", matcher.suffix()) 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/match_error_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type MatchErrorMatcher struct { 10 | Expected interface{} 11 | } 12 | 13 | func (matcher *MatchErrorMatcher) Match(actual interface{}) (success bool, err error) { 14 | if isNil(actual) { 15 | return false, fmt.Errorf("Expected an error, got nil") 16 | } 17 | 18 | if !isError(actual) { 19 | return false, fmt.Errorf("Expected an error. Got:\n%s", format.Object(actual, 1)) 20 | } 21 | 22 | actualErr := actual.(error) 23 | 24 | if isString(matcher.Expected) { 25 | return reflect.DeepEqual(actualErr.Error(), matcher.Expected), nil 26 | } 27 | 28 | if isError(matcher.Expected) { 29 | return reflect.DeepEqual(actualErr, matcher.Expected), nil 30 | } 31 | 32 | var subMatcher omegaMatcher 33 | var hasSubMatcher bool 34 | if matcher.Expected != nil { 35 | subMatcher, hasSubMatcher = (matcher.Expected).(omegaMatcher) 36 | if hasSubMatcher { 37 | return subMatcher.Match(actualErr.Error()) 38 | } 39 | } 40 | 41 | return false, fmt.Errorf("MatchError must be passed an error, string, or Matcher that can match on strings. Got:\n%s", format.Object(matcher.Expected, 1)) 42 | } 43 | 44 | func (matcher *MatchErrorMatcher) FailureMessage(actual interface{}) (message string) { 45 | return format.Message(actual, "to match error", matcher.Expected) 46 | } 47 | 48 | func (matcher *MatchErrorMatcher) NegatedFailureMessage(actual interface{}) (message string) { 49 | return format.Message(actual, "not to match error", matcher.Expected) 50 | } 51 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/match_json_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/onsi/gomega/format" 8 | "reflect" 9 | ) 10 | 11 | type MatchJSONMatcher struct { 12 | JSONToMatch interface{} 13 | } 14 | 15 | func (matcher *MatchJSONMatcher) Match(actual interface{}) (success bool, err error) { 16 | actualString, expectedString, err := matcher.prettyPrint(actual) 17 | if err != nil { 18 | return false, err 19 | } 20 | 21 | var aval interface{} 22 | var eval interface{} 23 | 24 | // this is guarded by prettyPrint 25 | json.Unmarshal([]byte(actualString), &aval) 26 | json.Unmarshal([]byte(expectedString), &eval) 27 | 28 | return reflect.DeepEqual(aval, eval), nil 29 | } 30 | 31 | func (matcher *MatchJSONMatcher) FailureMessage(actual interface{}) (message string) { 32 | actualString, expectedString, _ := matcher.prettyPrint(actual) 33 | return format.Message(actualString, "to match JSON of", expectedString) 34 | } 35 | 36 | func (matcher *MatchJSONMatcher) NegatedFailureMessage(actual interface{}) (message string) { 37 | actualString, expectedString, _ := matcher.prettyPrint(actual) 38 | return format.Message(actualString, "not to match JSON of", expectedString) 39 | } 40 | 41 | func (matcher *MatchJSONMatcher) prettyPrint(actual interface{}) (actualFormatted, expectedFormatted string, err error) { 42 | actualString, aok := toString(actual) 43 | expectedString, eok := toString(matcher.JSONToMatch) 44 | 45 | if !(aok && eok) { 46 | return "", "", fmt.Errorf("MatchJSONMatcher matcher requires a string or stringer. Got:\n%s", format.Object(actual, 1)) 47 | } 48 | 49 | abuf := new(bytes.Buffer) 50 | ebuf := new(bytes.Buffer) 51 | 52 | if err := json.Indent(abuf, []byte(actualString), "", " "); err != nil { 53 | return "", "", err 54 | } 55 | 56 | if err := json.Indent(ebuf, []byte(expectedString), "", " "); err != nil { 57 | return "", "", err 58 | } 59 | 60 | return actualString, expectedString, nil 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/match_regexp_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "regexp" 7 | ) 8 | 9 | type MatchRegexpMatcher struct { 10 | Regexp string 11 | Args []interface{} 12 | } 13 | 14 | func (matcher *MatchRegexpMatcher) Match(actual interface{}) (success bool, err error) { 15 | actualString, ok := toString(actual) 16 | if !ok { 17 | return false, fmt.Errorf("RegExp matcher requires a string or stringer.\nGot:%s", format.Object(actual, 1)) 18 | } 19 | 20 | match, err := regexp.Match(matcher.regexp(), []byte(actualString)) 21 | if err != nil { 22 | return false, fmt.Errorf("RegExp match failed to compile with error:\n\t%s", err.Error()) 23 | } 24 | 25 | return match, nil 26 | } 27 | 28 | func (matcher *MatchRegexpMatcher) FailureMessage(actual interface{}) (message string) { 29 | return format.Message(actual, "to match regular expression", matcher.regexp()) 30 | } 31 | 32 | func (matcher *MatchRegexpMatcher) NegatedFailureMessage(actual interface{}) (message string) { 33 | return format.Message(actual, "not to match regular expression", matcher.regexp()) 34 | } 35 | 36 | func (matcher *MatchRegexpMatcher) regexp() string { 37 | re := matcher.Regexp 38 | if len(matcher.Args) > 0 { 39 | re = fmt.Sprintf(matcher.Regexp, matcher.Args...) 40 | } 41 | return re 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/panic_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "github.com/onsi/gomega/format" 6 | "reflect" 7 | ) 8 | 9 | type PanicMatcher struct{} 10 | 11 | func (matcher *PanicMatcher) Match(actual interface{}) (success bool, err error) { 12 | if actual == nil { 13 | return false, fmt.Errorf("PanicMatcher expects a non-nil actual.") 14 | } 15 | 16 | actualType := reflect.TypeOf(actual) 17 | if actualType.Kind() != reflect.Func { 18 | return false, fmt.Errorf("PanicMatcher expects a function. Got:\n%s", format.Object(actual, 1)) 19 | } 20 | if !(actualType.NumIn() == 0 && actualType.NumOut() == 0) { 21 | return false, fmt.Errorf("PanicMatcher expects a function with no arguments and no return value. Got:\n%s", format.Object(actual, 1)) 22 | } 23 | 24 | success = false 25 | defer func() { 26 | if e := recover(); e != nil { 27 | success = true 28 | } 29 | }() 30 | 31 | reflect.ValueOf(actual).Call([]reflect.Value{}) 32 | 33 | return 34 | } 35 | 36 | func (matcher *PanicMatcher) FailureMessage(actual interface{}) (message string) { 37 | return format.Message(actual, "to panic") 38 | } 39 | 40 | func (matcher *PanicMatcher) NegatedFailureMessage(actual interface{}) (message string) { 41 | return format.Message(actual, "not to panic") 42 | } 43 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/receive_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | 7 | "github.com/onsi/gomega/format" 8 | ) 9 | 10 | type ReceiveMatcher struct { 11 | Arg interface{} 12 | receivedValue reflect.Value 13 | channelClosed bool 14 | } 15 | 16 | func (matcher *ReceiveMatcher) Match(actual interface{}) (success bool, err error) { 17 | if !isChan(actual) { 18 | return false, fmt.Errorf("ReceiveMatcher expects a channel. Got:\n%s", format.Object(actual, 1)) 19 | } 20 | 21 | channelType := reflect.TypeOf(actual) 22 | channelValue := reflect.ValueOf(actual) 23 | 24 | if channelType.ChanDir() == reflect.SendDir { 25 | return false, fmt.Errorf("ReceiveMatcher matcher cannot be passed a send-only channel. Got:\n%s", format.Object(actual, 1)) 26 | } 27 | 28 | var subMatcher omegaMatcher 29 | var hasSubMatcher bool 30 | 31 | if matcher.Arg != nil { 32 | subMatcher, hasSubMatcher = (matcher.Arg).(omegaMatcher) 33 | if !hasSubMatcher { 34 | argType := reflect.TypeOf(matcher.Arg) 35 | if argType.Kind() != reflect.Ptr { 36 | return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s\nYou need to pass a pointer!", format.Object(actual, 1), format.Object(matcher.Arg, 1)) 37 | } 38 | 39 | assignable := channelType.Elem().AssignableTo(argType.Elem()) 40 | if !assignable { 41 | return false, fmt.Errorf("Cannot assign a value from the channel:\n%s\nTo:\n%s", format.Object(actual, 1), format.Object(matcher.Arg, 1)) 42 | } 43 | } 44 | } 45 | 46 | winnerIndex, value, open := reflect.Select([]reflect.SelectCase{ 47 | reflect.SelectCase{Dir: reflect.SelectRecv, Chan: channelValue}, 48 | reflect.SelectCase{Dir: reflect.SelectDefault}, 49 | }) 50 | 51 | var closed bool 52 | var didReceive bool 53 | if winnerIndex == 0 { 54 | closed = !open 55 | didReceive = open 56 | } 57 | matcher.channelClosed = closed 58 | 59 | if closed { 60 | return false, nil 61 | } 62 | 63 | if hasSubMatcher { 64 | if didReceive { 65 | matcher.receivedValue = value 66 | return subMatcher.Match(matcher.receivedValue.Interface()) 67 | } else { 68 | return false, nil 69 | } 70 | } 71 | 72 | if didReceive { 73 | if matcher.Arg != nil { 74 | outValue := reflect.ValueOf(matcher.Arg) 75 | reflect.Indirect(outValue).Set(value) 76 | } 77 | 78 | return true, nil 79 | } else { 80 | return false, nil 81 | } 82 | } 83 | 84 | func (matcher *ReceiveMatcher) FailureMessage(actual interface{}) (message string) { 85 | subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher) 86 | 87 | closedAddendum := "" 88 | if matcher.channelClosed { 89 | closedAddendum = " The channel is closed." 90 | } 91 | 92 | if hasSubMatcher { 93 | if matcher.receivedValue.IsValid() { 94 | return subMatcher.FailureMessage(matcher.receivedValue.Interface()) 95 | } 96 | return "When passed a matcher, ReceiveMatcher's channel *must* receive something." 97 | } else { 98 | return format.Message(actual, "to receive something."+closedAddendum) 99 | } 100 | } 101 | 102 | func (matcher *ReceiveMatcher) NegatedFailureMessage(actual interface{}) (message string) { 103 | subMatcher, hasSubMatcher := (matcher.Arg).(omegaMatcher) 104 | 105 | closedAddendum := "" 106 | if matcher.channelClosed { 107 | closedAddendum = " The channel is closed." 108 | } 109 | 110 | if hasSubMatcher { 111 | if matcher.receivedValue.IsValid() { 112 | return subMatcher.NegatedFailureMessage(matcher.receivedValue.Interface()) 113 | } 114 | return "When passed a matcher, ReceiveMatcher's channel *must* receive something." 115 | } else { 116 | return format.Message(actual, "not to receive anything."+closedAddendum) 117 | } 118 | } 119 | 120 | func (matcher *ReceiveMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { 121 | if !isChan(actual) { 122 | return false 123 | } 124 | 125 | return !matcher.channelClosed 126 | } 127 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/succeed_matcher.go: -------------------------------------------------------------------------------- 1 | package matchers 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/onsi/gomega/format" 7 | ) 8 | 9 | type SucceedMatcher struct { 10 | } 11 | 12 | func (matcher *SucceedMatcher) Match(actual interface{}) (success bool, err error) { 13 | if actual == nil { 14 | return true, nil 15 | } 16 | 17 | if isError(actual) { 18 | return false, nil 19 | } 20 | 21 | return false, fmt.Errorf("Expected an error-type. Got:\n%s", format.Object(actual, 1)) 22 | } 23 | 24 | func (matcher *SucceedMatcher) FailureMessage(actual interface{}) (message string) { 25 | return fmt.Sprintf("Expected success, but got an error:\n%s", format.Object(actual, 1)) 26 | } 27 | 28 | func (matcher *SucceedMatcher) NegatedFailureMessage(actual interface{}) (message string) { 29 | return "Expected failure, but got no error." 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraph.go: -------------------------------------------------------------------------------- 1 | package bipartitegraph 2 | 3 | import "errors" 4 | import "fmt" 5 | 6 | import . "github.com/onsi/gomega/matchers/support/goraph/node" 7 | import . "github.com/onsi/gomega/matchers/support/goraph/edge" 8 | 9 | type BipartiteGraph struct { 10 | Left NodeOrderedSet 11 | Right NodeOrderedSet 12 | Edges EdgeSet 13 | } 14 | 15 | func NewBipartiteGraph(leftValues, rightValues []interface{}, neighbours func(interface{}, interface{}) (bool, error)) (*BipartiteGraph, error) { 16 | left := NodeOrderedSet{} 17 | for i, _ := range leftValues { 18 | left = append(left, Node{i}) 19 | } 20 | 21 | right := NodeOrderedSet{} 22 | for j, _ := range rightValues { 23 | right = append(right, Node{j + len(left)}) 24 | } 25 | 26 | edges := EdgeSet{} 27 | for i, leftValue := range leftValues { 28 | for j, rightValue := range rightValues { 29 | neighbours, err := neighbours(leftValue, rightValue) 30 | if err != nil { 31 | return nil, errors.New(fmt.Sprintf("error determining adjacency for %v and %v: %s", leftValue, rightValue, err.Error())) 32 | } 33 | 34 | if neighbours { 35 | edges = append(edges, Edge{left[i], right[j]}) 36 | } 37 | } 38 | } 39 | 40 | return &BipartiteGraph{left, right, edges}, nil 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/support/goraph/bipartitegraph/bipartitegraphmatching.go: -------------------------------------------------------------------------------- 1 | package bipartitegraph 2 | 3 | import . "github.com/onsi/gomega/matchers/support/goraph/node" 4 | import . "github.com/onsi/gomega/matchers/support/goraph/edge" 5 | import "github.com/onsi/gomega/matchers/support/goraph/util" 6 | 7 | func (bg *BipartiteGraph) LargestMatching() (matching EdgeSet) { 8 | paths := bg.maximalDisjointSLAPCollection(matching) 9 | 10 | for len(paths) > 0 { 11 | for _, path := range paths { 12 | matching = matching.SymmetricDifference(path) 13 | } 14 | paths = bg.maximalDisjointSLAPCollection(matching) 15 | } 16 | 17 | return 18 | } 19 | 20 | func (bg *BipartiteGraph) maximalDisjointSLAPCollection(matching EdgeSet) (result []EdgeSet) { 21 | guideLayers := bg.createSLAPGuideLayers(matching) 22 | if len(guideLayers) == 0 { 23 | return 24 | } 25 | 26 | used := make(map[Node]bool) 27 | 28 | for _, u := range guideLayers[len(guideLayers)-1] { 29 | slap, found := bg.findDisjointSLAP(u, matching, guideLayers, used) 30 | if found { 31 | for _, edge := range slap { 32 | used[edge.Node1] = true 33 | used[edge.Node2] = true 34 | } 35 | result = append(result, slap) 36 | } 37 | } 38 | 39 | return 40 | } 41 | 42 | func (bg *BipartiteGraph) findDisjointSLAP( 43 | start Node, 44 | matching EdgeSet, 45 | guideLayers []NodeOrderedSet, 46 | used map[Node]bool, 47 | ) ([]Edge, bool) { 48 | return bg.findDisjointSLAPHelper(start, EdgeSet{}, len(guideLayers)-1, matching, guideLayers, used) 49 | } 50 | 51 | func (bg *BipartiteGraph) findDisjointSLAPHelper( 52 | currentNode Node, 53 | currentSLAP EdgeSet, 54 | currentLevel int, 55 | matching EdgeSet, 56 | guideLayers []NodeOrderedSet, 57 | used map[Node]bool, 58 | ) (EdgeSet, bool) { 59 | used[currentNode] = true 60 | 61 | if currentLevel == 0 { 62 | return currentSLAP, true 63 | } 64 | 65 | for _, nextNode := range guideLayers[currentLevel-1] { 66 | if used[nextNode] { 67 | continue 68 | } 69 | 70 | edge, found := bg.Edges.FindByNodes(currentNode, nextNode) 71 | if !found { 72 | continue 73 | } 74 | 75 | if matching.Contains(edge) == util.Odd(currentLevel) { 76 | continue 77 | } 78 | 79 | currentSLAP = append(currentSLAP, edge) 80 | slap, found := bg.findDisjointSLAPHelper(nextNode, currentSLAP, currentLevel-1, matching, guideLayers, used) 81 | if found { 82 | return slap, true 83 | } 84 | currentSLAP = currentSLAP[:len(currentSLAP)-1] 85 | } 86 | 87 | used[currentNode] = false 88 | return nil, false 89 | } 90 | 91 | func (bg *BipartiteGraph) createSLAPGuideLayers(matching EdgeSet) (guideLayers []NodeOrderedSet) { 92 | used := make(map[Node]bool) 93 | currentLayer := NodeOrderedSet{} 94 | 95 | for _, node := range bg.Left { 96 | if matching.Free(node) { 97 | used[node] = true 98 | currentLayer = append(currentLayer, node) 99 | } 100 | } 101 | 102 | if len(currentLayer) == 0 { 103 | return []NodeOrderedSet{} 104 | } else { 105 | guideLayers = append(guideLayers, currentLayer) 106 | } 107 | 108 | done := false 109 | 110 | for !done { 111 | lastLayer := currentLayer 112 | currentLayer = NodeOrderedSet{} 113 | 114 | if util.Odd(len(guideLayers)) { 115 | for _, leftNode := range lastLayer { 116 | for _, rightNode := range bg.Right { 117 | if used[rightNode] { 118 | continue 119 | } 120 | 121 | edge, found := bg.Edges.FindByNodes(leftNode, rightNode) 122 | if !found || matching.Contains(edge) { 123 | continue 124 | } 125 | 126 | currentLayer = append(currentLayer, rightNode) 127 | used[rightNode] = true 128 | 129 | if matching.Free(rightNode) { 130 | done = true 131 | } 132 | } 133 | } 134 | } else { 135 | for _, rightNode := range lastLayer { 136 | for _, leftNode := range bg.Left { 137 | if used[leftNode] { 138 | continue 139 | } 140 | 141 | edge, found := bg.Edges.FindByNodes(leftNode, rightNode) 142 | if !found || !matching.Contains(edge) { 143 | continue 144 | } 145 | 146 | currentLayer = append(currentLayer, leftNode) 147 | used[leftNode] = true 148 | } 149 | } 150 | 151 | } 152 | 153 | if len(currentLayer) == 0 { 154 | return []NodeOrderedSet{} 155 | } else { 156 | guideLayers = append(guideLayers, currentLayer) 157 | } 158 | } 159 | 160 | return 161 | } 162 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/support/goraph/edge/edge.go: -------------------------------------------------------------------------------- 1 | package edge 2 | 3 | import . "github.com/onsi/gomega/matchers/support/goraph/node" 4 | 5 | type Edge struct { 6 | Node1 Node 7 | Node2 Node 8 | } 9 | 10 | type EdgeSet []Edge 11 | 12 | func (ec EdgeSet) Free(node Node) bool { 13 | for _, e := range ec { 14 | if e.Node1 == node || e.Node2 == node { 15 | return false 16 | } 17 | } 18 | 19 | return true 20 | } 21 | 22 | func (ec EdgeSet) Contains(edge Edge) bool { 23 | for _, e := range ec { 24 | if e == edge { 25 | return true 26 | } 27 | } 28 | 29 | return false 30 | } 31 | 32 | func (ec EdgeSet) FindByNodes(node1, node2 Node) (Edge, bool) { 33 | for _, e := range ec { 34 | if (e.Node1 == node1 && e.Node2 == node2) || (e.Node1 == node2 && e.Node2 == node1) { 35 | return e, true 36 | } 37 | } 38 | 39 | return Edge{}, false 40 | } 41 | 42 | func (ec EdgeSet) SymmetricDifference(ec2 EdgeSet) EdgeSet { 43 | edgesToInclude := make(map[Edge]bool) 44 | 45 | for _, e := range ec { 46 | edgesToInclude[e] = true 47 | } 48 | 49 | for _, e := range ec2 { 50 | edgesToInclude[e] = !edgesToInclude[e] 51 | } 52 | 53 | result := EdgeSet{} 54 | for e, include := range edgesToInclude { 55 | if include { 56 | result = append(result, e) 57 | } 58 | } 59 | 60 | return result 61 | } 62 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/support/goraph/node/node.go: -------------------------------------------------------------------------------- 1 | package node 2 | 3 | type Node struct { 4 | Id int 5 | } 6 | 7 | type NodeOrderedSet []Node 8 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/support/goraph/util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "math" 4 | 5 | func Odd(n int) bool { 6 | return math.Mod(float64(n), 2.0) == 1.0 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/matchers/type_support.go: -------------------------------------------------------------------------------- 1 | /* 2 | Gomega matchers 3 | 4 | This package implements the Gomega matchers and does not typically need to be imported. 5 | See the docs for Gomega for documentation on the matchers 6 | 7 | http://onsi.github.io/gomega/ 8 | */ 9 | package matchers 10 | 11 | import ( 12 | "fmt" 13 | "reflect" 14 | ) 15 | 16 | type omegaMatcher interface { 17 | Match(actual interface{}) (success bool, err error) 18 | FailureMessage(actual interface{}) (message string) 19 | NegatedFailureMessage(actual interface{}) (message string) 20 | } 21 | 22 | func isBool(a interface{}) bool { 23 | return reflect.TypeOf(a).Kind() == reflect.Bool 24 | } 25 | 26 | func isNumber(a interface{}) bool { 27 | if a == nil { 28 | return false 29 | } 30 | kind := reflect.TypeOf(a).Kind() 31 | return reflect.Int <= kind && kind <= reflect.Float64 32 | } 33 | 34 | func isInteger(a interface{}) bool { 35 | kind := reflect.TypeOf(a).Kind() 36 | return reflect.Int <= kind && kind <= reflect.Int64 37 | } 38 | 39 | func isUnsignedInteger(a interface{}) bool { 40 | kind := reflect.TypeOf(a).Kind() 41 | return reflect.Uint <= kind && kind <= reflect.Uint64 42 | } 43 | 44 | func isFloat(a interface{}) bool { 45 | kind := reflect.TypeOf(a).Kind() 46 | return reflect.Float32 <= kind && kind <= reflect.Float64 47 | } 48 | 49 | func toInteger(a interface{}) int64 { 50 | if isInteger(a) { 51 | return reflect.ValueOf(a).Int() 52 | } else if isUnsignedInteger(a) { 53 | return int64(reflect.ValueOf(a).Uint()) 54 | } else if isFloat(a) { 55 | return int64(reflect.ValueOf(a).Float()) 56 | } else { 57 | panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a)) 58 | } 59 | } 60 | 61 | func toUnsignedInteger(a interface{}) uint64 { 62 | if isInteger(a) { 63 | return uint64(reflect.ValueOf(a).Int()) 64 | } else if isUnsignedInteger(a) { 65 | return reflect.ValueOf(a).Uint() 66 | } else if isFloat(a) { 67 | return uint64(reflect.ValueOf(a).Float()) 68 | } else { 69 | panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a)) 70 | } 71 | } 72 | 73 | func toFloat(a interface{}) float64 { 74 | if isInteger(a) { 75 | return float64(reflect.ValueOf(a).Int()) 76 | } else if isUnsignedInteger(a) { 77 | return float64(reflect.ValueOf(a).Uint()) 78 | } else if isFloat(a) { 79 | return reflect.ValueOf(a).Float() 80 | } else { 81 | panic(fmt.Sprintf("Expected a number! Got <%T> %#v", a, a)) 82 | } 83 | } 84 | 85 | func isError(a interface{}) bool { 86 | _, ok := a.(error) 87 | return ok 88 | } 89 | 90 | func isChan(a interface{}) bool { 91 | if isNil(a) { 92 | return false 93 | } 94 | return reflect.TypeOf(a).Kind() == reflect.Chan 95 | } 96 | 97 | func isMap(a interface{}) bool { 98 | if a == nil { 99 | return false 100 | } 101 | return reflect.TypeOf(a).Kind() == reflect.Map 102 | } 103 | 104 | func isArrayOrSlice(a interface{}) bool { 105 | if a == nil { 106 | return false 107 | } 108 | switch reflect.TypeOf(a).Kind() { 109 | case reflect.Array, reflect.Slice: 110 | return true 111 | default: 112 | return false 113 | } 114 | } 115 | 116 | func isString(a interface{}) bool { 117 | if a == nil { 118 | return false 119 | } 120 | return reflect.TypeOf(a).Kind() == reflect.String 121 | } 122 | 123 | func toString(a interface{}) (string, bool) { 124 | aString, isString := a.(string) 125 | if isString { 126 | return aString, true 127 | } 128 | 129 | aBytes, isBytes := a.([]byte) 130 | if isBytes { 131 | return string(aBytes), true 132 | } 133 | 134 | aStringer, isStringer := a.(fmt.Stringer) 135 | if isStringer { 136 | return aStringer.String(), true 137 | } 138 | 139 | return "", false 140 | } 141 | 142 | func lengthOf(a interface{}) (int, bool) { 143 | if a == nil { 144 | return 0, false 145 | } 146 | switch reflect.TypeOf(a).Kind() { 147 | case reflect.Map, reflect.Array, reflect.String, reflect.Chan, reflect.Slice: 148 | return reflect.ValueOf(a).Len(), true 149 | default: 150 | return 0, false 151 | } 152 | } 153 | 154 | func isNil(a interface{}) bool { 155 | if a == nil { 156 | return true 157 | } 158 | 159 | switch reflect.TypeOf(a).Kind() { 160 | case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: 161 | return reflect.ValueOf(a).IsNil() 162 | } 163 | 164 | return false 165 | } 166 | -------------------------------------------------------------------------------- /vendor/github.com/onsi/gomega/types/types.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type GomegaFailHandler func(message string, callerSkip ...int) 4 | 5 | //A simple *testing.T interface wrapper 6 | type GomegaTestingT interface { 7 | Errorf(format string, args ...interface{}) 8 | } 9 | 10 | //All Gomega matchers must implement the GomegaMatcher interface 11 | // 12 | //For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding_your_own_matchers 13 | type GomegaMatcher interface { 14 | Match(actual interface{}) (success bool, err error) 15 | FailureMessage(actual interface{}) (message string) 16 | NegatedFailureMessage(actual interface{}) (message string) 17 | } 18 | -------------------------------------------------------------------------------- /vendor/github.com/rubenv/sql-migrate/.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | *.test 3 | 4 | /sql-migrate/test.db 5 | /test.db 6 | -------------------------------------------------------------------------------- /vendor/github.com/rubenv/sql-migrate/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.2 5 | - 1.3 6 | - tip 7 | 8 | services: 9 | - mysql 10 | 11 | before_install: 12 | - mysql -e "CREATE DATABASE IF NOT EXISTS test;" -uroot 13 | - psql -c "CREATE DATABASE test;" -U postgres 14 | 15 | install: 16 | - go get -t ./... 17 | - go install ./... 18 | 19 | script: 20 | - go test -v ./... 21 | - bash test-integration/postgres.sh 22 | - bash test-integration/mysql.sh 23 | - bash test-integration/mysql-flag.sh 24 | - bash test-integration/sqlite.sh 25 | -------------------------------------------------------------------------------- /vendor/github.com/rubenv/sql-migrate/sqlparse/README.md: -------------------------------------------------------------------------------- 1 | # SQL migration parser 2 | 3 | Based on the [goose](https://bitbucket.org/liamstask/goose) migration parser. 4 | 5 | ## License 6 | 7 | (The MIT License) 8 | 9 | Copyright (C) 2014 by Ruben Vermeersch 10 | Copyright (C) 2012-2014 by Liam Staskawicz 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /vendor/github.com/rubenv/sql-migrate/sqlparse/sqlparse.go: -------------------------------------------------------------------------------- 1 | package sqlparse 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "errors" 7 | "io" 8 | 9 | "strings" 10 | ) 11 | 12 | const sqlCmdPrefix = "-- +migrate " 13 | 14 | // Checks the line to see if the line has a statement-ending semicolon 15 | // or if the line contains a double-dash comment. 16 | func endsWithSemicolon(line string) bool { 17 | 18 | prev := "" 19 | scanner := bufio.NewScanner(strings.NewReader(line)) 20 | scanner.Split(bufio.ScanWords) 21 | 22 | for scanner.Scan() { 23 | word := scanner.Text() 24 | if strings.HasPrefix(word, "--") { 25 | break 26 | } 27 | prev = word 28 | } 29 | 30 | return strings.HasSuffix(prev, ";") 31 | } 32 | 33 | // Split the given sql script into individual statements. 34 | // 35 | // The base case is to simply split on semicolons, as these 36 | // naturally terminate a statement. 37 | // 38 | // However, more complex cases like pl/pgsql can have semicolons 39 | // within a statement. For these cases, we provide the explicit annotations 40 | // 'StatementBegin' and 'StatementEnd' to allow the script to 41 | // tell us to ignore semicolons. 42 | func SplitSQLStatements(r io.ReadSeeker, direction bool) ([]string, error) { 43 | _, err := r.Seek(0, 0) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | var buf bytes.Buffer 49 | scanner := bufio.NewScanner(r) 50 | 51 | // track the count of each section 52 | // so we can diagnose scripts with no annotations 53 | upSections := 0 54 | downSections := 0 55 | 56 | statementEnded := false 57 | ignoreSemicolons := false 58 | directionIsActive := false 59 | 60 | stmts := make([]string, 0) 61 | 62 | for scanner.Scan() { 63 | 64 | line := scanner.Text() 65 | 66 | // handle any migrate-specific commands 67 | if strings.HasPrefix(line, sqlCmdPrefix) { 68 | cmd := strings.TrimSpace(line[len(sqlCmdPrefix):]) 69 | switch cmd { 70 | case "Up": 71 | directionIsActive = (direction == true) 72 | upSections++ 73 | break 74 | 75 | case "Down": 76 | directionIsActive = (direction == false) 77 | downSections++ 78 | break 79 | 80 | case "StatementBegin": 81 | if directionIsActive { 82 | ignoreSemicolons = true 83 | } 84 | break 85 | 86 | case "StatementEnd": 87 | if directionIsActive { 88 | statementEnded = (ignoreSemicolons == true) 89 | ignoreSemicolons = false 90 | } 91 | break 92 | } 93 | } 94 | 95 | if !directionIsActive { 96 | continue 97 | } 98 | 99 | if _, err := buf.WriteString(line + "\n"); err != nil { 100 | return nil, err 101 | } 102 | 103 | // Wrap up the two supported cases: 1) basic with semicolon; 2) psql statement 104 | // Lines that end with semicolon that are in a statement block 105 | // do not conclude statement. 106 | if (!ignoreSemicolons && endsWithSemicolon(line)) || statementEnded { 107 | statementEnded = false 108 | stmts = append(stmts, buf.String()) 109 | buf.Reset() 110 | } 111 | } 112 | 113 | if err := scanner.Err(); err != nil { 114 | return nil, err 115 | } 116 | 117 | // diagnose likely migration script errors 118 | if ignoreSemicolons { 119 | return nil, errors.New("ERROR: saw '-- +migrate StatementBegin' with no matching '-- +migrate StatementEnd'") 120 | } 121 | 122 | if upSections == 0 && downSections == 0 { 123 | return nil, errors.New(`ERROR: no Up/Down annotations found, so no statements were executed. 124 | See https://github.com/rubenv/sql-migrate for details.`) 125 | } 126 | 127 | return stmts, nil 128 | } 129 | -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/.gitignore: -------------------------------------------------------------------------------- 1 | coverage.out -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Greg Roseberry 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/README.md: -------------------------------------------------------------------------------- 1 | ## null [![GoDoc](https://godoc.org/github.com/guregu/null?status.svg)](https://godoc.org/github.com/guregu/null) [![Coverage](http://gocover.io/_badge/github.com/guregu/null)](http://gocover.io/github.com/guregu/null) 2 | `import "gopkg.in/guregu/null.v2"` 3 | 4 | null is a library with reasonable options for dealing with nullable SQL and JSON values 5 | 6 | There are two packages: `null` and its subpackage `zero`. 7 | 8 | Types in `null` will only be considered null on null input, and will JSON encode to `null`. If you need zero and null be considered separate values, use these. 9 | 10 | Types in `zero` are treated like zero values in Go: blank string input will produce a null `zero.String`, and null Strings will JSON encode to `""`. If you need zero and null treated the same, use these. 11 | 12 | All types implement `sql.Scanner` and `driver.Valuer`, so you can use this library in place of `sql.NullXXX`. All types also implement: `encoding.TextMarshaler`, `encoding.TextUnmarshaler`, `json.Marshaler`, and `json.Unmarshaler`. 13 | 14 | #### zero.String 15 | A nullable string. 16 | 17 | Will marshal to a blank string if null. Blank string input produces a null String. In other words, null values and empty values are considered equivalent. Can unmarshal from `sql.NullString` JSON input. 18 | 19 | #### zero.Int 20 | A nullable int64. 21 | 22 | Will marshal to 0 if null. Blank string or 0 input produces a null Int. In other words, null values and empty values are considered equivalent. Can unmarshal from `sql.NullInt64` JSON input. 23 | 24 | #### zero.Float 25 | A nullable float64. 26 | 27 | Will marshal to 0 if null. Blank string or 0 input produces a null Float. In other words, null values and empty values are considered equivalent. Can unmarshal from `sql.NullFloat64` JSON input. 28 | 29 | #### zero.Bool 30 | A nullable bool. 31 | 32 | Will marshal to false if null. Blank string or false input produces a null Float. In other words, null values and empty values are considered equivalent. Can unmarshal from `sql.NullBool` JSON input. 33 | 34 | #### null.String 35 | An even nuller nullable string. 36 | 37 | Unlike `zero.String`, `null.String` will marshal to null if null. Zero (blank) input will not produce a null String. Can unmarshal from `sql.NullString` JSON input. 38 | 39 | #### null.Int 40 | An even nuller nullable int64. 41 | 42 | Unlike `zero.Int`, `null.Int` will marshal to null if null. Zero input will not produce a null Int. Can unmarshal from `sql.NullInt64` JSON input. 43 | 44 | #### null.Float 45 | An even nuller nullable float64. 46 | 47 | Unlike `zero.Float`, `null.Float` will marshal to null if null. Zero input will not produce a null Float. Can unmarshal from `sql.NullFloat64` JSON input. 48 | 49 | #### null.Bool 50 | An even nuller nullable float64. 51 | 52 | Unlike `zero.Bool`, `null.Bool` will marshal to null if null. False input will not produce a null Bool. Can unmarshal from `sql.NullBool` JSON input. 53 | 54 | ### Bugs 55 | `json`'s `",omitempty"` struct tag does not work correctly right now. It will never omit a null or empty String. This should be [fixed in Go 1.4](https://code.google.com/p/go/issues/detail?id=4357). 56 | 57 | ### License 58 | BSD -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/bool.go: -------------------------------------------------------------------------------- 1 | package null 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "reflect" 9 | ) 10 | 11 | // Bool is an even nuller nullable bool. 12 | // It does not consider false values to be null. 13 | // It will decode to null, not false, if null. 14 | type Bool struct { 15 | sql.NullBool 16 | } 17 | 18 | // NewBool creates a new Bool 19 | func NewBool(b bool, valid bool) Bool { 20 | return Bool{ 21 | NullBool: sql.NullBool{ 22 | Bool: b, 23 | Valid: valid, 24 | }, 25 | } 26 | } 27 | 28 | // BoolFrom creates a new Bool that will always be valid. 29 | func BoolFrom(b bool) Bool { 30 | return NewBool(b, true) 31 | } 32 | 33 | // BoolFromPtr creates a new Bool that will be null if f is nil. 34 | func BoolFromPtr(b *bool) Bool { 35 | if b == nil { 36 | return NewBool(false, false) 37 | } 38 | return NewBool(*b, true) 39 | } 40 | 41 | // UnmarshalJSON implements json.Unmarshaler. 42 | // It supports number and null input. 43 | // 0 will not be considered a null Bool. 44 | // It also supports unmarshalling a sql.NullBool. 45 | func (b *Bool) UnmarshalJSON(data []byte) error { 46 | var err error 47 | var v interface{} 48 | json.Unmarshal(data, &v) 49 | switch x := v.(type) { 50 | case bool: 51 | b.Bool = x 52 | case map[string]interface{}: 53 | err = json.Unmarshal(data, &b.NullBool) 54 | case nil: 55 | b.Valid = false 56 | return nil 57 | default: 58 | err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Bool", reflect.TypeOf(v).Name()) 59 | } 60 | b.Valid = err == nil 61 | return err 62 | } 63 | 64 | // UnmarshalText implements encoding.TextUnmarshaler. 65 | // It will unmarshal to a null Bool if the input is a blank or not an integer. 66 | // It will return an error if the input is not an integer, blank, or "null". 67 | func (b *Bool) UnmarshalText(text []byte) error { 68 | str := string(text) 69 | switch str { 70 | case "", "null": 71 | b.Valid = false 72 | return nil 73 | case "true": 74 | b.Bool = true 75 | case "false": 76 | b.Bool = false 77 | default: 78 | b.Valid = false 79 | return errors.New("invalid input:" + str) 80 | } 81 | b.Valid = true 82 | return nil 83 | } 84 | 85 | // MarshalJSON implements json.Marshaler. 86 | // It will encode null if this Bool is null. 87 | func (b Bool) MarshalJSON() ([]byte, error) { 88 | if !b.Valid { 89 | return []byte("null"), nil 90 | } 91 | if !b.Bool { 92 | return []byte("false"), nil 93 | } 94 | return []byte("true"), nil 95 | } 96 | 97 | // MarshalText implements encoding.TextMarshaler. 98 | // It will encode a blank string if this Bool is null. 99 | func (b Bool) MarshalText() ([]byte, error) { 100 | if !b.Valid { 101 | return []byte{}, nil 102 | } 103 | if !b.Bool { 104 | return []byte("false"), nil 105 | } 106 | return []byte("true"), nil 107 | } 108 | 109 | // SetValid changes this Bool's value and also sets it to be non-null. 110 | func (b *Bool) SetValid(v bool) { 111 | b.Bool = v 112 | b.Valid = true 113 | } 114 | 115 | // Ptr returns a pointer to this Bool's value, or a nil pointer if this Bool is null. 116 | func (b Bool) Ptr() *bool { 117 | if !b.Valid { 118 | return nil 119 | } 120 | return &b.Bool 121 | } 122 | 123 | // IsZero returns true for invalid Bools, for future omitempty support (Go 1.4?) 124 | // A non-null Bool with a 0 value will not be considered zero. 125 | func (b Bool) IsZero() bool { 126 | return !b.Valid 127 | } 128 | -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/float.go: -------------------------------------------------------------------------------- 1 | package null 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/json" 6 | "fmt" 7 | "reflect" 8 | "strconv" 9 | ) 10 | 11 | // Float is an even nuller nullable float64. 12 | // It does not consider zero values to be null. 13 | // It will decode to null, not zero, if null. 14 | type Float struct { 15 | sql.NullFloat64 16 | } 17 | 18 | // NewFloat creates a new Float 19 | func NewFloat(f float64, valid bool) Float { 20 | return Float{ 21 | NullFloat64: sql.NullFloat64{ 22 | Float64: f, 23 | Valid: valid, 24 | }, 25 | } 26 | } 27 | 28 | // FloatFrom creates a new Float that will always be valid. 29 | func FloatFrom(f float64) Float { 30 | return NewFloat(f, true) 31 | } 32 | 33 | // FloatFromPtr creates a new Float that be null if f is nil. 34 | func FloatFromPtr(f *float64) Float { 35 | if f == nil { 36 | return NewFloat(0, false) 37 | } 38 | return NewFloat(*f, true) 39 | } 40 | 41 | // UnmarshalJSON implements json.Unmarshaler. 42 | // It supports number and null input. 43 | // 0 will not be considered a null Float. 44 | // It also supports unmarshalling a sql.NullFloat64. 45 | func (f *Float) UnmarshalJSON(data []byte) error { 46 | var err error 47 | var v interface{} 48 | json.Unmarshal(data, &v) 49 | switch x := v.(type) { 50 | case float64: 51 | f.Float64 = float64(x) 52 | case map[string]interface{}: 53 | err = json.Unmarshal(data, &f.NullFloat64) 54 | case nil: 55 | f.Valid = false 56 | return nil 57 | default: 58 | err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Float", reflect.TypeOf(v).Name()) 59 | } 60 | f.Valid = err == nil 61 | return err 62 | } 63 | 64 | // UnmarshalText implements encoding.TextUnmarshaler. 65 | // It will unmarshal to a null Float if the input is a blank or not an integer. 66 | // It will return an error if the input is not an integer, blank, or "null". 67 | func (f *Float) UnmarshalText(text []byte) error { 68 | str := string(text) 69 | if str == "" || str == "null" { 70 | f.Valid = false 71 | return nil 72 | } 73 | var err error 74 | f.Float64, err = strconv.ParseFloat(string(text), 64) 75 | f.Valid = err == nil 76 | return err 77 | } 78 | 79 | // MarshalJSON implements json.Marshaler. 80 | // It will encode null if this Float is null. 81 | func (f Float) MarshalJSON() ([]byte, error) { 82 | if !f.Valid { 83 | return []byte("null"), nil 84 | } 85 | return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil 86 | } 87 | 88 | // MarshalText implements encoding.TextMarshaler. 89 | // It will encode a blank string if this Float is null. 90 | func (f Float) MarshalText() ([]byte, error) { 91 | if !f.Valid { 92 | return []byte{}, nil 93 | } 94 | return []byte(strconv.FormatFloat(f.Float64, 'f', -1, 64)), nil 95 | } 96 | 97 | // SetValid changes this Float's value and also sets it to be non-null. 98 | func (f *Float) SetValid(n float64) { 99 | f.Float64 = n 100 | f.Valid = true 101 | } 102 | 103 | // Ptr returns a pointer to this Float's value, or a nil pointer if this Float is null. 104 | func (f Float) Ptr() *float64 { 105 | if !f.Valid { 106 | return nil 107 | } 108 | return &f.Float64 109 | } 110 | 111 | // IsZero returns true for invalid Floats, for future omitempty support (Go 1.4?) 112 | // A non-null Float with a 0 value will not be considered zero. 113 | func (f Float) IsZero() bool { 114 | return !f.Valid 115 | } 116 | -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/int.go: -------------------------------------------------------------------------------- 1 | package null 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/json" 6 | "fmt" 7 | "reflect" 8 | "strconv" 9 | ) 10 | 11 | // Int is an even nuller nullable int64. 12 | // It does not consider zero values to be null. 13 | // It will decode to null, not zero, if null. 14 | type Int struct { 15 | sql.NullInt64 16 | } 17 | 18 | // NewInt creates a new Int 19 | func NewInt(i int64, valid bool) Int { 20 | return Int{ 21 | NullInt64: sql.NullInt64{ 22 | Int64: i, 23 | Valid: valid, 24 | }, 25 | } 26 | } 27 | 28 | // IntFrom creates a new Int that will always be valid. 29 | func IntFrom(i int64) Int { 30 | return NewInt(i, true) 31 | } 32 | 33 | // IntFromPtr creates a new Int that be null if i is nil. 34 | func IntFromPtr(i *int64) Int { 35 | if i == nil { 36 | return NewInt(0, false) 37 | } 38 | return NewInt(*i, true) 39 | } 40 | 41 | // UnmarshalJSON implements json.Unmarshaler. 42 | // It supports number and null input. 43 | // 0 will not be considered a null Int. 44 | // It also supports unmarshalling a sql.NullInt64. 45 | func (i *Int) UnmarshalJSON(data []byte) error { 46 | var err error 47 | var v interface{} 48 | json.Unmarshal(data, &v) 49 | switch v.(type) { 50 | case float64: 51 | // Unmarshal again, directly to int64, to avoid intermediate float64 52 | err = json.Unmarshal(data, &i.Int64) 53 | case map[string]interface{}: 54 | err = json.Unmarshal(data, &i.NullInt64) 55 | case nil: 56 | i.Valid = false 57 | return nil 58 | default: 59 | err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.Int", reflect.TypeOf(v).Name()) 60 | } 61 | i.Valid = err == nil 62 | return err 63 | } 64 | 65 | // UnmarshalText implements encoding.TextUnmarshaler. 66 | // It will unmarshal to a null Int if the input is a blank or not an integer. 67 | // It will return an error if the input is not an integer, blank, or "null". 68 | func (i *Int) UnmarshalText(text []byte) error { 69 | str := string(text) 70 | if str == "" || str == "null" { 71 | i.Valid = false 72 | return nil 73 | } 74 | var err error 75 | i.Int64, err = strconv.ParseInt(string(text), 10, 64) 76 | i.Valid = err == nil 77 | return err 78 | } 79 | 80 | // MarshalJSON implements json.Marshaler. 81 | // It will encode null if this Int is null. 82 | func (i Int) MarshalJSON() ([]byte, error) { 83 | if !i.Valid { 84 | return []byte("null"), nil 85 | } 86 | return []byte(strconv.FormatInt(i.Int64, 10)), nil 87 | } 88 | 89 | // MarshalText implements encoding.TextMarshaler. 90 | // It will encode a blank string if this Int is null. 91 | func (i Int) MarshalText() ([]byte, error) { 92 | if !i.Valid { 93 | return []byte{}, nil 94 | } 95 | return []byte(strconv.FormatInt(i.Int64, 10)), nil 96 | } 97 | 98 | // SetValid changes this Int's value and also sets it to be non-null. 99 | func (i *Int) SetValid(n int64) { 100 | i.Int64 = n 101 | i.Valid = true 102 | } 103 | 104 | // Ptr returns a pointer to this Int's value, or a nil pointer if this Int is null. 105 | func (i Int) Ptr() *int64 { 106 | if !i.Valid { 107 | return nil 108 | } 109 | return &i.Int64 110 | } 111 | 112 | // IsZero returns true for invalid Ints, for future omitempty support (Go 1.4?) 113 | // A non-null Int with a 0 value will not be considered zero. 114 | func (i Int) IsZero() bool { 115 | return !i.Valid 116 | } 117 | -------------------------------------------------------------------------------- /vendor/gopkg.in/guregu/null.v2/string.go: -------------------------------------------------------------------------------- 1 | // Package null contains types that consider zero input and null input as separate values. 2 | // Types in this package will always encode to their null value if null. 3 | // Use the zero subpackage if you want empty and null to be treated the same. 4 | package null 5 | 6 | import ( 7 | "database/sql" 8 | "encoding/json" 9 | "fmt" 10 | "reflect" 11 | ) 12 | 13 | // String is an even nuller nullable string. 14 | type String struct { 15 | sql.NullString 16 | } 17 | 18 | // StringFrom creates a new String that will never be blank. 19 | func StringFrom(s string) String { 20 | return NewString(s, true) 21 | } 22 | 23 | // StringFromPtr creates a new String that be null if s is nil. 24 | func StringFromPtr(s *string) String { 25 | if s == nil { 26 | return NewString("", false) 27 | } 28 | return NewString(*s, true) 29 | } 30 | 31 | // NewString creates a new String 32 | func NewString(s string, valid bool) String { 33 | return String{ 34 | NullString: sql.NullString{ 35 | String: s, 36 | Valid: valid, 37 | }, 38 | } 39 | } 40 | 41 | // UnmarshalJSON implements json.Unmarshaler. 42 | // It supports string and null input. Blank string input produces a null String. 43 | // It also supports unmarshalling a sql.NullString. 44 | func (s *String) UnmarshalJSON(data []byte) error { 45 | var err error 46 | var v interface{} 47 | json.Unmarshal(data, &v) 48 | switch x := v.(type) { 49 | case string: 50 | s.String = x 51 | case map[string]interface{}: 52 | err = json.Unmarshal(data, &s.NullString) 53 | case nil: 54 | s.Valid = false 55 | return nil 56 | default: 57 | err = fmt.Errorf("json: cannot unmarshal %v into Go value of type null.String", reflect.TypeOf(v).Name()) 58 | } 59 | s.Valid = (err == nil) && (s.String != "") 60 | return err 61 | } 62 | 63 | // MarshalJSON implements json.Marshaler. 64 | // It will encode null if this String is null. 65 | func (s String) MarshalJSON() ([]byte, error) { 66 | if !s.Valid { 67 | return []byte("null"), nil 68 | } 69 | return json.Marshal(s.String) 70 | } 71 | 72 | // UnmarshalText implements encoding.TextUnmarshaler. 73 | // It will unmarshal to a null String if the input is a blank string. 74 | func (s *String) UnmarshalText(text []byte) error { 75 | s.String = string(text) 76 | s.Valid = s.String != "" 77 | return nil 78 | } 79 | 80 | // SetValid changes this String's value and also sets it to be non-null. 81 | func (s *String) SetValid(v string) { 82 | s.String = v 83 | s.Valid = true 84 | } 85 | 86 | // Ptr returns a pointer to this String's value, or a nil pointer if this String is null. 87 | func (s String) Ptr() *string { 88 | if !s.Valid { 89 | return nil 90 | } 91 | return &s.String 92 | } 93 | 94 | // IsZero returns true for null or empty strings, for future omitempty support. (Go 1.4?) 95 | // Will return false s if blank but non-null. 96 | func (s String) IsZero() bool { 97 | return !s.Valid 98 | } 99 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/coopernurse/gorp v1.6.2-0.20140906144417-5d19ebd22fdc 2 | github.com/coopernurse/gorp 3 | # github.com/go-sql-driver/mysql v1.2.1-0.20140926190841-954375029540 4 | github.com/go-sql-driver/mysql 5 | # github.com/gorilla/context v0.0.0-20140604161150-14f550f51af5 6 | github.com/gorilla/context 7 | # github.com/gorilla/mux v0.0.0-20140926153814-e444e69cbd2e 8 | github.com/gorilla/mux 9 | # github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d 10 | github.com/nu7hatch/gouuid 11 | # github.com/onsi/ginkgo v1.1.1-0.20141113002505-9c7cbc493e1b 12 | github.com/onsi/ginkgo 13 | github.com/onsi/ginkgo/config 14 | github.com/onsi/ginkgo/internal/codelocation 15 | github.com/onsi/ginkgo/internal/containernode 16 | github.com/onsi/ginkgo/internal/failer 17 | github.com/onsi/ginkgo/internal/leafnodes 18 | github.com/onsi/ginkgo/internal/remote 19 | github.com/onsi/ginkgo/internal/spec 20 | github.com/onsi/ginkgo/internal/specrunner 21 | github.com/onsi/ginkgo/internal/suite 22 | github.com/onsi/ginkgo/internal/testingtproxy 23 | github.com/onsi/ginkgo/internal/writer 24 | github.com/onsi/ginkgo/reporters 25 | github.com/onsi/ginkgo/reporters/stenographer 26 | github.com/onsi/ginkgo/types 27 | # github.com/onsi/gomega v0.0.0-20141104003221-2cd6d99ccf3a 28 | github.com/onsi/gomega 29 | github.com/onsi/gomega/format 30 | github.com/onsi/gomega/internal/assertion 31 | github.com/onsi/gomega/internal/asyncassertion 32 | github.com/onsi/gomega/internal/testingtsupport 33 | github.com/onsi/gomega/matchers 34 | github.com/onsi/gomega/matchers/support/goraph/bipartitegraph 35 | github.com/onsi/gomega/matchers/support/goraph/edge 36 | github.com/onsi/gomega/matchers/support/goraph/node 37 | github.com/onsi/gomega/matchers/support/goraph/util 38 | github.com/onsi/gomega/types 39 | # github.com/rubenv/sql-migrate v0.0.0-20141001072755-09d124bf5f0e 40 | github.com/rubenv/sql-migrate 41 | github.com/rubenv/sql-migrate/sqlparse 42 | # gopkg.in/guregu/null.v2 v2.1.1 43 | gopkg.in/guregu/null.v2 44 | --------------------------------------------------------------------------------