@@ -289,3 +289,160 @@ func TestGeodist(t *testing.T) {
289289 mustFail (t , err , "WRONGTYPE Operation against a key holding the wrong kind of value" )
290290 })
291291}
292+
293+ // Test GEOADD / GEORADIUSBYMEMBER / GEORADIUSBYMEMBER_RO
294+ func TestGeobymember (t * testing.T ) {
295+ s , err := Run ()
296+ ok (t , err )
297+ defer s .Close ()
298+ c , err := redis .Dial ("tcp" , s .Addr ())
299+ ok (t , err )
300+ defer c .Close ()
301+
302+ _ , err = c .Do ("GEOADD" , "Sicily" , 13.361389 , 38.115556 , "Palermo" )
303+ ok (t , err )
304+ _ , err = c .Do ("GEOADD" , "Sicily" , 15.087269 , 37.502669 , "Catania" )
305+ ok (t , err )
306+
307+ t .Run ("WITHDIST WITHCOORD" , func (t * testing.T ) {
308+ res , err := redis .Values (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "WITHDIST" , "WITHCOORD" ))
309+ ok (t , err )
310+ equals (t , 2 , len (res ))
311+ for _ , loc := range res {
312+ item := loc .([]interface {})
313+ var (
314+ name , _ = redis .String (item [0 ], nil )
315+ coord , _ = redis .Float64s (item [2 ], nil )
316+ )
317+ if name != "Catania" && name != "Palermo" {
318+ t .Errorf ("unexpected name %q" , name )
319+ }
320+
321+ equals (t , 2 , len (coord ))
322+ if coord [0 ] == 0.00 || coord [1 ] == 0.00 {
323+ t .Errorf ("latitude/longitude shouldn't be empty" )
324+ }
325+ }
326+ })
327+
328+ t .Run ("WITHCOORD" , func (t * testing.T ) {
329+ res , err := redis .Values (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "WITHCOORD" ))
330+ ok (t , err )
331+ equals (t , 2 , len (res ))
332+ for _ , loc := range res {
333+ item := loc .([]interface {})
334+ var (
335+ name , _ = redis .String (item [0 ], nil )
336+ coord , _ = redis .Float64s (item [1 ], nil )
337+ )
338+ equals (t , 2 , len (item ))
339+ if name != "Catania" && name != "Palermo" {
340+ t .Errorf ("unexpected name %q" , name )
341+ }
342+ equals (t , 2 , len (coord ))
343+ if coord [0 ] == 0.00 || coord [1 ] == 0.00 {
344+ t .Errorf ("latitude/longitude shouldn't be empty" )
345+ }
346+ }
347+ })
348+
349+ t .Run ("WITHDIST" , func (t * testing.T ) {
350+ // in km
351+ res , err := redis .Values (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "WITHDIST" ))
352+ ok (t , err )
353+ equals (t , 2 , len (res ))
354+ var (
355+ name1 , name2 string
356+ dist1 , dist2 float64
357+ )
358+ leftover , err := redis .Scan (res [0 ].([]interface {}), & name1 , & dist1 )
359+ ok (t , err )
360+ equals (t , 0 , len (leftover ))
361+ equals (t , "Palermo" , name1 )
362+ equals (t , 0.0 , dist1 ) // in km
363+ _ , err = redis .Scan (res [1 ].([]interface {}), & name2 , & dist2 )
364+ ok (t , err )
365+ equals (t , "Catania" , name2 )
366+ equals (t , 166.2742 , dist2 )
367+
368+ // in meter
369+ res , err = redis .Values (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Catania" , 200000 , "m" , "WITHDIST" ))
370+ ok (t , err )
371+ equals (t , 2 , len (res ))
372+ distance , err := redis .Float64 (res [0 ].([]interface {})[1 ], nil )
373+ ok (t , err )
374+ equals (t , 166274.1514 , distance ) // in meter
375+ })
376+
377+ t .Run ("ASC DESC" , func (t * testing.T ) {
378+ asc , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "ASC" ))
379+ ok (t , err )
380+ equals (t , []string {"Palermo" , "Catania" }, asc )
381+
382+ asc2 , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Catania" , 200 , "km" , "ASC" ))
383+ ok (t , err )
384+ equals (t , []string {"Catania" , "Palermo" }, asc2 )
385+
386+ desc , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "DESC" ))
387+ ok (t , err )
388+ equals (t , []string {"Catania" , "Palermo" }, desc )
389+ })
390+
391+ t .Run ("COUNT" , func (t * testing.T ) {
392+ count1 , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "ASC" , "COUNT" , 1 ))
393+ ok (t , err )
394+ equals (t , []string {"Palermo" }, count1 )
395+
396+ count99 , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "ASC" , "COUNT" , 99 ))
397+ ok (t , err )
398+ equals (t , []string {"Palermo" , "Catania" }, count99 )
399+
400+ _ , err = c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "COUNT" )
401+ mustFail (t , err , "ERR syntax error" )
402+
403+ _ , err = c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "COUNT" , "notanumber" )
404+ mustFail (t , err , msgInvalidInt )
405+
406+ _ , err = c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" , "COUNT" , - 12 )
407+ mustFail (t , err , "ERR COUNT must be > 0" )
408+ })
409+
410+ t .Run ("no args" , func (t * testing.T ) {
411+ res , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "km" ))
412+ ok (t , err )
413+ equals (t , 2 , len (res ))
414+ equals (t , []string {"Palermo" , "Catania" }, res )
415+
416+ // Wrong map key
417+ n , err := c .Do ("GEORADIUSBYMEMBER" , "Capri" , "Palermo" , 200 , "km" )
418+ ok (t , err )
419+ equals (t , nil , n )
420+
421+ // Missing member
422+ res , err = redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "nosuch" , 200 , "km" ))
423+ mustFail (t , err , "ERR could not decode requested zset member" )
424+ equals (t , 0 , len (res ))
425+
426+ // Unsupported/unknown distance unit
427+ res , err = redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "Palermo" , 200 , "mm" ))
428+ mustFail (t , err , "ERR wrong number of arguments for 'georadiusbymember' command" )
429+ equals (t , 0 , len (res ))
430+
431+ // Wrong parameter type
432+ res , err = redis .Strings (c .Do ("GEORADIUSBYMEMBER" , "Sicily" , "abc" , "def" , "ghi" , "m" ))
433+ mustFail (t , err , "ERR wrong number of arguments for 'georadiusbymember' command" )
434+ equals (t , 0 , len (res ))
435+ })
436+
437+ t .Run ("GEORADIUSBYMEMBER_RO" , func (t * testing.T ) {
438+ asc , err := redis .Strings (c .Do ("GEORADIUSBYMEMBER_RO" , "Sicily" , "Palermo" , 200 , "km" , "ASC" ))
439+ ok (t , err )
440+ equals (t , []string {"Palermo" , "Catania" }, asc )
441+
442+ _ , err = c .Do ("GEORADIUSBYMEMBER_RO" , "Sicily" , "Palermo" , 200 , "km" , "STORE" , "foo" )
443+ mustFail (t , err , "ERR syntax error" )
444+
445+ _ , err = c .Do ("GEORADIUSBYMEMBER_RO" , "Sicily" , "Palermo" , 200 , "km" , "STOREDIST" , "foo" )
446+ mustFail (t , err , "ERR syntax error" )
447+ })
448+ }
0 commit comments