diff options
Diffstat (limited to 'Godeps/_workspace/src/github.com/garyburd')
10 files changed, 175 insertions, 2519 deletions
diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/LICENSE b/Godeps/_workspace/src/github.com/garyburd/redigo/LICENSE new file mode 100644 index 000000000..67db85882 --- /dev/null +++ b/Godeps/_workspace/src/github.com/garyburd/redigo/LICENSE @@ -0,0 +1,175 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/internal/commandinfo_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/internal/commandinfo_test.go deleted file mode 100644 index 118e94b67..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/internal/commandinfo_test.go +++ /dev/null @@ -1,27 +0,0 @@ -package internal - -import "testing" - -func TestLookupCommandInfo(t *testing.T) { - for _, n := range []string{"watch", "WATCH", "wAtch"} { - if LookupCommandInfo(n) == (CommandInfo{}) { - t.Errorf("LookupCommandInfo(%q) = CommandInfo{}, expected non-zero value", n) - } - } -} - -func benchmarkLookupCommandInfo(b *testing.B, names ...string) { - for i := 0; i < b.N; i++ { - for _, c := range names { - LookupCommandInfo(c) - } - } -} - -func BenchmarkLookupCommandInfoCorrectCase(b *testing.B) { - benchmarkLookupCommandInfo(b, "watch", "WATCH", "monitor", "MONITOR") -} - -func BenchmarkLookupCommandInfoMixedCase(b *testing.B) { - benchmarkLookupCommandInfo(b, "wAtch", "WeTCH", "monItor", "MONiTOR") -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/conn_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/conn_test.go deleted file mode 100644 index 24887cf03..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/conn_test.go +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "bytes" - "io" - "math" - "net" - "os" - "reflect" - "strings" - "testing" - "time" - - "github.com/garyburd/redigo/redis" -) - -type testConn struct { - io.Reader - io.Writer -} - -func (*testConn) Close() error { return nil } -func (*testConn) LocalAddr() net.Addr { return nil } -func (*testConn) RemoteAddr() net.Addr { return nil } -func (*testConn) SetDeadline(t time.Time) error { return nil } -func (*testConn) SetReadDeadline(t time.Time) error { return nil } -func (*testConn) SetWriteDeadline(t time.Time) error { return nil } - -func dialTestConn(r io.Reader, w io.Writer) redis.DialOption { - return redis.DialNetDial(func(net, addr string) (net.Conn, error) { - return &testConn{Reader: r, Writer: w}, nil - }) -} - -var writeTests = []struct { - args []interface{} - expected string -}{ - { - []interface{}{"SET", "key", "value"}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n", - }, - { - []interface{}{"SET", "key", "value"}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n", - }, - { - []interface{}{"SET", "key", byte(100)}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n", - }, - { - []interface{}{"SET", "key", 100}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$3\r\n100\r\n", - }, - { - []interface{}{"SET", "key", int64(math.MinInt64)}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$20\r\n-9223372036854775808\r\n", - }, - { - []interface{}{"SET", "key", float64(1349673917.939762)}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$21\r\n1.349673917939762e+09\r\n", - }, - { - []interface{}{"SET", "key", ""}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n", - }, - { - []interface{}{"SET", "key", nil}, - "*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$0\r\n\r\n", - }, - { - []interface{}{"ECHO", true, false}, - "*3\r\n$4\r\nECHO\r\n$1\r\n1\r\n$1\r\n0\r\n", - }, -} - -func TestWrite(t *testing.T) { - for _, tt := range writeTests { - var buf bytes.Buffer - c, _ := redis.Dial("", "", dialTestConn(nil, &buf)) - err := c.Send(tt.args[0].(string), tt.args[1:]...) - if err != nil { - t.Errorf("Send(%v) returned error %v", tt.args, err) - continue - } - c.Flush() - actual := buf.String() - if actual != tt.expected { - t.Errorf("Send(%v) = %q, want %q", tt.args, actual, tt.expected) - } - } -} - -var errorSentinel = &struct{}{} - -var readTests = []struct { - reply string - expected interface{} -}{ - { - "+OK\r\n", - "OK", - }, - { - "+PONG\r\n", - "PONG", - }, - { - "@OK\r\n", - errorSentinel, - }, - { - "$6\r\nfoobar\r\n", - []byte("foobar"), - }, - { - "$-1\r\n", - nil, - }, - { - ":1\r\n", - int64(1), - }, - { - ":-2\r\n", - int64(-2), - }, - { - "*0\r\n", - []interface{}{}, - }, - { - "*-1\r\n", - nil, - }, - { - "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n", - []interface{}{[]byte("foo"), []byte("bar"), []byte("Hello"), []byte("World")}, - }, - { - "*3\r\n$3\r\nfoo\r\n$-1\r\n$3\r\nbar\r\n", - []interface{}{[]byte("foo"), nil, []byte("bar")}, - }, - - { - // "x" is not a valid length - "$x\r\nfoobar\r\n", - errorSentinel, - }, - { - // -2 is not a valid length - "$-2\r\n", - errorSentinel, - }, - { - // "x" is not a valid integer - ":x\r\n", - errorSentinel, - }, - { - // missing \r\n following value - "$6\r\nfoobar", - errorSentinel, - }, - { - // short value - "$6\r\nxx", - errorSentinel, - }, - { - // long value - "$6\r\nfoobarx\r\n", - errorSentinel, - }, -} - -func TestRead(t *testing.T) { - for _, tt := range readTests { - c, _ := redis.Dial("", "", dialTestConn(strings.NewReader(tt.reply), nil)) - actual, err := c.Receive() - if tt.expected == errorSentinel { - if err == nil { - t.Errorf("Receive(%q) did not return expected error", tt.reply) - } - } else { - if err != nil { - t.Errorf("Receive(%q) returned error %v", tt.reply, err) - continue - } - if !reflect.DeepEqual(actual, tt.expected) { - t.Errorf("Receive(%q) = %v, want %v", tt.reply, actual, tt.expected) - } - } - } -} - -var testCommands = []struct { - args []interface{} - expected interface{} -}{ - { - []interface{}{"PING"}, - "PONG", - }, - { - []interface{}{"SET", "foo", "bar"}, - "OK", - }, - { - []interface{}{"GET", "foo"}, - []byte("bar"), - }, - { - []interface{}{"GET", "nokey"}, - nil, - }, - { - []interface{}{"MGET", "nokey", "foo"}, - []interface{}{nil, []byte("bar")}, - }, - { - []interface{}{"INCR", "mycounter"}, - int64(1), - }, - { - []interface{}{"LPUSH", "mylist", "foo"}, - int64(1), - }, - { - []interface{}{"LPUSH", "mylist", "bar"}, - int64(2), - }, - { - []interface{}{"LRANGE", "mylist", 0, -1}, - []interface{}{[]byte("bar"), []byte("foo")}, - }, - { - []interface{}{"MULTI"}, - "OK", - }, - { - []interface{}{"LRANGE", "mylist", 0, -1}, - "QUEUED", - }, - { - []interface{}{"PING"}, - "QUEUED", - }, - { - []interface{}{"EXEC"}, - []interface{}{ - []interface{}{[]byte("bar"), []byte("foo")}, - "PONG", - }, - }, -} - -func TestDoCommands(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - for _, cmd := range testCommands { - actual, err := c.Do(cmd.args[0].(string), cmd.args[1:]...) - if err != nil { - t.Errorf("Do(%v) returned error %v", cmd.args, err) - continue - } - if !reflect.DeepEqual(actual, cmd.expected) { - t.Errorf("Do(%v) = %v, want %v", cmd.args, actual, cmd.expected) - } - } -} - -func TestPipelineCommands(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - for _, cmd := range testCommands { - if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil { - t.Fatalf("Send(%v) returned error %v", cmd.args, err) - } - } - if err := c.Flush(); err != nil { - t.Errorf("Flush() returned error %v", err) - } - for _, cmd := range testCommands { - actual, err := c.Receive() - if err != nil { - t.Fatalf("Receive(%v) returned error %v", cmd.args, err) - } - if !reflect.DeepEqual(actual, cmd.expected) { - t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected) - } - } -} - -func TestBlankCommmand(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - for _, cmd := range testCommands { - if err := c.Send(cmd.args[0].(string), cmd.args[1:]...); err != nil { - t.Fatalf("Send(%v) returned error %v", cmd.args, err) - } - } - reply, err := redis.Values(c.Do("")) - if err != nil { - t.Fatalf("Do() returned error %v", err) - } - if len(reply) != len(testCommands) { - t.Fatalf("len(reply)=%d, want %d", len(reply), len(testCommands)) - } - for i, cmd := range testCommands { - actual := reply[i] - if !reflect.DeepEqual(actual, cmd.expected) { - t.Errorf("Receive(%v) = %v, want %v", cmd.args, actual, cmd.expected) - } - } -} - -func TestRecvBeforeSend(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - done := make(chan struct{}) - go func() { - c.Receive() - close(done) - }() - time.Sleep(time.Millisecond) - c.Send("PING") - c.Flush() - <-done - _, err = c.Do("") - if err != nil { - t.Fatalf("error=%v", err) - } -} - -func TestError(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - c.Do("SET", "key", "val") - _, err = c.Do("HSET", "key", "fld", "val") - if err == nil { - t.Errorf("Expected err for HSET on string key.") - } - if c.Err() != nil { - t.Errorf("Conn has Err()=%v, expect nil", c.Err()) - } - _, err = c.Do("SET", "key", "val") - if err != nil { - t.Errorf("Do(SET, key, val) returned error %v, expected nil.", err) - } -} - -func TestReadTimeout(t *testing.T) { - l, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - t.Fatalf("net.Listen returned %v", err) - } - defer l.Close() - - go func() { - for { - c, err := l.Accept() - if err != nil { - return - } - go func() { - time.Sleep(time.Second) - c.Write([]byte("+OK\r\n")) - c.Close() - }() - } - }() - - // Do - - c1, err := redis.Dial(l.Addr().Network(), l.Addr().String(), redis.DialReadTimeout(time.Millisecond)) - if err != nil { - t.Fatalf("redis.Dial returned %v", err) - } - defer c1.Close() - - _, err = c1.Do("PING") - if err == nil { - t.Fatalf("c1.Do() returned nil, expect error") - } - if c1.Err() == nil { - t.Fatalf("c1.Err() = nil, expect error") - } - - // Send/Flush/Receive - - c2, err := redis.Dial(l.Addr().Network(), l.Addr().String(), redis.DialReadTimeout(time.Millisecond)) - if err != nil { - t.Fatalf("redis.Dial returned %v", err) - } - defer c2.Close() - - c2.Send("PING") - c2.Flush() - _, err = c2.Receive() - if err == nil { - t.Fatalf("c2.Receive() returned nil, expect error") - } - if c2.Err() == nil { - t.Fatalf("c2.Err() = nil, expect error") - } -} - -var dialErrors = []struct { - rawurl string - expectedError string -}{ - { - "localhost", - "invalid redis URL scheme", - }, - // The error message for invalid hosts is diffferent in different - // versions of Go, so just check that there is an error message. - { - "redis://weird url", - "", - }, - { - "redis://foo:bar:baz", - "", - }, - { - "http://www.google.com", - "invalid redis URL scheme: http", - }, - { - "redis://localhost:6379/abc123", - "invalid database: abc123", - }, -} - -func TestDialURLErrors(t *testing.T) { - for _, d := range dialErrors { - _, err := redis.DialURL(d.rawurl) - if err == nil || !strings.Contains(err.Error(), d.expectedError) { - t.Errorf("DialURL did not return expected error (expected %v to contain %s)", err, d.expectedError) - } - } -} - -func TestDialURLPort(t *testing.T) { - checkPort := func(network, address string) (net.Conn, error) { - if address != "localhost:6379" { - t.Errorf("DialURL did not set port to 6379 by default (got %v)", address) - } - return nil, nil - } - _, err := redis.DialURL("redis://localhost", redis.DialNetDial(checkPort)) - if err != nil { - t.Error("dial error:", err) - } -} - -func TestDialURLHost(t *testing.T) { - checkHost := func(network, address string) (net.Conn, error) { - if address != "localhost:6379" { - t.Errorf("DialURL did not set host to localhost by default (got %v)", address) - } - return nil, nil - } - _, err := redis.DialURL("redis://:6379", redis.DialNetDial(checkHost)) - if err != nil { - t.Error("dial error:", err) - } -} - -func TestDialURLPassword(t *testing.T) { - var buf bytes.Buffer - _, err := redis.DialURL("redis://x:abc123@localhost", dialTestConn(strings.NewReader("+OK\r\n"), &buf)) - if err != nil { - t.Error("dial error:", err) - } - expected := "*2\r\n$4\r\nAUTH\r\n$6\r\nabc123\r\n" - actual := buf.String() - if actual != expected { - t.Errorf("commands = %q, want %q", actual, expected) - } -} - -func TestDialURLDatabase(t *testing.T) { - var buf bytes.Buffer - _, err := redis.DialURL("redis://localhost/3", dialTestConn(strings.NewReader("+OK\r\n"), &buf)) - if err != nil { - t.Error("dial error:", err) - } - expected := "*2\r\n$6\r\nSELECT\r\n$1\r\n3\r\n" - actual := buf.String() - if actual != expected { - t.Errorf("commands = %q, want %q", actual, expected) - } -} - -// Connect to local instance of Redis running on the default port. -func ExampleDial(x int) { - c, err := redis.Dial("tcp", ":6379") - if err != nil { - // handle error - } - defer c.Close() -} - -// Connect to remote instance of Redis using a URL. -func ExampleDialURL() { - c, err := redis.DialURL(os.Getenv("REDIS_URL")) - if err != nil { - // handle connection error - } - defer c.Close() -} - -// TextExecError tests handling of errors in a transaction. See -// http://redis.io/topics/transactions for information on how Redis handles -// errors in a transaction. -func TestExecError(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - // Execute commands that fail before EXEC is called. - - c.Do("DEL", "k0") - c.Do("ZADD", "k0", 0, 0) - c.Send("MULTI") - c.Send("NOTACOMMAND", "k0", 0, 0) - c.Send("ZINCRBY", "k0", 0, 0) - v, err := c.Do("EXEC") - if err == nil { - t.Fatalf("EXEC returned values %v, expected error", v) - } - - // Execute commands that fail after EXEC is called. The first command - // returns an error. - - c.Do("DEL", "k1") - c.Do("ZADD", "k1", 0, 0) - c.Send("MULTI") - c.Send("HSET", "k1", 0, 0) - c.Send("ZINCRBY", "k1", 0, 0) - v, err = c.Do("EXEC") - if err != nil { - t.Fatalf("EXEC returned error %v", err) - } - - vs, err := redis.Values(v, nil) - if err != nil { - t.Fatalf("Values(v) returned error %v", err) - } - - if len(vs) != 2 { - t.Fatalf("len(vs) == %d, want 2", len(vs)) - } - - if _, ok := vs[0].(error); !ok { - t.Fatalf("first result is type %T, expected error", vs[0]) - } - - if _, ok := vs[1].([]byte); !ok { - t.Fatalf("second result is type %T, expected []byte", vs[1]) - } - - // Execute commands that fail after EXEC is called. The second command - // returns an error. - - c.Do("ZADD", "k2", 0, 0) - c.Send("MULTI") - c.Send("ZINCRBY", "k2", 0, 0) - c.Send("HSET", "k2", 0, 0) - v, err = c.Do("EXEC") - if err != nil { - t.Fatalf("EXEC returned error %v", err) - } - - vs, err = redis.Values(v, nil) - if err != nil { - t.Fatalf("Values(v) returned error %v", err) - } - - if len(vs) != 2 { - t.Fatalf("len(vs) == %d, want 2", len(vs)) - } - - if _, ok := vs[0].([]byte); !ok { - t.Fatalf("first result is type %T, expected []byte", vs[0]) - } - - if _, ok := vs[1].(error); !ok { - t.Fatalf("second result is type %T, expected error", vs[2]) - } -} - -func BenchmarkDoEmpty(b *testing.B) { - b.StopTimer() - c, err := redis.DialDefaultServer() - if err != nil { - b.Fatal(err) - } - defer c.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, err := c.Do(""); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkDoPing(b *testing.B) { - b.StopTimer() - c, err := redis.DialDefaultServer() - if err != nil { - b.Fatal(err) - } - defer c.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - if _, err := c.Do("PING"); err != nil { - b.Fatal(err) - } - } -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pool_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pool_test.go deleted file mode 100644 index 9419a128f..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pool_test.go +++ /dev/null @@ -1,684 +0,0 @@ -// Copyright 2011 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "errors" - "io" - "reflect" - "sync" - "testing" - "time" - - "github.com/garyburd/redigo/redis" -) - -type poolTestConn struct { - d *poolDialer - err error - redis.Conn -} - -func (c *poolTestConn) Close() error { - c.d.mu.Lock() - c.d.open -= 1 - c.d.mu.Unlock() - return c.Conn.Close() -} - -func (c *poolTestConn) Err() error { return c.err } - -func (c *poolTestConn) Do(commandName string, args ...interface{}) (interface{}, error) { - if commandName == "ERR" { - c.err = args[0].(error) - commandName = "PING" - } - if commandName != "" { - c.d.commands = append(c.d.commands, commandName) - } - return c.Conn.Do(commandName, args...) -} - -func (c *poolTestConn) Send(commandName string, args ...interface{}) error { - c.d.commands = append(c.d.commands, commandName) - return c.Conn.Send(commandName, args...) -} - -type poolDialer struct { - mu sync.Mutex - t *testing.T - dialed int - open int - commands []string - dialErr error -} - -func (d *poolDialer) dial() (redis.Conn, error) { - d.mu.Lock() - d.dialed += 1 - dialErr := d.dialErr - d.mu.Unlock() - if dialErr != nil { - return nil, d.dialErr - } - c, err := redis.DialDefaultServer() - if err != nil { - return nil, err - } - d.mu.Lock() - d.open += 1 - d.mu.Unlock() - return &poolTestConn{d: d, Conn: c}, nil -} - -func (d *poolDialer) check(message string, p *redis.Pool, dialed, open int) { - d.mu.Lock() - if d.dialed != dialed { - d.t.Errorf("%s: dialed=%d, want %d", message, d.dialed, dialed) - } - if d.open != open { - d.t.Errorf("%s: open=%d, want %d", message, d.open, open) - } - if active := p.ActiveCount(); active != open { - d.t.Errorf("%s: active=%d, want %d", message, active, open) - } - d.mu.Unlock() -} - -func TestPoolReuse(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - Dial: d.dial, - } - - for i := 0; i < 10; i++ { - c1 := p.Get() - c1.Do("PING") - c2 := p.Get() - c2.Do("PING") - c1.Close() - c2.Close() - } - - d.check("before close", p, 2, 2) - p.Close() - d.check("after close", p, 2, 0) -} - -func TestPoolMaxIdle(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - Dial: d.dial, - } - defer p.Close() - - for i := 0; i < 10; i++ { - c1 := p.Get() - c1.Do("PING") - c2 := p.Get() - c2.Do("PING") - c3 := p.Get() - c3.Do("PING") - c1.Close() - c2.Close() - c3.Close() - } - d.check("before close", p, 12, 2) - p.Close() - d.check("after close", p, 12, 0) -} - -func TestPoolError(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - Dial: d.dial, - } - defer p.Close() - - c := p.Get() - c.Do("ERR", io.EOF) - if c.Err() == nil { - t.Errorf("expected c.Err() != nil") - } - c.Close() - - c = p.Get() - c.Do("ERR", io.EOF) - c.Close() - - d.check(".", p, 2, 0) -} - -func TestPoolClose(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - Dial: d.dial, - } - defer p.Close() - - c1 := p.Get() - c1.Do("PING") - c2 := p.Get() - c2.Do("PING") - c3 := p.Get() - c3.Do("PING") - - c1.Close() - if _, err := c1.Do("PING"); err == nil { - t.Errorf("expected error after connection closed") - } - - c2.Close() - c2.Close() - - p.Close() - - d.check("after pool close", p, 3, 1) - - if _, err := c1.Do("PING"); err == nil { - t.Errorf("expected error after connection and pool closed") - } - - c3.Close() - - d.check("after conn close", p, 3, 0) - - c1 = p.Get() - if _, err := c1.Do("PING"); err == nil { - t.Errorf("expected error after pool closed") - } -} - -func TestPoolTimeout(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - IdleTimeout: 300 * time.Second, - Dial: d.dial, - } - defer p.Close() - - now := time.Now() - redis.SetNowFunc(func() time.Time { return now }) - defer redis.SetNowFunc(time.Now) - - c := p.Get() - c.Do("PING") - c.Close() - - d.check("1", p, 1, 1) - - now = now.Add(p.IdleTimeout) - - c = p.Get() - c.Do("PING") - c.Close() - - d.check("2", p, 2, 1) -} - -func TestPoolConcurrenSendReceive(t *testing.T) { - p := &redis.Pool{ - Dial: redis.DialDefaultServer, - } - defer p.Close() - - c := p.Get() - done := make(chan error, 1) - go func() { - _, err := c.Receive() - done <- err - }() - c.Send("PING") - c.Flush() - err := <-done - if err != nil { - t.Fatalf("Receive() returned error %v", err) - } - _, err = c.Do("") - if err != nil { - t.Fatalf("Do() returned error %v", err) - } - c.Close() -} - -func TestPoolBorrowCheck(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - Dial: d.dial, - TestOnBorrow: func(redis.Conn, time.Time) error { return redis.Error("BLAH") }, - } - defer p.Close() - - for i := 0; i < 10; i++ { - c := p.Get() - c.Do("PING") - c.Close() - } - d.check("1", p, 10, 1) -} - -func TestPoolMaxActive(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - MaxActive: 2, - Dial: d.dial, - } - defer p.Close() - - c1 := p.Get() - c1.Do("PING") - c2 := p.Get() - c2.Do("PING") - - d.check("1", p, 2, 2) - - c3 := p.Get() - if _, err := c3.Do("PING"); err != redis.ErrPoolExhausted { - t.Errorf("expected pool exhausted") - } - - c3.Close() - d.check("2", p, 2, 2) - c2.Close() - d.check("3", p, 2, 2) - - c3 = p.Get() - if _, err := c3.Do("PING"); err != nil { - t.Errorf("expected good channel, err=%v", err) - } - c3.Close() - - d.check("4", p, 2, 2) -} - -func TestPoolMonitorCleanup(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - MaxActive: 2, - Dial: d.dial, - } - defer p.Close() - - c := p.Get() - c.Send("MONITOR") - c.Close() - - d.check("", p, 1, 0) -} - -func TestPoolPubSubCleanup(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - MaxActive: 2, - Dial: d.dial, - } - defer p.Close() - - c := p.Get() - c.Send("SUBSCRIBE", "x") - c.Close() - - want := []string{"SUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil - - c = p.Get() - c.Send("PSUBSCRIBE", "x*") - c.Close() - - want = []string{"PSUBSCRIBE", "UNSUBSCRIBE", "PUNSUBSCRIBE", "ECHO"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil -} - -func TestPoolTransactionCleanup(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 2, - MaxActive: 2, - Dial: d.dial, - } - defer p.Close() - - c := p.Get() - c.Do("WATCH", "key") - c.Do("PING") - c.Close() - - want := []string{"WATCH", "PING", "UNWATCH"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil - - c = p.Get() - c.Do("WATCH", "key") - c.Do("UNWATCH") - c.Do("PING") - c.Close() - - want = []string{"WATCH", "UNWATCH", "PING"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil - - c = p.Get() - c.Do("WATCH", "key") - c.Do("MULTI") - c.Do("PING") - c.Close() - - want = []string{"WATCH", "MULTI", "PING", "DISCARD"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil - - c = p.Get() - c.Do("WATCH", "key") - c.Do("MULTI") - c.Do("DISCARD") - c.Do("PING") - c.Close() - - want = []string{"WATCH", "MULTI", "DISCARD", "PING"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil - - c = p.Get() - c.Do("WATCH", "key") - c.Do("MULTI") - c.Do("EXEC") - c.Do("PING") - c.Close() - - want = []string{"WATCH", "MULTI", "EXEC", "PING"} - if !reflect.DeepEqual(d.commands, want) { - t.Errorf("got commands %v, want %v", d.commands, want) - } - d.commands = nil -} - -func startGoroutines(p *redis.Pool, cmd string, args ...interface{}) chan error { - errs := make(chan error, 10) - for i := 0; i < cap(errs); i++ { - go func() { - c := p.Get() - _, err := c.Do(cmd, args...) - errs <- err - c.Close() - }() - } - - // Wait for goroutines to block. - time.Sleep(time.Second / 4) - - return errs -} - -func TestWaitPool(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 1, - MaxActive: 1, - Dial: d.dial, - Wait: true, - } - defer p.Close() - - c := p.Get() - errs := startGoroutines(p, "PING") - d.check("before close", p, 1, 1) - c.Close() - timeout := time.After(2 * time.Second) - for i := 0; i < cap(errs); i++ { - select { - case err := <-errs: - if err != nil { - t.Fatal(err) - } - case <-timeout: - t.Fatalf("timeout waiting for blocked goroutine %d", i) - } - } - d.check("done", p, 1, 1) -} - -func TestWaitPoolClose(t *testing.T) { - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 1, - MaxActive: 1, - Dial: d.dial, - Wait: true, - } - defer p.Close() - - c := p.Get() - if _, err := c.Do("PING"); err != nil { - t.Fatal(err) - } - errs := startGoroutines(p, "PING") - d.check("before close", p, 1, 1) - p.Close() - timeout := time.After(2 * time.Second) - for i := 0; i < cap(errs); i++ { - select { - case err := <-errs: - switch err { - case nil: - t.Fatal("blocked goroutine did not get error") - case redis.ErrPoolExhausted: - t.Fatal("blocked goroutine got pool exhausted error") - } - case <-timeout: - t.Fatal("timeout waiting for blocked goroutine") - } - } - c.Close() - d.check("done", p, 1, 0) -} - -func TestWaitPoolCommandError(t *testing.T) { - testErr := errors.New("test") - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 1, - MaxActive: 1, - Dial: d.dial, - Wait: true, - } - defer p.Close() - - c := p.Get() - errs := startGoroutines(p, "ERR", testErr) - d.check("before close", p, 1, 1) - c.Close() - timeout := time.After(2 * time.Second) - for i := 0; i < cap(errs); i++ { - select { - case err := <-errs: - if err != nil { - t.Fatal(err) - } - case <-timeout: - t.Fatalf("timeout waiting for blocked goroutine %d", i) - } - } - d.check("done", p, cap(errs), 0) -} - -func TestWaitPoolDialError(t *testing.T) { - testErr := errors.New("test") - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: 1, - MaxActive: 1, - Dial: d.dial, - Wait: true, - } - defer p.Close() - - c := p.Get() - errs := startGoroutines(p, "ERR", testErr) - d.check("before close", p, 1, 1) - - d.dialErr = errors.New("dial") - c.Close() - - nilCount := 0 - errCount := 0 - timeout := time.After(2 * time.Second) - for i := 0; i < cap(errs); i++ { - select { - case err := <-errs: - switch err { - case nil: - nilCount++ - case d.dialErr: - errCount++ - default: - t.Fatalf("expected dial error or nil, got %v", err) - } - case <-timeout: - t.Fatalf("timeout waiting for blocked goroutine %d", i) - } - } - if nilCount != 1 { - t.Errorf("expected one nil error, got %d", nilCount) - } - if errCount != cap(errs)-1 { - t.Errorf("expected %d dial erors, got %d", cap(errs)-1, errCount) - } - d.check("done", p, cap(errs), 0) -} - -// Borrowing requires us to iterate over the idle connections, unlock the pool, -// and perform a blocking operation to check the connection still works. If -// TestOnBorrow fails, we must reacquire the lock and continue iteration. This -// test ensures that iteration will work correctly if multiple threads are -// iterating simultaneously. -func TestLocking_TestOnBorrowFails_PoolDoesntCrash(t *testing.T) { - const count = 100 - - // First we'll Create a pool where the pilfering of idle connections fails. - d := poolDialer{t: t} - p := &redis.Pool{ - MaxIdle: count, - MaxActive: count, - Dial: d.dial, - TestOnBorrow: func(c redis.Conn, t time.Time) error { - return errors.New("No way back into the real world.") - }, - } - defer p.Close() - - // Fill the pool with idle connections. - conns := make([]redis.Conn, count) - for i := range conns { - conns[i] = p.Get() - } - for i := range conns { - conns[i].Close() - } - - // Spawn a bunch of goroutines to thrash the pool. - var wg sync.WaitGroup - wg.Add(count) - for i := 0; i < count; i++ { - go func() { - c := p.Get() - if c.Err() != nil { - t.Errorf("pool get failed: %v", c.Err()) - } - c.Close() - wg.Done() - }() - } - wg.Wait() - if d.dialed != count*2 { - t.Errorf("Expected %d dials, got %d", count*2, d.dialed) - } -} - -func BenchmarkPoolGet(b *testing.B) { - b.StopTimer() - p := redis.Pool{Dial: redis.DialDefaultServer, MaxIdle: 2} - c := p.Get() - if err := c.Err(); err != nil { - b.Fatal(err) - } - c.Close() - defer p.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - c = p.Get() - c.Close() - } -} - -func BenchmarkPoolGetErr(b *testing.B) { - b.StopTimer() - p := redis.Pool{Dial: redis.DialDefaultServer, MaxIdle: 2} - c := p.Get() - if err := c.Err(); err != nil { - b.Fatal(err) - } - c.Close() - defer p.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - c = p.Get() - if err := c.Err(); err != nil { - b.Fatal(err) - } - c.Close() - } -} - -func BenchmarkPoolGetPing(b *testing.B) { - b.StopTimer() - p := redis.Pool{Dial: redis.DialDefaultServer, MaxIdle: 2} - c := p.Get() - if err := c.Err(); err != nil { - b.Fatal(err) - } - c.Close() - defer p.Close() - b.StartTimer() - for i := 0; i < b.N; i++ { - c = p.Get() - if _, err := c.Do("PING"); err != nil { - b.Fatal(err) - } - c.Close() - } -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pubsub_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pubsub_test.go deleted file mode 100644 index a3ed84e68..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/pubsub_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "fmt" - "reflect" - "sync" - "testing" - - "github.com/garyburd/redigo/redis" -) - -func publish(channel, value interface{}) { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - c.Do("PUBLISH", channel, value) -} - -// Applications can receive pushed messages from one goroutine and manage subscriptions from another goroutine. -func ExamplePubSubConn() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - var wg sync.WaitGroup - wg.Add(2) - - psc := redis.PubSubConn{Conn: c} - - // This goroutine receives and prints pushed notifications from the server. - // The goroutine exits when the connection is unsubscribed from all - // channels or there is an error. - go func() { - defer wg.Done() - for { - switch n := psc.Receive().(type) { - case redis.Message: - fmt.Printf("Message: %s %s\n", n.Channel, n.Data) - case redis.PMessage: - fmt.Printf("PMessage: %s %s %s\n", n.Pattern, n.Channel, n.Data) - case redis.Subscription: - fmt.Printf("Subscription: %s %s %d\n", n.Kind, n.Channel, n.Count) - if n.Count == 0 { - return - } - case error: - fmt.Printf("error: %v\n", n) - return - } - } - }() - - // This goroutine manages subscriptions for the connection. - go func() { - defer wg.Done() - - psc.Subscribe("example") - psc.PSubscribe("p*") - - // The following function calls publish a message using another - // connection to the Redis server. - publish("example", "hello") - publish("example", "world") - publish("pexample", "foo") - publish("pexample", "bar") - - // Unsubscribe from all connections. This will cause the receiving - // goroutine to exit. - psc.Unsubscribe() - psc.PUnsubscribe() - }() - - wg.Wait() - - // Output: - // Subscription: subscribe example 1 - // Subscription: psubscribe p* 2 - // Message: example hello - // Message: example world - // PMessage: p* pexample foo - // PMessage: p* pexample bar - // Subscription: unsubscribe example 1 - // Subscription: punsubscribe p* 0 -} - -func expectPushed(t *testing.T, c redis.PubSubConn, message string, expected interface{}) { - actual := c.Receive() - if !reflect.DeepEqual(actual, expected) { - t.Errorf("%s = %v, want %v", message, actual, expected) - } -} - -func TestPushed(t *testing.T) { - pc, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer pc.Close() - - sc, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer sc.Close() - - c := redis.PubSubConn{Conn: sc} - - c.Subscribe("c1") - expectPushed(t, c, "Subscribe(c1)", redis.Subscription{Kind: "subscribe", Channel: "c1", Count: 1}) - c.Subscribe("c2") - expectPushed(t, c, "Subscribe(c2)", redis.Subscription{Kind: "subscribe", Channel: "c2", Count: 2}) - c.PSubscribe("p1") - expectPushed(t, c, "PSubscribe(p1)", redis.Subscription{Kind: "psubscribe", Channel: "p1", Count: 3}) - c.PSubscribe("p2") - expectPushed(t, c, "PSubscribe(p2)", redis.Subscription{Kind: "psubscribe", Channel: "p2", Count: 4}) - c.PUnsubscribe() - expectPushed(t, c, "Punsubscribe(p1)", redis.Subscription{Kind: "punsubscribe", Channel: "p1", Count: 3}) - expectPushed(t, c, "Punsubscribe()", redis.Subscription{Kind: "punsubscribe", Channel: "p2", Count: 2}) - - pc.Do("PUBLISH", "c1", "hello") - expectPushed(t, c, "PUBLISH c1 hello", redis.Message{Channel: "c1", Data: []byte("hello")}) - - c.Ping("hello") - expectPushed(t, c, `Ping("hello")`, redis.Pong{"hello"}) - - c.Conn.Send("PING") - c.Conn.Flush() - expectPushed(t, c, `Send("PING")`, redis.Pong{}) -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/reply_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/reply_test.go deleted file mode 100644 index 2c774866d..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/reply_test.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "fmt" - "reflect" - "testing" - - "github.com/garyburd/redigo/redis" -) - -type valueError struct { - v interface{} - err error -} - -func ve(v interface{}, err error) valueError { - return valueError{v, err} -} - -var replyTests = []struct { - name interface{} - actual valueError - expected valueError -}{ - { - "ints([v1, v2])", - ve(redis.Ints([]interface{}{[]byte("4"), []byte("5")}, nil)), - ve([]int{4, 5}, nil), - }, - { - "ints(nil)", - ve(redis.Ints(nil, nil)), - ve([]int(nil), redis.ErrNil), - }, - { - "strings([v1, v2])", - ve(redis.Strings([]interface{}{[]byte("v1"), []byte("v2")}, nil)), - ve([]string{"v1", "v2"}, nil), - }, - { - "strings(nil)", - ve(redis.Strings(nil, nil)), - ve([]string(nil), redis.ErrNil), - }, - { - "byteslices([v1, v2])", - ve(redis.ByteSlices([]interface{}{[]byte("v1"), []byte("v2")}, nil)), - ve([][]byte{[]byte("v1"), []byte("v2")}, nil), - }, - { - "byteslices(nil)", - ve(redis.ByteSlices(nil, nil)), - ve([][]byte(nil), redis.ErrNil), - }, - { - "values([v1, v2])", - ve(redis.Values([]interface{}{[]byte("v1"), []byte("v2")}, nil)), - ve([]interface{}{[]byte("v1"), []byte("v2")}, nil), - }, - { - "values(nil)", - ve(redis.Values(nil, nil)), - ve([]interface{}(nil), redis.ErrNil), - }, - { - "float64(1.0)", - ve(redis.Float64([]byte("1.0"), nil)), - ve(float64(1.0), nil), - }, - { - "float64(nil)", - ve(redis.Float64(nil, nil)), - ve(float64(0.0), redis.ErrNil), - }, - { - "uint64(1)", - ve(redis.Uint64(int64(1), nil)), - ve(uint64(1), nil), - }, - { - "uint64(-1)", - ve(redis.Uint64(int64(-1), nil)), - ve(uint64(0), redis.ErrNegativeInt), - }, -} - -func TestReply(t *testing.T) { - for _, rt := range replyTests { - if rt.actual.err != rt.expected.err { - t.Errorf("%s returned err %v, want %v", rt.name, rt.actual.err, rt.expected.err) - continue - } - if !reflect.DeepEqual(rt.actual.v, rt.expected.v) { - t.Errorf("%s=%+v, want %+v", rt.name, rt.actual.v, rt.expected.v) - } - } -} - -// dial wraps DialDefaultServer() with a more suitable function name for examples. -func dial() (redis.Conn, error) { - return redis.DialDefaultServer() -} - -func ExampleBool() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Do("SET", "foo", 1) - exists, _ := redis.Bool(c.Do("EXISTS", "foo")) - fmt.Printf("%#v\n", exists) - // Output: - // true -} - -func ExampleInt() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Do("SET", "k1", 1) - n, _ := redis.Int(c.Do("GET", "k1")) - fmt.Printf("%#v\n", n) - n, _ = redis.Int(c.Do("INCR", "k1")) - fmt.Printf("%#v\n", n) - // Output: - // 1 - // 2 -} - -func ExampleInts() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Do("SADD", "set_with_integers", 4, 5, 6) - ints, _ := redis.Ints(c.Do("SMEMBERS", "set_with_integers")) - fmt.Printf("%#v\n", ints) - // Output: - // []int{4, 5, 6} -} - -func ExampleString() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Do("SET", "hello", "world") - s, err := redis.String(c.Do("GET", "hello")) - fmt.Printf("%#v\n", s) - // Output: - // "world" -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan_test.go deleted file mode 100644 index d364dff42..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/scan_test.go +++ /dev/null @@ -1,440 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "fmt" - "math" - "reflect" - "testing" - - "github.com/garyburd/redigo/redis" -) - -var scanConversionTests = []struct { - src interface{} - dest interface{} -}{ - {[]byte("-inf"), math.Inf(-1)}, - {[]byte("+inf"), math.Inf(1)}, - {[]byte("0"), float64(0)}, - {[]byte("3.14159"), float64(3.14159)}, - {[]byte("3.14"), float32(3.14)}, - {[]byte("-100"), int(-100)}, - {[]byte("101"), int(101)}, - {int64(102), int(102)}, - {[]byte("103"), uint(103)}, - {int64(104), uint(104)}, - {[]byte("105"), int8(105)}, - {int64(106), int8(106)}, - {[]byte("107"), uint8(107)}, - {int64(108), uint8(108)}, - {[]byte("0"), false}, - {int64(0), false}, - {[]byte("f"), false}, - {[]byte("1"), true}, - {int64(1), true}, - {[]byte("t"), true}, - {"hello", "hello"}, - {[]byte("hello"), "hello"}, - {[]byte("world"), []byte("world")}, - {[]interface{}{[]byte("foo")}, []interface{}{[]byte("foo")}}, - {[]interface{}{[]byte("foo")}, []string{"foo"}}, - {[]interface{}{[]byte("hello"), []byte("world")}, []string{"hello", "world"}}, - {[]interface{}{[]byte("bar")}, [][]byte{[]byte("bar")}}, - {[]interface{}{[]byte("1")}, []int{1}}, - {[]interface{}{[]byte("1"), []byte("2")}, []int{1, 2}}, - {[]interface{}{[]byte("1"), []byte("2")}, []float64{1, 2}}, - {[]interface{}{[]byte("1")}, []byte{1}}, - {[]interface{}{[]byte("1")}, []bool{true}}, -} - -func TestScanConversion(t *testing.T) { - for _, tt := range scanConversionTests { - values := []interface{}{tt.src} - dest := reflect.New(reflect.TypeOf(tt.dest)) - values, err := redis.Scan(values, dest.Interface()) - if err != nil { - t.Errorf("Scan(%v) returned error %v", tt, err) - continue - } - if !reflect.DeepEqual(tt.dest, dest.Elem().Interface()) { - t.Errorf("Scan(%v) returned %v, want %v", tt, dest.Elem().Interface(), tt.dest) - } - } -} - -var scanConversionErrorTests = []struct { - src interface{} - dest interface{} -}{ - {[]byte("1234"), byte(0)}, - {int64(1234), byte(0)}, - {[]byte("-1"), byte(0)}, - {int64(-1), byte(0)}, - {[]byte("junk"), false}, - {redis.Error("blah"), false}, -} - -func TestScanConversionError(t *testing.T) { - for _, tt := range scanConversionErrorTests { - values := []interface{}{tt.src} - dest := reflect.New(reflect.TypeOf(tt.dest)) - values, err := redis.Scan(values, dest.Interface()) - if err == nil { - t.Errorf("Scan(%v) did not return error", tt) - } - } -} - -func ExampleScan() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Send("HMSET", "album:1", "title", "Red", "rating", 5) - c.Send("HMSET", "album:2", "title", "Earthbound", "rating", 1) - c.Send("HMSET", "album:3", "title", "Beat") - c.Send("LPUSH", "albums", "1") - c.Send("LPUSH", "albums", "2") - c.Send("LPUSH", "albums", "3") - values, err := redis.Values(c.Do("SORT", "albums", - "BY", "album:*->rating", - "GET", "album:*->title", - "GET", "album:*->rating")) - if err != nil { - fmt.Println(err) - return - } - - for len(values) > 0 { - var title string - rating := -1 // initialize to illegal value to detect nil. - values, err = redis.Scan(values, &title, &rating) - if err != nil { - fmt.Println(err) - return - } - if rating == -1 { - fmt.Println(title, "not-rated") - } else { - fmt.Println(title, rating) - } - } - // Output: - // Beat not-rated - // Earthbound 1 - // Red 5 -} - -type s0 struct { - X int - Y int `redis:"y"` - Bt bool -} - -type s1 struct { - X int `redis:"-"` - I int `redis:"i"` - U uint `redis:"u"` - S string `redis:"s"` - P []byte `redis:"p"` - B bool `redis:"b"` - Bt bool - Bf bool - s0 -} - -var scanStructTests = []struct { - title string - reply []string - value interface{} -}{ - {"basic", - []string{"i", "-1234", "u", "5678", "s", "hello", "p", "world", "b", "t", "Bt", "1", "Bf", "0", "X", "123", "y", "456"}, - &s1{I: -1234, U: 5678, S: "hello", P: []byte("world"), B: true, Bt: true, Bf: false, s0: s0{X: 123, Y: 456}}, - }, -} - -func TestScanStruct(t *testing.T) { - for _, tt := range scanStructTests { - - var reply []interface{} - for _, v := range tt.reply { - reply = append(reply, []byte(v)) - } - - value := reflect.New(reflect.ValueOf(tt.value).Type().Elem()) - - if err := redis.ScanStruct(reply, value.Interface()); err != nil { - t.Fatalf("ScanStruct(%s) returned error %v", tt.title, err) - } - - if !reflect.DeepEqual(value.Interface(), tt.value) { - t.Fatalf("ScanStruct(%s) returned %v, want %v", tt.title, value.Interface(), tt.value) - } - } -} - -func TestBadScanStructArgs(t *testing.T) { - x := []interface{}{"A", "b"} - test := func(v interface{}) { - if err := redis.ScanStruct(x, v); err == nil { - t.Errorf("Expect error for ScanStruct(%T, %T)", x, v) - } - } - - test(nil) - - var v0 *struct{} - test(v0) - - var v1 int - test(&v1) - - x = x[:1] - v2 := struct{ A string }{} - test(&v2) -} - -var scanSliceTests = []struct { - src []interface{} - fieldNames []string - ok bool - dest interface{} -}{ - { - []interface{}{[]byte("1"), nil, []byte("-1")}, - nil, - true, - []int{1, 0, -1}, - }, - { - []interface{}{[]byte("1"), nil, []byte("2")}, - nil, - true, - []uint{1, 0, 2}, - }, - { - []interface{}{[]byte("-1")}, - nil, - false, - []uint{1}, - }, - { - []interface{}{[]byte("hello"), nil, []byte("world")}, - nil, - true, - [][]byte{[]byte("hello"), nil, []byte("world")}, - }, - { - []interface{}{[]byte("hello"), nil, []byte("world")}, - nil, - true, - []string{"hello", "", "world"}, - }, - { - []interface{}{[]byte("a1"), []byte("b1"), []byte("a2"), []byte("b2")}, - nil, - true, - []struct{ A, B string }{{"a1", "b1"}, {"a2", "b2"}}, - }, - { - []interface{}{[]byte("a1"), []byte("b1")}, - nil, - false, - []struct{ A, B, C string }{{"a1", "b1", ""}}, - }, - { - []interface{}{[]byte("a1"), []byte("b1"), []byte("a2"), []byte("b2")}, - nil, - true, - []*struct{ A, B string }{{"a1", "b1"}, {"a2", "b2"}}, - }, - { - []interface{}{[]byte("a1"), []byte("b1"), []byte("a2"), []byte("b2")}, - []string{"A", "B"}, - true, - []struct{ A, C, B string }{{"a1", "", "b1"}, {"a2", "", "b2"}}, - }, - { - []interface{}{[]byte("a1"), []byte("b1"), []byte("a2"), []byte("b2")}, - nil, - false, - []struct{}{}, - }, -} - -func TestScanSlice(t *testing.T) { - for _, tt := range scanSliceTests { - - typ := reflect.ValueOf(tt.dest).Type() - dest := reflect.New(typ) - - err := redis.ScanSlice(tt.src, dest.Interface(), tt.fieldNames...) - if tt.ok != (err == nil) { - t.Errorf("ScanSlice(%v, []%s, %v) returned error %v", tt.src, typ, tt.fieldNames, err) - continue - } - if tt.ok && !reflect.DeepEqual(dest.Elem().Interface(), tt.dest) { - t.Errorf("ScanSlice(src, []%s) returned %#v, want %#v", typ, dest.Elem().Interface(), tt.dest) - } - } -} - -func ExampleScanSlice() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - c.Send("HMSET", "album:1", "title", "Red", "rating", 5) - c.Send("HMSET", "album:2", "title", "Earthbound", "rating", 1) - c.Send("HMSET", "album:3", "title", "Beat", "rating", 4) - c.Send("LPUSH", "albums", "1") - c.Send("LPUSH", "albums", "2") - c.Send("LPUSH", "albums", "3") - values, err := redis.Values(c.Do("SORT", "albums", - "BY", "album:*->rating", - "GET", "album:*->title", - "GET", "album:*->rating")) - if err != nil { - fmt.Println(err) - return - } - - var albums []struct { - Title string - Rating int - } - if err := redis.ScanSlice(values, &albums); err != nil { - fmt.Println(err) - return - } - fmt.Printf("%v\n", albums) - // Output: - // [{Earthbound 1} {Beat 4} {Red 5}] -} - -var argsTests = []struct { - title string - actual redis.Args - expected redis.Args -}{ - {"struct ptr", - redis.Args{}.AddFlat(&struct { - I int `redis:"i"` - U uint `redis:"u"` - S string `redis:"s"` - P []byte `redis:"p"` - M map[string]string `redis:"m"` - Bt bool - Bf bool - }{ - -1234, 5678, "hello", []byte("world"), map[string]string{"hello": "world"}, true, false, - }), - redis.Args{"i", int(-1234), "u", uint(5678), "s", "hello", "p", []byte("world"), "m", map[string]string{"hello": "world"}, "Bt", true, "Bf", false}, - }, - {"struct", - redis.Args{}.AddFlat(struct{ I int }{123}), - redis.Args{"I", 123}, - }, - {"slice", - redis.Args{}.Add(1).AddFlat([]string{"a", "b", "c"}).Add(2), - redis.Args{1, "a", "b", "c", 2}, - }, - {"struct omitempty", - redis.Args{}.AddFlat(&struct { - I int `redis:"i,omitempty"` - U uint `redis:"u,omitempty"` - S string `redis:"s,omitempty"` - P []byte `redis:"p,omitempty"` - M map[string]string `redis:"m,omitempty"` - Bt bool `redis:"Bt,omitempty"` - Bf bool `redis:"Bf,omitempty"` - }{ - 0, 0, "", []byte{}, map[string]string{}, true, false, - }), - redis.Args{"Bt", true}, - }, -} - -func TestArgs(t *testing.T) { - for _, tt := range argsTests { - if !reflect.DeepEqual(tt.actual, tt.expected) { - t.Fatalf("%s is %v, want %v", tt.title, tt.actual, tt.expected) - } - } -} - -func ExampleArgs() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - var p1, p2 struct { - Title string `redis:"title"` - Author string `redis:"author"` - Body string `redis:"body"` - } - - p1.Title = "Example" - p1.Author = "Gary" - p1.Body = "Hello" - - if _, err := c.Do("HMSET", redis.Args{}.Add("id1").AddFlat(&p1)...); err != nil { - fmt.Println(err) - return - } - - m := map[string]string{ - "title": "Example2", - "author": "Steve", - "body": "Map", - } - - if _, err := c.Do("HMSET", redis.Args{}.Add("id2").AddFlat(m)...); err != nil { - fmt.Println(err) - return - } - - for _, id := range []string{"id1", "id2"} { - - v, err := redis.Values(c.Do("HGETALL", id)) - if err != nil { - fmt.Println(err) - return - } - - if err := redis.ScanStruct(v, &p2); err != nil { - fmt.Println(err) - return - } - - fmt.Printf("%+v\n", p2) - } - - // Output: - // {Title:Example Author:Gary Body:Hello} - // {Title:Example2 Author:Steve Body:Map} -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/script_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/script_test.go deleted file mode 100644 index 42f3c0363..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/script_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "fmt" - "reflect" - "testing" - "time" - - "github.com/garyburd/redigo/redis" -) - -func ExampleScript(c redis.Conn, reply interface{}, err error) { - // Initialize a package-level variable with a script. - var getScript = redis.NewScript(1, `return redis.call('get', KEYS[1])`) - - // In a function, use the script Do method to evaluate the script. The Do - // method optimistically uses the EVALSHA command. If the script is not - // loaded, then the Do method falls back to the EVAL command. - reply, err = getScript.Do(c, "foo") -} - -func TestScript(t *testing.T) { - c, err := redis.DialDefaultServer() - if err != nil { - t.Fatalf("error connection to database, %v", err) - } - defer c.Close() - - // To test fall back in Do, we make script unique by adding comment with current time. - script := fmt.Sprintf("--%d\nreturn {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", time.Now().UnixNano()) - s := redis.NewScript(2, script) - reply := []interface{}{[]byte("key1"), []byte("key2"), []byte("arg1"), []byte("arg2")} - - v, err := s.Do(c, "key1", "key2", "arg1", "arg2") - if err != nil { - t.Errorf("s.Do(c, ...) returned %v", err) - } - - if !reflect.DeepEqual(v, reply) { - t.Errorf("s.Do(c, ..); = %v, want %v", v, reply) - } - - err = s.Load(c) - if err != nil { - t.Errorf("s.Load(c) returned %v", err) - } - - err = s.SendHash(c, "key1", "key2", "arg1", "arg2") - if err != nil { - t.Errorf("s.SendHash(c, ...) returned %v", err) - } - - err = c.Flush() - if err != nil { - t.Errorf("c.Flush() returned %v", err) - } - - v, err = c.Receive() - if !reflect.DeepEqual(v, reply) { - t.Errorf("s.SendHash(c, ..); c.Receive() = %v, want %v", v, reply) - } - - err = s.Send(c, "key1", "key2", "arg1", "arg2") - if err != nil { - t.Errorf("s.Send(c, ...) returned %v", err) - } - - err = c.Flush() - if err != nil { - t.Errorf("c.Flush() returned %v", err) - } - - v, err = c.Receive() - if !reflect.DeepEqual(v, reply) { - t.Errorf("s.Send(c, ..); c.Receive() = %v, want %v", v, reply) - } - -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/test_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/test_test.go deleted file mode 100644 index 7240fa1f3..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/test_test.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2012 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis - -import ( - "bufio" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "strconv" - "strings" - "sync" - "testing" - "time" -) - -func SetNowFunc(f func() time.Time) { - nowFunc = f -} - -var ( - ErrNegativeInt = errNegativeInt - - serverPath = flag.String("redis-server", "redis-server", "Path to redis server binary") - serverBasePort = flag.Int("redis-port", 16379, "Beginning of port range for test servers") - serverLogName = flag.String("redis-log", "", "Write Redis server logs to `filename`") - serverLog = ioutil.Discard - - defaultServerMu sync.Mutex - defaultServer *Server - defaultServerErr error -) - -type Server struct { - name string - cmd *exec.Cmd - done chan struct{} -} - -func NewServer(name string, args ...string) (*Server, error) { - s := &Server{ - name: name, - cmd: exec.Command(*serverPath, args...), - done: make(chan struct{}), - } - - r, err := s.cmd.StdoutPipe() - if err != nil { - return nil, err - } - - err = s.cmd.Start() - if err != nil { - return nil, err - } - - ready := make(chan error, 1) - go s.watch(r, ready) - - select { - case err = <-ready: - case <-time.After(time.Second * 10): - err = errors.New("timeout waiting for server to start") - } - - if err != nil { - s.Stop() - return nil, err - } - - return s, nil -} - -func (s *Server) watch(r io.Reader, ready chan error) { - fmt.Fprintf(serverLog, "%d START %s \n", s.cmd.Process.Pid, s.name) - var listening bool - var text string - scn := bufio.NewScanner(r) - for scn.Scan() { - text = scn.Text() - fmt.Fprintf(serverLog, "%s\n", text) - if !listening { - if strings.Contains(text, "The server is now ready to accept connections on port") { - listening = true - ready <- nil - } - } - } - if !listening { - ready <- fmt.Errorf("server exited: %s", text) - } - s.cmd.Wait() - fmt.Fprintf(serverLog, "%d STOP %s \n", s.cmd.Process.Pid, s.name) - close(s.done) -} - -func (s *Server) Stop() { - s.cmd.Process.Signal(os.Interrupt) - <-s.done -} - -// stopDefaultServer stops the server created by DialDefaultServer. -func stopDefaultServer() { - defaultServerMu.Lock() - defer defaultServerMu.Unlock() - if defaultServer != nil { - defaultServer.Stop() - defaultServer = nil - } -} - -// startDefaultServer starts the default server if not already running. -func startDefaultServer() error { - defaultServerMu.Lock() - defer defaultServerMu.Unlock() - if defaultServer != nil || defaultServerErr != nil { - return defaultServerErr - } - defaultServer, defaultServerErr = NewServer( - "default", - "--port", strconv.Itoa(*serverBasePort), - "--save", "", - "--appendonly", "no") - return defaultServerErr -} - -// DialDefaultServer starts the test server if not already started and dials a -// connection to the server. -func DialDefaultServer() (Conn, error) { - if err := startDefaultServer(); err != nil { - return nil, err - } - c, err := Dial("tcp", fmt.Sprintf(":%d", *serverBasePort), DialReadTimeout(1*time.Second), DialWriteTimeout(1*time.Second)) - if err != nil { - return nil, err - } - c.Do("FLUSHDB") - return c, nil -} - -func TestMain(m *testing.M) { - os.Exit(func() int { - flag.Parse() - - var f *os.File - if *serverLogName != "" { - var err error - f, err = os.OpenFile(*serverLogName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600) - if err != nil { - fmt.Fprintf(os.Stderr, "Error opening redis-log: %v\n", err) - return 1 - } - defer f.Close() - serverLog = f - } - - defer stopDefaultServer() - - return m.Run() - }()) -} diff --git a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/zpop_example_test.go b/Godeps/_workspace/src/github.com/garyburd/redigo/redis/zpop_example_test.go deleted file mode 100644 index 1d86ee6ce..000000000 --- a/Godeps/_workspace/src/github.com/garyburd/redigo/redis/zpop_example_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2013 Gary Burd -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package redis_test - -import ( - "fmt" - "github.com/garyburd/redigo/redis" -) - -// zpop pops a value from the ZSET key using WATCH/MULTI/EXEC commands. -func zpop(c redis.Conn, key string) (result string, err error) { - - defer func() { - // Return connection to normal state on error. - if err != nil { - c.Do("DISCARD") - } - }() - - // Loop until transaction is successful. - for { - if _, err := c.Do("WATCH", key); err != nil { - return "", err - } - - members, err := redis.Strings(c.Do("ZRANGE", key, 0, 0)) - if err != nil { - return "", err - } - if len(members) != 1 { - return "", redis.ErrNil - } - - c.Send("MULTI") - c.Send("ZREM", key, members[0]) - queued, err := c.Do("EXEC") - if err != nil { - return "", err - } - - if queued != nil { - result = members[0] - break - } - } - - return result, nil -} - -// zpopScript pops a value from a ZSET. -var zpopScript = redis.NewScript(1, ` - local r = redis.call('ZRANGE', KEYS[1], 0, 0) - if r ~= nil then - r = r[1] - redis.call('ZREM', KEYS[1], r) - end - return r -`) - -// This example implements ZPOP as described at -// http://redis.io/topics/transactions using WATCH/MULTI/EXEC and scripting. -func Example_zpop() { - c, err := dial() - if err != nil { - fmt.Println(err) - return - } - defer c.Close() - - // Add test data using a pipeline. - - for i, member := range []string{"red", "blue", "green"} { - c.Send("ZADD", "zset", i, member) - } - if _, err := c.Do(""); err != nil { - fmt.Println(err) - return - } - - // Pop using WATCH/MULTI/EXEC - - v, err := zpop(c, "zset") - if err != nil { - fmt.Println(err) - return - } - fmt.Println(v) - - // Pop using a script. - - v, err = redis.String(zpopScript.Do(c, "zset")) - if err != nil { - fmt.Println(err) - return - } - fmt.Println(v) - - // Output: - // red - // blue -} |