gopkg.in/rethinkdb/rethinkdb-go.v6@v6.2.2/internal/integration/reql_tests/common.go (about) 1 package reql_tests 2 3 import ( 4 "fmt" 5 "math" 6 "reflect" 7 "regexp" 8 "strings" 9 "time" 10 11 "github.com/stretchr/testify/suite" 12 r "gopkg.in/rethinkdb/rethinkdb-go.v6" 13 "gopkg.in/rethinkdb/rethinkdb-go.v6/internal/compare" 14 ) 15 16 func maybeRun(query interface{}, session *r.Session, opts r.RunOpts) interface{} { 17 switch query := query.(type) { 18 case r.Term: 19 cursor, err := query.Run(session, opts) 20 if err != nil { 21 return err 22 } 23 24 switch cursor.Type() { 25 case "Cursor": 26 results, err := cursor.Interface() 27 if err != nil { 28 return err 29 } 30 31 return results 32 default: 33 // If this is a changefeed then return the cursor without attempting 34 // to read any documents 35 return cursor 36 } 37 default: 38 return query 39 } 40 } 41 42 func runAndAssert(suite suite.Suite, expected, v interface{}, session *r.Session, opts r.RunOpts) { 43 var cursor *r.Cursor 44 var err error 45 46 switch v := v.(type) { 47 case r.Term: 48 cursor, err = v.Run(session, opts) 49 case *r.Cursor: 50 cursor = v 51 case error: 52 err = v 53 } 54 55 assertExpected(suite, expected, cursor, err) 56 } 57 58 func fetchAndAssert(suite suite.Suite, expected, result interface{}, count int) { 59 switch v := expected.(type) { 60 case compare.Expected: 61 v.Fetch = true 62 v.FetchCount = count 63 64 expected = v 65 default: 66 expected = compare.Expected(compare.Expected{ 67 Val: v, 68 Fetch: true, 69 FetchCount: count, 70 }) 71 } 72 73 var cursor *r.Cursor 74 var err error 75 76 switch result := result.(type) { 77 case *r.Cursor: 78 cursor = result 79 case error: 80 err = result 81 } 82 83 assertExpected(suite, expected, cursor, err) 84 } 85 86 func maybeLen(v interface{}) interface{} { 87 switch v := v.(type) { 88 case *r.Cursor: 89 results := []interface{}{} 90 v.All(&results) 91 return len(results) 92 case []interface{}: 93 return len(v) 94 default: 95 return v 96 } 97 } 98 99 func assertExpected(suite suite.Suite, expected interface{}, obtainedCursor *r.Cursor, obtainedErr error) { 100 if expected == compare.AnythingIsFine { 101 suite.NoError(obtainedErr, "Query returned unexpected error") 102 return 103 } 104 105 switch expected := expected.(type) { 106 case Err: 107 expected.assert(suite, obtainedCursor, obtainedErr) 108 case compare.Expected: 109 assert(suite, expected, obtainedCursor, obtainedErr) 110 default: 111 assert(suite, compare.Expected{Val: expected}, obtainedCursor, obtainedErr) 112 } 113 } 114 115 func assert(suite suite.Suite, expected compare.Expected, obtainedCursor *r.Cursor, obtainedErr error) { 116 if !suite.NoError(obtainedErr, "Query returned unexpected error") { 117 return 118 } 119 120 expectedVal := reflect.ValueOf(expected.Val) 121 122 // If expected value is nil then ensure cursor is nil (assume that an 123 // invalid reflect value is because expected value is nil) 124 if !expectedVal.IsValid() || (expectedVal.Kind() == reflect.Ptr && expectedVal.IsNil()) { 125 suite.True(obtainedCursor.IsNil(), "Expected nil cursor") 126 return 127 } 128 129 expectedType := expectedVal.Type() 130 expectedKind := expectedType.Kind() 131 132 if expectedKind == reflect.Array || expectedKind == reflect.Slice || expected.Fetch { 133 if expectedType.Elem().Kind() == reflect.Uint8 { 134 // Decode byte slices slightly differently 135 var obtained = []byte{} 136 err := obtainedCursor.One(&obtained) 137 suite.NoError(err, "Error returned when reading query response") 138 compare.Assert(suite.T(), expected, obtained) 139 } else { 140 var obtained = []interface{}{} 141 if expected.Fetch { 142 var v interface{} 143 for obtainedCursor.Next(&v) { 144 obtained = append(obtained, v) 145 146 if expected.FetchCount != 0 && len(obtained) >= expected.FetchCount { 147 break 148 } 149 } 150 suite.NoError(obtainedCursor.Err(), "Error returned when reading query response") 151 } else { 152 err := obtainedCursor.All(&obtained) 153 suite.NoError(err, "Error returned when reading query response") 154 } 155 156 compare.Assert(suite.T(), expected, obtained) 157 } 158 } else if expectedKind == reflect.Map { 159 var obtained map[string]interface{} 160 err := obtainedCursor.One(&obtained) 161 suite.NoError(err, "Error returned when reading query response") 162 compare.Assert(suite.T(), expected, obtained) 163 } else { 164 var obtained interface{} 165 err := obtainedCursor.One(&obtained) 166 suite.NoError(err, "Error returned when reading query response") 167 compare.Assert(suite.T(), expected, obtained) 168 } 169 } 170 171 func int_cmp(i int) int { 172 return i 173 } 174 175 func float_cmp(i float64) float64 { 176 return i 177 } 178 179 func arrlen(length int, vs ...interface{}) []interface{} { 180 var v interface{} = compare.AnythingIsFine 181 if len(vs) == 1 { 182 v = vs[0] 183 } 184 185 arr := make([]interface{}, length) 186 for i := 0; i < length; i++ { 187 arr[i] = v 188 } 189 return arr 190 } 191 192 func str(v interface{}) string { 193 return fmt.Sprintf("%v", v) 194 } 195 196 func wait(s int) interface{} { 197 time.Sleep(time.Duration(s) * time.Second) 198 199 return nil 200 } 201 202 type Err struct { 203 Type string 204 Message string 205 Regex string 206 } 207 208 var exceptionRegex = regexp.MustCompile("^(?P<message>[^\n]*?)((?: in:)?\n|\nFailed assertion:)(?s).*$") 209 210 func (expected Err) assert(suite suite.Suite, obtainerCursor *r.Cursor, obtainedErr error) { 211 // If the error is nil then attempt to read from the cursor and see if an 212 // error is returned 213 if obtainedErr == nil { 214 var res []interface{} 215 obtainedErr = obtainerCursor.All(&res) 216 } 217 218 if !suite.Error(obtainedErr) { 219 return 220 } 221 222 obtainedType := reflect.TypeOf(obtainedErr).String() 223 obtainedMessage := strings.TrimPrefix(obtainedErr.Error(), "rethinkdb: ") 224 obtainedMessage = exceptionRegex.ReplaceAllString(obtainedMessage, "${message}") 225 226 suite.Equal(expected.Type, obtainedType) 227 if expected.Regex != "" { 228 suite.Regexp(expected.Regex, obtainedMessage) 229 } 230 if expected.Message != "" { 231 suite.Equal(expected.Message, obtainedMessage) 232 } 233 } 234 235 func err(errType, message string) Err { 236 return Err{ 237 Type: "rethinkdb.RQL" + errType[4:], 238 Message: message, 239 } 240 } 241 242 func err_regex(errType, expr string) Err { 243 return Err{ 244 Type: "rethinkdb.RQL" + errType[4:], 245 Regex: expr, 246 } 247 } 248 249 var Ast = struct { 250 RqlTzinfo func(tz string) *time.Location 251 Fromtimestamp func(ts float64, loc *time.Location) time.Time 252 Now func() time.Time 253 }{ 254 func(tz string) *time.Location { 255 t, _ := time.Parse("-07:00 UTC", tz+" UTC") 256 257 return t.Location() 258 }, 259 func(ts float64, loc *time.Location) time.Time { 260 sec, nsec := math.Modf(ts) 261 262 return time.Unix(int64(sec), int64(nsec*1000)*1000000).In(loc) 263 }, 264 time.Now, 265 } 266 267 func UTCTimeZone() *time.Location { 268 return time.UTC 269 } 270 271 func PacificTimeZone() *time.Location { 272 return Ast.RqlTzinfo("-07:00") 273 } 274 275 var FloatInfo = struct { 276 Min, Max float64 277 }{math.SmallestNonzeroFloat64, math.MaxFloat64} 278 279 var sys = struct { 280 FloatInfo struct { 281 Min, Max float64 282 } 283 }{FloatInfo}