scan_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. package redis_test
  15. import (
  16. "fmt"
  17. "github.com/garyburd/redigo/redis"
  18. "math"
  19. "reflect"
  20. "testing"
  21. )
  22. var scanConversionTests = []struct {
  23. src interface{}
  24. dest interface{}
  25. }{
  26. {[]byte("-inf"), math.Inf(-1)},
  27. {[]byte("+inf"), math.Inf(1)},
  28. {[]byte("0"), float64(0)},
  29. {[]byte("3.14159"), float64(3.14159)},
  30. {[]byte("3.14"), float32(3.14)},
  31. {[]byte("-100"), int(-100)},
  32. {[]byte("101"), int(101)},
  33. {int64(102), int(102)},
  34. {[]byte("103"), uint(103)},
  35. {int64(104), uint(104)},
  36. {[]byte("105"), int8(105)},
  37. {int64(106), int8(106)},
  38. {[]byte("107"), uint8(107)},
  39. {int64(108), uint8(108)},
  40. {[]byte("0"), false},
  41. {int64(0), false},
  42. {[]byte("f"), false},
  43. {[]byte("1"), true},
  44. {int64(1), true},
  45. {[]byte("t"), true},
  46. {[]byte("hello"), "hello"},
  47. {[]byte("world"), []byte("world")},
  48. {[]interface{}{[]byte("foo")}, []string{"foo"}},
  49. {[]interface{}{[]byte("bar")}, [][]byte{[]byte("bar")}},
  50. {[]interface{}{[]byte("1")}, []int{1}},
  51. {[]interface{}{[]byte("1"), []byte("2")}, []int{1, 2}},
  52. {[]interface{}{[]byte("1")}, []byte{1}},
  53. {[]interface{}{[]byte("1")}, []bool{true}},
  54. }
  55. var scanConversionErrorTests = []struct {
  56. src interface{}
  57. dest interface{}
  58. }{
  59. {[]byte("1234"), byte(0)},
  60. {int64(1234), byte(0)},
  61. {[]byte("-1"), byte(0)},
  62. {int64(-1), byte(0)},
  63. {[]byte("junk"), false},
  64. {redis.Error("blah"), false},
  65. }
  66. func TestScanConversion(t *testing.T) {
  67. for _, tt := range scanConversionTests {
  68. values := []interface{}{tt.src}
  69. dest := reflect.New(reflect.TypeOf(tt.dest))
  70. values, err := redis.Scan(values, dest.Interface())
  71. if err != nil {
  72. t.Errorf("Scan(%v) returned error %v", tt, err)
  73. continue
  74. }
  75. if !reflect.DeepEqual(tt.dest, dest.Elem().Interface()) {
  76. t.Errorf("Scan(%v) returned %v, want %v", tt, dest.Elem().Interface(), tt.dest)
  77. }
  78. }
  79. }
  80. func TestScanConversionError(t *testing.T) {
  81. for _, tt := range scanConversionErrorTests {
  82. values := []interface{}{tt.src}
  83. dest := reflect.New(reflect.TypeOf(tt.dest))
  84. values, err := redis.Scan(values, dest.Interface())
  85. if err == nil {
  86. t.Errorf("Scan(%v) did not return error", tt)
  87. }
  88. }
  89. }
  90. func ExampleScan() {
  91. c, err := dial()
  92. if err != nil {
  93. panic(err)
  94. }
  95. defer c.Close()
  96. c.Send("HMSET", "album:1", "title", "Red", "rating", 5)
  97. c.Send("HMSET", "album:2", "title", "Earthbound", "rating", 1)
  98. c.Send("HMSET", "album:3", "title", "Beat")
  99. c.Send("LPUSH", "albums", "1")
  100. c.Send("LPUSH", "albums", "2")
  101. c.Send("LPUSH", "albums", "3")
  102. values, err := redis.Values(c.Do("SORT", "albums",
  103. "BY", "album:*->rating",
  104. "GET", "album:*->title",
  105. "GET", "album:*->rating"))
  106. if err != nil {
  107. panic(err)
  108. }
  109. for len(values) > 0 {
  110. var title string
  111. rating := -1 // initialize to illegal value to detect nil.
  112. values, err = redis.Scan(values, &title, &rating)
  113. if err != nil {
  114. panic(err)
  115. }
  116. if rating == -1 {
  117. fmt.Println(title, "not-rated")
  118. } else {
  119. fmt.Println(title, rating)
  120. }
  121. }
  122. // Output:
  123. // Beat not-rated
  124. // Earthbound 1
  125. // Red 5
  126. }
  127. var scanStructTests = []struct {
  128. title string
  129. reply []string
  130. value interface{}
  131. }{
  132. {"basic",
  133. []string{"i", "-1234", "u", "5678", "s", "hello", "p", "world", "b", "f", "Bt", "1", "Bf", "0"},
  134. &struct {
  135. I int `redis:"i"`
  136. U uint `redis:"u"`
  137. S string `redis:"s"`
  138. P []byte `redis:"p"`
  139. B bool `redis:"b"`
  140. Bt bool
  141. Bf bool
  142. }{
  143. -1234, 5678, "hello", []byte("world"), false, true, false,
  144. },
  145. },
  146. }
  147. func TestScanStruct(t *testing.T) {
  148. for _, tt := range scanStructTests {
  149. var reply []interface{}
  150. for _, v := range tt.reply {
  151. reply = append(reply, []byte(v))
  152. }
  153. value := reflect.New(reflect.ValueOf(tt.value).Type().Elem())
  154. if err := redis.ScanStruct(reply, value.Interface()); err != nil {
  155. t.Fatalf("ScanStruct(%s) returned error %v", tt.title, err)
  156. }
  157. if !reflect.DeepEqual(value.Interface(), tt.value) {
  158. t.Fatalf("ScanStruct(%s) returned %v, want %v", tt.title, value.Interface(), tt.value)
  159. }
  160. }
  161. }