1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
import math
from math import inf
import pytest
import redis
topk_tests = pytest.importorskip("probables")
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_reset(r: redis.Redis):
assert r.tdigest().create("tDigest", 10)
# reset on empty histogram
assert r.tdigest().reset("tDigest")
# insert data-points into sketch
assert r.tdigest().add("tDigest", list(range(10)))
assert r.tdigest().reset("tDigest")
# assert we have 0 unmerged
info = r.tdigest().info("tDigest")
assert 0 == info.get("unmerged_weight")
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_merge(r: redis.Redis):
assert r.tdigest().create("to-tDigest", 10)
assert r.tdigest().create("from-tDigest", 10)
# insert data-points into sketch
assert r.tdigest().add("from-tDigest", [1.0] * 10)
assert r.tdigest().add("to-tDigest", [2.0] * 10)
# merge from-tdigest into to-tdigest
assert r.tdigest().merge("to-tDigest", 1, "from-tDigest")
# we should now have 110 weight on to-histogram
info = r.tdigest().info("to-tDigest")
assert 20 == float(info["merged_weight"]) + float(info["unmerged_weight"])
# test override
assert r.tdigest().create("from-override", 10)
assert r.tdigest().create("from-override-2", 10)
assert r.tdigest().add("from-override", [3.0] * 10)
assert r.tdigest().add("from-override-2", [4.0] * 10)
assert r.tdigest().merge("to-tDigest", 2, "from-override", "from-override-2", override=True)
assert 3.0 == r.tdigest().min("to-tDigest")
assert 4.0 == r.tdigest().max("to-tDigest")
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_min_and_max(r: redis.Redis):
assert r.tdigest().create("tDigest", 100)
# insert data-points into sketch
assert r.tdigest().add("tDigest", [1, 2, 3])
# min/max
assert 3 == r.tdigest().max("tDigest")
assert 1 == r.tdigest().min("tDigest")
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_quantile(r: redis.Redis):
assert r.tdigest().create("tDigest", 500)
# insert data-points into sketch
assert r.tdigest().add("tDigest", list([x * 0.01 for x in range(1, 10000)]))
# assert min min/max have same result as quantile 0 and 1
res = r.tdigest().quantile("tDigest", 1.0)
assert r.tdigest().max("tDigest") == res[0]
res = r.tdigest().quantile("tDigest", 0.0)
assert r.tdigest().min("tDigest") == res[0]
assert 1.0 == round(r.tdigest().quantile("tDigest", 0.01)[0], 2)
assert 99.0 == round(r.tdigest().quantile("tDigest", 0.99)[0], 2)
# test multiple quantiles
assert r.tdigest().create("t-digest", 100)
assert r.tdigest().add("t-digest", [1, 2, 3, 4, 5])
assert [3.0, 5.0] == r.tdigest().quantile("t-digest", 0.5, 0.8)
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_cdf(r: redis.Redis):
assert r.tdigest().create("tDigest", 100)
# insert data-points into sketch
assert r.tdigest().add("tDigest", list(range(1, 10)))
assert 0.1 == round(r.tdigest().cdf("tDigest", 1.0)[0], 1)
assert 0.9 == round(r.tdigest().cdf("tDigest", 9.0)[0], 1)
res = r.tdigest().cdf("tDigest", 1.0, 9.0)
assert [0.1, 0.9] == [round(x, 1) for x in res]
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_trimmed_mean(r: redis.Redis):
assert r.tdigest().create("tDigest", 100)
# insert data-points into sketch
assert r.tdigest().add("tDigest", list(range(1, 10)))
assert 5 == r.tdigest().trimmed_mean("tDigest", 0.1, 0.9)
assert 4.5 == r.tdigest().trimmed_mean("tDigest", 0.4, 0.5)
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_rank(r: redis.Redis):
assert r.tdigest().create("t-digest", 500)
assert r.tdigest().add("t-digest", list(range(0, 20)))
assert -1 == r.tdigest().rank("t-digest", -1)[0]
assert 0 == r.tdigest().rank("t-digest", 0)[0]
assert 10 == r.tdigest().rank("t-digest", 10)[0]
assert [-1, 20, 9] == r.tdigest().rank("t-digest", -20, 20, 9)
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_revrank(r: redis.Redis):
assert r.tdigest().create("t-digest", 500)
assert r.tdigest().add("t-digest", list(range(0, 20)))
assert -1 == r.tdigest().revrank("t-digest", 20)[0]
assert 19 == r.tdigest().revrank("t-digest", 0)[0]
assert [-1, 19, 9] == r.tdigest().revrank("t-digest", 21, 0, 10)
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_byrank(r: redis.Redis):
assert r.tdigest().create("t-digest", 500)
assert r.tdigest().add("t-digest", list(range(1, 11)))
assert 1 == r.tdigest().byrank("t-digest", 0)[0]
assert 10 == r.tdigest().byrank("t-digest", 9)[0]
assert r.tdigest().byrank("t-digest", 100)[0] == inf
with pytest.raises(redis.ResponseError):
r.tdigest().byrank("t-digest", -1)[0]
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_byrevrank(r: redis.Redis):
assert r.tdigest().create("t-digest", 500)
assert r.tdigest().add("t-digest", list(range(1, 11)))
assert 10 == r.tdigest().byrevrank("t-digest", 0)[0]
assert 1 == r.tdigest().byrevrank("t-digest", 9)[0]
assert r.tdigest().byrevrank("t-digest", 100)[0] == -inf
with pytest.raises(redis.ResponseError):
r.tdigest().byrevrank("t-digest", -1)[0]
@pytest.mark.unsupported_server_types("dragonfly")
def test_tdigest_quantile_nan(r: redis.Redis):
r.tdigest().create("foo")
r.tdigest().add("foo", [123])
res = r.tdigest().quantile("foo", 0.9)
assert isinstance(res, list)
assert len(res) == 1
assert math.isnan(float(res[0])), f"Expected NaN, got {res[0]}"
res = r.tdigest().quantile("foo", 0)[0]
assert math.isnan(float(res)), f"Expected NaN, got {res}"
res = r.tdigest().quantile("foo", 1)[0]
assert math.isnan(float(res)), f"Expected NaN, got {res}"
|