donghao526 commented on code in PR #3296:
URL: https://github.com/apache/kvrocks/pull/3296#discussion_r2625344412
##########
tests/gocase/unit/type/tdigest/tdigest_test.go:
##########
@@ -716,4 +747,231 @@ func tdigestTests(t *testing.T, configs
util.KvrocksServerConfigs) {
require.EqualValues(t, expected[i], rank, "REVRANK
mismatch at index %d", i)
}
})
+
+ t.Run("tdigest.byrank and tdigest.byrevrank on empty sketch", func(t
*testing.T) {
+ key := "tdigest_byrank_on_empty_sketch"
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.CREATE", key,
"compression", "100").Err())
+
+ // Test BYRANK on empty sketch
+ rsp := rdb.Do(ctx, "TDIGEST.BYRANK", key, "1", "2", "4", "5",
"0", "1", "20")
+ require.NoError(t, rsp.Err())
+ vals, err := rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 7)
+ isRESP3 := configs["resp3-enabled"] == "yes"
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ require.True(t, math.IsNaN(rank), "expected NaN
but got %v at index %d", rank, i)
+ }
+ } else {
+ expected := []string{"nan", "nan", "nan", "nan", "nan",
"nan", "nan"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.EqualValues(t, expected[i], rank, "RANK
mismatch at index %d", i)
+ }
+ }
+
+ // Test BYREVRANK on empty sketch
+ rsp = rdb.Do(ctx, "TDIGEST.BYREVRANK", key, "1", "2", "4", "5",
"0", "1", "20")
+ require.NoError(t, rsp.Err())
+ vals, err = rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 7)
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ require.True(t, math.IsNaN(rank), "expected NaN
but got %v at index %d", rank, i)
+ }
+ } else {
+ expected := []string{"nan", "nan", "nan", "nan", "nan",
"nan", "nan"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.EqualValues(t, expected[i], rank,
"REVRANK mismatch at index %d", i)
+ }
+ }
+ })
+
+ t.Run("tdigest.byrank and tdigest.byrevrank on non-empty sketch",
func(t *testing.T) {
+ key := "tdigest_byrank_non_empty"
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.CREATE", key,
"compression", "100").Err())
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.ADD", key, "1", "2",
"3", "4", "5").Err())
+ isRESP3 := configs["resp3-enabled"] == "yes"
+
+ rsp := rdb.Do(ctx, "TDIGEST.BYRANK", key, "0", "1", "2", "3",
"4", "5", "6")
+ require.NoError(t, rsp.Err())
+ vals, err := rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 7)
+ if isRESP3 {
+ // Expected: rank 0 -> 1, rank 1 -> 2, rank 2 -> 3,
rank 3 -> 4, rank 4 -> 5
+ // Expected: rank 5, 6 -> out of range (+inf)
+ expected := []float64{1, 2, 3, 4, 5, math.Inf(1),
math.Inf(1)}
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ if math.IsInf(expected[i], 1) {
+ require.True(t, math.IsInf(rank, 1),
"expected +Inf but got %v at index %d", rank, i)
+ } else {
+ require.InDelta(t, expected[i], rank,
0.1, "BYRANK mismatch at index %d", i)
+ }
+ }
+ } else {
+ expectedStrings := []string{"1", "2", "3", "4", "5",
"inf", "inf"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.Equal(t, expectedStrings[i], rank,
"BYRANK mismatch at index %d", i)
+ }
+ }
+
+ rsp = rdb.Do(ctx, "TDIGEST.BYREVRANK", key, "0", "1", "2", "3",
"4", "5", "6")
+ require.NoError(t, rsp.Err())
+ vals, err = rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 7)
+
+ if isRESP3 {
+ // Expected: rank 0 -> 5, rank 1 -> 4, rank 2 -> 3,
rank 3 -> 2, rank 4 -> 1
+ // Expected: rank 5, 6 -> out of range (-inf)
+ expected := []float64{5, 4, 3, 2, 1, math.Inf(-1),
math.Inf(-1)}
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ if math.IsInf(expected[i], -1) {
+ require.True(t, math.IsInf(rank, -1),
"expected -Inf but got %v at index %d", rank, i)
+ } else {
+ require.InDelta(t, expected[i], rank,
0.1, "BYREVRANK mismatch at index %d", i)
+ }
+ }
+ } else {
+ expectedStrings := []string{"5", "4", "3", "2", "1",
"-inf", "-inf"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.Equal(t, expectedStrings[i], rank,
"BYREVRANK mismatch at index %d", i)
+ }
+ }
+ })
+
+ t.Run("tdigest.byrank and tdigest.byrevrank with duplicate values",
func(t *testing.T) {
+ key := "tdigest_byrank_duplicates"
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.CREATE", key,
"compression", "100").Err())
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.ADD", key, "1", "2",
"2", "3", "3", "3").Err())
+ isRESP3 := configs["resp3-enabled"] == "yes"
+
+ rsp := rdb.Do(ctx, "TDIGEST.BYRANK", key, "0", "1", "2", "3",
"4", "5", "6", "7")
+ require.NoError(t, rsp.Err())
+ vals, err := rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 8)
+ // test BYRANK with duplicate values
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ expected := []float64{1, 2, 2, 3, 3, 3}
+ if i < 6 {
+ require.InDelta(t, expected[i], rank,
0.1, "BYRANK mismatch at index %d", i)
+ } else {
+ require.True(t, math.IsInf(rank, 1),
"rank %d should be +Inf, got %v", i, rank)
+ }
+ }
+ } else {
+ expectedStrings := []string{"1", "2", "2", "3", "3",
"3", "inf", "inf"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.Equal(t, expectedStrings[i], rank,
"BYRANK mismatch at index %d", i)
+ }
+ }
+
+ // test BYREVRANK with duplicate values
+ rsp = rdb.Do(ctx, "TDIGEST.BYREVRANK", key, "0", "1", "2", "3",
"4", "5", "6", "7")
+ require.NoError(t, rsp.Err())
+ vals, err = rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 8)
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ expected := []float64{3, 3, 3, 2, 2, 1}
+ if i < 6 {
+ require.InDelta(t, expected[i], rank,
0.1, "BYREVRANK mismatch at index %d", i)
+ } else {
+ require.True(t, math.IsInf(rank, -1),
"rank %d should be -Inf, got %v", i, rank)
+ }
+ }
+ } else {
+ expectedStrings := []string{"3", "3", "3", "2", "2",
"1", "-inf", "-inf"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.Equal(t, expectedStrings[i], rank,
"BYREVRANK mismatch at index %d", i)
+ }
+ }
+ })
+
+ t.Run("tdigest.byrank and tdigest.byrevrank with unordered duplicate
values", func(t *testing.T) {
+ key := "tdigest_byrank_unordered_dup_"
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.CREATE", key,
"compression", "100").Err())
+ require.NoError(t, rdb.Do(ctx, "TDIGEST.ADD", key, "12", "100",
"50", "36", "75", "81", "35.5", "46", "36", "8.8", "15", "4", "32.5", "12",
"8.8", "7", "99", "1").Err())
+ isRESP3 := configs["resp3-enabled"] == "yes"
+
+ rsp := rdb.Do(ctx, "TDIGEST.BYRANK", key, "0", "1", "2", "3",
"4", "5", "6", "7", "7", "5", "20", "100")
+ require.NoError(t, rsp.Err())
+ vals, err := rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 12)
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ expected := []float64{1, 4, 7, 8.8, 8.8, 12,
12, 15, 15, 12}
+ if i < 10 {
+ require.InDelta(t, expected[i], rank,
0.1, "BYRANK mismatch at index %d", i)
+ } else {
+ require.True(t, math.IsInf(rank, 1),
"rank %d should be +Inf, got %v", i, rank)
+ }
+ }
+ } else {
+ expectedStrings := []string{"1", "4", "7", "8.8",
"8.8", "12", "12", "15", "15", "12", "inf", "inf"}
+ for i, v := range vals {
+ rank, ok := v.(string)
+ require.True(t, ok, "expected string but got %T
at index %d", v, i)
+ require.Equal(t, expectedStrings[i], rank,
"BYRANK mismatch at index %d", i)
+ }
+ }
+
+ // test BYREVRANK with duplicate values
+ rsp = rdb.Do(ctx, "TDIGEST.BYREVRANK", key, "20", "75", "0",
"1", "2", "3", "4", "5", "6", "7")
+ require.NoError(t, rsp.Err())
+ vals, err = rsp.Slice()
+ require.NoError(t, err)
+ require.Len(t, vals, 10)
+ if isRESP3 {
+ for i, v := range vals {
+ rank, ok := v.(float64)
+ require.True(t, ok, "expected float64 but got
%T at index %d", v, i)
+ expected := []float64{0, 0, 100, 99, 81, 75,
50, 46, 36, 36}
Review Comment:
```
[donghao526@VM-165-13~]$ sudo docker run -d --name redis -p 6379:6379
redis:latest
2d77559739849b9fee49a86333ca5226fc5afdb8f46bf06bc318d09ca006f3b4
[donghao526@VM-165-13~]$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> TDIGEST.CREATE t COMPRESSION 1000
OK
127.0.0.1:6379> TDIGEST.ADD t 12 100 50 36 75 81 35.5 46 36 8.8 15 4 32.5 12
8.8 7 99 1
OK
127.0.0.1:6379> tdigest.byrevrank t 20 75 0 1 2 3 4 5 6 7
1) "-inf"
2) "-inf"
3) "100"
4) "99"
5) "81"
6) "75"
7) "50"
8) "46"
9) "36"
10) "36"
```
Test with the latest docker image, the last one is "36"
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]