├── .gitignore ├── Gopkg.lock ├── Gopkg.toml ├── LICENSE ├── README.md ├── dbmodel ├── dbmodel.go └── kallax.go ├── sidekiq └── cmd │ └── example │ └── main.go └── vendor ├── github.com ├── Masterminds │ └── squirrel │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE.txt │ │ ├── README.md │ │ ├── case.go │ │ ├── case_test.go │ │ ├── delete.go │ │ ├── delete_test.go │ │ ├── expr.go │ │ ├── expr_test.go │ │ ├── insert.go │ │ ├── insert_test.go │ │ ├── part.go │ │ ├── placeholder.go │ │ ├── placeholder_test.go │ │ ├── row.go │ │ ├── row_test.go │ │ ├── select.go │ │ ├── select_test.go │ │ ├── squirrel.go │ │ ├── squirrel_test.go │ │ ├── statement.go │ │ ├── statement_test.go │ │ ├── stmtcacher.go │ │ ├── stmtcacher_test.go │ │ ├── update.go │ │ ├── update_test.go │ │ ├── where.go │ │ └── where_test.go ├── bitly │ └── go-simplejson │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── simplejson.go │ │ ├── simplejson_go10.go │ │ ├── simplejson_go10_test.go │ │ ├── simplejson_go11.go │ │ ├── simplejson_go11_test.go │ │ └── simplejson_test.go ├── garyburd │ └── redigo │ │ ├── .github │ │ ├── CONTRIBUTING.md │ │ └── ISSUE_TEMPLATE.md │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.markdown │ │ ├── internal │ │ ├── commandinfo.go │ │ ├── commandinfo_test.go │ │ └── redistest │ │ │ └── testdb.go │ │ ├── redis │ │ ├── conn.go │ │ ├── conn_test.go │ │ ├── doc.go │ │ ├── go17.go │ │ ├── log.go │ │ ├── pool.go │ │ ├── pool_test.go │ │ ├── pre_go17.go │ │ ├── pubsub.go │ │ ├── pubsub_test.go │ │ ├── redis.go │ │ ├── reply.go │ │ ├── reply_test.go │ │ ├── scan.go │ │ ├── scan_test.go │ │ ├── script.go │ │ ├── script_test.go │ │ ├── test_test.go │ │ └── zpop_example_test.go │ │ └── redisx │ │ ├── connmux.go │ │ ├── connmux_test.go │ │ └── doc.go ├── go-redis │ └── redis │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── bench_test.go │ │ ├── cluster.go │ │ ├── cluster_test.go │ │ ├── command.go │ │ ├── command_test.go │ │ ├── commands.go │ │ ├── commands_test.go │ │ ├── doc.go │ │ ├── example_instrumentation_test.go │ │ ├── example_test.go │ │ ├── export_test.go │ │ ├── internal │ │ ├── consistenthash │ │ │ ├── consistenthash.go │ │ │ └── consistenthash_test.go │ │ ├── errors.go │ │ ├── hashtag │ │ │ ├── hashtag.go │ │ │ └── hashtag_test.go │ │ ├── log.go │ │ ├── pool │ │ │ ├── bench_test.go │ │ │ ├── conn.go │ │ │ ├── main_test.go │ │ │ ├── pool.go │ │ │ ├── pool_single.go │ │ │ ├── pool_sticky.go │ │ │ └── pool_test.go │ │ ├── proto │ │ │ ├── proto_test.go │ │ │ ├── reader.go │ │ │ ├── reader_test.go │ │ │ ├── scan.go │ │ │ ├── scan_test.go │ │ │ ├── write_buffer.go │ │ │ └── write_buffer_test.go │ │ ├── safe.go │ │ ├── unsafe.go │ │ └── util.go │ │ ├── iterator.go │ │ ├── iterator_test.go │ │ ├── main_test.go │ │ ├── options.go │ │ ├── options_test.go │ │ ├── parser.go │ │ ├── pipeline.go │ │ ├── pipeline_test.go │ │ ├── pool_test.go │ │ ├── pubsub.go │ │ ├── pubsub_test.go │ │ ├── race_test.go │ │ ├── redis.go │ │ ├── redis_context.go │ │ ├── redis_no_context.go │ │ ├── redis_test.go │ │ ├── result.go │ │ ├── ring.go │ │ ├── ring_test.go │ │ ├── script.go │ │ ├── sentinel.go │ │ ├── sentinel_test.go │ │ ├── testdata │ │ └── redis.conf │ │ ├── tx.go │ │ ├── tx_test.go │ │ ├── universal.go │ │ └── universal_test.go ├── jrallison │ └── go-workers │ │ ├── .travis.yml │ │ ├── LICENSE.txt │ │ ├── README.md │ │ ├── all_specs_test.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── enqueue.go │ │ ├── enqueue_test.go │ │ ├── fetch_test.go │ │ ├── fetcher.go │ │ ├── hooks.go │ │ ├── job.go │ │ ├── manager.go │ │ ├── manager_test.go │ │ ├── middleware.go │ │ ├── middleware_logging.go │ │ ├── middleware_retry.go │ │ ├── middleware_retry_test.go │ │ ├── middleware_stats.go │ │ ├── middleware_stats_test.go │ │ ├── middleware_test.go │ │ ├── msg.go │ │ ├── msg_test.go │ │ ├── scheduled.go │ │ ├── scheduled_test.go │ │ ├── signals_posix.go │ │ ├── signals_windows.go │ │ ├── stats.go │ │ ├── worker.go │ │ ├── worker_test.go │ │ ├── workers.go │ │ ├── workers_logger.go │ │ └── workers_test.go ├── lann │ ├── builder │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── README.md │ │ ├── builder.go │ │ ├── builder_test.go │ │ ├── example_test.go │ │ ├── reflect.go │ │ └── registry.go │ └── ps │ │ ├── LICENSE │ │ ├── README.md │ │ ├── list.go │ │ ├── list_test.go │ │ ├── map.go │ │ ├── map_test.go │ │ └── profile.sh ├── lib │ └── pq │ │ ├── .gitignore │ │ ├── .travis.sh │ │ ├── .travis.yml │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── array.go │ │ ├── array_test.go │ │ ├── bench_test.go │ │ ├── buf.go │ │ ├── certs │ │ ├── README │ │ ├── bogus_root.crt │ │ ├── postgresql.crt │ │ ├── postgresql.key │ │ ├── root.crt │ │ ├── server.crt │ │ └── server.key │ │ ├── conn.go │ │ ├── conn_go18.go │ │ ├── conn_test.go │ │ ├── copy.go │ │ ├── copy_test.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── encode_test.go │ │ ├── error.go │ │ ├── go18_test.go │ │ ├── hstore │ │ ├── hstore.go │ │ └── hstore_test.go │ │ ├── issues_test.go │ │ ├── listen_example │ │ └── doc.go │ │ ├── notify.go │ │ ├── notify_test.go │ │ ├── oid │ │ ├── doc.go │ │ ├── gen.go │ │ └── types.go │ │ ├── ssl.go │ │ ├── ssl_go1.7.go │ │ ├── ssl_permissions.go │ │ ├── ssl_renegotiation.go │ │ ├── ssl_test.go │ │ ├── ssl_windows.go │ │ ├── url.go │ │ ├── url_test.go │ │ ├── user_posix.go │ │ ├── user_windows.go │ │ ├── uuid.go │ │ └── uuid_test.go ├── oklog │ └── ulid │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── AUTHORS.md │ │ ├── CHANGELOG.md │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── ulid.go │ │ └── ulid_test.go ├── pkg │ └── errors │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── appveyor.yml │ │ ├── bench_test.go │ │ ├── errors.go │ │ ├── errors_test.go │ │ ├── example_test.go │ │ ├── format_test.go │ │ ├── stack.go │ │ └── stack_test.go └── satori │ └── go.uuid │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── benchmarks_test.go │ ├── uuid.go │ └── uuid_test.go └── gopkg.in └── src-d └── go-kallax.v1 ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── batcher.go ├── batcher_test.go ├── benchmarks ├── bench_test.go ├── kallax.go ├── models_gorm.go └── models_kallax.go ├── common_test.go ├── doc.go ├── events.go ├── events_test.go ├── generator ├── cli │ └── kallax │ │ └── cmd.go ├── common_test.go ├── generator.go ├── processor.go ├── processor_test.go ├── template.go ├── template_test.go ├── templates │ ├── base.tgo │ ├── model.tgo │ ├── query.tgo │ ├── resultset.tgo │ └── schema.tgo ├── types.go └── types_test.go ├── kallax.svg ├── model.go ├── model_test.go ├── operators.go ├── operators_test.go ├── query.go ├── query_test.go ├── resultset.go ├── schema.go ├── schema_test.go ├── store.go ├── store_test.go ├── tests ├── common.go ├── common_test.go ├── connection_test.go ├── events.go ├── events_test.go ├── fixtures │ └── fixtures.go ├── json.go ├── json_test.go ├── kallax.go ├── query.go ├── query_test.go ├── relationships.go ├── relationships_test.go ├── resultset.go ├── resultset_test.go ├── schema.go ├── schema_test.go ├── store.go └── store_test.go ├── timestamps.go ├── timestamps_test.go └── types ├── slices.go ├── slices_test.go ├── types.go └── types_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | .envrc 2 | -------------------------------------------------------------------------------- /Gopkg.lock: -------------------------------------------------------------------------------- 1 | memo = "abcfc51fba3afe887fa1ee42b4ebdecf6202adeea1b0389f5c009cefa1d174a0" 2 | 3 | [[projects]] 4 | branch = "v1" 5 | name = "github.com/Masterminds/squirrel" 6 | packages = ["."] 7 | revision = "20f192218cf52a73397fa2df45bdda720f3e47c8" 8 | 9 | [[projects]] 10 | branch = "master" 11 | name = "github.com/bitly/go-simplejson" 12 | packages = ["."] 13 | revision = "da1a8928f709389522c8023062a3739f3b4af419" 14 | 15 | [[projects]] 16 | branch = "master" 17 | name = "github.com/garyburd/redigo" 18 | packages = ["internal","redis"] 19 | revision = "0d253a66e6e1349f4581d6d2b300ee434ee2da9f" 20 | 21 | [[projects]] 22 | branch = "master" 23 | name = "github.com/go-redis/redis" 24 | packages = [".","internal","internal/consistenthash","internal/hashtag","internal/pool","internal/proto"] 25 | revision = "d0dd05b65910c3c658378f2ddd17cc96df56b17d" 26 | 27 | [[projects]] 28 | branch = "master" 29 | name = "github.com/jrallison/go-workers" 30 | packages = ["."] 31 | revision = "d60d79dbbfbb83f849d2430013a59152845fa598" 32 | 33 | [[projects]] 34 | branch = "master" 35 | name = "github.com/lann/builder" 36 | packages = ["."] 37 | revision = "f22ce00fd9394014049dad11c244859432bd6820" 38 | 39 | [[projects]] 40 | branch = "master" 41 | name = "github.com/lann/ps" 42 | packages = ["."] 43 | revision = "62de8c46ede02a7675c4c79c84883eb164cb71e3" 44 | 45 | [[projects]] 46 | branch = "master" 47 | name = "github.com/lib/pq" 48 | packages = [".","oid"] 49 | revision = "2704adc878c21e1329f46f6e56a1c387d788ff94" 50 | 51 | [[projects]] 52 | branch = "master" 53 | name = "github.com/oklog/ulid" 54 | packages = ["."] 55 | revision = "66bb6560562feca7045b23db1ae85b01260f87c5" 56 | 57 | [[projects]] 58 | branch = "master" 59 | name = "github.com/pkg/errors" 60 | packages = ["."] 61 | revision = "ff09b135c25aae272398c51a07235b90a75aa4f0" 62 | 63 | [[projects]] 64 | branch = "master" 65 | name = "github.com/satori/go.uuid" 66 | packages = ["."] 67 | revision = "5bf94b69c6b68ee1b541973bb8e1144db23a194b" 68 | 69 | [[projects]] 70 | name = "gopkg.in/src-d/go-kallax.v1" 71 | packages = [".","types"] 72 | revision = "26fcb7f94ac98eb6520e2bfe1f6a179781a07e60" 73 | version = "v1.1.1" 74 | -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | 2 | [[dependencies]] 3 | branch = "master" 4 | name = "github.com/go-redis/redis" 5 | 6 | [[dependencies]] 7 | branch = "master" 8 | name = "github.com/jrallison/go-workers" 9 | 10 | [[dependencies]] 11 | branch = "master" 12 | name = "github.com/pkg/errors" 13 | 14 | [[dependencies]] 15 | name = "gopkg.in/src-d/go-kallax.v1" 16 | version = "1.1.1" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mastogon 2 | ======== 3 | 4 | Pre-alpha status. 5 | 6 | Currently just a proof of concept of partially implemented one sidekiq job of [tootsuite/mastodon: A GNU Social-compatible microblogging server](https://github.com/tootsuite/mastodon/). 7 | 8 | 9 | ## License 10 | 11 | AGPL-3.0. 12 | 13 | It's because this is a port of [tootsuite/mastodon: A GNU Social-compatible microblogging server](https://github.com/tootsuite/mastodon/) whose license is AGPL-3.0. 14 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/.gitignore: -------------------------------------------------------------------------------- 1 | squirrel.test -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.2 6 | - 1.3 7 | - 1.4 8 | - 1.5 9 | - tip 10 | 11 | # Setting sudo access to false will let Travis CI use containers rather than 12 | # VMs to run the tests. For more details see: 13 | # - http://docs.travis-ci.com/user/workers/container-based-infrastructure/ 14 | # - http://docs.travis-ci.com/user/workers/standard-infrastructure/ 15 | sudo: false 16 | 17 | install: 18 | - go get 19 | - go get github.com/stretchr/testify/assert 20 | 21 | notifications: 22 | irc: "irc.freenode.net#masterminds" 23 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Squirrel 2 | The Masterminds 3 | Copyright (C) 2014-2015, Lann Martin 4 | Copyright (C) 2015-2016, Google 5 | Copyright (C) 2015, Matt Farina and Matt Butcher 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/delete_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestDeleteBuilderToSql(t *testing.T) { 10 | b := Delete(""). 11 | Prefix("WITH prefix AS ?", 0). 12 | From("a"). 13 | Where("b = ?", 1). 14 | OrderBy("c"). 15 | Limit(2). 16 | Offset(3). 17 | Suffix("RETURNING ?", 4) 18 | 19 | sql, args, err := b.ToSql() 20 | assert.NoError(t, err) 21 | 22 | expectedSql := 23 | "WITH prefix AS ? " + 24 | "DELETE FROM a WHERE b = ? ORDER BY c LIMIT 2 OFFSET 3 " + 25 | "RETURNING ?" 26 | assert.Equal(t, expectedSql, sql) 27 | 28 | expectedArgs := []interface{}{0, 1, 4} 29 | assert.Equal(t, expectedArgs, args) 30 | } 31 | 32 | func TestDeleteBuilderToSqlErr(t *testing.T) { 33 | _, _, err := Delete("").ToSql() 34 | assert.Error(t, err) 35 | } 36 | 37 | func TestDeleteBuilderPlaceholders(t *testing.T) { 38 | b := Delete("test").Where("x = ? AND y = ?", 1, 2) 39 | 40 | sql, _, _ := b.PlaceholderFormat(Question).ToSql() 41 | assert.Equal(t, "DELETE FROM test WHERE x = ? AND y = ?", sql) 42 | 43 | sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() 44 | assert.Equal(t, "DELETE FROM test WHERE x = $1 AND y = $2", sql) 45 | } 46 | 47 | func TestDeleteBuilderRunners(t *testing.T) { 48 | db := &DBStub{} 49 | b := Delete("test").Where("x = ?", 1).RunWith(db) 50 | 51 | expectedSql := "DELETE FROM test WHERE x = ?" 52 | 53 | b.Exec() 54 | assert.Equal(t, expectedSql, db.LastExecSql) 55 | } 56 | 57 | func TestDeleteBuilderNoRunner(t *testing.T) { 58 | b := Delete("test") 59 | 60 | _, err := b.Exec() 61 | assert.Equal(t, RunnerNotSet, err) 62 | } 63 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/insert_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestInsertBuilderToSql(t *testing.T) { 10 | b := Insert(""). 11 | Prefix("WITH prefix AS ?", 0). 12 | Into("a"). 13 | Options("DELAYED", "IGNORE"). 14 | Columns("b", "c"). 15 | Values(1, 2). 16 | Values(3, Expr("? + 1", 4)). 17 | Suffix("RETURNING ?", 5) 18 | 19 | sql, args, err := b.ToSql() 20 | assert.NoError(t, err) 21 | 22 | expectedSql := 23 | "WITH prefix AS ? " + 24 | "INSERT DELAYED IGNORE INTO a (b,c) VALUES (?,?),(?,? + 1) " + 25 | "RETURNING ?" 26 | assert.Equal(t, expectedSql, sql) 27 | 28 | expectedArgs := []interface{}{0, 1, 2, 3, 4, 5} 29 | assert.Equal(t, expectedArgs, args) 30 | } 31 | 32 | func TestInsertBuilderToSqlErr(t *testing.T) { 33 | _, _, err := Insert("").Values(1).ToSql() 34 | assert.Error(t, err) 35 | 36 | _, _, err = Insert("x").ToSql() 37 | assert.Error(t, err) 38 | } 39 | 40 | func TestInsertBuilderPlaceholders(t *testing.T) { 41 | b := Insert("test").Values(1, 2) 42 | 43 | sql, _, _ := b.PlaceholderFormat(Question).ToSql() 44 | assert.Equal(t, "INSERT INTO test VALUES (?,?)", sql) 45 | 46 | sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() 47 | assert.Equal(t, "INSERT INTO test VALUES ($1,$2)", sql) 48 | } 49 | 50 | func TestInsertBuilderRunners(t *testing.T) { 51 | db := &DBStub{} 52 | b := Insert("test").Values(1).RunWith(db) 53 | 54 | expectedSql := "INSERT INTO test VALUES (?)" 55 | 56 | b.Exec() 57 | assert.Equal(t, expectedSql, db.LastExecSql) 58 | } 59 | 60 | func TestInsertBuilderNoRunner(t *testing.T) { 61 | b := Insert("test").Values(1) 62 | 63 | _, err := b.Exec() 64 | assert.Equal(t, RunnerNotSet, err) 65 | } 66 | 67 | func TestInsertBuilderSetMap(t *testing.T) { 68 | b := Insert("table").SetMap(Eq{"field1": 1}) 69 | 70 | sql, args, err := b.ToSql() 71 | assert.NoError(t, err) 72 | 73 | expectedSql := "INSERT INTO table (field1) VALUES (?)" 74 | assert.Equal(t, expectedSql, sql) 75 | 76 | expectedArgs := []interface{}{1} 77 | assert.Equal(t, expectedArgs, args) 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/part.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | type part struct { 9 | pred interface{} 10 | args []interface{} 11 | } 12 | 13 | func newPart(pred interface{}, args ...interface{}) Sqlizer { 14 | return &part{pred, args} 15 | } 16 | 17 | func (p part) ToSql() (sql string, args []interface{}, err error) { 18 | switch pred := p.pred.(type) { 19 | case nil: 20 | // no-op 21 | case Sqlizer: 22 | sql, args, err = pred.ToSql() 23 | case string: 24 | sql = pred 25 | args = p.args 26 | default: 27 | err = fmt.Errorf("expected string or Sqlizer, not %T", pred) 28 | } 29 | return 30 | } 31 | 32 | func appendToSql(parts []Sqlizer, w io.Writer, sep string, args []interface{}) ([]interface{}, error) { 33 | for i, p := range parts { 34 | partSql, partArgs, err := p.ToSql() 35 | if err != nil { 36 | return nil, err 37 | } else if len(partSql) == 0 { 38 | continue 39 | } 40 | 41 | if i > 0 { 42 | _, err := io.WriteString(w, sep) 43 | if err != nil { 44 | return nil, err 45 | } 46 | } 47 | 48 | _, err = io.WriteString(w, partSql) 49 | if err != nil { 50 | return nil, err 51 | } 52 | args = append(args, partArgs...) 53 | } 54 | return args, nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/placeholder.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | // PlaceholderFormat is the interface that wraps the ReplacePlaceholders method. 10 | // 11 | // ReplacePlaceholders takes a SQL statement and replaces each question mark 12 | // placeholder with a (possibly different) SQL placeholder. 13 | type PlaceholderFormat interface { 14 | ReplacePlaceholders(sql string) (string, error) 15 | } 16 | 17 | var ( 18 | // Question is a PlaceholderFormat instance that leaves placeholders as 19 | // question marks. 20 | Question = questionFormat{} 21 | 22 | // Dollar is a PlaceholderFormat instance that replaces placeholders with 23 | // dollar-prefixed positional placeholders (e.g. $1, $2, $3). 24 | Dollar = dollarFormat{} 25 | ) 26 | 27 | type questionFormat struct{} 28 | 29 | func (_ questionFormat) ReplacePlaceholders(sql string) (string, error) { 30 | return sql, nil 31 | } 32 | 33 | type dollarFormat struct{} 34 | 35 | func (_ dollarFormat) ReplacePlaceholders(sql string) (string, error) { 36 | buf := &bytes.Buffer{} 37 | i := 0 38 | for { 39 | p := strings.Index(sql, "?") 40 | if p == -1 { 41 | break 42 | } 43 | 44 | if len(sql[p:]) > 1 && sql[p:p+2] == "??" { // escape ?? => ? 45 | buf.WriteString(sql[:p]) 46 | buf.WriteString("?") 47 | if len(sql[p:]) == 1 { 48 | break 49 | } 50 | sql = sql[p+2:] 51 | } else { 52 | i++ 53 | buf.WriteString(sql[:p]) 54 | fmt.Fprintf(buf, "$%d", i) 55 | sql = sql[p+1:] 56 | } 57 | } 58 | 59 | buf.WriteString(sql) 60 | return buf.String(), nil 61 | } 62 | 63 | // Placeholders returns a string with count ? placeholders joined with commas. 64 | func Placeholders(count int) string { 65 | if count < 1 { 66 | return "" 67 | } 68 | 69 | return strings.Repeat(",?", count)[1:] 70 | } 71 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/placeholder_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestQuestion(t *testing.T) { 11 | sql := "x = ? AND y = ?" 12 | s, _ := Question.ReplacePlaceholders(sql) 13 | assert.Equal(t, sql, s) 14 | } 15 | 16 | func TestDollar(t *testing.T) { 17 | sql := "x = ? AND y = ?" 18 | s, _ := Dollar.ReplacePlaceholders(sql) 19 | assert.Equal(t, "x = $1 AND y = $2", s) 20 | } 21 | 22 | func TestPlaceholders(t *testing.T) { 23 | assert.Equal(t, Placeholders(2), "?,?") 24 | } 25 | 26 | func TestEscape(t *testing.T) { 27 | sql := "SELECT uuid, \"data\" #> '{tags}' AS tags FROM nodes WHERE \"data\" -> 'tags' ??| array['?'] AND enabled = ?" 28 | s, _ := Dollar.ReplacePlaceholders(sql) 29 | assert.Equal(t, "SELECT uuid, \"data\" #> '{tags}' AS tags FROM nodes WHERE \"data\" -> 'tags' ?| array['$1'] AND enabled = $2", s) 30 | } 31 | 32 | func BenchmarkPlaceholdersArray(b *testing.B) { 33 | var count = b.N 34 | placeholders := make([]string, count) 35 | for i := 0; i < count; i++ { 36 | placeholders[i] = "?" 37 | } 38 | var _ = strings.Join(placeholders, ",") 39 | } 40 | 41 | func BenchmarkPlaceholdersStrings(b *testing.B) { 42 | Placeholders(b.N) 43 | } 44 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/row.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | // RowScanner is the interface that wraps the Scan method. 4 | // 5 | // Scan behaves like database/sql.Row.Scan. 6 | type RowScanner interface { 7 | Scan(...interface{}) error 8 | } 9 | 10 | // Row wraps database/sql.Row to let squirrel return new errors on Scan. 11 | type Row struct { 12 | RowScanner 13 | err error 14 | } 15 | 16 | // Scan returns Row.err or calls RowScanner.Scan. 17 | func (r *Row) Scan(dest ...interface{}) error { 18 | if r.err != nil { 19 | return r.err 20 | } 21 | return r.RowScanner.Scan(dest...) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/row_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | type RowStub struct { 11 | Scanned bool 12 | } 13 | 14 | func (r *RowStub) Scan(_ ...interface{}) error { 15 | r.Scanned = true 16 | return nil 17 | } 18 | 19 | func TestRowScan(t *testing.T) { 20 | stub := &RowStub{} 21 | row := &Row{RowScanner: stub} 22 | err := row.Scan() 23 | assert.True(t, stub.Scanned, "row was not scanned") 24 | assert.NoError(t, err) 25 | } 26 | 27 | func TestRowScanErr(t *testing.T) { 28 | stub := &RowStub{} 29 | rowErr := fmt.Errorf("scan err") 30 | row := &Row{RowScanner: stub, err: rowErr} 31 | err := row.Scan() 32 | assert.False(t, stub.Scanned, "row was scanned") 33 | assert.Equal(t, rowErr, err) 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/statement_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "database/sql" 5 | "testing" 6 | 7 | "github.com/lann/builder" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestStatementBuilder(t *testing.T) { 12 | db := &DBStub{} 13 | sb := StatementBuilder.RunWith(db) 14 | 15 | sb.Select("test").Exec() 16 | assert.Equal(t, "SELECT test", db.LastExecSql) 17 | } 18 | 19 | func TestStatementBuilderPlaceholderFormat(t *testing.T) { 20 | db := &DBStub{} 21 | sb := StatementBuilder.RunWith(db).PlaceholderFormat(Dollar) 22 | 23 | sb.Select("test").Where("x = ?").Exec() 24 | assert.Equal(t, "SELECT test WHERE x = $1", db.LastExecSql) 25 | } 26 | 27 | func TestRunWithDB(t *testing.T) { 28 | db := &sql.DB{} 29 | assert.NotPanics(t, func() { 30 | builder.GetStruct(Select().RunWith(db)) 31 | builder.GetStruct(Insert("t").RunWith(db)) 32 | builder.GetStruct(Update("t").RunWith(db)) 33 | builder.GetStruct(Delete("t").RunWith(db)) 34 | }, "RunWith(*sql.DB) should not panic") 35 | 36 | } 37 | 38 | func TestRunWithTx(t *testing.T) { 39 | tx := &sql.Tx{} 40 | assert.NotPanics(t, func() { 41 | builder.GetStruct(Select().RunWith(tx)) 42 | builder.GetStruct(Insert("t").RunWith(tx)) 43 | builder.GetStruct(Update("t").RunWith(tx)) 44 | builder.GetStruct(Delete("t").RunWith(tx)) 45 | }, "RunWith(*sql.Tx) should not panic") 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/stmtcacher.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "database/sql" 5 | "sync" 6 | ) 7 | 8 | // Prepareer is the interface that wraps the Prepare method. 9 | // 10 | // Prepare executes the given query as implemented by database/sql.Prepare. 11 | type Preparer interface { 12 | Prepare(query string) (*sql.Stmt, error) 13 | } 14 | 15 | // DBProxy groups the Execer, Queryer, QueryRower, and Preparer interfaces. 16 | type DBProxy interface { 17 | Execer 18 | Queryer 19 | QueryRower 20 | Preparer 21 | } 22 | 23 | type stmtCacher struct { 24 | prep Preparer 25 | cache map[string]*sql.Stmt 26 | mu sync.Mutex 27 | } 28 | 29 | // NewStmtCacher returns a DBProxy wrapping prep that caches Prepared Stmts. 30 | // 31 | // Stmts are cached based on the string value of their queries. 32 | func NewStmtCacher(prep Preparer) DBProxy { 33 | return &stmtCacher{prep: prep, cache: make(map[string]*sql.Stmt)} 34 | } 35 | 36 | func (sc *stmtCacher) Prepare(query string) (*sql.Stmt, error) { 37 | sc.mu.Lock() 38 | defer sc.mu.Unlock() 39 | stmt, ok := sc.cache[query] 40 | if ok { 41 | return stmt, nil 42 | } 43 | stmt, err := sc.prep.Prepare(query) 44 | if err == nil { 45 | sc.cache[query] = stmt 46 | } 47 | return stmt, err 48 | } 49 | 50 | func (sc *stmtCacher) Exec(query string, args ...interface{}) (res sql.Result, err error) { 51 | stmt, err := sc.Prepare(query) 52 | if err != nil { 53 | return 54 | } 55 | return stmt.Exec(args...) 56 | } 57 | 58 | func (sc *stmtCacher) Query(query string, args ...interface{}) (rows *sql.Rows, err error) { 59 | stmt, err := sc.Prepare(query) 60 | if err != nil { 61 | return 62 | } 63 | return stmt.Query(args...) 64 | } 65 | 66 | func (sc *stmtCacher) QueryRow(query string, args ...interface{}) RowScanner { 67 | stmt, err := sc.Prepare(query) 68 | if err != nil { 69 | return &Row{err: err} 70 | } 71 | return stmt.QueryRow(args...) 72 | } 73 | 74 | type DBProxyBeginner interface { 75 | DBProxy 76 | Begin() (*sql.Tx, error) 77 | } 78 | 79 | type stmtCacheProxy struct { 80 | DBProxy 81 | db *sql.DB 82 | } 83 | 84 | func NewStmtCacheProxy(db *sql.DB) DBProxyBeginner { 85 | return &stmtCacheProxy{DBProxy: NewStmtCacher(db), db: db} 86 | } 87 | 88 | func (sp *stmtCacheProxy) Begin() (*sql.Tx, error) { 89 | return sp.db.Begin() 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/stmtcacher_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestStmtCacherPrepare(t *testing.T) { 10 | db := &DBStub{} 11 | sc := NewStmtCacher(db) 12 | query := "SELECT 1" 13 | 14 | sc.Prepare(query) 15 | assert.Equal(t, query, db.LastPrepareSql) 16 | 17 | sc.Prepare(query) 18 | assert.Equal(t, 1, db.PrepareCount, "expected 1 Prepare, got %d", db.PrepareCount) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/update_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestUpdateBuilderToSql(t *testing.T) { 10 | b := Update(""). 11 | Prefix("WITH prefix AS ?", 0). 12 | Table("a"). 13 | Set("b", Expr("? + 1", 1)). 14 | SetMap(Eq{"c": 2}). 15 | Where("d = ?", 3). 16 | OrderBy("e"). 17 | Limit(4). 18 | Offset(5). 19 | Suffix("RETURNING ?", 6) 20 | 21 | sql, args, err := b.ToSql() 22 | assert.NoError(t, err) 23 | 24 | expectedSql := 25 | "WITH prefix AS ? " + 26 | "UPDATE a SET b = ? + 1, c = ? WHERE d = ? " + 27 | "ORDER BY e LIMIT 4 OFFSET 5 " + 28 | "RETURNING ?" 29 | assert.Equal(t, expectedSql, sql) 30 | 31 | expectedArgs := []interface{}{0, 1, 2, 3, 6} 32 | assert.Equal(t, expectedArgs, args) 33 | } 34 | 35 | func TestUpdateBuilderToSqlErr(t *testing.T) { 36 | _, _, err := Update("").Set("x", 1).ToSql() 37 | assert.Error(t, err) 38 | 39 | _, _, err = Update("x").ToSql() 40 | assert.Error(t, err) 41 | } 42 | 43 | func TestUpdateBuilderPlaceholders(t *testing.T) { 44 | b := Update("test").SetMap(Eq{"x": 1, "y": 2}) 45 | 46 | sql, _, _ := b.PlaceholderFormat(Question).ToSql() 47 | assert.Equal(t, "UPDATE test SET x = ?, y = ?", sql) 48 | 49 | sql, _, _ = b.PlaceholderFormat(Dollar).ToSql() 50 | assert.Equal(t, "UPDATE test SET x = $1, y = $2", sql) 51 | } 52 | 53 | func TestUpdateBuilderRunners(t *testing.T) { 54 | db := &DBStub{} 55 | b := Update("test").Set("x", 1).RunWith(db) 56 | 57 | expectedSql := "UPDATE test SET x = ?" 58 | 59 | b.Exec() 60 | assert.Equal(t, expectedSql, db.LastExecSql) 61 | } 62 | 63 | func TestUpdateBuilderNoRunner(t *testing.T) { 64 | b := Update("test").Set("x", 1) 65 | 66 | _, err := b.Exec() 67 | assert.Equal(t, RunnerNotSet, err) 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/where.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type wherePart part 8 | 9 | func newWherePart(pred interface{}, args ...interface{}) Sqlizer { 10 | return &wherePart{pred: pred, args: args} 11 | } 12 | 13 | func (p wherePart) ToSql() (sql string, args []interface{}, err error) { 14 | switch pred := p.pred.(type) { 15 | case nil: 16 | // no-op 17 | case Sqlizer: 18 | return pred.ToSql() 19 | case map[string]interface{}: 20 | return Eq(pred).ToSql() 21 | case string: 22 | sql = pred 23 | args = p.args 24 | default: 25 | err = fmt.Errorf("expected string-keyed map or string, not %T", pred) 26 | } 27 | return 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/Masterminds/squirrel/where_test.go: -------------------------------------------------------------------------------- 1 | package squirrel 2 | 3 | import ( 4 | "testing" 5 | 6 | "bytes" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestWherePartsAppendToSql(t *testing.T) { 12 | parts := []Sqlizer{ 13 | newWherePart("x = ?", 1), 14 | newWherePart(nil), 15 | newWherePart(Eq{"y": 2}), 16 | } 17 | sql := &bytes.Buffer{} 18 | args, _ := appendToSql(parts, sql, " AND ", []interface{}{}) 19 | assert.Equal(t, "x = ? AND y = ?", sql.String()) 20 | assert.Equal(t, []interface{}{1, 2}, args) 21 | } 22 | 23 | func TestWherePartsAppendToSqlErr(t *testing.T) { 24 | parts := []Sqlizer{newWherePart(1)} 25 | _, err := appendToSql(parts, &bytes.Buffer{}, "", []interface{}{}) 26 | assert.Error(t, err) 27 | } 28 | 29 | func TestWherePartNil(t *testing.T) { 30 | sql, _, _ := newWherePart(nil).ToSql() 31 | assert.Equal(t, "", sql) 32 | } 33 | 34 | func TestWherePartErr(t *testing.T) { 35 | _, _, err := newWherePart(1).ToSql() 36 | assert.Error(t, err) 37 | } 38 | 39 | func TestWherePartString(t *testing.T) { 40 | sql, args, _ := newWherePart("x = ?", 1).ToSql() 41 | assert.Equal(t, "x = ?", sql) 42 | assert.Equal(t, []interface{}{1}, args) 43 | } 44 | 45 | func TestWherePartMap(t *testing.T) { 46 | test := func(pred interface{}) { 47 | sql, _, _ := newWherePart(pred).ToSql() 48 | expect := []string{"x = ? AND y = ?", "y = ? AND x = ?"} 49 | if sql != expect[0] && sql != expect[1] { 50 | t.Errorf("expected one of %#v, got %#v", expect, sql) 51 | } 52 | } 53 | m := map[string]interface{}{"x": 1, "y": 2} 54 | test(m) 55 | test(Eq(m)) 56 | } 57 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: go 4 | 5 | go: 6 | - 1.2.x 7 | - 1.3.x 8 | - 1.4.x 9 | - 1.6.x 10 | - 1.7.x 11 | - tip 12 | 13 | os: 14 | - linux 15 | 16 | matrix: 17 | fast_finish: true 18 | allow_failures: 19 | - go: tip 20 | 21 | before_install: 22 | - go get -v github.com/bmizerany/assert 23 | 24 | script: 25 | - go test -v ./... 26 | 27 | notifications: 28 | email: false 29 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the "Software"), to deal 3 | in the Software without restriction, including without limitation the rights 4 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/README.md: -------------------------------------------------------------------------------- 1 | ### go-simplejson 2 | 3 | a Go package to interact with arbitrary JSON 4 | 5 | [![Build Status](https://secure.travis-ci.org/bitly/go-simplejson.png)](http://travis-ci.org/bitly/go-simplejson) 6 | 7 | ### Importing 8 | 9 | import github.com/bitly/go-simplejson 10 | 11 | ### Documentation 12 | 13 | Visit the docs on [gopkgdoc](http://godoc.org/github.com/bitly/go-simplejson) 14 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/simplejson_go10.go: -------------------------------------------------------------------------------- 1 | // +build !go1.1 2 | 3 | package simplejson 4 | 5 | import ( 6 | "encoding/json" 7 | "errors" 8 | "io" 9 | "reflect" 10 | ) 11 | 12 | // NewFromReader returns a *Json by decoding from an io.Reader 13 | func NewFromReader(r io.Reader) (*Json, error) { 14 | j := new(Json) 15 | dec := json.NewDecoder(r) 16 | err := dec.Decode(&j.data) 17 | return j, err 18 | } 19 | 20 | // Implements the json.Unmarshaler interface. 21 | func (j *Json) UnmarshalJSON(p []byte) error { 22 | return json.Unmarshal(p, &j.data) 23 | } 24 | 25 | // Float64 coerces into a float64 26 | func (j *Json) Float64() (float64, error) { 27 | switch j.data.(type) { 28 | case float32, float64: 29 | return reflect.ValueOf(j.data).Float(), nil 30 | case int, int8, int16, int32, int64: 31 | return float64(reflect.ValueOf(j.data).Int()), nil 32 | case uint, uint8, uint16, uint32, uint64: 33 | return float64(reflect.ValueOf(j.data).Uint()), nil 34 | } 35 | return 0, errors.New("invalid value type") 36 | } 37 | 38 | // Int coerces into an int 39 | func (j *Json) Int() (int, error) { 40 | switch j.data.(type) { 41 | case float32, float64: 42 | return int(reflect.ValueOf(j.data).Float()), nil 43 | case int, int8, int16, int32, int64: 44 | return int(reflect.ValueOf(j.data).Int()), nil 45 | case uint, uint8, uint16, uint32, uint64: 46 | return int(reflect.ValueOf(j.data).Uint()), nil 47 | } 48 | return 0, errors.New("invalid value type") 49 | } 50 | 51 | // Int64 coerces into an int64 52 | func (j *Json) Int64() (int64, error) { 53 | switch j.data.(type) { 54 | case float32, float64: 55 | return int64(reflect.ValueOf(j.data).Float()), nil 56 | case int, int8, int16, int32, int64: 57 | return reflect.ValueOf(j.data).Int(), nil 58 | case uint, uint8, uint16, uint32, uint64: 59 | return int64(reflect.ValueOf(j.data).Uint()), nil 60 | } 61 | return 0, errors.New("invalid value type") 62 | } 63 | 64 | // Uint64 coerces into an uint64 65 | func (j *Json) Uint64() (uint64, error) { 66 | switch j.data.(type) { 67 | case float32, float64: 68 | return uint64(reflect.ValueOf(j.data).Float()), nil 69 | case int, int8, int16, int32, int64: 70 | return uint64(reflect.ValueOf(j.data).Int()), nil 71 | case uint, uint8, uint16, uint32, uint64: 72 | return reflect.ValueOf(j.data).Uint(), nil 73 | } 74 | return 0, errors.New("invalid value type") 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/simplejson_go10_test.go: -------------------------------------------------------------------------------- 1 | // +build !go1.1 2 | 3 | package simplejson 4 | 5 | import ( 6 | "bytes" 7 | "github.com/bmizerany/assert" 8 | "strconv" 9 | "testing" 10 | ) 11 | 12 | func TestNewFromReader(t *testing.T) { 13 | buf := bytes.NewBuffer([]byte(`{ 14 | "test": { 15 | "array": [1, "2", 3], 16 | "arraywithsubs": [ 17 | {"subkeyone": 1}, 18 | {"subkeytwo": 2, "subkeythree": 3} 19 | ], 20 | "bignum": 8000000000 21 | } 22 | }`)) 23 | js, err := NewFromReader(buf) 24 | 25 | //Standard Test Case 26 | assert.NotEqual(t, nil, js) 27 | assert.Equal(t, nil, err) 28 | 29 | arr, _ := js.Get("test").Get("array").Array() 30 | assert.NotEqual(t, nil, arr) 31 | for i, v := range arr { 32 | var iv int 33 | switch v.(type) { 34 | case float64: 35 | iv = int(v.(float64)) 36 | case string: 37 | iv, _ = strconv.Atoi(v.(string)) 38 | } 39 | assert.Equal(t, i+1, iv) 40 | } 41 | 42 | ma := js.Get("test").Get("array").MustArray() 43 | assert.Equal(t, ma, []interface{}{float64(1), "2", float64(3)}) 44 | 45 | mm := js.Get("test").Get("arraywithsubs").GetIndex(0).MustMap() 46 | assert.Equal(t, mm, map[string]interface{}{"subkeyone": float64(1)}) 47 | 48 | assert.Equal(t, js.Get("test").Get("bignum").MustInt64(), int64(8000000000)) 49 | } 50 | 51 | func TestSimplejsonGo10(t *testing.T) { 52 | js, err := NewJson([]byte(`{ 53 | "test": { 54 | "array": [1, "2", 3], 55 | "arraywithsubs": [ 56 | {"subkeyone": 1}, 57 | {"subkeytwo": 2, "subkeythree": 3} 58 | ], 59 | "bignum": 8000000000 60 | } 61 | }`)) 62 | 63 | assert.NotEqual(t, nil, js) 64 | assert.Equal(t, nil, err) 65 | 66 | arr, _ := js.Get("test").Get("array").Array() 67 | assert.NotEqual(t, nil, arr) 68 | for i, v := range arr { 69 | var iv int 70 | switch v.(type) { 71 | case float64: 72 | iv = int(v.(float64)) 73 | case string: 74 | iv, _ = strconv.Atoi(v.(string)) 75 | } 76 | assert.Equal(t, i+1, iv) 77 | } 78 | 79 | ma := js.Get("test").Get("array").MustArray() 80 | assert.Equal(t, ma, []interface{}{float64(1), "2", float64(3)}) 81 | 82 | mm := js.Get("test").Get("arraywithsubs").GetIndex(0).MustMap() 83 | assert.Equal(t, mm, map[string]interface{}{"subkeyone": float64(1)}) 84 | 85 | assert.Equal(t, js.Get("test").Get("bignum").MustInt64(), int64(8000000000)) 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/bitly/go-simplejson/simplejson_go11.go: -------------------------------------------------------------------------------- 1 | // +build go1.1 2 | 3 | package simplejson 4 | 5 | import ( 6 | "bytes" 7 | "encoding/json" 8 | "errors" 9 | "io" 10 | "reflect" 11 | "strconv" 12 | ) 13 | 14 | // Implements the json.Unmarshaler interface. 15 | func (j *Json) UnmarshalJSON(p []byte) error { 16 | dec := json.NewDecoder(bytes.NewBuffer(p)) 17 | dec.UseNumber() 18 | return dec.Decode(&j.data) 19 | } 20 | 21 | // NewFromReader returns a *Json by decoding from an io.Reader 22 | func NewFromReader(r io.Reader) (*Json, error) { 23 | j := new(Json) 24 | dec := json.NewDecoder(r) 25 | dec.UseNumber() 26 | err := dec.Decode(&j.data) 27 | return j, err 28 | } 29 | 30 | // Float64 coerces into a float64 31 | func (j *Json) Float64() (float64, error) { 32 | switch j.data.(type) { 33 | case json.Number: 34 | return j.data.(json.Number).Float64() 35 | case float32, float64: 36 | return reflect.ValueOf(j.data).Float(), nil 37 | case int, int8, int16, int32, int64: 38 | return float64(reflect.ValueOf(j.data).Int()), nil 39 | case uint, uint8, uint16, uint32, uint64: 40 | return float64(reflect.ValueOf(j.data).Uint()), nil 41 | } 42 | return 0, errors.New("invalid value type") 43 | } 44 | 45 | // Int coerces into an int 46 | func (j *Json) Int() (int, error) { 47 | switch j.data.(type) { 48 | case json.Number: 49 | i, err := j.data.(json.Number).Int64() 50 | return int(i), err 51 | case float32, float64: 52 | return int(reflect.ValueOf(j.data).Float()), nil 53 | case int, int8, int16, int32, int64: 54 | return int(reflect.ValueOf(j.data).Int()), nil 55 | case uint, uint8, uint16, uint32, uint64: 56 | return int(reflect.ValueOf(j.data).Uint()), nil 57 | } 58 | return 0, errors.New("invalid value type") 59 | } 60 | 61 | // Int64 coerces into an int64 62 | func (j *Json) Int64() (int64, error) { 63 | switch j.data.(type) { 64 | case json.Number: 65 | return j.data.(json.Number).Int64() 66 | case float32, float64: 67 | return int64(reflect.ValueOf(j.data).Float()), nil 68 | case int, int8, int16, int32, int64: 69 | return reflect.ValueOf(j.data).Int(), nil 70 | case uint, uint8, uint16, uint32, uint64: 71 | return int64(reflect.ValueOf(j.data).Uint()), nil 72 | } 73 | return 0, errors.New("invalid value type") 74 | } 75 | 76 | // Uint64 coerces into an uint64 77 | func (j *Json) Uint64() (uint64, error) { 78 | switch j.data.(type) { 79 | case json.Number: 80 | return strconv.ParseUint(j.data.(json.Number).String(), 10, 64) 81 | case float32, float64: 82 | return uint64(reflect.ValueOf(j.data).Float()), nil 83 | case int, int8, int16, int32, int64: 84 | return uint64(reflect.ValueOf(j.data).Int()), nil 85 | case uint, uint8, uint16, uint32, uint64: 86 | return reflect.ValueOf(j.data).Uint(), nil 87 | } 88 | return 0, errors.New("invalid value type") 89 | } 90 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Ask questions at 2 | [StackOverflow](https://stackoverflow.com/questions/ask?tags=go+redis). 3 | 4 | [Open an issue](https://github.com/garyburd/redigo/issues/new) to discuss your 5 | plans before doing any work on Redigo. 6 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Ask questions at https://stackoverflow.com/questions/ask?tags=go+redis 2 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | services: 4 | - redis-server 5 | 6 | go: 7 | - 1.4 8 | - 1.5 9 | - 1.6 10 | - 1.7 11 | - 1.8 12 | - tip 13 | 14 | script: 15 | - go get -t -v ./... 16 | - diff -u <(echo -n) <(gofmt -d .) 17 | - go vet $(go list ./... | grep -v /vendor/) 18 | - go test -v -race ./... 19 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/README.markdown: -------------------------------------------------------------------------------- 1 | Redigo 2 | ====== 3 | 4 | [![Build Status](https://travis-ci.org/garyburd/redigo.svg?branch=master)](https://travis-ci.org/garyburd/redigo) 5 | [![GoDoc](https://godoc.org/github.com/garyburd/redigo/redis?status.svg)](https://godoc.org/github.com/garyburd/redigo/redis) 6 | 7 | Redigo is a [Go](http://golang.org/) client for the [Redis](http://redis.io/) database. 8 | 9 | Features 10 | ------- 11 | 12 | * A [Print-like](http://godoc.org/github.com/garyburd/redigo/redis#hdr-Executing_Commands) API with support for all Redis commands. 13 | * [Pipelining](http://godoc.org/github.com/garyburd/redigo/redis#hdr-Pipelining), including pipelined transactions. 14 | * [Publish/Subscribe](http://godoc.org/github.com/garyburd/redigo/redis#hdr-Publish_and_Subscribe). 15 | * [Connection pooling](http://godoc.org/github.com/garyburd/redigo/redis#Pool). 16 | * [Script helper type](http://godoc.org/github.com/garyburd/redigo/redis#Script) with optimistic use of EVALSHA. 17 | * [Helper functions](http://godoc.org/github.com/garyburd/redigo/redis#hdr-Reply_Helpers) for working with command replies. 18 | 19 | Documentation 20 | ------------- 21 | 22 | - [API Reference](http://godoc.org/github.com/garyburd/redigo/redis) 23 | - [FAQ](https://github.com/garyburd/redigo/wiki/FAQ) 24 | 25 | Installation 26 | ------------ 27 | 28 | Install Redigo using the "go get" command: 29 | 30 | go get github.com/garyburd/redigo/redis 31 | 32 | The Go distribution is Redigo's only dependency. 33 | 34 | Related Projects 35 | ---------------- 36 | 37 | - [rafaeljusto/redigomock](https://godoc.org/github.com/rafaeljusto/redigomock) - A mock library for Redigo. 38 | - [chasex/redis-go-cluster](https://github.com/chasex/redis-go-cluster) - A Redis cluster client implementation. 39 | - [FZambia/go-sentinel](https://github.com/FZambia/go-sentinel) - Redis Sentinel support for Redigo 40 | - [PuerkitoBio/redisc](https://github.com/PuerkitoBio/redisc) - Redis Cluster client built on top of Redigo 41 | 42 | Contributing 43 | ------------ 44 | 45 | See [CONTRIBUTING.md](https://github.com/garyburd/redigo/blob/master/.github/CONTRIBUTING.md). 46 | 47 | License 48 | ------- 49 | 50 | Redigo is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). 51 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/internal/commandinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package internal // import "github.com/garyburd/redigo/internal" 16 | 17 | import ( 18 | "strings" 19 | ) 20 | 21 | const ( 22 | WatchState = 1 << iota 23 | MultiState 24 | SubscribeState 25 | MonitorState 26 | ) 27 | 28 | type CommandInfo struct { 29 | Set, Clear int 30 | } 31 | 32 | var commandInfos = map[string]CommandInfo{ 33 | "WATCH": {Set: WatchState}, 34 | "UNWATCH": {Clear: WatchState}, 35 | "MULTI": {Set: MultiState}, 36 | "EXEC": {Clear: WatchState | MultiState}, 37 | "DISCARD": {Clear: WatchState | MultiState}, 38 | "PSUBSCRIBE": {Set: SubscribeState}, 39 | "SUBSCRIBE": {Set: SubscribeState}, 40 | "MONITOR": {Set: MonitorState}, 41 | } 42 | 43 | func init() { 44 | for n, ci := range commandInfos { 45 | commandInfos[strings.ToLower(n)] = ci 46 | } 47 | } 48 | 49 | func LookupCommandInfo(commandName string) CommandInfo { 50 | if ci, ok := commandInfos[commandName]; ok { 51 | return ci 52 | } 53 | return commandInfos[strings.ToUpper(commandName)] 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/internal/commandinfo_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "testing" 4 | 5 | func TestLookupCommandInfo(t *testing.T) { 6 | for _, n := range []string{"watch", "WATCH", "wAtch"} { 7 | if LookupCommandInfo(n) == (CommandInfo{}) { 8 | t.Errorf("LookupCommandInfo(%q) = CommandInfo{}, expected non-zero value", n) 9 | } 10 | } 11 | } 12 | 13 | func benchmarkLookupCommandInfo(b *testing.B, names ...string) { 14 | for i := 0; i < b.N; i++ { 15 | for _, c := range names { 16 | LookupCommandInfo(c) 17 | } 18 | } 19 | } 20 | 21 | func BenchmarkLookupCommandInfoCorrectCase(b *testing.B) { 22 | benchmarkLookupCommandInfo(b, "watch", "WATCH", "monitor", "MONITOR") 23 | } 24 | 25 | func BenchmarkLookupCommandInfoMixedCase(b *testing.B) { 26 | benchmarkLookupCommandInfo(b, "wAtch", "WeTCH", "monItor", "MONiTOR") 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/internal/redistest/testdb.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | // Package redistest contains utilities for writing Redigo tests. 16 | package redistest 17 | 18 | import ( 19 | "errors" 20 | "time" 21 | 22 | "github.com/garyburd/redigo/redis" 23 | ) 24 | 25 | type testConn struct { 26 | redis.Conn 27 | } 28 | 29 | func (t testConn) Close() error { 30 | _, err := t.Conn.Do("SELECT", "9") 31 | if err != nil { 32 | return nil 33 | } 34 | _, err = t.Conn.Do("FLUSHDB") 35 | if err != nil { 36 | return err 37 | } 38 | return t.Conn.Close() 39 | } 40 | 41 | // Dial dials the local Redis server and selects database 9. To prevent 42 | // stomping on real data, DialTestDB fails if database 9 contains data. The 43 | // returned connection flushes database 9 on close. 44 | func Dial() (redis.Conn, error) { 45 | c, err := redis.DialTimeout("tcp", ":6379", 0, 1*time.Second, 1*time.Second) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | _, err = c.Do("SELECT", "9") 51 | if err != nil { 52 | c.Close() 53 | return nil, err 54 | } 55 | 56 | n, err := redis.Int(c.Do("DBSIZE")) 57 | if err != nil { 58 | c.Close() 59 | return nil, err 60 | } 61 | 62 | if n != 0 { 63 | c.Close() 64 | return nil, errors.New("database #9 is not empty, test can not continue") 65 | } 66 | 67 | return testConn{c}, nil 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/go17.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package redis 4 | 5 | import "crypto/tls" 6 | 7 | // similar cloneTLSClientConfig in the stdlib, but also honor skipVerify for the nil case 8 | func cloneTLSClientConfig(cfg *tls.Config, skipVerify bool) *tls.Config { 9 | if cfg == nil { 10 | return &tls.Config{InsecureSkipVerify: skipVerify} 11 | } 12 | return &tls.Config{ 13 | Rand: cfg.Rand, 14 | Time: cfg.Time, 15 | Certificates: cfg.Certificates, 16 | NameToCertificate: cfg.NameToCertificate, 17 | GetCertificate: cfg.GetCertificate, 18 | RootCAs: cfg.RootCAs, 19 | NextProtos: cfg.NextProtos, 20 | ServerName: cfg.ServerName, 21 | ClientAuth: cfg.ClientAuth, 22 | ClientCAs: cfg.ClientCAs, 23 | InsecureSkipVerify: cfg.InsecureSkipVerify, 24 | CipherSuites: cfg.CipherSuites, 25 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 26 | ClientSessionCache: cfg.ClientSessionCache, 27 | MinVersion: cfg.MinVersion, 28 | MaxVersion: cfg.MaxVersion, 29 | CurvePreferences: cfg.CurvePreferences, 30 | DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 31 | Renegotiation: cfg.Renegotiation, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/pre_go17.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package redis 4 | 5 | import "crypto/tls" 6 | 7 | // similar cloneTLSClientConfig in the stdlib, but also honor skipVerify for the nil case 8 | func cloneTLSClientConfig(cfg *tls.Config, skipVerify bool) *tls.Config { 9 | if cfg == nil { 10 | return &tls.Config{InsecureSkipVerify: skipVerify} 11 | } 12 | return &tls.Config{ 13 | Rand: cfg.Rand, 14 | Time: cfg.Time, 15 | Certificates: cfg.Certificates, 16 | NameToCertificate: cfg.NameToCertificate, 17 | GetCertificate: cfg.GetCertificate, 18 | RootCAs: cfg.RootCAs, 19 | NextProtos: cfg.NextProtos, 20 | ServerName: cfg.ServerName, 21 | ClientAuth: cfg.ClientAuth, 22 | ClientCAs: cfg.ClientCAs, 23 | InsecureSkipVerify: cfg.InsecureSkipVerify, 24 | CipherSuites: cfg.CipherSuites, 25 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 26 | ClientSessionCache: cfg.ClientSessionCache, 27 | MinVersion: cfg.MinVersion, 28 | MaxVersion: cfg.MaxVersion, 29 | CurvePreferences: cfg.CurvePreferences, 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/redis.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | // Error represents an error returned in a command reply. 18 | type Error string 19 | 20 | func (err Error) Error() string { return string(err) } 21 | 22 | // Conn represents a connection to a Redis server. 23 | type Conn interface { 24 | // Close closes the connection. 25 | Close() error 26 | 27 | // Err returns a non-nil value when the connection is not usable. 28 | Err() error 29 | 30 | // Do sends a command to the server and returns the received reply. 31 | Do(commandName string, args ...interface{}) (reply interface{}, err error) 32 | 33 | // Send writes the command to the client's output buffer. 34 | Send(commandName string, args ...interface{}) error 35 | 36 | // Flush flushes the output buffer to the Redis server. 37 | Flush() error 38 | 39 | // Receive receives a single reply from the Redis server 40 | Receive() (reply interface{}, err error) 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redisx/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | // Package redisx contains experimental features for Redigo. Features in this 16 | // package may be modified or deleted at any time. 17 | package redisx // import "github.com/garyburd/redigo/redisx" 18 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/.gitignore: -------------------------------------------------------------------------------- 1 | *.rdb 2 | testdata/*/ 3 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: go 3 | 4 | services: 5 | - redis-server 6 | 7 | go: 8 | - 1.4 9 | - 1.7 10 | - 1.8 11 | - tip 12 | 13 | matrix: 14 | allow_failures: 15 | - go: 1.4 16 | - go: tip 17 | 18 | install: 19 | - go get github.com/onsi/ginkgo 20 | - go get github.com/onsi/gomega 21 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 The github.com/go-redis/redis Authors. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/Makefile: -------------------------------------------------------------------------------- 1 | all: testdeps 2 | go test ./... 3 | go test ./... -short -race 4 | go vet 5 | 6 | testdeps: testdata/redis/src/redis-server 7 | 8 | bench: testdeps 9 | go test ./... -test.run=NONE -test.bench=. -test.benchmem 10 | 11 | .PHONY: all test testdeps bench 12 | 13 | testdata/redis: 14 | mkdir -p $@ 15 | wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@ 16 | 17 | testdata/redis/src/redis-server: testdata/redis 18 | sed -i 's/libjemalloc.a/libjemalloc.a -lrt/g' $= hash }) 74 | 75 | // Means we have cycled back to the first replica. 76 | if idx == len(m.keys) { 77 | idx = 0 78 | } 79 | 80 | return m.hashMap[m.keys[idx]] 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/errors.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "strings" 7 | ) 8 | 9 | const Nil = RedisError("redis: nil") 10 | 11 | type RedisError string 12 | 13 | func (e RedisError) Error() string { return string(e) } 14 | 15 | func IsRetryableError(err error) bool { 16 | return IsNetworkError(err) 17 | } 18 | 19 | func IsInternalError(err error) bool { 20 | _, ok := err.(RedisError) 21 | return ok 22 | } 23 | 24 | func IsNetworkError(err error) bool { 25 | if err == io.EOF { 26 | return true 27 | } 28 | _, ok := err.(net.Error) 29 | return ok 30 | } 31 | 32 | func IsBadConn(err error, allowTimeout bool) bool { 33 | if err == nil { 34 | return false 35 | } 36 | if IsInternalError(err) { 37 | return false 38 | } 39 | if allowTimeout { 40 | if netErr, ok := err.(net.Error); ok && netErr.Timeout() { 41 | return false 42 | } 43 | } 44 | return true 45 | } 46 | 47 | func IsMovedError(err error) (moved bool, ask bool, addr string) { 48 | if !IsInternalError(err) { 49 | return 50 | } 51 | 52 | s := err.Error() 53 | if strings.HasPrefix(s, "MOVED ") { 54 | moved = true 55 | } else if strings.HasPrefix(s, "ASK ") { 56 | ask = true 57 | } else { 58 | return 59 | } 60 | 61 | ind := strings.LastIndex(s, " ") 62 | if ind == -1 { 63 | return false, false, "" 64 | } 65 | addr = s[ind+1:] 66 | return 67 | } 68 | 69 | func IsLoadingError(err error) bool { 70 | return strings.HasPrefix(err.Error(), "LOADING") 71 | } 72 | 73 | func IsExecAbortError(err error) bool { 74 | return strings.HasPrefix(err.Error(), "EXECABORT") 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/hashtag/hashtag_test.go: -------------------------------------------------------------------------------- 1 | package hashtag 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | ) 10 | 11 | func TestGinkgoSuite(t *testing.T) { 12 | RegisterFailHandler(Fail) 13 | RunSpecs(t, "hashtag") 14 | } 15 | 16 | var _ = Describe("CRC16", func() { 17 | 18 | // http://redis.io/topics/cluster-spec#keys-distribution-model 19 | It("should calculate CRC16", func() { 20 | tests := []struct { 21 | s string 22 | n uint16 23 | }{ 24 | {"123456789", 0x31C3}, 25 | {string([]byte{83, 153, 134, 118, 229, 214, 244, 75, 140, 37, 215, 215}), 21847}, 26 | } 27 | 28 | for _, test := range tests { 29 | Expect(crc16sum(test.s)).To(Equal(test.n), "for %s", test.s) 30 | } 31 | }) 32 | 33 | }) 34 | 35 | var _ = Describe("HashSlot", func() { 36 | 37 | It("should calculate hash slots", func() { 38 | tests := []struct { 39 | key string 40 | slot int 41 | }{ 42 | {"123456789", 12739}, 43 | {"{}foo", 9500}, 44 | {"foo{}", 5542}, 45 | {"foo{}{bar}", 8363}, 46 | {"", 10503}, 47 | {"", 5176}, 48 | {string([]byte{83, 153, 134, 118, 229, 214, 244, 75, 140, 37, 215, 215}), 5463}, 49 | } 50 | // Empty keys receive random slot. 51 | rand.Seed(100) 52 | 53 | for _, test := range tests { 54 | Expect(Slot(test.key)).To(Equal(test.slot), "for %s", test.key) 55 | } 56 | }) 57 | 58 | It("should extract keys from tags", func() { 59 | tests := []struct { 60 | one, two string 61 | }{ 62 | {"foo{bar}", "bar"}, 63 | {"{foo}bar", "foo"}, 64 | {"{user1000}.following", "{user1000}.followers"}, 65 | {"foo{{bar}}zap", "{bar"}, 66 | {"foo{bar}{zap}", "bar"}, 67 | } 68 | 69 | for _, test := range tests { 70 | Expect(Slot(test.one)).To(Equal(Slot(test.two)), "for %s <-> %s", test.one, test.two) 71 | } 72 | }) 73 | 74 | }) 75 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/log.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | var Logger *log.Logger 9 | 10 | func Logf(s string, args ...interface{}) { 11 | if Logger == nil { 12 | return 13 | } 14 | Logger.Output(2, fmt.Sprintf(s, args...)) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/bench_test.go: -------------------------------------------------------------------------------- 1 | package pool_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/go-redis/redis/internal/pool" 8 | ) 9 | 10 | func benchmarkPoolGetPut(b *testing.B, poolSize int) { 11 | connPool := pool.NewConnPool(dummyDialer, poolSize, time.Second, time.Hour, time.Hour) 12 | 13 | b.ResetTimer() 14 | 15 | b.RunParallel(func(pb *testing.PB) { 16 | for pb.Next() { 17 | cn, _, err := connPool.Get() 18 | if err != nil { 19 | b.Fatal(err) 20 | } 21 | if err = connPool.Put(cn); err != nil { 22 | b.Fatal(err) 23 | } 24 | } 25 | }) 26 | } 27 | 28 | func BenchmarkPoolGetPut10Conns(b *testing.B) { 29 | benchmarkPoolGetPut(b, 10) 30 | } 31 | 32 | func BenchmarkPoolGetPut100Conns(b *testing.B) { 33 | benchmarkPoolGetPut(b, 100) 34 | } 35 | 36 | func BenchmarkPoolGetPut1000Conns(b *testing.B) { 37 | benchmarkPoolGetPut(b, 1000) 38 | } 39 | 40 | func benchmarkPoolGetRemove(b *testing.B, poolSize int) { 41 | connPool := pool.NewConnPool(dummyDialer, poolSize, time.Second, time.Hour, time.Hour) 42 | 43 | b.ResetTimer() 44 | 45 | b.RunParallel(func(pb *testing.PB) { 46 | for pb.Next() { 47 | cn, _, err := connPool.Get() 48 | if err != nil { 49 | b.Fatal(err) 50 | } 51 | if err := connPool.Remove(cn); err != nil { 52 | b.Fatal(err) 53 | } 54 | } 55 | }) 56 | } 57 | 58 | func BenchmarkPoolGetRemove10Conns(b *testing.B) { 59 | benchmarkPoolGetRemove(b, 10) 60 | } 61 | 62 | func BenchmarkPoolGetRemove100Conns(b *testing.B) { 63 | benchmarkPoolGetRemove(b, 100) 64 | } 65 | 66 | func BenchmarkPoolGetRemove1000Conns(b *testing.B) { 67 | benchmarkPoolGetRemove(b, 1000) 68 | } 69 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/conn.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import ( 4 | "net" 5 | "sync/atomic" 6 | "time" 7 | 8 | "github.com/go-redis/redis/internal/proto" 9 | ) 10 | 11 | var noDeadline = time.Time{} 12 | 13 | type Conn struct { 14 | netConn net.Conn 15 | 16 | Rd *proto.Reader 17 | Wb *proto.WriteBuffer 18 | 19 | Inited bool 20 | usedAt atomic.Value 21 | } 22 | 23 | func NewConn(netConn net.Conn) *Conn { 24 | cn := &Conn{ 25 | netConn: netConn, 26 | Wb: proto.NewWriteBuffer(), 27 | } 28 | cn.Rd = proto.NewReader(cn.netConn) 29 | cn.SetUsedAt(time.Now()) 30 | return cn 31 | } 32 | 33 | func (cn *Conn) UsedAt() time.Time { 34 | return cn.usedAt.Load().(time.Time) 35 | } 36 | 37 | func (cn *Conn) SetUsedAt(tm time.Time) { 38 | cn.usedAt.Store(tm) 39 | } 40 | 41 | func (cn *Conn) SetNetConn(netConn net.Conn) { 42 | cn.netConn = netConn 43 | cn.Rd.Reset(netConn) 44 | } 45 | 46 | func (cn *Conn) IsStale(timeout time.Duration) bool { 47 | return timeout > 0 && time.Since(cn.UsedAt()) > timeout 48 | } 49 | 50 | func (cn *Conn) SetReadTimeout(timeout time.Duration) error { 51 | now := time.Now() 52 | cn.SetUsedAt(now) 53 | if timeout > 0 { 54 | return cn.netConn.SetReadDeadline(now.Add(timeout)) 55 | } 56 | return cn.netConn.SetReadDeadline(noDeadline) 57 | } 58 | 59 | func (cn *Conn) SetWriteTimeout(timeout time.Duration) error { 60 | now := time.Now() 61 | cn.SetUsedAt(now) 62 | if timeout > 0 { 63 | return cn.netConn.SetWriteDeadline(now.Add(timeout)) 64 | } 65 | return cn.netConn.SetWriteDeadline(noDeadline) 66 | } 67 | 68 | func (cn *Conn) Write(b []byte) (int, error) { 69 | return cn.netConn.Write(b) 70 | } 71 | 72 | func (cn *Conn) RemoteAddr() net.Addr { 73 | return cn.netConn.RemoteAddr() 74 | } 75 | 76 | func (cn *Conn) Close() error { 77 | return cn.netConn.Close() 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/main_test.go: -------------------------------------------------------------------------------- 1 | package pool_test 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | "testing" 7 | 8 | . "github.com/onsi/ginkgo" 9 | . "github.com/onsi/gomega" 10 | ) 11 | 12 | func TestGinkgoSuite(t *testing.T) { 13 | RegisterFailHandler(Fail) 14 | RunSpecs(t, "pool") 15 | } 16 | 17 | func perform(n int, cbs ...func(int)) { 18 | var wg sync.WaitGroup 19 | for _, cb := range cbs { 20 | for i := 0; i < n; i++ { 21 | wg.Add(1) 22 | go func(cb func(int), i int) { 23 | defer GinkgoRecover() 24 | defer wg.Done() 25 | 26 | cb(i) 27 | }(cb, i) 28 | } 29 | } 30 | wg.Wait() 31 | } 32 | 33 | func dummyDialer() (net.Conn, error) { 34 | return &net.TCPConn{}, nil 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/pool_single.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | type SingleConnPool struct { 4 | cn *Conn 5 | } 6 | 7 | var _ Pooler = (*SingleConnPool)(nil) 8 | 9 | func NewSingleConnPool(cn *Conn) *SingleConnPool { 10 | return &SingleConnPool{ 11 | cn: cn, 12 | } 13 | } 14 | 15 | func (p *SingleConnPool) NewConn() (*Conn, error) { 16 | panic("not implemented") 17 | } 18 | 19 | func (p *SingleConnPool) CloseConn(*Conn) error { 20 | panic("not implemented") 21 | } 22 | 23 | func (p *SingleConnPool) Get() (*Conn, bool, error) { 24 | return p.cn, false, nil 25 | } 26 | 27 | func (p *SingleConnPool) Put(cn *Conn) error { 28 | if p.cn != cn { 29 | panic("p.cn != cn") 30 | } 31 | return nil 32 | } 33 | 34 | func (p *SingleConnPool) Remove(cn *Conn) error { 35 | if p.cn != cn { 36 | panic("p.cn != cn") 37 | } 38 | return nil 39 | } 40 | 41 | func (p *SingleConnPool) Len() int { 42 | return 1 43 | } 44 | 45 | func (p *SingleConnPool) FreeLen() int { 46 | return 0 47 | } 48 | 49 | func (p *SingleConnPool) Stats() *Stats { 50 | return nil 51 | } 52 | 53 | func (p *SingleConnPool) Close() error { 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/pool/pool_sticky.go: -------------------------------------------------------------------------------- 1 | package pool 2 | 3 | import "sync" 4 | 5 | type StickyConnPool struct { 6 | pool *ConnPool 7 | reusable bool 8 | 9 | cn *Conn 10 | closed bool 11 | mu sync.Mutex 12 | } 13 | 14 | var _ Pooler = (*StickyConnPool)(nil) 15 | 16 | func NewStickyConnPool(pool *ConnPool, reusable bool) *StickyConnPool { 17 | return &StickyConnPool{ 18 | pool: pool, 19 | reusable: reusable, 20 | } 21 | } 22 | 23 | func (p *StickyConnPool) NewConn() (*Conn, error) { 24 | panic("not implemented") 25 | } 26 | 27 | func (p *StickyConnPool) CloseConn(*Conn) error { 28 | panic("not implemented") 29 | } 30 | 31 | func (p *StickyConnPool) Get() (*Conn, bool, error) { 32 | p.mu.Lock() 33 | defer p.mu.Unlock() 34 | 35 | if p.closed { 36 | return nil, false, ErrClosed 37 | } 38 | if p.cn != nil { 39 | return p.cn, false, nil 40 | } 41 | 42 | cn, _, err := p.pool.Get() 43 | if err != nil { 44 | return nil, false, err 45 | } 46 | p.cn = cn 47 | return cn, true, nil 48 | } 49 | 50 | func (p *StickyConnPool) putUpstream() (err error) { 51 | err = p.pool.Put(p.cn) 52 | p.cn = nil 53 | return err 54 | } 55 | 56 | func (p *StickyConnPool) Put(cn *Conn) error { 57 | p.mu.Lock() 58 | defer p.mu.Unlock() 59 | 60 | if p.closed { 61 | return ErrClosed 62 | } 63 | return nil 64 | } 65 | 66 | func (p *StickyConnPool) removeUpstream() error { 67 | err := p.pool.Remove(p.cn) 68 | p.cn = nil 69 | return err 70 | } 71 | 72 | func (p *StickyConnPool) Remove(cn *Conn) error { 73 | p.mu.Lock() 74 | defer p.mu.Unlock() 75 | 76 | if p.closed { 77 | return nil 78 | } 79 | return p.removeUpstream() 80 | } 81 | 82 | func (p *StickyConnPool) Len() int { 83 | p.mu.Lock() 84 | defer p.mu.Unlock() 85 | 86 | if p.cn == nil { 87 | return 0 88 | } 89 | return 1 90 | } 91 | 92 | func (p *StickyConnPool) FreeLen() int { 93 | p.mu.Lock() 94 | defer p.mu.Unlock() 95 | 96 | if p.cn == nil { 97 | return 1 98 | } 99 | return 0 100 | } 101 | 102 | func (p *StickyConnPool) Stats() *Stats { 103 | return nil 104 | } 105 | 106 | func (p *StickyConnPool) Close() error { 107 | p.mu.Lock() 108 | defer p.mu.Unlock() 109 | 110 | if p.closed { 111 | return ErrClosed 112 | } 113 | p.closed = true 114 | var err error 115 | if p.cn != nil { 116 | if p.reusable { 117 | err = p.putUpstream() 118 | } else { 119 | err = p.removeUpstream() 120 | } 121 | } 122 | return err 123 | } 124 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/proto/proto_test.go: -------------------------------------------------------------------------------- 1 | package proto_test 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestGinkgoSuite(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "proto") 13 | } 14 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/proto/reader_test.go: -------------------------------------------------------------------------------- 1 | package proto_test 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/go-redis/redis/internal/proto" 9 | 10 | . "github.com/onsi/ginkgo" 11 | . "github.com/onsi/gomega" 12 | ) 13 | 14 | var _ = Describe("Reader", func() { 15 | 16 | It("should read n bytes", func() { 17 | data, err := proto.NewReader(strings.NewReader("ABCDEFGHIJKLMNO")).ReadN(10) 18 | Expect(err).NotTo(HaveOccurred()) 19 | Expect(len(data)).To(Equal(10)) 20 | Expect(string(data)).To(Equal("ABCDEFGHIJ")) 21 | 22 | data, err = proto.NewReader(strings.NewReader(strings.Repeat("x", 8192))).ReadN(6000) 23 | Expect(err).NotTo(HaveOccurred()) 24 | Expect(len(data)).To(Equal(6000)) 25 | }) 26 | 27 | It("should read lines", func() { 28 | p := proto.NewReader(strings.NewReader("$5\r\nhello\r\n")) 29 | 30 | data, err := p.ReadLine() 31 | Expect(err).NotTo(HaveOccurred()) 32 | Expect(string(data)).To(Equal("$5")) 33 | 34 | data, err = p.ReadLine() 35 | Expect(err).NotTo(HaveOccurred()) 36 | Expect(string(data)).To(Equal("hello")) 37 | }) 38 | 39 | }) 40 | 41 | func BenchmarkReader_ParseReply_Status(b *testing.B) { 42 | benchmarkParseReply(b, "+OK\r\n", nil, false) 43 | } 44 | 45 | func BenchmarkReader_ParseReply_Int(b *testing.B) { 46 | benchmarkParseReply(b, ":1\r\n", nil, false) 47 | } 48 | 49 | func BenchmarkReader_ParseReply_Error(b *testing.B) { 50 | benchmarkParseReply(b, "-Error message\r\n", nil, true) 51 | } 52 | 53 | func BenchmarkReader_ParseReply_String(b *testing.B) { 54 | benchmarkParseReply(b, "$5\r\nhello\r\n", nil, false) 55 | } 56 | 57 | func BenchmarkReader_ParseReply_Slice(b *testing.B) { 58 | benchmarkParseReply(b, "*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n", multiBulkParse, false) 59 | } 60 | 61 | func benchmarkParseReply(b *testing.B, reply string, m proto.MultiBulkParse, wanterr bool) { 62 | buf := new(bytes.Buffer) 63 | for i := 0; i < b.N; i++ { 64 | buf.WriteString(reply) 65 | } 66 | p := proto.NewReader(buf) 67 | b.ResetTimer() 68 | 69 | for i := 0; i < b.N; i++ { 70 | _, err := p.ReadReply(m) 71 | if !wanterr && err != nil { 72 | b.Fatal(err) 73 | } 74 | } 75 | } 76 | 77 | func multiBulkParse(p *proto.Reader, n int64) (interface{}, error) { 78 | vv := make([]interface{}, 0, n) 79 | for i := int64(0); i < n; i++ { 80 | v, err := p.ReadReply(multiBulkParse) 81 | if err != nil { 82 | return nil, err 83 | } 84 | vv = append(vv, v) 85 | } 86 | return vv, nil 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/proto/scan_test.go: -------------------------------------------------------------------------------- 1 | package proto 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | type testScanSliceStruct struct { 11 | ID int 12 | Name string 13 | } 14 | 15 | func (s *testScanSliceStruct) MarshalBinary() ([]byte, error) { 16 | return json.Marshal(s) 17 | } 18 | 19 | func (s *testScanSliceStruct) UnmarshalBinary(b []byte) error { 20 | return json.Unmarshal(b, s) 21 | } 22 | 23 | var _ = Describe("ScanSlice", func() { 24 | data := []string{ 25 | `{"ID":-1,"Name":"Back Yu"}`, 26 | `{"ID":1,"Name":"szyhf"}`, 27 | } 28 | 29 | It("[]testScanSliceStruct", func() { 30 | var slice []testScanSliceStruct 31 | err := ScanSlice(data, &slice) 32 | Expect(err).NotTo(HaveOccurred()) 33 | Expect(slice).To(Equal([]testScanSliceStruct{ 34 | {-1, "Back Yu"}, 35 | {1, "szyhf"}, 36 | })) 37 | }) 38 | 39 | It("var testContainer []*testScanSliceStruct", func() { 40 | var slice []*testScanSliceStruct 41 | err := ScanSlice(data, &slice) 42 | Expect(err).NotTo(HaveOccurred()) 43 | Expect(slice).To(Equal([]*testScanSliceStruct{ 44 | {-1, "Back Yu"}, 45 | {1, "szyhf"}, 46 | })) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/proto/write_buffer_test.go: -------------------------------------------------------------------------------- 1 | package proto_test 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/go-redis/redis/internal/proto" 8 | 9 | . "github.com/onsi/ginkgo" 10 | . "github.com/onsi/gomega" 11 | ) 12 | 13 | var _ = Describe("WriteBuffer", func() { 14 | var buf *proto.WriteBuffer 15 | 16 | BeforeEach(func() { 17 | buf = proto.NewWriteBuffer() 18 | }) 19 | 20 | It("should reset", func() { 21 | buf.AppendString("string") 22 | Expect(buf.Len()).To(Equal(12)) 23 | buf.Reset() 24 | Expect(buf.Len()).To(Equal(0)) 25 | }) 26 | 27 | It("should append args", func() { 28 | err := buf.Append([]interface{}{ 29 | "string", 30 | 12, 31 | 34.56, 32 | []byte{'b', 'y', 't', 'e', 's'}, 33 | true, 34 | nil, 35 | }) 36 | Expect(err).NotTo(HaveOccurred()) 37 | Expect(buf.Bytes()).To(Equal([]byte("*6\r\n" + 38 | "$6\r\nstring\r\n" + 39 | "$2\r\n12\r\n" + 40 | "$5\r\n34.56\r\n" + 41 | "$5\r\nbytes\r\n" + 42 | "$1\r\n1\r\n" + 43 | "$0\r\n" + 44 | "\r\n"))) 45 | }) 46 | 47 | It("should append marshalable args", func() { 48 | err := buf.Append([]interface{}{time.Unix(1414141414, 0)}) 49 | Expect(err).NotTo(HaveOccurred()) 50 | Expect(buf.Len()).To(Equal(26)) 51 | }) 52 | 53 | }) 54 | 55 | func BenchmarkWriteBuffer_Append(b *testing.B) { 56 | buf := proto.NewWriteBuffer() 57 | args := []interface{}{"hello", "world", "foo", "bar"} 58 | 59 | for i := 0; i < b.N; i++ { 60 | buf.Append(args) 61 | buf.Reset() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/safe.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package internal 4 | 5 | func BytesToString(b []byte) string { 6 | return string(b) 7 | } 8 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/unsafe.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package internal 4 | 5 | import ( 6 | "reflect" 7 | "unsafe" 8 | ) 9 | 10 | func BytesToString(b []byte) string { 11 | bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) 12 | strHeader := reflect.StringHeader{bytesHeader.Data, bytesHeader.Len} 13 | return *(*string)(unsafe.Pointer(&strHeader)) 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/internal/util.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "reflect" 4 | 5 | func ToLower(s string) string { 6 | if isLower(s) { 7 | return s 8 | } 9 | 10 | b := make([]byte, len(s)) 11 | for i := range b { 12 | c := s[i] 13 | if c >= 'A' && c <= 'Z' { 14 | c += 'a' - 'A' 15 | } 16 | b[i] = c 17 | } 18 | return BytesToString(b) 19 | } 20 | 21 | func isLower(s string) bool { 22 | for i := 0; i < len(s); i++ { 23 | c := s[i] 24 | if c >= 'A' && c <= 'Z' { 25 | return false 26 | } 27 | } 28 | return true 29 | } 30 | 31 | func SliceNextElem(v reflect.Value) reflect.Value { 32 | if v.Len() < v.Cap() { 33 | v.Set(v.Slice(0, v.Len()+1)) 34 | return v.Index(v.Len() - 1) 35 | } 36 | 37 | elemType := v.Type().Elem() 38 | 39 | if elemType.Kind() == reflect.Ptr { 40 | elem := reflect.New(elemType.Elem()) 41 | v.Set(reflect.Append(v, elem)) 42 | return elem.Elem() 43 | } 44 | 45 | v.Set(reflect.Append(v, reflect.Zero(elemType))) 46 | return v.Index(v.Len() - 1) 47 | } 48 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/iterator.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "sync" 4 | 5 | // ScanIterator is used to incrementally iterate over a collection of elements. 6 | // It's safe for concurrent use by multiple goroutines. 7 | type ScanIterator struct { 8 | mu sync.Mutex // protects Scanner and pos 9 | cmd *ScanCmd 10 | pos int 11 | } 12 | 13 | // Err returns the last iterator error, if any. 14 | func (it *ScanIterator) Err() error { 15 | it.mu.Lock() 16 | err := it.cmd.Err() 17 | it.mu.Unlock() 18 | return err 19 | } 20 | 21 | // Next advances the cursor and returns true if more values can be read. 22 | func (it *ScanIterator) Next() bool { 23 | it.mu.Lock() 24 | defer it.mu.Unlock() 25 | 26 | // Instantly return on errors. 27 | if it.cmd.Err() != nil { 28 | return false 29 | } 30 | 31 | // Advance cursor, check if we are still within range. 32 | if it.pos < len(it.cmd.page) { 33 | it.pos++ 34 | return true 35 | } 36 | 37 | for { 38 | // Return if there is no more data to fetch. 39 | if it.cmd.cursor == 0 { 40 | return false 41 | } 42 | 43 | // Fetch next page. 44 | if it.cmd._args[0] == "scan" { 45 | it.cmd._args[1] = it.cmd.cursor 46 | } else { 47 | it.cmd._args[2] = it.cmd.cursor 48 | } 49 | 50 | err := it.cmd.process(it.cmd) 51 | if err != nil { 52 | return false 53 | } 54 | 55 | it.pos = 1 56 | 57 | // Redis can occasionally return empty page. 58 | if len(it.cmd.page) > 0 { 59 | return true 60 | } 61 | } 62 | } 63 | 64 | // Val returns the key/field at the current cursor position. 65 | func (it *ScanIterator) Val() string { 66 | var v string 67 | it.mu.Lock() 68 | if it.cmd.Err() == nil && it.pos > 0 && it.pos <= len(it.cmd.page) { 69 | v = it.cmd.page[it.pos-1] 70 | } 71 | it.mu.Unlock() 72 | return v 73 | } 74 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/options_test.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package redis 4 | 5 | import ( 6 | "errors" 7 | "testing" 8 | ) 9 | 10 | func TestParseURL(t *testing.T) { 11 | cases := []struct { 12 | u string 13 | addr string 14 | db int 15 | tls bool 16 | err error 17 | }{ 18 | { 19 | "redis://localhost:123/1", 20 | "localhost:123", 21 | 1, false, nil, 22 | }, 23 | { 24 | "redis://localhost:123", 25 | "localhost:123", 26 | 0, false, nil, 27 | }, 28 | { 29 | "redis://localhost/1", 30 | "localhost:6379", 31 | 1, false, nil, 32 | }, 33 | { 34 | "redis://12345", 35 | "12345:6379", 36 | 0, false, nil, 37 | }, 38 | { 39 | "rediss://localhost:123", 40 | "localhost:123", 41 | 0, true, nil, 42 | }, 43 | { 44 | "redis://localhost/?abc=123", 45 | "", 46 | 0, false, errors.New("no options supported"), 47 | }, 48 | { 49 | "http://google.com", 50 | "", 51 | 0, false, errors.New("invalid redis URL scheme: http"), 52 | }, 53 | { 54 | "redis://localhost/1/2/3/4", 55 | "", 56 | 0, false, errors.New("invalid redis URL path: /1/2/3/4"), 57 | }, 58 | { 59 | "12345", 60 | "", 61 | 0, false, errors.New("invalid redis URL scheme: "), 62 | }, 63 | { 64 | "redis://localhost/iamadatabase", 65 | "", 66 | 0, false, errors.New(`invalid redis database number: "iamadatabase"`), 67 | }, 68 | } 69 | 70 | for _, c := range cases { 71 | t.Run(c.u, func(t *testing.T) { 72 | o, err := ParseURL(c.u) 73 | if c.err == nil && err != nil { 74 | t.Fatalf("unexpected error: '%q'", err) 75 | return 76 | } 77 | if c.err != nil && err != nil { 78 | if c.err.Error() != err.Error() { 79 | t.Fatalf("got %q, expected %q", err, c.err) 80 | } 81 | return 82 | } 83 | if o.Addr != c.addr { 84 | t.Errorf("got %q, want %q", o.Addr, c.addr) 85 | } 86 | if o.DB != c.db { 87 | t.Errorf("got %q, expected %q", o.DB, c.db) 88 | } 89 | if c.tls && o.TLSConfig == nil { 90 | t.Errorf("got nil TLSConfig, expected a TLSConfig") 91 | } 92 | }) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/pipeline.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "errors" 5 | "sync" 6 | 7 | "github.com/go-redis/redis/internal/pool" 8 | ) 9 | 10 | type pipelineExecer func([]Cmder) error 11 | 12 | // Pipeline implements pipelining as described in 13 | // http://redis.io/topics/pipelining. It's safe for concurrent use 14 | // by multiple goroutines. 15 | type Pipeline struct { 16 | cmdable 17 | statefulCmdable 18 | 19 | exec pipelineExecer 20 | 21 | mu sync.Mutex 22 | cmds []Cmder 23 | closed bool 24 | } 25 | 26 | func (c *Pipeline) Process(cmd Cmder) error { 27 | c.mu.Lock() 28 | c.cmds = append(c.cmds, cmd) 29 | c.mu.Unlock() 30 | return nil 31 | } 32 | 33 | // Close closes the pipeline, releasing any open resources. 34 | func (c *Pipeline) Close() error { 35 | c.mu.Lock() 36 | c.discard() 37 | c.closed = true 38 | c.mu.Unlock() 39 | return nil 40 | } 41 | 42 | // Discard resets the pipeline and discards queued commands. 43 | func (c *Pipeline) Discard() error { 44 | c.mu.Lock() 45 | err := c.discard() 46 | c.mu.Unlock() 47 | return err 48 | } 49 | 50 | func (c *Pipeline) discard() error { 51 | if c.closed { 52 | return pool.ErrClosed 53 | } 54 | c.cmds = c.cmds[:0] 55 | return nil 56 | } 57 | 58 | // Exec executes all previously queued commands using one 59 | // client-server roundtrip. 60 | // 61 | // Exec always returns list of commands and error of the first failed 62 | // command if any. 63 | func (c *Pipeline) Exec() ([]Cmder, error) { 64 | c.mu.Lock() 65 | defer c.mu.Unlock() 66 | 67 | if c.closed { 68 | return nil, pool.ErrClosed 69 | } 70 | 71 | if len(c.cmds) == 0 { 72 | return nil, errors.New("redis: pipeline is empty") 73 | } 74 | 75 | cmds := c.cmds 76 | c.cmds = nil 77 | 78 | return cmds, c.exec(cmds) 79 | } 80 | 81 | func (c *Pipeline) pipelined(fn func(*Pipeline) error) ([]Cmder, error) { 82 | if err := fn(c); err != nil { 83 | return nil, err 84 | } 85 | cmds, err := c.Exec() 86 | _ = c.Close() 87 | return cmds, err 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/pipeline_test.go: -------------------------------------------------------------------------------- 1 | package redis_test 2 | 3 | import ( 4 | "github.com/go-redis/redis" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | var _ = Describe("pipelining", func() { 11 | var client *redis.Client 12 | var pipe *redis.Pipeline 13 | 14 | BeforeEach(func() { 15 | client = redis.NewClient(redisOptions()) 16 | Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) 17 | }) 18 | 19 | AfterEach(func() { 20 | Expect(client.Close()).NotTo(HaveOccurred()) 21 | }) 22 | 23 | It("supports block style", func() { 24 | var get *redis.StringCmd 25 | cmds, err := client.Pipelined(func(pipe *redis.Pipeline) error { 26 | get = pipe.Get("foo") 27 | return nil 28 | }) 29 | Expect(err).To(Equal(redis.Nil)) 30 | Expect(cmds).To(HaveLen(1)) 31 | Expect(cmds[0]).To(Equal(get)) 32 | Expect(get.Err()).To(Equal(redis.Nil)) 33 | Expect(get.Val()).To(Equal("")) 34 | }) 35 | 36 | assertPipeline := func() { 37 | It("returns an error when there are no commands", func() { 38 | _, err := pipe.Exec() 39 | Expect(err).To(MatchError("redis: pipeline is empty")) 40 | }) 41 | 42 | It("discards queued commands", func() { 43 | pipe.Get("key") 44 | pipe.Discard() 45 | _, err := pipe.Exec() 46 | Expect(err).To(MatchError("redis: pipeline is empty")) 47 | }) 48 | 49 | It("handles val/err", func() { 50 | err := client.Set("key", "value", 0).Err() 51 | Expect(err).NotTo(HaveOccurred()) 52 | 53 | get := pipe.Get("key") 54 | cmds, err := pipe.Exec() 55 | Expect(err).NotTo(HaveOccurred()) 56 | Expect(cmds).To(HaveLen(1)) 57 | 58 | val, err := get.Result() 59 | Expect(err).NotTo(HaveOccurred()) 60 | Expect(val).To(Equal("value")) 61 | }) 62 | } 63 | 64 | Describe("Pipeline", func() { 65 | BeforeEach(func() { 66 | pipe = client.Pipeline() 67 | }) 68 | 69 | assertPipeline() 70 | }) 71 | 72 | Describe("TxPipeline", func() { 73 | BeforeEach(func() { 74 | pipe = client.TxPipeline() 75 | }) 76 | 77 | assertPipeline() 78 | }) 79 | }) 80 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/redis_context.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package redis 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/go-redis/redis/internal/pool" 9 | ) 10 | 11 | type baseClient struct { 12 | connPool pool.Pooler 13 | opt *Options 14 | 15 | process func(Cmder) error 16 | onClose func() error // hook called when client is closed 17 | 18 | ctx context.Context 19 | } 20 | 21 | func (c *Client) Context() context.Context { 22 | if c.ctx != nil { 23 | return c.ctx 24 | } 25 | return context.Background() 26 | } 27 | 28 | func (c *Client) WithContext(ctx context.Context) *Client { 29 | if ctx == nil { 30 | panic("nil context") 31 | } 32 | c2 := c.copy() 33 | c2.ctx = ctx 34 | return c2 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/redis_no_context.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package redis 4 | 5 | import ( 6 | "github.com/go-redis/redis/internal/pool" 7 | ) 8 | 9 | type baseClient struct { 10 | connPool pool.Pooler 11 | opt *Options 12 | 13 | process func(Cmder) error 14 | onClose func() error // hook called when client is closed 15 | } 16 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/script.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "crypto/sha1" 5 | "encoding/hex" 6 | "io" 7 | "strings" 8 | ) 9 | 10 | type scripter interface { 11 | Eval(script string, keys []string, args ...interface{}) *Cmd 12 | EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd 13 | ScriptExists(scripts ...string) *BoolSliceCmd 14 | ScriptLoad(script string) *StringCmd 15 | } 16 | 17 | var _ scripter = (*Client)(nil) 18 | var _ scripter = (*Ring)(nil) 19 | var _ scripter = (*ClusterClient)(nil) 20 | 21 | type Script struct { 22 | src, hash string 23 | } 24 | 25 | func NewScript(src string) *Script { 26 | h := sha1.New() 27 | io.WriteString(h, src) 28 | return &Script{ 29 | src: src, 30 | hash: hex.EncodeToString(h.Sum(nil)), 31 | } 32 | } 33 | 34 | func (s *Script) Load(c scripter) *StringCmd { 35 | return c.ScriptLoad(s.src) 36 | } 37 | 38 | func (s *Script) Exists(c scripter) *BoolSliceCmd { 39 | return c.ScriptExists(s.src) 40 | } 41 | 42 | func (s *Script) Eval(c scripter, keys []string, args ...interface{}) *Cmd { 43 | return c.Eval(s.src, keys, args...) 44 | } 45 | 46 | func (s *Script) EvalSha(c scripter, keys []string, args ...interface{}) *Cmd { 47 | return c.EvalSha(s.hash, keys, args...) 48 | } 49 | 50 | // Run optimistically uses EVALSHA to run the script. If script does not exist 51 | // it is retried using EVAL. 52 | func (s *Script) Run(c scripter, keys []string, args ...interface{}) *Cmd { 53 | r := s.EvalSha(c, keys, args...) 54 | if err := r.Err(); err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") { 55 | return s.Eval(c, keys, args...) 56 | } 57 | return r 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/sentinel_test.go: -------------------------------------------------------------------------------- 1 | package redis_test 2 | 3 | import ( 4 | "github.com/go-redis/redis" 5 | 6 | . "github.com/onsi/ginkgo" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | var _ = Describe("Sentinel", func() { 11 | var client *redis.Client 12 | 13 | BeforeEach(func() { 14 | client = redis.NewFailoverClient(&redis.FailoverOptions{ 15 | MasterName: sentinelName, 16 | SentinelAddrs: []string{":" + sentinelPort}, 17 | }) 18 | Expect(client.FlushDb().Err()).NotTo(HaveOccurred()) 19 | }) 20 | 21 | AfterEach(func() { 22 | Expect(client.Close()).NotTo(HaveOccurred()) 23 | }) 24 | 25 | It("should facilitate failover", func() { 26 | // Set value on master, verify 27 | err := client.Set("foo", "master", 0).Err() 28 | Expect(err).NotTo(HaveOccurred()) 29 | 30 | val, err := sentinelMaster.Get("foo").Result() 31 | Expect(err).NotTo(HaveOccurred()) 32 | Expect(val).To(Equal("master")) 33 | 34 | // Wait until replicated 35 | Eventually(func() string { 36 | return sentinelSlave1.Get("foo").Val() 37 | }, "1s", "100ms").Should(Equal("master")) 38 | Eventually(func() string { 39 | return sentinelSlave2.Get("foo").Val() 40 | }, "1s", "100ms").Should(Equal("master")) 41 | 42 | // Wait until slaves are picked up by sentinel. 43 | Eventually(func() string { 44 | return sentinel.Info().Val() 45 | }, "10s", "100ms").Should(ContainSubstring("slaves=2")) 46 | 47 | // Kill master. 48 | sentinelMaster.Shutdown() 49 | Eventually(func() error { 50 | return sentinelMaster.Ping().Err() 51 | }, "5s", "100ms").Should(HaveOccurred()) 52 | 53 | // Wait for Redis sentinel to elect new master. 54 | Eventually(func() string { 55 | return sentinelSlave1.Info().Val() + sentinelSlave2.Info().Val() 56 | }, "30s", "1s").Should(ContainSubstring("role:master")) 57 | 58 | // Check that client picked up new master. 59 | Eventually(func() error { 60 | return client.Get("foo").Err() 61 | }, "5s", "100ms").ShouldNot(HaveOccurred()) 62 | }) 63 | 64 | It("supports DB selection", func() { 65 | Expect(client.Close()).NotTo(HaveOccurred()) 66 | 67 | client = redis.NewFailoverClient(&redis.FailoverOptions{ 68 | MasterName: sentinelName, 69 | SentinelAddrs: []string{":" + sentinelPort}, 70 | DB: 1, 71 | }) 72 | err := client.Ping().Err() 73 | Expect(err).NotTo(HaveOccurred()) 74 | }) 75 | }) 76 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/testdata/redis.conf: -------------------------------------------------------------------------------- 1 | # Minimal redis.conf 2 | 3 | port 6379 4 | daemonize no 5 | dir . 6 | save "" 7 | appendonly yes 8 | cluster-config-file nodes.conf 9 | cluster-node-timeout 30000 10 | -------------------------------------------------------------------------------- /vendor/github.com/go-redis/redis/universal_test.go: -------------------------------------------------------------------------------- 1 | package redis_test 2 | 3 | import ( 4 | . "github.com/onsi/ginkgo" 5 | . "github.com/onsi/gomega" 6 | 7 | "github.com/go-redis/redis" 8 | ) 9 | 10 | var _ = Describe("UniversalClient", func() { 11 | var client redis.UniversalClient 12 | 13 | AfterEach(func() { 14 | if client != nil { 15 | Expect(client.Close()).To(Succeed()) 16 | } 17 | }) 18 | 19 | It("should connect to failover servers", func() { 20 | client = redis.NewUniversalClient(&redis.UniversalOptions{ 21 | MasterName: sentinelName, 22 | Addrs: []string{":" + sentinelPort}, 23 | }) 24 | Expect(client.Ping().Err()).NotTo(HaveOccurred()) 25 | }) 26 | 27 | It("should connect to simple servers", func() { 28 | client = redis.NewUniversalClient(&redis.UniversalOptions{ 29 | Addrs: []string{redisAddr}, 30 | }) 31 | Expect(client.Ping().Err()).NotTo(HaveOccurred()) 32 | }) 33 | 34 | It("should connect to clusters", func() { 35 | client = redis.NewUniversalClient(&redis.UniversalOptions{ 36 | Addrs: cluster.addrs(), 37 | }) 38 | Expect(client.Ping().Err()).NotTo(HaveOccurred()) 39 | }) 40 | 41 | }) 42 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7 5 | 6 | script: 7 | - go get github.com/customerio/gospec 8 | - go test -v 9 | 10 | services: 11 | - redis-server 12 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 John Allison 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/jrallison/go-workers.png)](https://travis-ci.org/jrallison/go-workers) 2 | [![GoDoc](https://godoc.org/github.com/jrallison/go-workers?status.png)](https://godoc.org/github.com/jrallison/go-workers) 3 | 4 | [Sidekiq](http://sidekiq.org/) compatible 5 | background workers in [golang](http://golang.org/). 6 | 7 | * reliable queueing for all queues using [brpoplpush](http://redis.io/commands/brpoplpush) 8 | * handles retries 9 | * support custom middleware 10 | * customize concurrency per queue 11 | * responds to Unix signals to safely wait for jobs to finish before exiting. 12 | * provides stats on what jobs are currently running 13 | * well tested 14 | 15 | Example usage: 16 | 17 | ```go 18 | package main 19 | 20 | import ( 21 | "github.com/jrallison/go-workers" 22 | ) 23 | 24 | func myJob(message *workers.Msg) { 25 | // do something with your message 26 | // message.Jid() 27 | // message.Args() is a wrapper around go-simplejson (http://godoc.org/github.com/bitly/go-simplejson) 28 | } 29 | 30 | type myMiddleware struct{} 31 | 32 | func (r *myMiddleware) Call(queue string, message *workers.Msg, next func() bool) (acknowledge bool) { 33 | // do something before each message is processed 34 | acknowledge = next() 35 | // do something after each message is processed 36 | return 37 | } 38 | 39 | func main() { 40 | workers.Configure(map[string]string{ 41 | // location of redis instance 42 | "server": "localhost:6379", 43 | // instance of the database 44 | "database": "0", 45 | // number of connections to keep open with redis 46 | "pool": "30", 47 | // unique process id for this instance of workers (for proper recovery of inprogress jobs on crash) 48 | "process": "1", 49 | }) 50 | 51 | workers.Middleware.Append(&myMiddleware{}) 52 | 53 | // pull messages from "myqueue" with concurrency of 10 54 | workers.Process("myqueue", myJob, 10) 55 | 56 | // pull messages from "myqueue2" with concurrency of 20 57 | workers.Process("myqueue2", myJob, 20) 58 | 59 | // Add a job to a queue 60 | workers.Enqueue("myqueue3", "Add", []int{1, 2}) 61 | 62 | // Add a job to a queue with retry 63 | workers.EnqueueWithOptions("myqueue3", "Add", []int{1, 2}, workers.EnqueueOptions{Retry: true}) 64 | 65 | // stats will be available at http://localhost:8080/stats 66 | go workers.StatsServer(8080) 67 | 68 | // Blocks until process is told to exit via unix signal 69 | workers.Run() 70 | } 71 | ``` 72 | 73 | Initial development sponsored by [Customer.io](http://customer.io) 74 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/all_specs_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/customerio/gospec" 7 | ) 8 | 9 | // You will need to list every spec in a TestXxx method like this, 10 | // so that gotest can be used to run the specs. Later GoSpec might 11 | // get its own command line tool similar to gotest, but for now this 12 | // is the way to go. This shouldn't require too much typing, because 13 | // there will be typically only one top-level spec per class/feature. 14 | 15 | func TestAllSpecs(t *testing.T) { 16 | r := gospec.NewRunner() 17 | 18 | r.Parallel = false 19 | 20 | r.BeforeEach = func() { 21 | Configure(map[string]string{ 22 | "server": "localhost:6379", 23 | "process": "1", 24 | "database": "15", 25 | "pool": "1", 26 | }) 27 | 28 | conn := Config.Pool.Get() 29 | conn.Do("flushdb") 30 | conn.Close() 31 | } 32 | 33 | // List all specs here 34 | r.AddSpec(WorkersSpec) 35 | r.AddSpec(ConfigSpec) 36 | r.AddSpec(MsgSpec) 37 | r.AddSpec(FetchSpec) 38 | r.AddSpec(WorkerSpec) 39 | r.AddSpec(ManagerSpec) 40 | r.AddSpec(ScheduledSpec) 41 | r.AddSpec(EnqueueSpec) 42 | r.AddSpec(MiddlewareSpec) 43 | r.AddSpec(MiddlewareRetrySpec) 44 | r.AddSpec(MiddlewareStatsSpec) 45 | 46 | // Run GoSpec and report any errors to gotest's `testing.T` instance 47 | gospec.MainGoTest(r, t) 48 | } 49 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/config.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "github.com/garyburd/redigo/redis" 8 | ) 9 | 10 | type config struct { 11 | processId string 12 | Namespace string 13 | PollInterval int 14 | Pool *redis.Pool 15 | Fetch func(queue string) Fetcher 16 | } 17 | 18 | var Config *config 19 | 20 | func Configure(options map[string]string) { 21 | var poolSize int 22 | var namespace string 23 | var pollInterval int 24 | 25 | if options["server"] == "" { 26 | panic("Configure requires a 'server' option, which identifies a Redis instance") 27 | } 28 | if options["process"] == "" { 29 | panic("Configure requires a 'process' option, which uniquely identifies this instance") 30 | } 31 | if options["pool"] == "" { 32 | options["pool"] = "1" 33 | } 34 | if options["namespace"] != "" { 35 | namespace = options["namespace"] + ":" 36 | } 37 | if seconds, err := strconv.Atoi(options["poll_interval"]); err == nil { 38 | pollInterval = seconds 39 | } else { 40 | pollInterval = 15 41 | } 42 | 43 | poolSize, _ = strconv.Atoi(options["pool"]) 44 | 45 | Config = &config{ 46 | options["process"], 47 | namespace, 48 | pollInterval, 49 | &redis.Pool{ 50 | MaxIdle: poolSize, 51 | IdleTimeout: 240 * time.Second, 52 | Dial: func() (redis.Conn, error) { 53 | c, err := redis.Dial("tcp", options["server"]) 54 | if err != nil { 55 | return nil, err 56 | } 57 | if options["password"] != "" { 58 | if _, err := c.Do("AUTH", options["password"]); err != nil { 59 | c.Close() 60 | return nil, err 61 | } 62 | } 63 | if options["database"] != "" { 64 | if _, err := c.Do("SELECT", options["database"]); err != nil { 65 | c.Close() 66 | return nil, err 67 | } 68 | } 69 | return c, err 70 | }, 71 | TestOnBorrow: func(c redis.Conn, t time.Time) error { 72 | _, err := c.Do("PING") 73 | return err 74 | }, 75 | }, 76 | func(queue string) Fetcher { 77 | return NewFetch(queue, make(chan *Msg), make(chan bool)) 78 | }, 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/config_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/customerio/gospec" 5 | . "github.com/customerio/gospec" 6 | ) 7 | 8 | func ConfigSpec(c gospec.Context) { 9 | var recoverOnPanic = func(f func()) (err interface{}) { 10 | defer func() { 11 | if cause := recover(); cause != nil { 12 | err = cause 13 | } 14 | }() 15 | 16 | f() 17 | 18 | return 19 | } 20 | 21 | c.Specify("sets redis pool size which defaults to 1", func() { 22 | c.Expect(Config.Pool.MaxIdle, Equals, 1) 23 | 24 | Configure(map[string]string{ 25 | "server": "localhost:6379", 26 | "process": "1", 27 | "pool": "20", 28 | }) 29 | 30 | c.Expect(Config.Pool.MaxIdle, Equals, 20) 31 | }) 32 | 33 | c.Specify("can specify custom process", func() { 34 | c.Expect(Config.processId, Equals, "1") 35 | 36 | Configure(map[string]string{ 37 | "server": "localhost:6379", 38 | "process": "2", 39 | }) 40 | 41 | c.Expect(Config.processId, Equals, "2") 42 | }) 43 | 44 | c.Specify("requires a server parameter", func() { 45 | err := recoverOnPanic(func() { 46 | Configure(map[string]string{"process": "2"}) 47 | }) 48 | 49 | c.Expect(err, Equals, "Configure requires a 'server' option, which identifies a Redis instance") 50 | }) 51 | 52 | c.Specify("requires a process parameter", func() { 53 | err := recoverOnPanic(func() { 54 | Configure(map[string]string{"server": "localhost:6379"}) 55 | }) 56 | 57 | c.Expect(err, Equals, "Configure requires a 'process' option, which uniquely identifies this instance") 58 | }) 59 | 60 | c.Specify("adds ':' to the end of the namespace", func() { 61 | c.Expect(Config.Namespace, Equals, "") 62 | 63 | Configure(map[string]string{ 64 | "server": "localhost:6379", 65 | "process": "1", 66 | "namespace": "prod", 67 | }) 68 | 69 | c.Expect(Config.Namespace, Equals, "prod:") 70 | }) 71 | 72 | c.Specify("defaults poll interval to 15 seconds", func() { 73 | Configure(map[string]string{ 74 | "server": "localhost:6379", 75 | "process": "1", 76 | }) 77 | 78 | c.Expect(Config.PollInterval, Equals, 15) 79 | }) 80 | 81 | c.Specify("allows customization of poll interval", func() { 82 | Configure(map[string]string{ 83 | "server": "localhost:6379", 84 | "process": "1", 85 | "poll_interval": "1", 86 | }) 87 | 88 | c.Expect(Config.PollInterval, Equals, 1) 89 | }) 90 | } 91 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/hooks.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | var beforeStart []func() 4 | var duringDrain []func() 5 | 6 | func BeforeStart(f func()) { 7 | access.Lock() 8 | defer access.Unlock() 9 | beforeStart = append(beforeStart, f) 10 | } 11 | 12 | // func AfterStart 13 | // func BeforeQuit 14 | // func AfterQuit 15 | 16 | func DuringDrain(f func()) { 17 | access.Lock() 18 | defer access.Unlock() 19 | duringDrain = append(duringDrain, f) 20 | } 21 | 22 | func runHooks(hooks []func()) { 23 | for _, f := range hooks { 24 | f() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/job.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | type jobFunc func(message *Msg) 4 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/manager.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | ) 7 | 8 | type manager struct { 9 | queue string 10 | fetch Fetcher 11 | job jobFunc 12 | concurrency int 13 | workers []*worker 14 | workersM *sync.Mutex 15 | confirm chan *Msg 16 | stop chan bool 17 | exit chan bool 18 | mids *Middlewares 19 | *sync.WaitGroup 20 | } 21 | 22 | func (m *manager) start() { 23 | m.Add(1) 24 | m.loadWorkers() 25 | go m.manage() 26 | } 27 | 28 | func (m *manager) prepare() { 29 | if !m.fetch.Closed() { 30 | m.fetch.Close() 31 | } 32 | } 33 | 34 | func (m *manager) quit() { 35 | Logger.Println("quitting queue", m.queueName(), "(waiting for", m.processing(), "/", len(m.workers), "workers).") 36 | m.prepare() 37 | 38 | m.workersM.Lock() 39 | for _, worker := range m.workers { 40 | worker.quit() 41 | } 42 | m.workersM.Unlock() 43 | 44 | m.stop <- true 45 | <-m.exit 46 | 47 | m.reset() 48 | 49 | m.Done() 50 | } 51 | 52 | func (m *manager) manage() { 53 | Logger.Println("processing queue", m.queueName(), "with", m.concurrency, "workers.") 54 | 55 | go m.fetch.Fetch() 56 | 57 | for { 58 | select { 59 | case message := <-m.confirm: 60 | m.fetch.Acknowledge(message) 61 | case <-m.stop: 62 | m.exit <- true 63 | break 64 | } 65 | } 66 | } 67 | 68 | func (m *manager) loadWorkers() { 69 | m.workersM.Lock() 70 | for i := 0; i < m.concurrency; i++ { 71 | m.workers[i] = newWorker(m) 72 | m.workers[i].start() 73 | } 74 | m.workersM.Unlock() 75 | } 76 | 77 | func (m *manager) processing() (count int) { 78 | m.workersM.Lock() 79 | for _, worker := range m.workers { 80 | if worker.processing() { 81 | count++ 82 | } 83 | } 84 | m.workersM.Unlock() 85 | return 86 | } 87 | 88 | func (m *manager) queueName() string { 89 | return strings.Replace(m.queue, "queue:", "", 1) 90 | } 91 | 92 | func (m *manager) reset() { 93 | m.fetch = Config.Fetch(m.queue) 94 | } 95 | 96 | func newManager(queue string, job jobFunc, concurrency int, mids ...Action) *manager { 97 | var customMids *Middlewares 98 | if len(mids) == 0 { 99 | customMids = Middleware 100 | } else { 101 | customMids = NewMiddleware(Middleware.actions...) 102 | for _, m := range mids { 103 | customMids.Append(m) 104 | } 105 | } 106 | m := &manager{ 107 | Config.Namespace + "queue:" + queue, 108 | nil, 109 | job, 110 | concurrency, 111 | make([]*worker, concurrency), 112 | &sync.Mutex{}, 113 | make(chan *Msg), 114 | make(chan bool), 115 | make(chan bool), 116 | customMids, 117 | &sync.WaitGroup{}, 118 | } 119 | 120 | m.fetch = Config.Fetch(m.queue) 121 | 122 | return m 123 | } 124 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | type Action interface { 4 | Call(queue string, message *Msg, next func() bool) bool 5 | } 6 | 7 | type Middlewares struct { 8 | actions []Action 9 | } 10 | 11 | func (m *Middlewares) Append(action Action) { 12 | m.actions = append(m.actions, action) 13 | } 14 | 15 | func (m *Middlewares) Prepend(action Action) { 16 | actions := make([]Action, len(m.actions)+1) 17 | actions[0] = action 18 | copy(actions[1:], m.actions) 19 | m.actions = actions 20 | } 21 | 22 | func (m *Middlewares) call(queue string, message *Msg, final func()) bool { 23 | return continuation(m.actions, queue, message, final)() 24 | } 25 | 26 | func continuation(actions []Action, queue string, message *Msg, final func()) func() bool { 27 | return func() (acknowledge bool) { 28 | if len(actions) > 0 { 29 | acknowledge = actions[0].Call( 30 | queue, 31 | message, 32 | continuation(actions[1:], queue, message, final), 33 | ) 34 | 35 | if !acknowledge { 36 | return 37 | } 38 | } else { 39 | final() 40 | } 41 | 42 | return true 43 | } 44 | } 45 | 46 | func NewMiddleware(actions ...Action) *Middlewares { 47 | return &Middlewares{actions} 48 | } 49 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware_logging.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "time" 7 | ) 8 | 9 | type MiddlewareLogging struct{} 10 | 11 | func (l *MiddlewareLogging) Call(queue string, message *Msg, next func() bool) (acknowledge bool) { 12 | prefix := fmt.Sprint(queue, " JID-", message.Jid()) 13 | 14 | start := time.Now() 15 | Logger.Println(prefix, "start") 16 | Logger.Println(prefix, "args:", message.Args().ToJson()) 17 | 18 | defer func() { 19 | if e := recover(); e != nil { 20 | Logger.Println(prefix, "fail:", time.Since(start)) 21 | 22 | buf := make([]byte, 4096) 23 | buf = buf[:runtime.Stack(buf, false)] 24 | Logger.Printf("%s error: %v\n%s", prefix, e, buf) 25 | 26 | panic(e) 27 | } 28 | }() 29 | 30 | acknowledge = next() 31 | 32 | Logger.Println(prefix, "done:", time.Since(start)) 33 | 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware_retry.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "math/rand" 7 | "time" 8 | ) 9 | 10 | const ( 11 | DEFAULT_MAX_RETRY = 25 12 | LAYOUT = "2006-01-02 15:04:05 MST" 13 | ) 14 | 15 | type MiddlewareRetry struct{} 16 | 17 | func (r *MiddlewareRetry) Call(queue string, message *Msg, next func() bool) (acknowledge bool) { 18 | defer func() { 19 | if e := recover(); e != nil { 20 | conn := Config.Pool.Get() 21 | defer conn.Close() 22 | 23 | if retry(message) { 24 | message.Set("queue", queue) 25 | message.Set("error_message", fmt.Sprintf("%v", e)) 26 | retryCount := incrementRetry(message) 27 | 28 | waitDuration := durationToSecondsWithNanoPrecision( 29 | time.Duration( 30 | secondsToDelay(retryCount), 31 | ) * time.Second, 32 | ) 33 | 34 | _, err := conn.Do( 35 | "zadd", 36 | Config.Namespace+RETRY_KEY, 37 | nowToSecondsWithNanoPrecision()+waitDuration, 38 | message.ToJson(), 39 | ) 40 | 41 | // If we can't add the job to the retry queue, 42 | // then we shouldn't acknowledge the job, otherwise 43 | // it'll disappear into the void. 44 | if err != nil { 45 | acknowledge = false 46 | } 47 | } 48 | 49 | panic(e) 50 | } 51 | }() 52 | 53 | acknowledge = next() 54 | 55 | return 56 | } 57 | 58 | func retry(message *Msg) bool { 59 | retry := false 60 | max := DEFAULT_MAX_RETRY 61 | 62 | if param, err := message.Get("retry").Bool(); err == nil { 63 | retry = param 64 | } else if param, err := message.Get("retry").Int(); err == nil { 65 | max = param 66 | retry = true 67 | } 68 | 69 | count, _ := message.Get("retry_count").Int() 70 | 71 | return retry && count < max 72 | } 73 | 74 | func incrementRetry(message *Msg) (retryCount int) { 75 | retryCount = 0 76 | 77 | if count, err := message.Get("retry_count").Int(); err != nil { 78 | message.Set("failed_at", time.Now().UTC().Format(LAYOUT)) 79 | } else { 80 | message.Set("retried_at", time.Now().UTC().Format(LAYOUT)) 81 | retryCount = count + 1 82 | } 83 | 84 | message.Set("retry_count", retryCount) 85 | 86 | return 87 | } 88 | 89 | func secondsToDelay(count int) int { 90 | power := math.Pow(float64(count), 4) 91 | return int(power) + 15 + (rand.Intn(30) * (count + 1)) 92 | } 93 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware_stats.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type MiddlewareStats struct{} 8 | 9 | func (l *MiddlewareStats) Call(queue string, message *Msg, next func() bool) (acknowledge bool) { 10 | defer func() { 11 | if e := recover(); e != nil { 12 | incrementStats("failed") 13 | panic(e) 14 | } 15 | }() 16 | 17 | acknowledge = next() 18 | 19 | incrementStats("processed") 20 | 21 | return 22 | } 23 | 24 | func incrementStats(metric string) { 25 | conn := Config.Pool.Get() 26 | defer conn.Close() 27 | 28 | today := time.Now().UTC().Format("2006-01-02") 29 | 30 | conn.Send("multi") 31 | conn.Send("incr", Config.Namespace+"stat:"+metric) 32 | conn.Send("incr", Config.Namespace+"stat:"+metric+":"+today) 33 | 34 | if _, err := conn.Do("exec"); err != nil { 35 | Logger.Println("couldn't save stats:", err) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware_stats_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/customerio/gospec" 5 | . "github.com/customerio/gospec" 6 | "github.com/garyburd/redigo/redis" 7 | "time" 8 | ) 9 | 10 | func MiddlewareStatsSpec(c gospec.Context) { 11 | var job = (func(message *Msg) { 12 | // noop 13 | }) 14 | 15 | layout := "2006-01-02" 16 | manager := newManager("myqueue", job, 1) 17 | worker := newWorker(manager) 18 | message, _ := NewMsg("{\"jid\":\"2\",\"retry\":true}") 19 | 20 | was := Config.Namespace 21 | Config.Namespace = "prod:" 22 | 23 | c.Specify("increments processed stats", func() { 24 | conn := Config.Pool.Get() 25 | defer conn.Close() 26 | 27 | count, _ := redis.Int(conn.Do("get", "prod:stat:processed")) 28 | dayCount, _ := redis.Int(conn.Do("get", "prod:stat:processed:"+time.Now().UTC().Format(layout))) 29 | 30 | c.Expect(count, Equals, 0) 31 | c.Expect(dayCount, Equals, 0) 32 | 33 | worker.process(message) 34 | 35 | count, _ = redis.Int(conn.Do("get", "prod:stat:processed")) 36 | dayCount, _ = redis.Int(conn.Do("get", "prod:stat:processed:"+time.Now().UTC().Format(layout))) 37 | 38 | c.Expect(count, Equals, 1) 39 | c.Expect(dayCount, Equals, 1) 40 | }) 41 | 42 | c.Specify("failed job", func() { 43 | var job = (func(message *Msg) { 44 | panic("AHHHH") 45 | }) 46 | 47 | manager := newManager("myqueue", job, 1) 48 | worker := newWorker(manager) 49 | 50 | c.Specify("increments failed stats", func() { 51 | conn := Config.Pool.Get() 52 | defer conn.Close() 53 | 54 | count, _ := redis.Int(conn.Do("get", "prod:stat:failed")) 55 | dayCount, _ := redis.Int(conn.Do("get", "prod:stat:failed:"+time.Now().UTC().Format(layout))) 56 | 57 | c.Expect(count, Equals, 0) 58 | c.Expect(dayCount, Equals, 0) 59 | 60 | worker.process(message) 61 | 62 | count, _ = redis.Int(conn.Do("get", "prod:stat:failed")) 63 | dayCount, _ = redis.Int(conn.Do("get", "prod:stat:failed:"+time.Now().UTC().Format(layout))) 64 | 65 | c.Expect(count, Equals, 1) 66 | c.Expect(dayCount, Equals, 1) 67 | }) 68 | }) 69 | 70 | Config.Namespace = was 71 | } 72 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/middleware_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/customerio/gospec" 5 | . "github.com/customerio/gospec" 6 | ) 7 | 8 | func arrayCompare(a1, a2 []string) bool { 9 | if len(a1) != len(a2) { 10 | return false 11 | } 12 | 13 | for i := 0; i < len(a1); i++ { 14 | if a1[i] != a2[i] { 15 | return false 16 | } 17 | } 18 | 19 | return true 20 | } 21 | 22 | var order = make([]string, 0) 23 | 24 | type m1 struct{} 25 | type m2 struct{} 26 | 27 | func (m *m1) Call(queue string, message *Msg, next func() bool) (result bool) { 28 | order = append(order, "m1 enter") 29 | result = next() 30 | order = append(order, "m1 leave") 31 | return 32 | } 33 | 34 | func (m *m2) Call(queue string, message *Msg, next func() bool) (result bool) { 35 | order = append(order, "m2 enter") 36 | result = next() 37 | order = append(order, "m2 leave") 38 | return 39 | } 40 | 41 | func MiddlewareSpec(c gospec.Context) { 42 | middleware := NewMiddleware() 43 | message, _ := NewMsg("{\"foo\":\"bar\"}") 44 | order = make([]string, 0) 45 | first := &m1{} 46 | second := &m2{} 47 | 48 | c.Specify("newMiddleware", func() { 49 | c.Specify("doesn't contain any middleware", func() { 50 | c.Expect(len(middleware.actions), Equals, 0) 51 | }) 52 | 53 | c.Specify("can specify middleware when initializing", func() { 54 | middleware = NewMiddleware(first, second) 55 | c.Expect(middleware.actions[0], Equals, first) 56 | c.Expect(middleware.actions[1], Equals, second) 57 | }) 58 | }) 59 | 60 | c.Specify("Append", func() { 61 | c.Specify("adds function at the end of the list", func() { 62 | middleware.Append(first) 63 | middleware.Append(second) 64 | 65 | middleware.call("myqueue", message, func() { 66 | order = append(order, "job") 67 | }) 68 | 69 | c.Expect( 70 | arrayCompare(order, []string{ 71 | "m1 enter", 72 | "m2 enter", 73 | "job", 74 | "m2 leave", 75 | "m1 leave", 76 | }), 77 | IsTrue, 78 | ) 79 | }) 80 | }) 81 | 82 | c.Specify("{repend", func() { 83 | c.Specify("adds function at the beginning of the list", func() { 84 | middleware.Prepend(first) 85 | middleware.Prepend(second) 86 | 87 | middleware.call("myqueue", message, func() { 88 | order = append(order, "job") 89 | }) 90 | 91 | c.Expect( 92 | arrayCompare(order, []string{ 93 | "m2 enter", 94 | "m1 enter", 95 | "job", 96 | "m1 leave", 97 | "m2 leave", 98 | }), 99 | IsTrue, 100 | ) 101 | }) 102 | }) 103 | } 104 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/msg.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/bitly/go-simplejson" 5 | "reflect" 6 | ) 7 | 8 | type data struct { 9 | *simplejson.Json 10 | } 11 | 12 | type Msg struct { 13 | *data 14 | original string 15 | } 16 | 17 | type Args struct { 18 | *data 19 | } 20 | 21 | func (m *Msg) Jid() string { 22 | return m.Get("jid").MustString() 23 | } 24 | 25 | func (m *Msg) Args() *Args { 26 | if args, ok := m.CheckGet("args"); ok { 27 | return &Args{&data{args}} 28 | } else { 29 | d, _ := newData("[]") 30 | return &Args{d} 31 | } 32 | } 33 | 34 | func (m *Msg) OriginalJson() string { 35 | return m.original 36 | } 37 | 38 | func (d *data) ToJson() string { 39 | json, err := d.Encode() 40 | 41 | if err != nil { 42 | Logger.Println("ERR: Couldn't generate json from", d, ":", err) 43 | } 44 | 45 | return string(json) 46 | } 47 | 48 | func (d *data) Equals(other interface{}) bool { 49 | otherJson := reflect.ValueOf(other).MethodByName("ToJson").Call([]reflect.Value{}) 50 | return d.ToJson() == otherJson[0].String() 51 | } 52 | 53 | func NewMsg(content string) (*Msg, error) { 54 | if d, err := newData(content); err != nil { 55 | return nil, err 56 | } else { 57 | return &Msg{d, content}, nil 58 | } 59 | } 60 | 61 | func newData(content string) (*data, error) { 62 | if json, err := simplejson.NewJson([]byte(content)); err != nil { 63 | return nil, err 64 | } else { 65 | return &data{json}, nil 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/msg_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/customerio/gospec" 5 | . "github.com/customerio/gospec" 6 | ) 7 | 8 | func MsgSpec(c gospec.Context) { 9 | c.Specify("NewMsg", func() { 10 | c.Specify("unmarshals json", func() { 11 | msg, _ := NewMsg("{\"hello\":\"world\",\"foo\":3}") 12 | hello, _ := msg.Get("hello").String() 13 | foo, _ := msg.Get("foo").Int() 14 | 15 | c.Expect(hello, Equals, "world") 16 | c.Expect(foo, Equals, 3) 17 | }) 18 | 19 | c.Specify("returns an error if invalid json", func() { 20 | msg, err := NewMsg("{\"hello:\"world\",\"foo\":3}") 21 | 22 | c.Expect(msg, IsNil) 23 | c.Expect(err, Not(IsNil)) 24 | }) 25 | }) 26 | 27 | c.Specify("Args", func() { 28 | c.Specify("returns args key", func() { 29 | msg, _ := NewMsg("{\"hello\":\"world\",\"args\":[\"foo\",\"bar\"]}") 30 | c.Expect(msg.Args().ToJson(), Equals, "[\"foo\",\"bar\"]") 31 | }) 32 | 33 | c.Specify("returns empty array if args key doesn't exist", func() { 34 | msg, _ := NewMsg("{\"hello\":\"world\"}") 35 | c.Expect(msg.Args().ToJson(), Equals, "[]") 36 | }) 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/scheduled.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "strings" 5 | "time" 6 | 7 | "github.com/garyburd/redigo/redis" 8 | ) 9 | 10 | type scheduled struct { 11 | keys []string 12 | closed chan bool 13 | exit chan bool 14 | } 15 | 16 | func (s *scheduled) start() { 17 | go (func() { 18 | for { 19 | select { 20 | case <-s.closed: 21 | return 22 | default: 23 | } 24 | 25 | s.poll() 26 | 27 | time.Sleep(time.Duration(Config.PollInterval) * time.Second) 28 | } 29 | })() 30 | } 31 | 32 | func (s *scheduled) quit() { 33 | close(s.closed) 34 | } 35 | 36 | func (s *scheduled) poll() { 37 | conn := Config.Pool.Get() 38 | 39 | now := nowToSecondsWithNanoPrecision() 40 | 41 | for _, key := range s.keys { 42 | key = Config.Namespace + key 43 | for { 44 | messages, _ := redis.Strings(conn.Do("zrangebyscore", key, "-inf", now, "limit", 0, 1)) 45 | 46 | if len(messages) == 0 { 47 | break 48 | } 49 | 50 | message, _ := NewMsg(messages[0]) 51 | 52 | if removed, _ := redis.Bool(conn.Do("zrem", key, messages[0])); removed { 53 | queue, _ := message.Get("queue").String() 54 | queue = strings.TrimPrefix(queue, Config.Namespace) 55 | message.Set("enqueued_at", nowToSecondsWithNanoPrecision()) 56 | conn.Do("lpush", Config.Namespace+"queue:"+queue, message.ToJson()) 57 | } 58 | } 59 | } 60 | 61 | conn.Close() 62 | } 63 | 64 | func newScheduled(keys ...string) *scheduled { 65 | return &scheduled{keys, make(chan bool), make(chan bool)} 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/scheduled_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "github.com/customerio/gospec" 5 | . "github.com/customerio/gospec" 6 | "github.com/garyburd/redigo/redis" 7 | ) 8 | 9 | func ScheduledSpec(c gospec.Context) { 10 | scheduled := newScheduled(RETRY_KEY) 11 | 12 | was := Config.Namespace 13 | Config.Namespace = "prod:" 14 | 15 | c.Specify("empties retry queues up to the current time", func() { 16 | conn := Config.Pool.Get() 17 | defer conn.Close() 18 | 19 | now := nowToSecondsWithNanoPrecision() 20 | 21 | message1, _ := NewMsg("{\"queue\":\"default\",\"foo\":\"bar1\"}") 22 | message2, _ := NewMsg("{\"queue\":\"myqueue\",\"foo\":\"bar2\"}") 23 | message3, _ := NewMsg("{\"queue\":\"default\",\"foo\":\"bar3\"}") 24 | 25 | conn.Do("zadd", "prod:"+RETRY_KEY, now-60.0, message1.ToJson()) 26 | conn.Do("zadd", "prod:"+RETRY_KEY, now-10.0, message2.ToJson()) 27 | conn.Do("zadd", "prod:"+RETRY_KEY, now+60.0, message3.ToJson()) 28 | 29 | scheduled.poll() 30 | 31 | defaultCount, _ := redis.Int(conn.Do("llen", "prod:queue:default")) 32 | myqueueCount, _ := redis.Int(conn.Do("llen", "prod:queue:myqueue")) 33 | pending, _ := redis.Int(conn.Do("zcard", "prod:"+RETRY_KEY)) 34 | 35 | c.Expect(defaultCount, Equals, 1) 36 | c.Expect(myqueueCount, Equals, 1) 37 | c.Expect(pending, Equals, 1) 38 | }) 39 | 40 | Config.Namespace = was 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/signals_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package workers 4 | 5 | import ( 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | ) 10 | 11 | func handleSignals() { 12 | signals := make(chan os.Signal, 1) 13 | signal.Notify(signals, syscall.SIGUSR1, syscall.SIGINT, syscall.SIGTERM) 14 | 15 | for sig := range signals { 16 | switch sig { 17 | case syscall.SIGINT, syscall.SIGUSR1, syscall.SIGTERM: 18 | Quit() 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/signals_windows.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "os" 5 | "os/signal" 6 | "syscall" 7 | ) 8 | 9 | func handleSignals() { 10 | signals := make(chan os.Signal, 1) 11 | signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) 12 | 13 | for sig := range signals { 14 | switch sig { 15 | case syscall.SIGINT, syscall.SIGTERM: 16 | Quit() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/stats.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "net/http" 7 | "strconv" 8 | ) 9 | 10 | type stats struct { 11 | Processed int `json:"processed"` 12 | Failed int `json:"failed"` 13 | Jobs interface{} `json:"jobs"` 14 | Enqueued interface{} `json:"enqueued"` 15 | Retries int64 `json:"retries"` 16 | } 17 | 18 | func Stats(w http.ResponseWriter, req *http.Request) { 19 | w.Header().Set("Content-Type", "application/json; charset=utf-8") 20 | w.Header().Set("Access-Control-Allow-Origin", "*") 21 | 22 | jobs := make(map[string][]*map[string]interface{}) 23 | enqueued := make(map[string]string) 24 | 25 | for _, m := range managers { 26 | queue := m.queueName() 27 | jobs[queue] = make([]*map[string]interface{}, 0) 28 | enqueued[queue] = "" 29 | for _, worker := range m.workers { 30 | message := worker.currentMsg 31 | startedAt := worker.startedAt 32 | 33 | if message != nil && startedAt > 0 { 34 | jobs[queue] = append(jobs[queue], &map[string]interface{}{ 35 | "message": message, 36 | "started_at": startedAt, 37 | }) 38 | } 39 | } 40 | } 41 | 42 | stats := stats{ 43 | 0, 44 | 0, 45 | jobs, 46 | enqueued, 47 | 0, 48 | } 49 | 50 | conn := Config.Pool.Get() 51 | defer conn.Close() 52 | 53 | conn.Send("multi") 54 | conn.Send("get", Config.Namespace+"stat:processed") 55 | conn.Send("get", Config.Namespace+"stat:failed") 56 | conn.Send("zcard", Config.Namespace+RETRY_KEY) 57 | 58 | for key, _ := range enqueued { 59 | conn.Send("llen", fmt.Sprintf("%squeue:%s", Config.Namespace, key)) 60 | } 61 | 62 | r, err := conn.Do("exec") 63 | 64 | if err != nil { 65 | Logger.Println("couldn't retrieve stats:", err) 66 | } 67 | 68 | results := r.([]interface{}) 69 | if len(results) == (3 + len(enqueued)) { 70 | for index, result := range results { 71 | if index == 0 && result != nil { 72 | stats.Processed, _ = strconv.Atoi(string(result.([]byte))) 73 | continue 74 | } 75 | if index == 1 && result != nil { 76 | stats.Failed, _ = strconv.Atoi(string(result.([]byte))) 77 | continue 78 | } 79 | 80 | if index == 2 && result != nil { 81 | stats.Retries = result.(int64) 82 | continue 83 | } 84 | 85 | queueIndex := 0 86 | for key, _ := range enqueued { 87 | if queueIndex == (index - 3) { 88 | enqueued[key] = fmt.Sprintf("%d", result.(int64)) 89 | } 90 | queueIndex++ 91 | } 92 | } 93 | } 94 | 95 | body, _ := json.MarshalIndent(stats, "", " ") 96 | fmt.Fprintln(w, string(body)) 97 | } 98 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/worker.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "sync/atomic" 5 | "time" 6 | ) 7 | 8 | type worker struct { 9 | manager *manager 10 | stop chan bool 11 | exit chan bool 12 | currentMsg *Msg 13 | startedAt int64 14 | } 15 | 16 | func (w *worker) start() { 17 | go w.work(w.manager.fetch.Messages()) 18 | } 19 | 20 | func (w *worker) quit() { 21 | w.stop <- true 22 | <-w.exit 23 | } 24 | 25 | func (w *worker) work(messages chan *Msg) { 26 | for { 27 | select { 28 | case message := <-messages: 29 | atomic.StoreInt64(&w.startedAt, time.Now().UTC().Unix()) 30 | w.currentMsg = message 31 | 32 | if w.process(message) { 33 | w.manager.confirm <- message 34 | } 35 | 36 | atomic.StoreInt64(&w.startedAt, 0) 37 | w.currentMsg = nil 38 | 39 | // Attempt to tell fetcher we're finished. 40 | // Can be used when the fetcher has slept due 41 | // to detecting an empty queue to requery the 42 | // queue immediately if we finish work. 43 | select { 44 | case w.manager.fetch.FinishedWork() <- true: 45 | default: 46 | } 47 | case w.manager.fetch.Ready() <- true: 48 | // Signaled to fetcher that we're 49 | // ready to accept a message 50 | case <-w.stop: 51 | w.exit <- true 52 | return 53 | } 54 | } 55 | } 56 | 57 | func (w *worker) process(message *Msg) (acknowledge bool) { 58 | acknowledge = true 59 | 60 | defer func() { 61 | recover() 62 | }() 63 | 64 | return w.manager.mids.call(w.manager.queueName(), message, func() { 65 | w.manager.job(message) 66 | }) 67 | } 68 | 69 | func (w *worker) processing() bool { 70 | return atomic.LoadInt64(&w.startedAt) > 0 71 | } 72 | 73 | func newWorker(m *manager) *worker { 74 | return &worker{m, make(chan bool), make(chan bool), nil, 0} 75 | } 76 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/workers.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "log" 7 | "net/http" 8 | "os" 9 | "sync" 10 | ) 11 | 12 | const ( 13 | RETRY_KEY = "goretry" 14 | SCHEDULED_JOBS_KEY = "schedule" 15 | ) 16 | 17 | var Logger WorkersLogger = log.New(os.Stdout, "workers: ", log.Ldate|log.Lmicroseconds) 18 | 19 | var managers = make(map[string]*manager) 20 | var schedule *scheduled 21 | var control = make(map[string]chan string) 22 | var access sync.Mutex 23 | var started bool 24 | 25 | var Middleware = NewMiddleware( 26 | &MiddlewareLogging{}, 27 | &MiddlewareRetry{}, 28 | &MiddlewareStats{}, 29 | ) 30 | 31 | func Process(queue string, job jobFunc, concurrency int, mids ...Action) { 32 | access.Lock() 33 | defer access.Unlock() 34 | 35 | managers[queue] = newManager(queue, job, concurrency, mids...) 36 | } 37 | 38 | func Run() { 39 | Start() 40 | go handleSignals() 41 | waitForExit() 42 | } 43 | 44 | func ResetManagers() error { 45 | access.Lock() 46 | defer access.Unlock() 47 | 48 | if started { 49 | return errors.New("Cannot reset worker managers while workers are running") 50 | } 51 | 52 | managers = make(map[string]*manager) 53 | 54 | return nil 55 | } 56 | 57 | func Start() { 58 | access.Lock() 59 | defer access.Unlock() 60 | 61 | if started { 62 | return 63 | } 64 | 65 | runHooks(beforeStart) 66 | startSchedule() 67 | startManagers() 68 | 69 | started = true 70 | } 71 | 72 | func Quit() { 73 | access.Lock() 74 | defer access.Unlock() 75 | 76 | if !started { 77 | return 78 | } 79 | 80 | quitManagers() 81 | quitSchedule() 82 | runHooks(duringDrain) 83 | waitForExit() 84 | 85 | started = false 86 | } 87 | 88 | func StatsServer(port int) { 89 | http.HandleFunc("/stats", Stats) 90 | 91 | Logger.Println("Stats are available at", fmt.Sprint("http://localhost:", port, "/stats")) 92 | 93 | if err := http.ListenAndServe(fmt.Sprint(":", port), nil); err != nil { 94 | Logger.Println(err) 95 | } 96 | } 97 | 98 | func startSchedule() { 99 | if schedule == nil { 100 | schedule = newScheduled(RETRY_KEY, SCHEDULED_JOBS_KEY) 101 | } 102 | 103 | schedule.start() 104 | } 105 | 106 | func quitSchedule() { 107 | if schedule != nil { 108 | schedule.quit() 109 | schedule = nil 110 | } 111 | } 112 | 113 | func startManagers() { 114 | for _, manager := range managers { 115 | manager.start() 116 | } 117 | } 118 | 119 | func quitManagers() { 120 | for _, m := range managers { 121 | go (func(m *manager) { m.quit() })(m) 122 | } 123 | } 124 | 125 | func waitForExit() { 126 | for _, manager := range managers { 127 | manager.Wait() 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/workers_logger.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | type WorkersLogger interface { 4 | Println(...interface{}) 5 | Printf(string, ...interface{}) 6 | } 7 | -------------------------------------------------------------------------------- /vendor/github.com/jrallison/go-workers/workers_test.go: -------------------------------------------------------------------------------- 1 | package workers 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/customerio/gospec" 7 | . "github.com/customerio/gospec" 8 | ) 9 | 10 | var called chan bool 11 | 12 | func myJob(message *Msg) { 13 | called <- true 14 | } 15 | 16 | func WorkersSpec(c gospec.Context) { 17 | c.Specify("Workers", func() { 18 | c.Specify("allows running in tests", func() { 19 | called = make(chan bool) 20 | 21 | Process("myqueue", myJob, 10) 22 | 23 | Start() 24 | 25 | Enqueue("myqueue", "Add", []int{1, 2}) 26 | <-called 27 | 28 | Quit() 29 | }) 30 | 31 | // TODO make this test more deterministic, randomly locks up in travis. 32 | //c.Specify("allows starting and stopping multiple times", func() { 33 | // called = make(chan bool) 34 | 35 | // Process("myqueue", myJob, 10) 36 | 37 | // Start() 38 | // Quit() 39 | 40 | // Start() 41 | 42 | // Enqueue("myqueue", "Add", []int{1, 2}) 43 | // <-called 44 | 45 | // Quit() 46 | //}) 47 | 48 | c.Specify("runs beforeStart hooks", func() { 49 | hooks := []string{} 50 | 51 | BeforeStart(func() { 52 | hooks = append(hooks, "1") 53 | }) 54 | BeforeStart(func() { 55 | hooks = append(hooks, "2") 56 | }) 57 | BeforeStart(func() { 58 | hooks = append(hooks, "3") 59 | }) 60 | 61 | Start() 62 | 63 | c.Expect(reflect.DeepEqual(hooks, []string{"1", "2", "3"}), IsTrue) 64 | 65 | Quit() 66 | 67 | // Clear out global hooks variable 68 | beforeStart = nil 69 | }) 70 | 71 | c.Specify("runs beforeStart hooks", func() { 72 | hooks := []string{} 73 | 74 | DuringDrain(func() { 75 | hooks = append(hooks, "1") 76 | }) 77 | DuringDrain(func() { 78 | hooks = append(hooks, "2") 79 | }) 80 | DuringDrain(func() { 81 | hooks = append(hooks, "3") 82 | }) 83 | 84 | Start() 85 | 86 | c.Expect(reflect.DeepEqual(hooks, []string{}), IsTrue) 87 | 88 | Quit() 89 | 90 | c.Expect(reflect.DeepEqual(hooks, []string{"1", "2", "3"}), IsTrue) 91 | 92 | // Clear out global hooks variable 93 | duringDrain = nil 94 | }) 95 | }) 96 | } 97 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#*# 3 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.2 6 | - tip 7 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/README.md: -------------------------------------------------------------------------------- 1 | # Builder - fluent immutable builders for Go 2 | 3 | [![GoDoc](https://godoc.org/github.com/lann/builder?status.png)](https://godoc.org/github.com/lann/builder) 4 | [![Build Status](https://travis-ci.org/lann/builder.png?branch=master)](https://travis-ci.org/lann/builder) 5 | 6 | Builder was originally written for 7 | [Squirrel](https://github.com/lann/squirrel), a fluent SQL generator. It 8 | is probably the best example of Builder in action. 9 | 10 | Builder helps you write **fluent** DSLs for your libraries with method chaining: 11 | 12 | ```go 13 | resp := ReqBuilder. 14 | Url("http://golang.org"). 15 | Header("User-Agent", "Builder"). 16 | Get() 17 | ``` 18 | 19 | Builder uses **immutable** persistent data structures 20 | ([these](https://github.com/mndrix/ps), specifically) 21 | so that each step in your method chain can be reused: 22 | 23 | ```go 24 | build := WordBuilder.AddLetters("Build") 25 | builder := build.AddLetters("er") 26 | building := build.AddLetters("ing") 27 | ``` 28 | 29 | Builder makes it easy to **build** structs using the **builder** pattern 30 | (*surprise!*): 31 | 32 | ```go 33 | import "github.com/lann/builder" 34 | 35 | type Muppet struct { 36 | Name string 37 | Friends []string 38 | } 39 | 40 | type muppetBuilder builder.Builder 41 | 42 | func (b muppetBuilder) Name(name string) muppetBuilder { 43 | return builder.Set(b, "Name", name).(muppetBuilder) 44 | } 45 | 46 | func (b muppetBuilder) AddFriend(friend string) muppetBuilder { 47 | return builder.Append(b, "Friends", friend).(muppetBuilder) 48 | } 49 | 50 | func (b muppetBuilder) Build() Muppet { 51 | return builder.GetStruct(b).(Muppet) 52 | } 53 | 54 | var MuppetBuilder = builder.Register(muppetBuilder{}, Muppet{}).(muppetBuilder) 55 | ``` 56 | ```go 57 | MuppetBuilder. 58 | Name("Beaker"). 59 | AddFriend("Dr. Honeydew"). 60 | Build() 61 | 62 | => Muppet{Name:"Beaker", Friends:[]string{"Dr. Honeydew"}} 63 | ``` 64 | 65 | ## License 66 | 67 | Builder is released under the 68 | [MIT License](http://www.opensource.org/licenses/MIT). 69 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/example_test.go: -------------------------------------------------------------------------------- 1 | package builder_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/lann/builder" 6 | ) 7 | 8 | // Simple math expression allowing multiple adds/subtracts and a single 9 | // (optional) multiply. 10 | type simpleExpr struct { 11 | Multiplier int 12 | Adds []int 13 | Subtracts []int 14 | } 15 | 16 | func (e simpleExpr) Equals() (total int) { 17 | for _, i := range e.Adds { total += i } 18 | for _, i := range e.Subtracts { total -= i } 19 | if e.Multiplier != 0 { total *= e.Multiplier } 20 | return 21 | } 22 | 23 | // Start builder definition 24 | 25 | type simpleExprBuilder builder.Builder 26 | 27 | func (b simpleExprBuilder) Multiplier(i int) simpleExprBuilder { 28 | return builder.Set(b, "Multiplier", i).(simpleExprBuilder) 29 | } 30 | 31 | func (b simpleExprBuilder) Add(i int) simpleExprBuilder { 32 | return builder.Append(b, "Adds", i).(simpleExprBuilder) 33 | } 34 | 35 | func (b simpleExprBuilder) Subtract(i int) simpleExprBuilder { 36 | return builder.Append(b, "Subtracts", i).(simpleExprBuilder) 37 | } 38 | 39 | func (b simpleExprBuilder) Equals() int { 40 | return builder.GetStruct(b).(simpleExpr).Equals() 41 | } 42 | 43 | // SimpleExprBuilder is an empty builder 44 | var SimpleExprBuilder = 45 | builder.Register(simpleExprBuilder{}, simpleExpr{}).(simpleExprBuilder) 46 | 47 | // End builder definition 48 | 49 | func Example_basic() { 50 | b := SimpleExprBuilder.Add(10).Subtract(3) 51 | 52 | // Intermediate values can be reused 53 | b2 := b.Multiplier(2) 54 | b3 := b.Multiplier(3) 55 | 56 | fmt.Println(b.Equals(), b2.Equals(), b3.Equals()) 57 | 58 | // Output: 59 | // 7 14 21 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/reflect.go: -------------------------------------------------------------------------------- 1 | package builder 2 | 3 | import "reflect" 4 | 5 | func convert(from interface{}, to interface{}) interface{} { 6 | return reflect. 7 | ValueOf(from). 8 | Convert(reflect.TypeOf(to)). 9 | Interface() 10 | } 11 | 12 | func forEach(s interface{}, f func(interface{})) { 13 | val := reflect.ValueOf(s) 14 | 15 | kind := val.Kind() 16 | if kind != reflect.Slice && kind != reflect.Array { 17 | panic(&reflect.ValueError{Method: "builder.forEach", Kind: kind}) 18 | } 19 | 20 | l := val.Len() 21 | for i := 0; i < l; i++ { 22 | f(val.Index(i).Interface()) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/lann/builder/registry.go: -------------------------------------------------------------------------------- 1 | package builder 2 | 3 | import "reflect" 4 | 5 | var registry = make(map[reflect.Type]reflect.Type) 6 | 7 | // RegisterType maps the given builderType to a structType. 8 | // This mapping affects the type of slices returned by Get and is required for 9 | // GetStruct to work. 10 | // 11 | // Returns a Value containing an empty instance of the registered builderType. 12 | // 13 | // RegisterType will panic if builderType's underlying type is not Builder or 14 | // if structType's Kind is not Struct. 15 | func RegisterType(builderType reflect.Type, structType reflect.Type) *reflect.Value { 16 | structType.NumField() // Panic if structType is not a struct 17 | registry[builderType] = structType 18 | emptyValue := emptyBuilderValue.Convert(builderType) 19 | return &emptyValue 20 | } 21 | 22 | // Register wraps RegisterType, taking instances instead of Types. 23 | // 24 | // Returns an empty instance of the registered builder type which can be used 25 | // as the initial value for builder expressions. See example. 26 | func Register(builderProto interface{}, structProto interface{}) interface{} { 27 | empty := RegisterType( 28 | reflect.TypeOf(builderProto), 29 | reflect.TypeOf(structProto), 30 | ).Interface() 31 | return empty 32 | } 33 | 34 | func getBuilderStructType(builderType reflect.Type) *reflect.Type { 35 | structType, ok := registry[builderType] 36 | if !ok { 37 | return nil 38 | } 39 | return &structType 40 | } 41 | 42 | func newBuilderStruct(builderType reflect.Type) *reflect.Value { 43 | structType := getBuilderStructType(builderType) 44 | if structType == nil { 45 | return nil 46 | } 47 | newStruct := reflect.New(*structType).Elem() 48 | return &newStruct 49 | } 50 | -------------------------------------------------------------------------------- /vendor/github.com/lann/ps/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Michael Hendricks 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /vendor/github.com/lann/ps/README.md: -------------------------------------------------------------------------------- 1 | **This is a stable fork of https://github.com/mndrix/ps; it will not introduce breaking changes.** 2 | 3 | ps 4 | == 5 | 6 | Persistent data structures for Go. See the [full package documentation](http://godoc.org/github.com/lann/ps) 7 | 8 | Install with 9 | 10 | go get github.com/lann/ps 11 | -------------------------------------------------------------------------------- /vendor/github.com/lann/ps/list.go: -------------------------------------------------------------------------------- 1 | package ps 2 | 3 | // List is a persistent list of possibly heterogenous values. 4 | type List interface { 5 | // IsNil returns true if the list is empty 6 | IsNil() bool 7 | 8 | // Cons returns a new list with val as the head 9 | Cons(val Any) List 10 | 11 | // Head returns the first element of the list; 12 | // panics if the list is empty 13 | Head() Any 14 | 15 | // Tail returns a list with all elements except the head; 16 | // panics if the list is empty 17 | Tail() List 18 | 19 | // Size returns the list's length. This takes O(1) time. 20 | Size() int 21 | 22 | // ForEach executes a callback for each value in the list. 23 | ForEach(f func(Any)) 24 | 25 | // Reverse returns a list whose elements are in the opposite order as 26 | // the original list. 27 | Reverse() List 28 | } 29 | 30 | // Immutable (i.e. persistent) list 31 | type list struct { 32 | depth int // the number of nodes after, and including, this one 33 | value Any 34 | tail *list 35 | } 36 | 37 | // An empty list shared by all lists 38 | var nilList = &list{} 39 | 40 | // NewList returns a new, empty list. The result is a singly linked 41 | // list implementation. All lists share an empty tail, so allocating 42 | // empty lists is efficient in time and memory. 43 | func NewList() List { 44 | return nilList 45 | } 46 | 47 | func (self *list) IsNil() bool { 48 | return self == nilList 49 | } 50 | 51 | func (self *list) Size() int { 52 | return self.depth 53 | } 54 | 55 | func (tail *list) Cons(val Any) List { 56 | var xs list 57 | xs.depth = tail.depth + 1 58 | xs.value = val 59 | xs.tail = tail 60 | return &xs 61 | } 62 | 63 | func (self *list) Head() Any { 64 | if self.IsNil() { 65 | panic("Called Head() on an empty list") 66 | } 67 | 68 | return self.value 69 | } 70 | 71 | func (self *list) Tail() List { 72 | if self.IsNil() { 73 | panic("Called Tail() on an empty list") 74 | } 75 | 76 | return self.tail 77 | } 78 | 79 | // ForEach executes a callback for each value in the list 80 | func (self *list) ForEach(f func(Any)) { 81 | if self.IsNil() { 82 | return 83 | } 84 | f(self.Head()) 85 | self.Tail().ForEach(f) 86 | } 87 | 88 | // Reverse returns a list with elements in opposite order as this list 89 | func (self *list) Reverse() List { 90 | reversed := NewList() 91 | self.ForEach(func(v Any) { reversed = reversed.Cons(v) }) 92 | return reversed 93 | } 94 | -------------------------------------------------------------------------------- /vendor/github.com/lann/ps/list_test.go: -------------------------------------------------------------------------------- 1 | package ps 2 | 3 | import "testing" 4 | 5 | func TestListImmutable(t *testing.T) { 6 | // build some lists 7 | one := NewList().Cons("first") 8 | two := one.Cons("second") 9 | zwei := one.Cons("zweite") 10 | 11 | // check each list's length 12 | if size := one.Size(); size != 1 { 13 | t.Errorf("one doesn't have 1 item, it has %d", size) 14 | } 15 | if size := two.Size(); size != 2 { 16 | t.Errorf("two doesn't have 2 items, it has %d", size) 17 | } 18 | if size := zwei.Size(); size != 2 { 19 | t.Errorf("zwei doesn't have 2 item, it has %d", size) 20 | } 21 | 22 | // check each list's contents 23 | if one.Head() != "first" { 24 | t.Errorf("one has the wrong head") 25 | } 26 | if two.Head() != "second" { 27 | t.Errorf("two has the wrong head") 28 | } 29 | if two.Tail().Head() != "first" { 30 | t.Errorf("two has the wrong ending") 31 | } 32 | if zwei.Head() != "zweite" { 33 | t.Errorf("zwei has the wrong head") 34 | } 35 | if zwei.Tail().Head() != "first" { 36 | t.Errorf("zwei has the wrong ending") 37 | } 38 | } 39 | 40 | // benchmark making a really long list 41 | func BenchmarkListCons(b *testing.B) { 42 | l := NewList() 43 | for i := 0; i < b.N; i++ { 44 | l = l.Cons(i) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/lann/ps/profile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | go test -c 3 | ./ps.test -test.run=none -test.bench=$2 -test.$1profile=$1.profile 4 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.gitignore: -------------------------------------------------------------------------------- 1 | .db 2 | *.test 3 | *~ 4 | *.swp 5 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | client_configure() { 6 | sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key 7 | } 8 | 9 | pgdg_repository() { 10 | local sourcelist='sources.list.d/postgresql.list' 11 | 12 | curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo apt-key add - 13 | echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist" 14 | sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update 15 | } 16 | 17 | postgresql_configure() { 18 | sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null <<-config 19 | local all all trust 20 | hostnossl all pqgossltest 127.0.0.1/32 reject 21 | hostnossl all pqgosslcert 127.0.0.1/32 reject 22 | hostssl all pqgossltest 127.0.0.1/32 trust 23 | hostssl all pqgosslcert 127.0.0.1/32 cert 24 | host all all 127.0.0.1/32 trust 25 | hostnossl all pqgossltest ::1/128 reject 26 | hostnossl all pqgosslcert ::1/128 reject 27 | hostssl all pqgossltest ::1/128 trust 28 | hostssl all pqgosslcert ::1/128 cert 29 | host all all ::1/128 trust 30 | config 31 | 32 | xargs sudo install -o postgres -g postgres -m 600 -t /var/lib/postgresql/$PGVERSION/main/ <<-certificates 33 | certs/root.crt 34 | certs/server.crt 35 | certs/server.key 36 | certificates 37 | 38 | sort -VCu <<-versions || 39 | $PGVERSION 40 | 9.2 41 | versions 42 | sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null <<-config 43 | ssl_ca_file = 'root.crt' 44 | ssl_cert_file = 'server.crt' 45 | ssl_key_file = 'server.key' 46 | config 47 | 48 | echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null 49 | 50 | sudo service postgresql restart 51 | } 52 | 53 | postgresql_install() { 54 | xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages 55 | postgresql-$PGVERSION 56 | postgresql-server-dev-$PGVERSION 57 | postgresql-contrib-$PGVERSION 58 | packages 59 | } 60 | 61 | postgresql_uninstall() { 62 | sudo service postgresql stop 63 | xargs sudo apt-get -y --purge remove <<-packages 64 | libpq-dev 65 | libpq5 66 | postgresql 67 | postgresql-client-common 68 | postgresql-common 69 | packages 70 | sudo rm -rf /var/lib/postgresql 71 | } 72 | 73 | $1 74 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.5.x 5 | - 1.6.x 6 | - 1.7.x 7 | - 1.8.x 8 | - master 9 | 10 | sudo: true 11 | 12 | env: 13 | global: 14 | - PGUSER=postgres 15 | - PQGOSSLTESTS=1 16 | - PQSSLCERTTEST_PATH=$PWD/certs 17 | - PGHOST=127.0.0.1 18 | matrix: 19 | - PGVERSION=9.6 20 | - PGVERSION=9.5 21 | - PGVERSION=9.4 22 | - PGVERSION=9.3 23 | - PGVERSION=9.2 24 | - PGVERSION=9.1 25 | - PGVERSION=9.0 26 | 27 | before_install: 28 | - ./.travis.sh postgresql_uninstall 29 | - ./.travis.sh pgdg_repository 30 | - ./.travis.sh postgresql_install 31 | - ./.travis.sh postgresql_configure 32 | - ./.travis.sh client_configure 33 | - go get golang.org/x/tools/cmd/goimports 34 | 35 | before_script: 36 | - createdb pqgotest 37 | - createuser -DRS pqgossltest 38 | - createuser -DRS pqgosslcert 39 | 40 | script: 41 | - > 42 | goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' 43 | - go vet ./... 44 | - PQTEST_BINARY_PARAMETERS=no go test -race -v ./... 45 | - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... 46 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to pq 2 | 3 | `pq` has a backlog of pull requests, but contributions are still very 4 | much welcome. You can help with patch review, submitting bug reports, 5 | or adding new functionality. There is no formal style guide, but 6 | please conform to the style of existing code and general Go formatting 7 | conventions when submitting patches. 8 | 9 | ### Patch review 10 | 11 | Help review existing open pull requests by commenting on the code or 12 | proposed functionality. 13 | 14 | ### Bug reports 15 | 16 | We appreciate any bug reports, but especially ones with self-contained 17 | (doesn't depend on code outside of pq), minimal (can't be simplified 18 | further) test cases. It's especially helpful if you can submit a pull 19 | request with just the failing test case (you'll probably want to 20 | pattern it after the tests in 21 | [conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go). 22 | 23 | ### New functionality 24 | 25 | There are a number of pending patches for new functionality, so 26 | additional feature patches will take a while to merge. Still, patches 27 | are generally reviewed based on usefulness and complexity in addition 28 | to time-in-queue, so if you have a knockout idea, take a shot. Feel 29 | free to open an issue discussion your proposed patch beforehand. 30 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2013, 'pq' Contributors 2 | Portions Copyright (C) 2011 Blake Mizerany 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/buf.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | 7 | "github.com/lib/pq/oid" 8 | ) 9 | 10 | type readBuf []byte 11 | 12 | func (b *readBuf) int32() (n int) { 13 | n = int(int32(binary.BigEndian.Uint32(*b))) 14 | *b = (*b)[4:] 15 | return 16 | } 17 | 18 | func (b *readBuf) oid() (n oid.Oid) { 19 | n = oid.Oid(binary.BigEndian.Uint32(*b)) 20 | *b = (*b)[4:] 21 | return 22 | } 23 | 24 | // N.B: this is actually an unsigned 16-bit integer, unlike int32 25 | func (b *readBuf) int16() (n int) { 26 | n = int(binary.BigEndian.Uint16(*b)) 27 | *b = (*b)[2:] 28 | return 29 | } 30 | 31 | func (b *readBuf) string() string { 32 | i := bytes.IndexByte(*b, 0) 33 | if i < 0 { 34 | errorf("invalid message format; expected string terminator") 35 | } 36 | s := (*b)[:i] 37 | *b = (*b)[i+1:] 38 | return string(s) 39 | } 40 | 41 | func (b *readBuf) next(n int) (v []byte) { 42 | v = (*b)[:n] 43 | *b = (*b)[n:] 44 | return 45 | } 46 | 47 | func (b *readBuf) byte() byte { 48 | return b.next(1)[0] 49 | } 50 | 51 | type writeBuf struct { 52 | buf []byte 53 | pos int 54 | } 55 | 56 | func (b *writeBuf) int32(n int) { 57 | x := make([]byte, 4) 58 | binary.BigEndian.PutUint32(x, uint32(n)) 59 | b.buf = append(b.buf, x...) 60 | } 61 | 62 | func (b *writeBuf) int16(n int) { 63 | x := make([]byte, 2) 64 | binary.BigEndian.PutUint16(x, uint16(n)) 65 | b.buf = append(b.buf, x...) 66 | } 67 | 68 | func (b *writeBuf) string(s string) { 69 | b.buf = append(b.buf, (s + "\000")...) 70 | } 71 | 72 | func (b *writeBuf) byte(c byte) { 73 | b.buf = append(b.buf, c) 74 | } 75 | 76 | func (b *writeBuf) bytes(v []byte) { 77 | b.buf = append(b.buf, v...) 78 | } 79 | 80 | func (b *writeBuf) wrap() []byte { 81 | p := b.buf[b.pos:] 82 | binary.BigEndian.PutUint32(p, uint32(len(p))) 83 | return b.buf 84 | } 85 | 86 | func (b *writeBuf) next(c byte) { 87 | p := b.buf[b.pos:] 88 | binary.BigEndian.PutUint32(p, uint32(len(p))) 89 | b.pos = len(b.buf) + 1 90 | b.buf = append(b.buf, c, 0, 0, 0, 0) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/certs/README: -------------------------------------------------------------------------------- 1 | This directory contains certificates and private keys for testing some 2 | SSL-related functionality in Travis. Do NOT use these certificates for 3 | anything other than testing. 4 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/certs/bogus_root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDBjCCAe6gAwIBAgIQSnDYp/Naet9HOZljF5PuwDANBgkqhkiG9w0BAQsFADAr 3 | MRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENvY2tyb2FjaCBDQTAeFw0x 4 | NjAyMDcxNjQ0MzdaFw0xNzAyMDYxNjQ0MzdaMCsxEjAQBgNVBAoTCUNvY2tyb2Fj 5 | aDEVMBMGA1UEAxMMQ29ja3JvYWNoIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 6 | MIIBCgKCAQEAxdln3/UdgP7ayA/G1kT7upjLe4ERwQjYQ25q0e1+vgsB5jhiirxJ 7 | e0+WkhhYu/mwoSAXzvlsbZ2PWFyfdanZeD/Lh6SvIeWXVVaPcWVWL1TEcoN2jr5+ 8 | E85MMHmbbmaT2he8s6br2tM/UZxyTQ2XRprIzApbDssyw1c0Yufcpu3C6267FLEl 9 | IfcWrzDhnluFhthhtGXv3ToD8IuMScMC5qlKBXtKmD1B5x14ngO/ecNJ+OlEi0HU 10 | mavK4KWgI2rDXRZ2EnCpyTZdkc3kkRnzKcg653oOjMDRZdrhfIrha+Jq38ACsUmZ 11 | Su7Sp5jkIHOCO8Zg+l6GKVSq37dKMapD8wIDAQABoyYwJDAOBgNVHQ8BAf8EBAMC 12 | AuQwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAQEAwZ2Tu0Yu 13 | rrSVdMdoPEjT1IZd+5OhM/SLzL0ddtvTithRweLHsw2lDQYlXFqr24i3UGZJQ1sp 14 | cqSrNwswgLUQT3vWyTjmM51HEb2vMYWKmjZ+sBQYAUP1CadrN/+OTfNGnlF1+B4w 15 | IXOzh7EvQmJJnNybLe4a/aRvj1NE2n8Z898B76SVU9WbfKKz8VwLzuIPDqkKcZda 16 | lMy5yzthyztV9YjcWs2zVOUGZvGdAhDrvZuUq6mSmxrBEvR2LBOggmVf3tGRT+Ls 17 | lW7c9Lrva5zLHuqmoPP07A+vuI9a0D1X44jwGDuPWJ5RnTOQ63Uez12mKNjqleHw 18 | DnkwNanuO8dhAA== 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/certs/postgresql.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWwIBAAKBgQDjjAaacFRR0TQ0gznNolkPBe2N2A400JL0CU3ujHhVSST4POA0 3 | WAKy55RYwejlu9Gv9lTBQLGQcHkNNVScjxbpwvCS5mRJOMF2+EdmxFtKtqlDzsi+ 4 | bE0rlJc8VbzR0G63U66JXEtrhkC+wa4eZM6crocKaeXIIRK+rh32Rd8WpwIDAQAB 5 | AoGAM5dM6/kp9P700i8qjOgRPym96Zoh5nGfz/rIE5z/r36NBkdvIg8OVZfR96nH 6 | b0b9TOMR5lsPp0sI9yivTWvX6qyvLJRWy2vvx17hXK9NxXUNTAm0PYZUTvCtcPeX 7 | RnJpzQKNZQPkFzF0uXBc4CtPK2Vz0+FGvAelrhYAxnw1dIkCQQD+9qaW5QhXjsjb 8 | Nl85CmXgxPmGROcgLQCO+omfrjf9UXrituU9Dz6auym5lDGEdMFnkzfr+wpasEy9 9 | mf5ZZOhDAkEA5HjXfVGaCtpydOt6hDon/uZsyssCK2lQ7NSuE3vP+sUsYMzIpEoy 10 | t3VWXqKbo+g9KNDTP4WEliqp1aiSIylzzQJANPeqzihQnlgEdD4MdD4rwhFJwVIp 11 | Le8Lcais1KaN7StzOwxB/XhgSibd2TbnPpw+3bSg5n5lvUdo+e62/31OHwJAU1jS 12 | I+F09KikQIr28u3UUWT2IzTT4cpVv1AHAQyV3sG3YsjSGT0IK20eyP9BEBZU2WL0 13 | 7aNjrvR5aHxKc5FXsQJABsFtyGpgI5X4xufkJZVZ+Mklz2n7iXa+XPatMAHFxAtb 14 | EEMt60rngwMjXAzBSC6OYuYogRRAY3UCacNC5VhLYQ== 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/certs/root.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEAzCCAuugAwIBAgIJANmheROCdW1NMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV 3 | BAYTAlVTMQ8wDQYDVQQIEwZOZXZhZGExEjAQBgNVBAcTCUxhcyBWZWdhczEaMBgG 4 | A1UEChMRZ2l0aHViLmNvbS9saWIvcHExDjAMBgNVBAMTBXBxIENBMB4XDTE0MTAx 5 | MTE1MDQyOVoXDTI0MTAwODE1MDQyOVowXjELMAkGA1UEBhMCVVMxDzANBgNVBAgT 6 | Bk5ldmFkYTESMBAGA1UEBxMJTGFzIFZlZ2FzMRowGAYDVQQKExFnaXRodWIuY29t 7 | L2xpYi9wcTEOMAwGA1UEAxMFcHEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 8 | ggEKAoIBAQCV4PxP7ShzWBzUCThcKk3qZtOLtHmszQVtbqhvgTpm1kTRtKBdVMu0 9 | pLAHQ3JgJCnAYgH0iZxVGoMP16T3irdgsdC48+nNTFM2T0cCdkfDURGIhSFN47cb 10 | Pgy306BcDUD2q7ucW33+dlFSRuGVewocoh4BWM/vMtMvvWzdi4Ag/L/jhb+5wZxZ 11 | sWymsadOVSDePEMKOvlCa3EdVwVFV40TVyDb+iWBUivDAYsS2a3KajuJrO6MbZiE 12 | Sp2RCIkZS2zFmzWxVRi9ZhzIZhh7EVF9JAaNC3T52jhGUdlRq3YpBTMnd89iOh74 13 | 6jWXG7wSuPj3haFzyNhmJ0ZUh+2Ynoh1AgMBAAGjgcMwgcAwHQYDVR0OBBYEFFKT 14 | 7R52Cp9lT94ZZsHVIkA1y6ByMIGQBgNVHSMEgYgwgYWAFFKT7R52Cp9lT94ZZsHV 15 | IkA1y6ByoWKkYDBeMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGTmV2YWRhMRIwEAYD 16 | VQQHEwlMYXMgVmVnYXMxGjAYBgNVBAoTEWdpdGh1Yi5jb20vbGliL3BxMQ4wDAYD 17 | VQQDEwVwcSBDQYIJANmheROCdW1NMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF 18 | BQADggEBAAEhCLWkqJNMI8b4gkbmj5fqQ/4+oO83bZ3w2Oqf6eZ8I8BC4f2NOyE6 19 | tRUlq5+aU7eqC1cOAvGjO+YHN/bF/DFpwLlzvUSXt+JP/pYcUjL7v+pIvwqec9hD 20 | ndvM4iIbkD/H/OYQ3L+N3W+G1x7AcFIX+bGCb3PzYVQAjxreV6//wgKBosMGFbZo 21 | HPxT9RPMun61SViF04H5TNs0derVn1+5eiiYENeAhJzQNyZoOOUuX1X/Inx9bEPh 22 | C5vFBtSMgIytPgieRJVWAiMLYsfpIAStrHztRAbBs2DU01LmMgRvHdxgFEKinC/d 23 | UHZZQDP+6pT+zADrGhQGXe4eThaO6f0= 24 | -----END CERTIFICATE----- 25 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/certs/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA14pMhfsXpTyP4HIRKc4/sB8/fcbuf6f8Ais1RwimPZDfXFYU 3 | lADHbdHS4mGVd7jjpmYx+R8hfWLhJ9qUN2FK6mNToGG4nLul4ue3ptgPBQTHKeLq 4 | SSt/3hUAphhwUMcM3pr5Wpaw4ZQGxm1KITu0D6VtkoY0sk7XDqcZwHcLe4fIkt5C 5 | /4bSt5qk1BUjyq2laSG4zn5my4Vdue2LLQmNlOQEHnLs79B2kBVapPeRS+nOTp1d 6 | mnAXnNjpc4PqPWGZps2skUBaiHflTiqOPRPz+ThvgWuKlcoOB6tv2rSM2f+qeAOq 7 | x8LPb2SS09iD1a/xIxinLnsXC+d98fqoQaMEVwIDAQABAoIBAF3ZoihUhJ82F4+r 8 | Gz4QyDpv4L1reT2sb1aiabhcU8ZK5nbWJG+tRyjSS/i2dNaEcttpdCj9HR/zhgZM 9 | bm0OuAgG58rVwgS80CZUruq++Qs+YVojq8/gWPTiQD4SNhV2Fmx3HkwLgUk3oxuT 10 | SsvdqzGE3okGVrutCIcgy126eA147VPMoej1Bb3fO6npqK0pFPhZfAc0YoqJuM+k 11 | obRm5pAnGUipyLCFXjA9HYPKwYZw2RtfdA3CiImHeanSdqS+ctrC9y8BV40Th7gZ 12 | haXdKUNdjmIxV695QQ1mkGqpKLZFqhzKioGQ2/Ly2d1iaKN9fZltTusu8unepWJ2 13 | tlT9qMECgYEA9uHaF1t2CqE+AJvWTihHhPIIuLxoOQXYea1qvxfcH/UMtaLKzCNm 14 | lQ5pqCGsPvp+10f36yttO1ZehIvlVNXuJsjt0zJmPtIolNuJY76yeussfQ9jHheB 15 | 5uPEzCFlHzxYbBUyqgWaF6W74okRGzEGJXjYSP0yHPPdU4ep2q3bGiUCgYEA34Af 16 | wBSuQSK7uLxArWHvQhyuvi43ZGXls6oRGl+Ysj54s8BP6XGkq9hEJ6G4yxgyV+BR 17 | DUOs5X8/TLT8POuIMYvKTQthQyCk0eLv2FLdESDuuKx0kBVY3s8lK3/z5HhrdOiN 18 | VMNZU+xDKgKc3hN9ypkk8vcZe6EtH7Y14e0rVcsCgYBTgxi8F/M5K0wG9rAqphNz 19 | VFBA9XKn/2M33cKjO5X5tXIEKzpAjaUQvNxexG04rJGljzG8+mar0M6ONahw5yD1 20 | O7i/XWgazgpuOEkkVYiYbd8RutfDgR4vFVMn3hAP3eDnRtBplRWH9Ec3HTiNIys6 21 | F8PKBOQjyRZQQC7jyzW3hQKBgACe5HeuFwXLSOYsb6mLmhR+6+VPT4wR1F95W27N 22 | USk9jyxAnngxfpmTkiziABdgS9N+pfr5cyN4BP77ia/Jn6kzkC5Cl9SN5KdIkA3z 23 | vPVtN/x/ThuQU5zaymmig1ThGLtMYggYOslG4LDfLPxY5YKIhle+Y+259twdr2yf 24 | Mf2dAoGAaGv3tWMgnIdGRk6EQL/yb9PKHo7ShN+tKNlGaK7WwzBdKs+Fe8jkgcr7 25 | pz4Ne887CmxejdISzOCcdT+Zm9Bx6I/uZwWOtDvWpIgIxVX9a9URj/+D1MxTE/y4 26 | d6H+c89yDY62I2+drMpdjCd3EtCaTlxpTbRS+s1eAHMH7aEkcCE= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/conn_go18.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package pq 4 | 5 | import ( 6 | "context" 7 | "database/sql/driver" 8 | "errors" 9 | "io" 10 | "io/ioutil" 11 | ) 12 | 13 | // Implement the "QueryerContext" interface 14 | func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { 15 | list := make([]driver.Value, len(args)) 16 | for i, nv := range args { 17 | list[i] = nv.Value 18 | } 19 | finish := cn.watchCancel(ctx) 20 | r, err := cn.query(query, list) 21 | if err != nil { 22 | return nil, err 23 | } 24 | r.finish = finish 25 | return r, nil 26 | } 27 | 28 | // Implement the "ExecerContext" interface 29 | func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { 30 | list := make([]driver.Value, len(args)) 31 | for i, nv := range args { 32 | list[i] = nv.Value 33 | } 34 | 35 | if finish := cn.watchCancel(ctx); finish != nil { 36 | defer finish() 37 | } 38 | 39 | return cn.Exec(query, list) 40 | } 41 | 42 | // Implement the "ConnBeginTx" interface 43 | func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { 44 | if opts.Isolation != 0 { 45 | return nil, errors.New("isolation levels not supported") 46 | } 47 | if opts.ReadOnly { 48 | return nil, errors.New("read-only transactions not supported") 49 | } 50 | tx, err := cn.Begin() 51 | if err != nil { 52 | return nil, err 53 | } 54 | cn.txnFinish = cn.watchCancel(ctx) 55 | return tx, nil 56 | } 57 | 58 | func (cn *conn) watchCancel(ctx context.Context) func() { 59 | if done := ctx.Done(); done != nil { 60 | finished := make(chan struct{}) 61 | go func() { 62 | select { 63 | case <-done: 64 | _ = cn.cancel() 65 | finished <- struct{}{} 66 | case <-finished: 67 | } 68 | }() 69 | return func() { 70 | select { 71 | case <-finished: 72 | case finished <- struct{}{}: 73 | } 74 | } 75 | } 76 | return nil 77 | } 78 | 79 | func (cn *conn) cancel() error { 80 | c, err := dial(cn.dialer, cn.opts) 81 | if err != nil { 82 | return err 83 | } 84 | defer c.Close() 85 | 86 | { 87 | can := conn{ 88 | c: c, 89 | } 90 | can.ssl(cn.opts) 91 | 92 | w := can.writeBuf(0) 93 | w.int32(80877102) // cancel request code 94 | w.int32(cn.processID) 95 | w.int32(cn.secretKey) 96 | 97 | if err := can.sendStartupPacket(w); err != nil { 98 | return err 99 | } 100 | } 101 | 102 | // Read until EOF to ensure that the server received the cancel. 103 | { 104 | _, err := io.Copy(ioutil.Discard, c) 105 | return err 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/issues_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import "testing" 4 | 5 | func TestIssue494(t *testing.T) { 6 | db := openTestConn(t) 7 | defer db.Close() 8 | 9 | query := `CREATE TEMP TABLE t (i INT PRIMARY KEY)` 10 | if _, err := db.Exec(query); err != nil { 11 | t.Fatal(err) 12 | } 13 | 14 | txn, err := db.Begin() 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | 19 | if _, err := txn.Prepare(CopyIn("t", "i")); err != nil { 20 | t.Fatal(err) 21 | } 22 | 23 | if _, err := txn.Query("SELECT 1"); err == nil { 24 | t.Fatal("expected error") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/doc.go: -------------------------------------------------------------------------------- 1 | // Package oid contains OID constants 2 | // as defined by the Postgres server. 3 | package oid 4 | 5 | // Oid is a Postgres Object ID. 6 | type Oid uint32 7 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/oid/gen.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | // Generate the table of OID values 4 | // Run with 'go run gen.go'. 5 | package main 6 | 7 | import ( 8 | "database/sql" 9 | "fmt" 10 | "log" 11 | "os" 12 | "os/exec" 13 | 14 | _ "github.com/lib/pq" 15 | ) 16 | 17 | func main() { 18 | datname := os.Getenv("PGDATABASE") 19 | sslmode := os.Getenv("PGSSLMODE") 20 | 21 | if datname == "" { 22 | os.Setenv("PGDATABASE", "pqgotest") 23 | } 24 | 25 | if sslmode == "" { 26 | os.Setenv("PGSSLMODE", "disable") 27 | } 28 | 29 | db, err := sql.Open("postgres", "") 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | cmd := exec.Command("gofmt") 34 | cmd.Stderr = os.Stderr 35 | w, err := cmd.StdinPipe() 36 | if err != nil { 37 | log.Fatal(err) 38 | } 39 | f, err := os.Create("types.go") 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | cmd.Stdout = f 44 | err = cmd.Start() 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | fmt.Fprintln(w, "// generated by 'go run gen.go'; do not edit") 49 | fmt.Fprintln(w, "\npackage oid") 50 | fmt.Fprintln(w, "const (") 51 | rows, err := db.Query(` 52 | SELECT typname, oid 53 | FROM pg_type WHERE oid < 10000 54 | ORDER BY oid; 55 | `) 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | var name string 60 | var oid int 61 | for rows.Next() { 62 | err = rows.Scan(&name, &oid) 63 | if err != nil { 64 | log.Fatal(err) 65 | } 66 | fmt.Fprintf(w, "T_%s Oid = %d\n", name, oid) 67 | } 68 | if err = rows.Err(); err != nil { 69 | log.Fatal(err) 70 | } 71 | fmt.Fprintln(w, ")") 72 | w.Close() 73 | cmd.Wait() 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_go1.7.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Accept renegotiation requests initiated by the backend. 8 | // 9 | // Renegotiation was deprecated then removed from PostgreSQL 9.5, but 10 | // the default configuration of older versions has it enabled. Redshift 11 | // also initiates renegotiations and cannot be reconfigured. 12 | func sslRenegotiation(conf *tls.Config) { 13 | conf.Renegotiation = tls.RenegotiateFreelyAsClient 14 | } 15 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_permissions.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package pq 4 | 5 | import "os" 6 | 7 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 8 | // The key file should have very little access. 9 | // 10 | // libpq does not check key file permissions on Windows. 11 | func sslKeyPermissions(sslkey string) error { 12 | info, err := os.Stat(sslkey) 13 | if err != nil { 14 | return err 15 | } 16 | if info.Mode().Perm()&0077 != 0 { 17 | return ErrSSLKeyHasWorldPermissions 18 | } 19 | return nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_renegotiation.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package pq 4 | 5 | import "crypto/tls" 6 | 7 | // Renegotiation is not supported by crypto/tls until Go 1.7. 8 | func sslRenegotiation(*tls.Config) {} 9 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/ssl_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package pq 4 | 5 | // sslKeyPermissions checks the permissions on user-supplied ssl key files. 6 | // The key file should have very little access. 7 | // 8 | // libpq does not check key file permissions on Windows. 9 | func sslKeyPermissions(string) error { return nil } 10 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/url.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | nurl "net/url" 7 | "sort" 8 | "strings" 9 | ) 10 | 11 | // ParseURL no longer needs to be used by clients of this library since supplying a URL as a 12 | // connection string to sql.Open() is now supported: 13 | // 14 | // sql.Open("postgres", "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full") 15 | // 16 | // It remains exported here for backwards-compatibility. 17 | // 18 | // ParseURL converts a url to a connection string for driver.Open. 19 | // Example: 20 | // 21 | // "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" 22 | // 23 | // converts to: 24 | // 25 | // "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" 26 | // 27 | // A minimal example: 28 | // 29 | // "postgres://" 30 | // 31 | // This will be blank, causing driver.Open to use all of the defaults 32 | func ParseURL(url string) (string, error) { 33 | u, err := nurl.Parse(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | if u.Scheme != "postgres" && u.Scheme != "postgresql" { 39 | return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) 40 | } 41 | 42 | var kvs []string 43 | escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`) 44 | accrue := func(k, v string) { 45 | if v != "" { 46 | kvs = append(kvs, k+"="+escaper.Replace(v)) 47 | } 48 | } 49 | 50 | if u.User != nil { 51 | v := u.User.Username() 52 | accrue("user", v) 53 | 54 | v, _ = u.User.Password() 55 | accrue("password", v) 56 | } 57 | 58 | if host, port, err := net.SplitHostPort(u.Host); err != nil { 59 | accrue("host", u.Host) 60 | } else { 61 | accrue("host", host) 62 | accrue("port", port) 63 | } 64 | 65 | if u.Path != "" { 66 | accrue("dbname", u.Path[1:]) 67 | } 68 | 69 | q := u.Query() 70 | for k := range q { 71 | accrue(k, q.Get(k)) 72 | } 73 | 74 | sort.Strings(kvs) // Makes testing easier (not a performance concern) 75 | return strings.Join(kvs, " "), nil 76 | } 77 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/url_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestSimpleParseURL(t *testing.T) { 8 | expected := "host=hostname.remote" 9 | str, err := ParseURL("postgres://hostname.remote") 10 | if err != nil { 11 | t.Fatal(err) 12 | } 13 | 14 | if str != expected { 15 | t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) 16 | } 17 | } 18 | 19 | func TestIPv6LoopbackParseURL(t *testing.T) { 20 | expected := "host=::1 port=1234" 21 | str, err := ParseURL("postgres://[::1]:1234") 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | if str != expected { 27 | t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) 28 | } 29 | } 30 | 31 | func TestFullParseURL(t *testing.T) { 32 | expected := `dbname=database host=hostname.remote password=top\ secret port=1234 user=username` 33 | str, err := ParseURL("postgres://username:top%20secret@hostname.remote:1234/database") 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | 38 | if str != expected { 39 | t.Fatalf("unexpected result from ParseURL:\n+ %s\n- %s", str, expected) 40 | } 41 | } 42 | 43 | func TestInvalidProtocolParseURL(t *testing.T) { 44 | _, err := ParseURL("http://hostname.remote") 45 | switch err { 46 | case nil: 47 | t.Fatal("Expected an error from parsing invalid protocol") 48 | default: 49 | msg := "invalid connection protocol: http" 50 | if err.Error() != msg { 51 | t.Fatalf("Unexpected error message:\n+ %s\n- %s", 52 | err.Error(), msg) 53 | } 54 | } 55 | } 56 | 57 | func TestMinimalURL(t *testing.T) { 58 | cs, err := ParseURL("postgres://") 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | 63 | if cs != "" { 64 | t.Fatalf("expected blank connection string, got: %q", cs) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_posix.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | 3 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris rumprun 4 | 5 | package pq 6 | 7 | import ( 8 | "os" 9 | "os/user" 10 | ) 11 | 12 | func userCurrent() (string, error) { 13 | u, err := user.Current() 14 | if err == nil { 15 | return u.Username, nil 16 | } 17 | 18 | name := os.Getenv("USER") 19 | if name != "" { 20 | return name, nil 21 | } 22 | 23 | return "", ErrCouldNotDetectUsername 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/user_windows.go: -------------------------------------------------------------------------------- 1 | // Package pq is a pure Go Postgres driver for the database/sql package. 2 | package pq 3 | 4 | import ( 5 | "path/filepath" 6 | "syscall" 7 | ) 8 | 9 | // Perform Windows user name lookup identically to libpq. 10 | // 11 | // The PostgreSQL code makes use of the legacy Win32 function 12 | // GetUserName, and that function has not been imported into stock Go. 13 | // GetUserNameEx is available though, the difference being that a 14 | // wider range of names are available. To get the output to be the 15 | // same as GetUserName, only the base (or last) component of the 16 | // result is returned. 17 | func userCurrent() (string, error) { 18 | pw_name := make([]uint16, 128) 19 | pwname_size := uint32(len(pw_name)) - 1 20 | err := syscall.GetUserNameEx(syscall.NameSamCompatible, &pw_name[0], &pwname_size) 21 | if err != nil { 22 | return "", ErrCouldNotDetectUsername 23 | } 24 | s := syscall.UTF16ToString(pw_name) 25 | u := filepath.Base(s) 26 | return u, nil 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/uuid.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | ) 7 | 8 | // decodeUUIDBinary interprets the binary format of a uuid, returning it in text format. 9 | func decodeUUIDBinary(src []byte) ([]byte, error) { 10 | if len(src) != 16 { 11 | return nil, fmt.Errorf("pq: unable to decode uuid; bad length: %d", len(src)) 12 | } 13 | 14 | dst := make([]byte, 36) 15 | dst[8], dst[13], dst[18], dst[23] = '-', '-', '-', '-' 16 | hex.Encode(dst[0:], src[0:4]) 17 | hex.Encode(dst[9:], src[4:6]) 18 | hex.Encode(dst[14:], src[6:8]) 19 | hex.Encode(dst[19:], src[8:10]) 20 | hex.Encode(dst[24:], src[10:16]) 21 | 22 | return dst, nil 23 | } 24 | -------------------------------------------------------------------------------- /vendor/github.com/lib/pq/uuid_test.go: -------------------------------------------------------------------------------- 1 | package pq 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestDecodeUUIDBinaryError(t *testing.T) { 10 | t.Parallel() 11 | _, err := decodeUUIDBinary([]byte{0x12, 0x34}) 12 | 13 | if err == nil { 14 | t.Fatal("Expected error, got none") 15 | } 16 | if !strings.HasPrefix(err.Error(), "pq:") { 17 | t.Errorf("Expected error to start with %q, got %q", "pq:", err.Error()) 18 | } 19 | if !strings.Contains(err.Error(), "bad length: 2") { 20 | t.Errorf("Expected error to contain length, got %q", err.Error()) 21 | } 22 | } 23 | 24 | func BenchmarkDecodeUUIDBinary(b *testing.B) { 25 | x := []byte{0x03, 0xa3, 0x52, 0x2f, 0x89, 0x28, 0x49, 0x87, 0x84, 0xd6, 0x93, 0x7b, 0x36, 0xec, 0x27, 0x6f} 26 | 27 | for i := 0; i < b.N; i++ { 28 | decodeUUIDBinary(x) 29 | } 30 | } 31 | 32 | func TestDecodeUUIDBackend(t *testing.T) { 33 | db := openTestConn(t) 34 | defer db.Close() 35 | 36 | var s string = "a0ecc91d-a13f-4fe4-9fce-7e09777cc70a" 37 | var scanned interface{} 38 | 39 | err := db.QueryRow(`SELECT $1::uuid`, s).Scan(&scanned) 40 | if err != nil { 41 | t.Fatalf("Expected no error, got %v", err) 42 | } 43 | if !reflect.DeepEqual(scanned, []byte(s)) { 44 | t.Errorf("Expected []byte(%q), got %T(%q)", s, scanned, scanned) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vendor/github.com/oklog/ulid/.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | 3 | #####=== Go ===##### 4 | 5 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 6 | *.o 7 | *.a 8 | *.so 9 | 10 | # Folders 11 | _obj 12 | _test 13 | 14 | # Architecture specific extensions/prefixes 15 | *.[568vq] 16 | [568vq].out 17 | 18 | *.cgo1.go 19 | *.cgo2.c 20 | _cgo_defun.c 21 | _cgo_gotypes.go 22 | _cgo_export.* 23 | 24 | _testmain.go 25 | 26 | *.exe 27 | *.test 28 | *.prof 29 | 30 | -------------------------------------------------------------------------------- /vendor/github.com/oklog/ulid/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.7.4 5 | - tip 6 | install: 7 | - go get -v github.com/golang/lint/golint 8 | - go get golang.org/x/tools/cmd/cover 9 | - go get github.com/mattn/goveralls 10 | - go get -d -t -v ./... 11 | - go build -v ./... 12 | script: 13 | - go vet ./... 14 | - $HOME/gopath/bin/golint . 15 | - go test -v -race ./... 16 | - go test -v -covermode=count -coverprofile=cov.out 17 | - $HOME/gopath/bin/goveralls -coverprofile=cov.out -service=travis-ci -repotoken $COVERALLS_TOKEN 18 | -------------------------------------------------------------------------------- /vendor/github.com/oklog/ulid/AUTHORS.md: -------------------------------------------------------------------------------- 1 | - Peter Bourgon (@peterbourgon) 2 | - Tomás Senart (@tsenart) 3 | -------------------------------------------------------------------------------- /vendor/github.com/oklog/ulid/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.3.0 / 2017-01-03 2 | 3 | * Implement ULID.Compare method 4 | 5 | ## 0.2.0 / 2016-12-13 6 | 7 | * Remove year 2262 Timestamp bug. (#1) 8 | * Gracefully handle invalid encodings when parsing. 9 | 10 | ## 0.1.0 / 2016-12-06 11 | 12 | * First ULID release 13 | -------------------------------------------------------------------------------- /vendor/github.com/oklog/ulid/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We use GitHub to manage reviews of pull requests. 4 | 5 | * If you have a trivial fix or improvement, go ahead and create a pull 6 | request, addressing (with `@...`) one or more of the maintainers 7 | (see [AUTHORS.md](AUTHORS.md)) in the description of the pull request. 8 | 9 | * If you plan to do something more involved, first propose your ideas 10 | in a Github issue. This will avoid unnecessary work and surely give 11 | you and us a good deal of inspiration. 12 | 13 | * Relevant coding style guidelines are the [Go Code Review 14 | Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) 15 | and the _Formatting and style_ section of Peter Bourgon's [Go: Best 16 | Practices for Production 17 | Environments](http://peter.bourgon.org/go-in-production/#formatting-and-style). 18 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/pkg/errors 3 | go: 4 | - 1.4.x 5 | - 1.5.x 6 | - 1.6.x 7 | - 1.7.x 8 | - 1.8.x 9 | - tip 10 | 11 | script: 12 | - go test -v ./... 13 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/README.md: -------------------------------------------------------------------------------- 1 | # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) 2 | 3 | Package errors provides simple error handling primitives. 4 | 5 | `go get github.com/pkg/errors` 6 | 7 | The traditional error handling idiom in Go is roughly akin to 8 | ```go 9 | if err != nil { 10 | return err 11 | } 12 | ``` 13 | which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. 14 | 15 | ## Adding context to an error 16 | 17 | The errors.Wrap function returns a new error that adds context to the original error. For example 18 | ```go 19 | _, err := ioutil.ReadAll(r) 20 | if err != nil { 21 | return errors.Wrap(err, "read failed") 22 | } 23 | ``` 24 | ## Retrieving the cause of an error 25 | 26 | Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. 27 | ```go 28 | type causer interface { 29 | Cause() error 30 | } 31 | ``` 32 | `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: 33 | ```go 34 | switch err := errors.Cause(err).(type) { 35 | case *MyError: 36 | // handle specifically 37 | default: 38 | // unknown error 39 | } 40 | ``` 41 | 42 | [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). 43 | 44 | ## Contributing 45 | 46 | We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. 47 | 48 | Before proposing a change, please discuss your change by raising an issue. 49 | 50 | ## Licence 51 | 52 | BSD-2-Clause 53 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: build-{build}.{branch} 2 | 3 | clone_folder: C:\gopath\src\github.com\pkg\errors 4 | shallow_clone: true # for startup speed 5 | 6 | environment: 7 | GOPATH: C:\gopath 8 | 9 | platform: 10 | - x64 11 | 12 | # http://www.appveyor.com/docs/installed-software 13 | install: 14 | # some helpful output for debugging builds 15 | - go version 16 | - go env 17 | # pre-installed MinGW at C:\MinGW is 32bit only 18 | # but MSYS2 at C:\msys64 has mingw64 19 | - set PATH=C:\msys64\mingw64\bin;%PATH% 20 | - gcc --version 21 | - g++ --version 22 | 23 | build_script: 24 | - go install -v ./... 25 | 26 | test_script: 27 | - set PATH=C:\gopath\bin;%PATH% 28 | - go test -v ./... 29 | 30 | #artifacts: 31 | # - path: '%GOPATH%\bin\*.exe' 32 | deploy: off 33 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/bench_test.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package errors 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | 9 | stderrors "errors" 10 | ) 11 | 12 | func noErrors(at, depth int) error { 13 | if at >= depth { 14 | return stderrors.New("no error") 15 | } 16 | return noErrors(at+1, depth) 17 | } 18 | 19 | func yesErrors(at, depth int) error { 20 | if at >= depth { 21 | return New("ye error") 22 | } 23 | return yesErrors(at+1, depth) 24 | } 25 | 26 | // GlobalE is an exported global to store the result of benchmark results, 27 | // preventing the compiler from optimising the benchmark functions away. 28 | var GlobalE error 29 | 30 | func BenchmarkErrors(b *testing.B) { 31 | type run struct { 32 | stack int 33 | std bool 34 | } 35 | runs := []run{ 36 | {10, false}, 37 | {10, true}, 38 | {100, false}, 39 | {100, true}, 40 | {1000, false}, 41 | {1000, true}, 42 | } 43 | for _, r := range runs { 44 | part := "pkg/errors" 45 | if r.std { 46 | part = "errors" 47 | } 48 | name := fmt.Sprintf("%s-stack-%d", part, r.stack) 49 | b.Run(name, func(b *testing.B) { 50 | var err error 51 | f := yesErrors 52 | if r.std { 53 | f = noErrors 54 | } 55 | b.ReportAllocs() 56 | for i := 0; i < b.N; i++ { 57 | err = f(0, r.stack) 58 | } 59 | b.StopTimer() 60 | GlobalE = err 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /vendor/github.com/satori/go.uuid/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | sudo: false 3 | go: 4 | - 1.2 5 | - 1.3 6 | - 1.4 7 | - 1.5 8 | - 1.6 9 | - 1.7 10 | - 1.8 11 | - tip 12 | matrix: 13 | allow_failures: 14 | - go: tip 15 | fast_finish: true 16 | before_install: 17 | - go get github.com/mattn/goveralls 18 | - go get golang.org/x/tools/cmd/cover 19 | script: 20 | - $HOME/gopath/bin/goveralls -service=travis-ci 21 | notifications: 22 | email: false 23 | -------------------------------------------------------------------------------- /vendor/github.com/satori/go.uuid/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013-2016 by Maxim Bublis 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/satori/go.uuid/README.md: -------------------------------------------------------------------------------- 1 | # UUID package for Go language 2 | 3 | [![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) 4 | [![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) 5 | [![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) 6 | 7 | This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. 8 | 9 | With 100% test coverage and benchmarks out of box. 10 | 11 | Supported versions: 12 | * Version 1, based on timestamp and MAC address (RFC 4122) 13 | * Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) 14 | * Version 3, based on MD5 hashing (RFC 4122) 15 | * Version 4, based on random numbers (RFC 4122) 16 | * Version 5, based on SHA-1 hashing (RFC 4122) 17 | 18 | ## Installation 19 | 20 | Use the `go` command: 21 | 22 | $ go get github.com/satori/go.uuid 23 | 24 | ## Requirements 25 | 26 | UUID package requires Go >= 1.2. 27 | 28 | ## Example 29 | 30 | ```go 31 | package main 32 | 33 | import ( 34 | "fmt" 35 | "github.com/satori/go.uuid" 36 | ) 37 | 38 | func main() { 39 | // Creating UUID Version 4 40 | u1 := uuid.NewV4() 41 | fmt.Printf("UUIDv4: %s\n", u1) 42 | 43 | // Parsing UUID from string input 44 | u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") 45 | if err != nil { 46 | fmt.Printf("Something gone wrong: %s", err) 47 | } 48 | fmt.Printf("Successfully parsed: %s", u2) 49 | } 50 | ``` 51 | 52 | ## Documentation 53 | 54 | [Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. 55 | 56 | ## Links 57 | * [RFC 4122](http://tools.ietf.org/html/rfc4122) 58 | * [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) 59 | 60 | ## Copyright 61 | 62 | Copyright (C) 2013-2016 by Maxim Bublis . 63 | 64 | UUID package released under MIT License. 65 | See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. 66 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.7 5 | - 1.8 6 | - tip 7 | 8 | matrix: 9 | allow_failures: 10 | - go: tip 11 | 12 | addons: 13 | postgresql: "9.4" 14 | 15 | env: 16 | - DBNAME=kallax_test DBUSER=postgres DBPASS='' 17 | 18 | services: 19 | - postgresql 20 | 21 | before_script: 22 | - psql -c 'create database kallax_test;' -U postgres 23 | 24 | install: 25 | - rm -rf $GOPATH/src/gopkg.in/src-d 26 | - mkdir -p $GOPATH/src/gopkg.in/src-d 27 | - mv $PWD $GOPATH/src/gopkg.in/src-d/go-kallax.v1 28 | - cd $GOPATH/src/gopkg.in/src-d/go-kallax.v1 29 | - go get -v -t . 30 | - go get -v -t ./generator/... 31 | 32 | script: 33 | - make test 34 | 35 | after_success: 36 | - bash <(curl -s https://codecov.io/bash) 37 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 source{d} 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/Makefile: -------------------------------------------------------------------------------- 1 | COVERAGE_REPORT := coverage.txt 2 | COVERAGE_PROFILE := profile.out 3 | COVERAGE_MODE := atomic 4 | 5 | test: 6 | @echo "mode: $(COVERAGE_MODE)" > $(COVERAGE_REPORT); \ 7 | if [ -f $(COVERAGE_PROFILE) ]; then \ 8 | tail -n +2 $(COVERAGE_PROFILE) >> $(COVERAGE_REPORT); \ 9 | rm $(COVERAGE_PROFILE); \ 10 | fi; \ 11 | for dir in `find . -name "*.go" | grep -o '.*/' | sort -u | grep -v './tests/' | grep -v './fixtures/' | grep -v './benchmarks/'`; do \ 12 | go test $$dir -coverprofile=$(COVERAGE_PROFILE) -covermode=$(COVERAGE_MODE); \ 13 | if [ $$? != 0 ]; then \ 14 | exit 2; \ 15 | fi; \ 16 | if [ -f $(COVERAGE_PROFILE) ]; then \ 17 | tail -n +2 $(COVERAGE_PROFILE) >> $(COVERAGE_REPORT); \ 18 | rm $(COVERAGE_PROFILE); \ 19 | fi; \ 20 | done; \ 21 | go install ./generator/...; \ 22 | go generate ./tests/...; \ 23 | git diff --no-prefix -U1000; \ 24 | if [ `git status | grep 'Changes not staged for commit' | wc -l` != '0' ]; then \ 25 | echo 'There are differences between the commited tests/kallax.go and the one generated right now'; \ 26 | exit 2; \ 27 | fi; \ 28 | go test -v ./tests/...; 29 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/batcher_test.go: -------------------------------------------------------------------------------- 1 | package kallax 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/Masterminds/squirrel" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestOneToManyWithFilterNotWritable(t *testing.T) { 12 | r := require.New(t) 13 | db, err := openTestDB() 14 | r.NoError(err) 15 | setupTables(t, db) 16 | defer db.Close() 17 | defer teardownTables(t, db) 18 | 19 | store := NewStore(db) 20 | m := newModel("foo", "bar", 1) 21 | r.NoError(store.Insert(ModelSchema, m)) 22 | 23 | for i := 0; i < 4; i++ { 24 | r.NoError(store.Insert(RelSchema, newRel(m.GetID(), fmt.Sprint(i)))) 25 | } 26 | 27 | q := NewBaseQuery(ModelSchema) 28 | r.NoError(q.AddRelation(RelSchema, "rels", OneToMany, Eq(f("foo"), "1"))) 29 | runner := newBatchQueryRunner(ModelSchema, squirrel.NewStmtCacher(db), q) 30 | record, err := runner.next() 31 | r.NoError(err) 32 | r.False(record.IsWritable()) 33 | } 34 | 35 | func TestBatcherLimit(t *testing.T) { 36 | r := require.New(t) 37 | db, err := openTestDB() 38 | r.NoError(err) 39 | setupTables(t, db) 40 | defer db.Close() 41 | defer teardownTables(t, db) 42 | 43 | store := NewStore(db) 44 | for i := 0; i < 10; i++ { 45 | m := newModel("foo", "bar", 1) 46 | r.NoError(store.Insert(ModelSchema, m)) 47 | 48 | for i := 0; i < 4; i++ { 49 | r.NoError(store.Insert(RelSchema, newRel(m.GetID(), fmt.Sprint(i)))) 50 | } 51 | } 52 | 53 | q := NewBaseQuery(ModelSchema) 54 | q.BatchSize(2) 55 | q.Limit(5) 56 | r.NoError(q.AddRelation(RelSchema, "rels", OneToMany, Eq(f("foo"), "1"))) 57 | runner := newBatchQueryRunner(ModelSchema, squirrel.NewStmtCacher(db), q) 58 | rs := NewBatchingResultSet(runner) 59 | 60 | var count int 61 | for rs.Next() { 62 | _, err := rs.Get(nil) 63 | r.NoError(err) 64 | count++ 65 | } 66 | r.NoError(err) 67 | r.Equal(5, count) 68 | } 69 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/benchmarks/models_gorm.go: -------------------------------------------------------------------------------- 1 | package benchmark 2 | 3 | type GORMPerson struct { 4 | ID int64 `gorm:"primary_key"` 5 | Name string 6 | Pets []*GORMPet `gorm:"ForeignKey:PersonID"` 7 | } 8 | 9 | func (GORMPerson) TableName() string { 10 | return "people" 11 | } 12 | 13 | type GORMPet struct { 14 | ID int64 `gorm:"primary_key"` 15 | PersonID int64 16 | Name string 17 | Kind string 18 | } 19 | 20 | func (GORMPet) TableName() string { 21 | return "pets" 22 | } 23 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/benchmarks/models_kallax.go: -------------------------------------------------------------------------------- 1 | package benchmark 2 | 3 | import kallax "gopkg.in/src-d/go-kallax.v1" 4 | 5 | type Person struct { 6 | kallax.Model `table:"people"` 7 | ID int64 `pk:"autoincr"` 8 | Name string 9 | Pets []*Pet 10 | } 11 | 12 | type Pet struct { 13 | kallax.Model `table:"pets"` 14 | ID int64 `pk:"autoincr"` 15 | Name string 16 | Kind PetKind 17 | } 18 | 19 | type PetKind string 20 | 21 | const ( 22 | Cat PetKind = "cat" 23 | Dog PetKind = "dog" 24 | Fish PetKind = "fish" 25 | ) 26 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/doc.go: -------------------------------------------------------------------------------- 1 | // Kallax is a PostgreSQL typesafe ORM for the Go language. 2 | // 3 | // Kallax aims to provide a way of programmatically write queries and interact 4 | // with a PostgreSQL database without having to write a single line of SQL, 5 | // use strings to refer to columns and use values of any type in queries. 6 | // For that reason, the first priority of kallax is to provide type safety to 7 | // the data access layer. 8 | // Another of the goals of kallax is make sure all models are, first and 9 | // foremost, Go structs without having to use database-specific types such as, 10 | // for example, `sql.NullInt64`. 11 | // Support for arrays of all basic Go types and all JSON and arrays operators is 12 | // provided as well. 13 | package kallax // import "gopkg.in/src-d/go-kallax.v1" 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/cli/kallax/cmd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "path/filepath" 8 | 9 | "gopkg.in/src-d/go-kallax.v1/generator" 10 | 11 | "gopkg.in/urfave/cli.v1" 12 | ) 13 | 14 | func main() { 15 | app := cli.NewApp() 16 | app.Name = "kallax" 17 | app.Version = "1.1.1" 18 | app.Usage = "generate kallax models" 19 | app.Flags = []cli.Flag{ 20 | cli.StringFlag{ 21 | Name: "input", 22 | Value: ".", 23 | Usage: "Input package directory", 24 | }, 25 | cli.StringFlag{ 26 | Name: "output", 27 | Value: "kallax.go", 28 | Usage: "Output file name", 29 | }, 30 | cli.StringSliceFlag{ 31 | Name: "exclude, e", 32 | Usage: "List of excluded files from the package when generating the code for your models. Use this to exclude files in your package that uses the generated code. You can use this flag as many times as you want.", 33 | }, 34 | } 35 | app.Action = generateModels 36 | app.Commands = []cli.Command{ 37 | { 38 | Name: "gen", 39 | Usage: "Generate kallax models", 40 | Action: app.Action, 41 | Flags: app.Flags, 42 | }, 43 | } 44 | 45 | app.Run(os.Args) 46 | } 47 | 48 | func generateModels(c *cli.Context) error { 49 | input := c.String("input") 50 | output := c.String("output") 51 | excluded := c.StringSlice("exclude") 52 | 53 | if !isDirectory(input) { 54 | return fmt.Errorf("kallax: Input path should be a directory %s", input) 55 | } 56 | 57 | p := generator.NewProcessor(input, excluded) 58 | pkg, err := p.Do() 59 | if err != nil { 60 | return err 61 | } 62 | 63 | gen := generator.NewGenerator(filepath.Join(input, output)) 64 | err = gen.Generate(pkg) 65 | if err != nil { 66 | return err 67 | } 68 | 69 | return nil 70 | } 71 | 72 | func isDirectory(name string) bool { 73 | info, err := os.Stat(name) 74 | if err != nil { 75 | log.Fatal(err) 76 | } 77 | 78 | return info.IsDir() 79 | } 80 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/common_test.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "go/token" 5 | "go/types" 6 | "reflect" 7 | ) 8 | 9 | func mkField(name, typ string, fields ...*Field) *Field { 10 | f := NewField(name, typ, reflect.StructTag("")) 11 | f.SetFields(fields) 12 | return f 13 | } 14 | 15 | func withKind(f *Field, kind FieldKind) *Field { 16 | f.Kind = kind 17 | return f 18 | } 19 | 20 | func withPtr(f *Field) *Field { 21 | f.IsPtr = true 22 | return f 23 | } 24 | 25 | func withAlias(f *Field) *Field { 26 | f.IsAlias = true 27 | return f 28 | } 29 | 30 | func withJSON(f *Field) *Field { 31 | f.IsJSON = true 32 | return f 33 | } 34 | 35 | func withParent(f *Field, parent *Field) *Field { 36 | f.Parent = parent 37 | return f 38 | } 39 | 40 | func withNode(f *Field, name string, typ types.Type) *Field { 41 | f.Node = types.NewVar(token.NoPos, nil, name, typ) 42 | return f 43 | } 44 | 45 | func withTag(f *Field, tag string) *Field { 46 | f.Tag = reflect.StructTag(tag) 47 | return f 48 | } 49 | 50 | func inline(f *Field) *Field { 51 | return withTag(f, `kallax:",inline"`) 52 | } 53 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/generator.go: -------------------------------------------------------------------------------- 1 | // Package generator implements the processor of source code and generator of 2 | // kallax models based on Go source code. 3 | package generator // import "gopkg.in/src-d/go-kallax.v1/generator" 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "runtime/debug" 9 | ) 10 | 11 | // Generator is in charge of generating files for packages. 12 | type Generator struct { 13 | filename string 14 | } 15 | 16 | // NewGenerator creates a new generator that can save on the given filename. 17 | func NewGenerator(filename string) *Generator { 18 | return &Generator{filename} 19 | } 20 | 21 | // Generate writes the file with the contents of the given package. 22 | func (g *Generator) Generate(pkg *Package) error { 23 | return g.writeFile(pkg) 24 | } 25 | 26 | func (g *Generator) writeFile(pkg *Package) (err error) { 27 | file, err := os.Create(g.filename) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | defer func() { 33 | if r := recover(); r != nil { 34 | fmt.Printf("kallax: PANIC during '%s' generation:\n%s\n\n", g.filename, r) 35 | if err == nil { 36 | err = fmt.Errorf(string(debug.Stack())) 37 | } 38 | } 39 | 40 | file.Close() 41 | if err != nil { 42 | if os.Remove(g.filename) == nil { 43 | fmt.Println("kallax: No file generated due to an occurred error:") 44 | } else { 45 | fmt.Printf("kallax: The autogenerated file '%s' could not be completed nor deleted due to an occurred error:\n", g.filename) 46 | } 47 | } 48 | }() 49 | 50 | return Base.Execute(file, pkg) 51 | } 52 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/templates/base.tgo: -------------------------------------------------------------------------------- 1 | // IMPORTANT! This is auto generated code by https://github.com/src-d/go-kallax 2 | // Please, do not touch the code below, and if you do, do it under your own 3 | // risk. Take into account that all the code you write here will be completely 4 | // erased from earth the next time you generate the kallax models. 5 | package {{.Name}} 6 | 7 | import ( 8 | "gopkg.in/src-d/go-kallax.v1" 9 | "gopkg.in/src-d/go-kallax.v1/types" 10 | "database/sql" 11 | "database/sql/driver" 12 | "fmt" 13 | ) 14 | 15 | var _ types.SQLType 16 | var _ fmt.Formatter 17 | 18 | {{template "model" .}} 19 | {{template "schema" .}} 20 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/templates/query.tgo: -------------------------------------------------------------------------------- 1 | 2 | // {{.QueryName}} is the object used to create queries for the {{.Name}} 3 | // entity. 4 | type {{.QueryName}} struct { 5 | *kallax.BaseQuery 6 | } 7 | 8 | // New{{.QueryName}} returns a new instance of {{.QueryName}}. 9 | func New{{.QueryName}}() *{{.QueryName}} { 10 | return &{{.QueryName}}{ 11 | BaseQuery: kallax.NewBaseQuery(Schema.{{.Name}}.BaseSchema), 12 | } 13 | } 14 | 15 | // Select adds columns to select in the query. 16 | func (q *{{.QueryName}}) Select(columns ...kallax.SchemaField) *{{.QueryName}} { 17 | if len(columns) == 0 { 18 | return q 19 | } 20 | q.BaseQuery.Select(columns...) 21 | return q 22 | } 23 | 24 | // SelectNot excludes columns from being selected in the query. 25 | func (q *{{.QueryName}}) SelectNot(columns ...kallax.SchemaField) *{{.QueryName}} { 26 | q.BaseQuery.SelectNot(columns...) 27 | return q 28 | } 29 | 30 | // Copy returns a new identical copy of the query. Remember queries are mutable 31 | // so make a copy any time you need to reuse them. 32 | func (q *{{.QueryName}}) Copy() *{{.QueryName}} { 33 | return &{{.QueryName}}{ 34 | BaseQuery: q.BaseQuery.Copy(), 35 | } 36 | } 37 | 38 | // Order adds order clauses to the query for the given columns. 39 | func (q *{{.QueryName}}) Order(cols ...kallax.ColumnOrder) *{{.QueryName}} { 40 | q.BaseQuery.Order(cols...) 41 | return q 42 | } 43 | 44 | // BatchSize sets the number of items to fetch per batch when there are 1:N 45 | // relationships selected in the query. 46 | func (q *{{.QueryName}}) BatchSize(size uint64) *{{.QueryName}} { 47 | q.BaseQuery.BatchSize(size) 48 | return q 49 | } 50 | 51 | // Limit sets the max number of items to retrieve. 52 | func (q *{{.QueryName}}) Limit(n uint64) *{{.QueryName}} { 53 | q.BaseQuery.Limit(n) 54 | return q 55 | } 56 | 57 | // Offset sets the number of items to skip from the result set of items. 58 | func (q *{{.QueryName}}) Offset(n uint64) *{{.QueryName}} { 59 | q.BaseQuery.Offset(n) 60 | return q 61 | } 62 | 63 | // Where adds a condition to the query. All conditions added are concatenated 64 | // using a logical AND. 65 | func (q *{{.QueryName}}) Where(cond kallax.Condition) *{{.QueryName}} { 66 | q.BaseQuery.Where(cond) 67 | return q 68 | } 69 | 70 | {{range .Relationships}} 71 | {{if not .IsOneToManyRelationship}} 72 | func (q *{{$.QueryName}}) With{{.Name}}() *{{$.QueryName}} { 73 | q.AddRelation(Schema.{{.TypeSchemaName}}.BaseSchema, "{{.Name}}", kallax.OneToOne, nil) 74 | return q 75 | } 76 | {{else}} 77 | func (q *{{$.QueryName}}) With{{.Name}}(cond kallax.Condition) *{{$.QueryName}} { 78 | q.AddRelation(Schema.{{.TypeSchemaName}}.BaseSchema, "{{.Name}}", kallax.OneToMany, cond) 79 | return q 80 | } 81 | {{end}} 82 | {{end}} 83 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/generator/templates/schema.tgo: -------------------------------------------------------------------------------- 1 | 2 | type schema struct { 3 | {{range .Models}}{{.Name}} *schema{{.Name}} 4 | {{end}} 5 | } 6 | 7 | {{range .Models}} 8 | type schema{{.Name}} struct { 9 | *kallax.BaseSchema 10 | {{$.GenModelSchema .}} 11 | } 12 | {{end}} 13 | 14 | {{$.GenSubSchemas}} 15 | 16 | var Schema = &schema{ 17 | {{range .Models}}{{.Name}}: &schema{{.Name}}{ 18 | BaseSchema: kallax.NewBaseSchema( 19 | "{{.Table}}", 20 | "{{.Alias}}", 21 | kallax.NewSchemaField("{{.ID.ColumnName}}"), 22 | kallax.ForeignKeys{ 23 | {{range .Relationships}}"{{.Name}}": kallax.NewForeignKey("{{.ForeignKey}}", {{if .IsInverse}}true{{else}}false{{end}}), 24 | {{end}} 25 | }, 26 | func() kallax.Record { 27 | return new({{.Name}}) 28 | }, 29 | {{if .ID.IsAutoIncrement}}true{{else}}false{{end}}, 30 | {{$.GenModelColumns .}} 31 | ), 32 | {{$.GenSchemaInit .}} 33 | }, 34 | {{end}} 35 | } 36 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/model_test.go: -------------------------------------------------------------------------------- 1 | package kallax 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestUULIDIsEmpty(t *testing.T) { 10 | r := require.New(t) 11 | var id ULID 12 | r.True(id.IsEmpty()) 13 | 14 | id = NewULID() 15 | r.False(id.IsEmpty()) 16 | } 17 | 18 | func TestULID_Value(t *testing.T) { 19 | id := NewULID() 20 | v, _ := id.Value() 21 | require.Equal(t, id.String(), v) 22 | } 23 | 24 | func TestUULID_ThreeNewIDsAreDifferent(t *testing.T) { 25 | r := require.New(t) 26 | id1 := NewULID() 27 | id2 := NewULID() 28 | id3 := NewULID() 29 | 30 | r.NotEqual(id1, id2) 31 | r.NotEqual(id1, id3) 32 | r.NotEqual(id2, id3) 33 | 34 | r.True(id1 == id1) 35 | r.False(id1 == id2) 36 | } 37 | 38 | func TestULID_ScanValue(t *testing.T) { 39 | r := require.New(t) 40 | 41 | expected := NewULID() 42 | v, err := expected.Value() 43 | r.NoError(err) 44 | 45 | var id ULID 46 | r.NoError(id.Scan(v)) 47 | 48 | r.Equal(expected, id) 49 | r.Equal(expected.String(), id.String()) 50 | 51 | r.NoError(id.Scan([]byte("015af13d-2271-fb69-2dcd-fb24a1fd7dcc"))) 52 | } 53 | 54 | func TestVirtualColumn(t *testing.T) { 55 | r := require.New(t) 56 | record := newModel("", "", 0) 57 | record.virtualColumns = nil 58 | r.Equal(nil, record.VirtualColumn("foo")) 59 | 60 | record.virtualColumns = nil 61 | s := VirtualColumn("foo", record, new(ULID)) 62 | 63 | id := NewULID() 64 | v, err := id.Value() 65 | r.NoError(err) 66 | r.NoError(s.Scan(v)) 67 | r.Len(record.virtualColumns, 1) 68 | r.Equal(&id, record.VirtualColumn("foo")) 69 | 70 | r.Error(s.Scan(nil)) 71 | } 72 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/schema_test.go: -------------------------------------------------------------------------------- 1 | package kallax 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | var emptySchema = NewBaseSchema("", "", nil, nil, nil, false) 10 | 11 | func TestBaseSchemaFieldQualifiedName(t *testing.T) { 12 | var cases = []struct { 13 | name string 14 | field SchemaField 15 | schema Schema 16 | expected string 17 | }{ 18 | {"non empty schema alias", f("foo"), ModelSchema, "__model.foo"}, 19 | {"empty schema alias", f("foo"), emptySchema, "foo"}, 20 | } 21 | 22 | r := require.New(t) 23 | for _, c := range cases { 24 | r.Equal(c.expected, c.field.QualifiedName(c.schema), c.name) 25 | } 26 | } 27 | 28 | func TestJSONSchemaKeyQualifiedName(t *testing.T) { 29 | var cases = []struct { 30 | name string 31 | key *JSONSchemaKey 32 | schema Schema 33 | expected string 34 | }{ 35 | { 36 | "json text key", 37 | NewJSONSchemaKey(JSONText, "foo", "bar", "baz"), 38 | ModelSchema, 39 | "__model.foo #>>'{bar,baz}'", 40 | }, 41 | { 42 | "json int key", 43 | NewJSONSchemaKey(JSONInt, "foo", "bar", "baz"), 44 | ModelSchema, 45 | "CAST(__model.foo #>>'{bar,baz}' as bigint)", 46 | }, 47 | { 48 | "json any key", 49 | NewJSONSchemaKey(JSONAny, "foo", "bar", "baz"), 50 | ModelSchema, 51 | "__model.foo #>'{bar,baz}'", 52 | }, 53 | { 54 | "json key with empty schema", 55 | NewJSONSchemaKey(JSONBool, "foo", "bar", "baz"), 56 | nil, 57 | "CAST(foo #>>'{bar,baz}' as bool)", 58 | }, 59 | } 60 | 61 | r := require.New(t) 62 | for _, c := range cases { 63 | r.Equal(c.expected, c.key.QualifiedName(c.schema), c.name) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/common.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | //go:generate kallax gen 4 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/connection_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | ) 8 | 9 | func TestConnectionSuite(t *testing.T) { 10 | suite.Run(t, new(ConnectionSuite)) 11 | } 12 | 13 | type ConnectionSuite struct { 14 | BaseTestSuite 15 | } 16 | 17 | func (s *ConnectionSuite) TestConnection() { 18 | s.QuerySucceed( 19 | `CREATE TABLE testing (id uuid primary key)`, 20 | `DROP TABLE testing`, 21 | `DROP TABLE IF EXISTS testing`, 22 | ) 23 | s.QueryFails(`DROP TABLE _THIS_TABLE_DOES_NOT_EXIST`) 24 | } 25 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/fixtures/fixtures.go: -------------------------------------------------------------------------------- 1 | package fixtures 2 | 3 | import "database/sql/driver" 4 | 5 | type AliasArray [3]string 6 | type AliasSlice []string 7 | type AliasString string 8 | type AliasInt int 9 | type AliasArrAliasSlice []AliasSlice 10 | type AliasArrAliasString []AliasString 11 | type AliasDummyParam QueryDummy 12 | 13 | type QueryDummy struct { 14 | name string 15 | } 16 | 17 | type InterfaceImplementation struct { 18 | ScannerValuer 19 | Str string 20 | } 21 | 22 | type ScannerValuer struct{} 23 | 24 | func (i ScannerValuer) Value() (driver.Value, error) { 25 | return nil, nil 26 | } 27 | 28 | func (i ScannerValuer) Scan(src interface{}) error { 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/json.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import kallax "gopkg.in/src-d/go-kallax.v1" 4 | 5 | type JSONModel struct { 6 | kallax.Model `table:"jsons"` 7 | ID kallax.ULID `pk:""` 8 | Foo string 9 | Bar *Bar 10 | BazSlice []Baz 11 | Baz map[string]interface{} 12 | } 13 | 14 | type Bar struct { 15 | Qux []Qux 16 | Mux string 17 | } 18 | 19 | type Baz struct { 20 | Mux string 21 | } 22 | 23 | type Qux struct { 24 | Schnooga string 25 | Balooga int 26 | Boo float64 27 | } 28 | 29 | func newJSONModel() *JSONModel { 30 | return &JSONModel{ID: kallax.NewULID(), Baz: make(map[string]interface{})} 31 | } 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/json_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/suite" 7 | kallax "gopkg.in/src-d/go-kallax.v1" 8 | ) 9 | 10 | type JSONSuite struct { 11 | BaseTestSuite 12 | } 13 | 14 | func TestJSON(t *testing.T) { 15 | schema := []string{ 16 | `CREATE TABLE IF NOT EXISTS jsons ( 17 | id uuid primary key, 18 | foo text, 19 | bar jsonb, 20 | baz jsonb, 21 | baz_slice jsonb 22 | )`, 23 | } 24 | suite.Run(t, &JSONSuite{NewBaseSuite(schema, "jsons")}) 25 | } 26 | 27 | func (s *JSONSuite) TestSearchByField() { 28 | s.insertFixtures() 29 | q := NewJSONModelQuery().Where( 30 | kallax.Eq(Schema.JSONModel.Bar.Mux, "mux1"), 31 | ) 32 | s.assertFound(q, "1") 33 | } 34 | 35 | func (s *JSONSuite) TestSearchByCustomField() { 36 | s.insertFixtures() 37 | q := NewJSONModelQuery().Where( 38 | kallax.Eq(kallax.AtJSONPath(Schema.JSONModel.Baz, kallax.JSONInt, "a", "0", "b"), 3), 39 | ) 40 | 41 | s.assertFound(q, "2") 42 | 43 | q = NewJSONModelQuery().Where( 44 | kallax.Eq(kallax.AtJSONPath(Schema.JSONModel.Baz, kallax.JSONBool, "b"), true), 45 | ) 46 | 47 | s.assertFound(q, "1") 48 | } 49 | 50 | func (s *JSONSuite) assertFound(q *JSONModelQuery, foos ...string) { 51 | require := s.Require() 52 | store := NewJSONModelStore(s.db) 53 | rs, err := store.Find(q) 54 | require.NoError(err) 55 | 56 | models, err := rs.All() 57 | require.NoError(err) 58 | require.Len(models, len(foos)) 59 | for i, f := range foos { 60 | require.Equal(f, models[i].Foo) 61 | } 62 | } 63 | 64 | func (s *JSONSuite) insertFixtures() { 65 | store := NewJSONModelStore(s.db) 66 | 67 | m := NewJSONModel() 68 | m.Foo = "1" 69 | m.Baz = map[string]interface{}{ 70 | "a": []interface{}{ 71 | map[string]interface{}{ 72 | "b": 1, 73 | }, 74 | map[string]interface{}{ 75 | "b": 2, 76 | }, 77 | }, 78 | "b": true, 79 | } 80 | m.Bar = &Bar{ 81 | Qux: []Qux{ 82 | {"schnooga1", 1, .5}, 83 | {"schnooga2", 2, .6}, 84 | }, 85 | Mux: "mux1", 86 | } 87 | 88 | s.NoError(store.Insert(m)) 89 | 90 | m = NewJSONModel() 91 | m.Foo = "2" 92 | m.Baz = map[string]interface{}{ 93 | "a": []interface{}{ 94 | map[string]interface{}{ 95 | "b": 3, 96 | }, 97 | map[string]interface{}{ 98 | "b": 4, 99 | }, 100 | }, 101 | "b": false, 102 | } 103 | m.Bar = &Bar{ 104 | Qux: []Qux{ 105 | {"schnooga3", 3, .7}, 106 | {"schnooga4", 4, .8}, 107 | }, 108 | Mux: "mux2", 109 | } 110 | 111 | s.NoError(store.Insert(m)) 112 | } 113 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/resultset.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "gopkg.in/src-d/go-kallax.v1" 4 | 5 | type ResultSetFixture struct { 6 | kallax.Model `table:"resultset"` 7 | ID kallax.ULID `pk:""` 8 | Foo string 9 | } 10 | 11 | func newResultSetFixture(f string) *ResultSetFixture { 12 | return &ResultSetFixture{ID: kallax.NewULID(), Foo: f} 13 | } 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/schema.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "gopkg.in/src-d/go-kallax.v1" 4 | 5 | type SchemaFixture struct { 6 | kallax.Model `table:"schema"` 7 | ID kallax.ULID `pk:""` 8 | ShouldIgnore string `kallax:"-"` 9 | String string 10 | Int int 11 | Nested *SchemaFixture 12 | Inline struct { 13 | Inline string 14 | } `kallax:",inline"` 15 | MapOfString map[string]string 16 | MapOfInterface map[string]interface{} 17 | MapOfSomeType map[string]struct { 18 | Foo string 19 | } 20 | Inverse *SchemaRelationshipFixture `fk:"rel_id,inverse"` 21 | } 22 | 23 | type SchemaRelationshipFixture struct { 24 | kallax.Model `table:"relationship"` 25 | ID kallax.ULID `pk:""` 26 | } 27 | 28 | func newSchemaFixture() *SchemaFixture { 29 | return &SchemaFixture{ID: kallax.NewULID()} 30 | } 31 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/schema_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/suite" 8 | ) 9 | 10 | type SchemaSuite struct { 11 | BaseTestSuite 12 | } 13 | 14 | func TestSchemaSuite(t *testing.T) { 15 | suite.Run(t, new(SchemaSuite)) 16 | } 17 | 18 | func (s *SchemaSuite) TestSchemaID() { 19 | s.Equal("id", Schema.SchemaFixture.ID.String()) 20 | } 21 | 22 | func (s *SchemaSuite) TestSchemaBasicField() { 23 | s.Equal("string", Schema.SchemaFixture.String.String()) 24 | } 25 | 26 | func (s *SchemaSuite) TestSchemaRanamedField() { 27 | s.Equal("int", Schema.SchemaFixture.Int.String()) 28 | } 29 | 30 | func (s *SchemaSuite) TestSchemaInlineField() { 31 | s.Equal("inline", Schema.SchemaFixture.Inline.String()) 32 | } 33 | 34 | func (s *SchemaSuite) TestSchemaMapsOfString() { 35 | s.Equal("map_of_string", Schema.SchemaFixture.MapOfString.String()) 36 | } 37 | 38 | func (s *SchemaSuite) TestSchemaMapOfSomeType() { 39 | s.Equal("map_of_interface", Schema.SchemaFixture.MapOfInterface.String()) 40 | } 41 | 42 | func (s *SchemaSuite) TestSchemaMapOfInterface() { 43 | s.Equal("map_of_some_type", Schema.SchemaFixture.MapOfSomeType.String()) 44 | } 45 | 46 | func (s *SchemaSuite) TestSchemaInverse() { 47 | s.Equal("rel_id", Schema.SchemaFixture.InverseFK.String()) 48 | } 49 | 50 | func (s *SchemaSuite) TestSchemaIgnored() { 51 | schema := reflect.ValueOf(Schema.SchemaFixture) 52 | field := reflect.Indirect(schema).FieldByName("ShouldIgnore") 53 | s.False(field.IsValid()) 54 | } 55 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/tests/store.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "time" 5 | 6 | "gopkg.in/src-d/go-kallax.v1" 7 | ) 8 | 9 | type AliasSliceString []string 10 | 11 | type StoreFixture struct { 12 | kallax.Model `table:"store"` 13 | ID kallax.ULID `pk:""` 14 | Foo string 15 | SliceProp []string 16 | AliasSliceProp AliasSliceString 17 | } 18 | 19 | func newStoreFixture() *StoreFixture { 20 | return &StoreFixture{ID: kallax.NewULID()} 21 | } 22 | 23 | type StoreWithConstructFixture struct { 24 | kallax.Model `table:"store_construct"` 25 | ID kallax.ULID `pk:""` 26 | Foo string 27 | } 28 | 29 | func newStoreWithConstructFixture(f string) *StoreWithConstructFixture { 30 | if f == "" { 31 | return nil 32 | } 33 | return &StoreWithConstructFixture{ID: kallax.NewULID(), Foo: f} 34 | } 35 | 36 | type StoreWithNewFixture struct { 37 | kallax.Model `table:"store_new"` 38 | ID kallax.ULID `pk:""` 39 | Foo string 40 | Bar string 41 | } 42 | 43 | func newStoreWithNewFixture() *StoreWithNewFixture { 44 | return &StoreWithNewFixture{ID: kallax.NewULID()} 45 | } 46 | 47 | type MultiKeySortFixture struct { 48 | kallax.Model `table:"query"` 49 | ID kallax.ULID `pk:""` 50 | Name string 51 | Start time.Time 52 | End time.Time 53 | } 54 | 55 | func newMultiKeySortFixture() *MultiKeySortFixture { 56 | return &MultiKeySortFixture{ID: kallax.NewULID()} 57 | } 58 | 59 | type SomeJSON struct { 60 | Foo int 61 | } 62 | 63 | type Nullable struct { 64 | kallax.Model `table:"nullable"` 65 | ID int64 `pk:"autoincr"` 66 | T *time.Time 67 | SomeJSON *SomeJSON 68 | Scanner *kallax.ULID 69 | } 70 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/timestamps.go: -------------------------------------------------------------------------------- 1 | package kallax 2 | 3 | import "time" 4 | 5 | // Timestamps contains the dates of the last time the model was created 6 | // or deleted. Because this is such a common functionality in models, it is 7 | // provided by default by the library. It is intended to be embedded in the 8 | // model. 9 | // 10 | // type MyModel struct { 11 | // kallax.Model 12 | // kallax.Timestamps 13 | // Foo string 14 | // } 15 | type Timestamps struct { 16 | // CreatedAt is the time where the object was created. 17 | CreatedAt time.Time 18 | // UpdatedAt is the time where the object was updated. 19 | UpdatedAt time.Time 20 | } 21 | 22 | // BeforeSave updates the last time the model was updated every single time the 23 | // model is saved, and the last time the model was created only if the model 24 | // has no date of creation yet. 25 | func (t *Timestamps) BeforeSave() error { 26 | if t.CreatedAt.IsZero() { 27 | t.CreatedAt = time.Now() 28 | } 29 | 30 | t.UpdatedAt = time.Now() 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /vendor/gopkg.in/src-d/go-kallax.v1/timestamps_test.go: -------------------------------------------------------------------------------- 1 | package kallax 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/require" 7 | ) 8 | 9 | func TestTimestampsBeforeSave(t *testing.T) { 10 | s := require.New(t) 11 | 12 | var ts Timestamps 13 | s.True(ts.CreatedAt.IsZero()) 14 | s.True(ts.UpdatedAt.IsZero()) 15 | 16 | s.NoError(ts.BeforeSave()) 17 | s.False(ts.CreatedAt.IsZero()) 18 | s.False(ts.UpdatedAt.IsZero()) 19 | 20 | createdAt := ts.CreatedAt 21 | updatedAt := ts.CreatedAt 22 | s.NoError(ts.BeforeSave()) 23 | s.Equal(createdAt, ts.CreatedAt) 24 | s.NotEqual(updatedAt, ts.UpdatedAt) 25 | } 26 | --------------------------------------------------------------------------------