summaryrefslogtreecommitdiff
path: root/tests/test_timeseries.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_timeseries.py')
-rw-r--r--tests/test_timeseries.py593
1 files changed, 593 insertions, 0 deletions
diff --git a/tests/test_timeseries.py b/tests/test_timeseries.py
new file mode 100644
index 0000000..b2df3fe
--- /dev/null
+++ b/tests/test_timeseries.py
@@ -0,0 +1,593 @@
+import pytest
+import time
+from time import sleep
+from .conftest import skip_ifmodversion_lt
+
+
+@pytest.fixture
+def client(modclient):
+ modclient.flushdb()
+ return modclient
+
+
+@pytest.mark.redismod
+def testCreate(client):
+ assert client.ts().create(1)
+ assert client.ts().create(2, retention_msecs=5)
+ assert client.ts().create(3, labels={"Redis": "Labs"})
+ assert client.ts().create(4, retention_msecs=20, labels={"Time": "Series"})
+ info = client.ts().info(4)
+ assert 20 == info.retention_msecs
+ assert "Series" == info.labels["Time"]
+
+ # Test for a chunk size of 128 Bytes
+ assert client.ts().create("time-serie-1", chunk_size=128)
+ info = client.ts().info("time-serie-1")
+ assert 128, info.chunk_size
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("1.4.0", "timeseries")
+def testCreateDuplicatePolicy(client):
+ # Test for duplicate policy
+ for duplicate_policy in ["block", "last", "first", "min", "max"]:
+ ts_name = "time-serie-ooo-{0}".format(duplicate_policy)
+ assert client.ts().create(ts_name, duplicate_policy=duplicate_policy)
+ info = client.ts().info(ts_name)
+ assert duplicate_policy == info.duplicate_policy
+
+
+@pytest.mark.redismod
+def testAlter(client):
+ assert client.ts().create(1)
+ assert 0 == client.ts().info(1).retention_msecs
+ assert client.ts().alter(1, retention_msecs=10)
+ assert {} == client.ts().info(1).labels
+ assert 10, client.ts().info(1).retention_msecs
+ assert client.ts().alter(1, labels={"Time": "Series"})
+ assert "Series" == client.ts().info(1).labels["Time"]
+ assert 10 == client.ts().info(1).retention_msecs
+
+
+# pipe = client.ts().pipeline()
+# assert pipe.create(2)
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("1.4.0", "timeseries")
+def testAlterDiplicatePolicy(client):
+ assert client.ts().create(1)
+ info = client.ts().info(1)
+ assert info.duplicate_policy is None
+ assert client.ts().alter(1, duplicate_policy="min")
+ info = client.ts().info(1)
+ assert "min" == info.duplicate_policy
+
+
+@pytest.mark.redismod
+def testAdd(client):
+ assert 1 == client.ts().add(1, 1, 1)
+ assert 2 == client.ts().add(2, 2, 3, retention_msecs=10)
+ assert 3 == client.ts().add(3, 3, 2, labels={"Redis": "Labs"})
+ assert 4 == client.ts().add(
+ 4, 4, 2, retention_msecs=10, labels={"Redis": "Labs", "Time": "Series"}
+ )
+ assert round(time.time()) == \
+ round(float(client.ts().add(5, "*", 1)) / 1000)
+
+ info = client.ts().info(4)
+ assert 10 == info.retention_msecs
+ assert "Labs" == info.labels["Redis"]
+
+ # Test for a chunk size of 128 Bytes on TS.ADD
+ assert client.ts().add("time-serie-1", 1, 10.0, chunk_size=128)
+ info = client.ts().info("time-serie-1")
+ assert 128 == info.chunk_size
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("1.4.0", "timeseries")
+def testAddDuplicatePolicy(client):
+
+ # Test for duplicate policy BLOCK
+ assert 1 == client.ts().add("time-serie-add-ooo-block", 1, 5.0)
+ with pytest.raises(Exception):
+ client.ts().add(
+ "time-serie-add-ooo-block",
+ 1,
+ 5.0,
+ duplicate_policy="block"
+ )
+
+ # Test for duplicate policy LAST
+ assert 1 == client.ts().add("time-serie-add-ooo-last", 1, 5.0)
+ assert 1 == client.ts().add(
+ "time-serie-add-ooo-last", 1, 10.0, duplicate_policy="last"
+ )
+ assert 10.0 == client.ts().get("time-serie-add-ooo-last")[1]
+
+ # Test for duplicate policy FIRST
+ assert 1 == client.ts().add("time-serie-add-ooo-first", 1, 5.0)
+ assert 1 == client.ts().add(
+ "time-serie-add-ooo-first", 1, 10.0, duplicate_policy="first"
+ )
+ assert 5.0 == client.ts().get("time-serie-add-ooo-first")[1]
+
+ # Test for duplicate policy MAX
+ assert 1 == client.ts().add("time-serie-add-ooo-max", 1, 5.0)
+ assert 1 == client.ts().add(
+ "time-serie-add-ooo-max", 1, 10.0, duplicate_policy="max"
+ )
+ assert 10.0 == client.ts().get("time-serie-add-ooo-max")[1]
+
+ # Test for duplicate policy MIN
+ assert 1 == client.ts().add("time-serie-add-ooo-min", 1, 5.0)
+ assert 1 == client.ts().add(
+ "time-serie-add-ooo-min", 1, 10.0, duplicate_policy="min"
+ )
+ assert 5.0 == client.ts().get("time-serie-add-ooo-min")[1]
+
+
+@pytest.mark.redismod
+def testMAdd(client):
+ client.ts().create("a")
+ assert [1, 2, 3] == \
+ client.ts().madd([("a", 1, 5), ("a", 2, 10), ("a", 3, 15)])
+
+
+@pytest.mark.redismod
+def testIncrbyDecrby(client):
+ for _ in range(100):
+ assert client.ts().incrby(1, 1)
+ sleep(0.001)
+ assert 100 == client.ts().get(1)[1]
+ for _ in range(100):
+ assert client.ts().decrby(1, 1)
+ sleep(0.001)
+ assert 0 == client.ts().get(1)[1]
+
+ assert client.ts().incrby(2, 1.5, timestamp=5)
+ assert (5, 1.5) == client.ts().get(2)
+ assert client.ts().incrby(2, 2.25, timestamp=7)
+ assert (7, 3.75) == client.ts().get(2)
+ assert client.ts().decrby(2, 1.5, timestamp=15)
+ assert (15, 2.25) == client.ts().get(2)
+
+ # Test for a chunk size of 128 Bytes on TS.INCRBY
+ assert client.ts().incrby("time-serie-1", 10, chunk_size=128)
+ info = client.ts().info("time-serie-1")
+ assert 128 == info.chunk_size
+
+ # Test for a chunk size of 128 Bytes on TS.DECRBY
+ assert client.ts().decrby("time-serie-2", 10, chunk_size=128)
+ info = client.ts().info("time-serie-2")
+ assert 128 == info.chunk_size
+
+
+@pytest.mark.redismod
+def testCreateAndDeleteRule(client):
+ # test rule creation
+ time = 100
+ client.ts().create(1)
+ client.ts().create(2)
+ client.ts().createrule(1, 2, "avg", 100)
+ for i in range(50):
+ client.ts().add(1, time + i * 2, 1)
+ client.ts().add(1, time + i * 2 + 1, 2)
+ client.ts().add(1, time * 2, 1.5)
+ assert round(client.ts().get(2)[1], 5) == 1.5
+ info = client.ts().info(1)
+ assert info.rules[0][1] == 100
+
+ # test rule deletion
+ client.ts().deleterule(1, 2)
+ info = client.ts().info(1)
+ assert not info.rules
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("99.99.99", "timeseries")
+def testDelRange(client):
+ try:
+ client.ts().delete("test", 0, 100)
+ except Exception as e:
+ assert e.__str__() != ""
+
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ assert 22 == client.ts().delete(1, 0, 21)
+ assert [] == client.ts().range(1, 0, 21)
+ assert [(22, 1.0)] == client.ts().range(1, 22, 22)
+
+
+@pytest.mark.redismod
+def testRange(client):
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ assert 100 == len(client.ts().range(1, 0, 200))
+ for i in range(100):
+ client.ts().add(1, i + 200, i % 7)
+ assert 200 == len(client.ts().range(1, 0, 500))
+ # last sample isn't returned
+ assert 20 == len(
+ client.ts().range(
+ 1,
+ 0,
+ 500,
+ aggregation_type="avg",
+ bucket_size_msec=10
+ )
+ )
+ assert 10 == len(client.ts().range(1, 0, 500, count=10))
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("99.99.99", "timeseries")
+def testRangeAdvanced(client):
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ client.ts().add(1, i + 200, i % 7)
+
+ assert 2 == len(
+ client.ts().range(
+ 1,
+ 0,
+ 500,
+ filter_by_ts=[i for i in range(10, 20)],
+ filter_by_min_value=1,
+ filter_by_max_value=2,
+ )
+ )
+ assert [(0, 10.0), (10, 1.0)] == client.ts().range(
+ 1, 0, 10, aggregation_type="count", bucket_size_msec=10, align="+"
+ )
+ assert [(-5, 5.0), (5, 6.0)] == client.ts().range(
+ 1, 0, 10, aggregation_type="count", bucket_size_msec=10, align=5
+ )
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("99.99.99", "timeseries")
+def testRevRange(client):
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ assert 100 == len(client.ts().range(1, 0, 200))
+ for i in range(100):
+ client.ts().add(1, i + 200, i % 7)
+ assert 200 == len(client.ts().range(1, 0, 500))
+ # first sample isn't returned
+ assert 20 == len(
+ client.ts().revrange(
+ 1,
+ 0,
+ 500,
+ aggregation_type="avg",
+ bucket_size_msec=10
+ )
+ )
+ assert 10 == len(client.ts().revrange(1, 0, 500, count=10))
+ assert 2 == len(
+ client.ts().revrange(
+ 1,
+ 0,
+ 500,
+ filter_by_ts=[i for i in range(10, 20)],
+ filter_by_min_value=1,
+ filter_by_max_value=2,
+ )
+ )
+ assert [(10, 1.0), (0, 10.0)] == client.ts().revrange(
+ 1, 0, 10, aggregation_type="count", bucket_size_msec=10, align="+"
+ )
+ assert [(1, 10.0), (-9, 1.0)] == client.ts().revrange(
+ 1, 0, 10, aggregation_type="count", bucket_size_msec=10, align=1
+ )
+
+
+@pytest.mark.redismod
+def testMultiRange(client):
+ client.ts().create(1, labels={"Test": "This", "team": "ny"})
+ client.ts().create(
+ 2,
+ labels={"Test": "This", "Taste": "That", "team": "sf"}
+ )
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ client.ts().add(2, i, i % 11)
+
+ res = client.ts().mrange(0, 200, filters=["Test=This"])
+ assert 2 == len(res)
+ assert 100 == len(res[0]["1"][1])
+
+ res = client.ts().mrange(0, 200, filters=["Test=This"], count=10)
+ assert 10 == len(res[0]["1"][1])
+
+ for i in range(100):
+ client.ts().add(1, i + 200, i % 7)
+ res = client.ts().mrange(
+ 0,
+ 500,
+ filters=["Test=This"],
+ aggregation_type="avg",
+ bucket_size_msec=10
+ )
+ assert 2 == len(res)
+ assert 20 == len(res[0]["1"][1])
+
+ # test withlabels
+ assert {} == res[0]["1"][0]
+ res = client.ts().mrange(0, 200, filters=["Test=This"], with_labels=True)
+ assert {"Test": "This", "team": "ny"} == res[0]["1"][0]
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("99.99.99", "timeseries")
+def testMultiRangeAdvanced(client):
+ client.ts().create(1, labels={"Test": "This", "team": "ny"})
+ client.ts().create(
+ 2,
+ labels={"Test": "This", "Taste": "That", "team": "sf"}
+ )
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ client.ts().add(2, i, i % 11)
+
+ # test with selected labels
+ res = client.ts().mrange(
+ 0,
+ 200,
+ filters=["Test=This"],
+ select_labels=["team"]
+ )
+ assert {"team": "ny"} == res[0]["1"][0]
+ assert {"team": "sf"} == res[1]["2"][0]
+
+ # test with filterby
+ res = client.ts().mrange(
+ 0,
+ 200,
+ filters=["Test=This"],
+ filter_by_ts=[i for i in range(10, 20)],
+ filter_by_min_value=1,
+ filter_by_max_value=2,
+ )
+ assert [(15, 1.0), (16, 2.0)] == res[0]["1"][1]
+
+ # test groupby
+ res = client.ts().mrange(
+ 0,
+ 3,
+ filters=["Test=This"],
+ groupby="Test",
+ reduce="sum"
+ )
+ assert [(0, 0.0), (1, 2.0), (2, 4.0), (3, 6.0)] == res[0]["Test=This"][1]
+ res = client.ts().mrange(
+ 0,
+ 3,
+ filters=["Test=This"],
+ groupby="Test",
+ reduce="max"
+ )
+ assert [(0, 0.0), (1, 1.0), (2, 2.0), (3, 3.0)] == res[0]["Test=This"][1]
+ res = client.ts().mrange(
+ 0,
+ 3,
+ filters=["Test=This"],
+ groupby="team",
+ reduce="min")
+ assert 2 == len(res)
+ assert [(0, 0.0), (1, 1.0), (2, 2.0), (3, 3.0)] == res[0]["team=ny"][1]
+ assert [(0, 0.0), (1, 1.0), (2, 2.0), (3, 3.0)] == res[1]["team=sf"][1]
+
+ # test align
+ res = client.ts().mrange(
+ 0,
+ 10,
+ filters=["team=ny"],
+ aggregation_type="count",
+ bucket_size_msec=10,
+ align="-",
+ )
+ assert [(0, 10.0), (10, 1.0)] == res[0]["1"][1]
+ res = client.ts().mrange(
+ 0,
+ 10,
+ filters=["team=ny"],
+ aggregation_type="count",
+ bucket_size_msec=10,
+ align=5,
+ )
+ assert [(-5, 5.0), (5, 6.0)] == res[0]["1"][1]
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("99.99.99", "timeseries")
+def testMultiReverseRange(client):
+ client.ts().create(1, labels={"Test": "This", "team": "ny"})
+ client.ts().create(
+ 2,
+ labels={"Test": "This", "Taste": "That", "team": "sf"}
+ )
+ for i in range(100):
+ client.ts().add(1, i, i % 7)
+ client.ts().add(2, i, i % 11)
+
+ res = client.ts().mrange(0, 200, filters=["Test=This"])
+ assert 2 == len(res)
+ assert 100 == len(res[0]["1"][1])
+
+ res = client.ts().mrange(0, 200, filters=["Test=This"], count=10)
+ assert 10 == len(res[0]["1"][1])
+
+ for i in range(100):
+ client.ts().add(1, i + 200, i % 7)
+ res = client.ts().mrevrange(
+ 0,
+ 500,
+ filters=["Test=This"],
+ aggregation_type="avg",
+ bucket_size_msec=10
+ )
+ assert 2 == len(res)
+ assert 20 == len(res[0]["1"][1])
+ assert {} == res[0]["1"][0]
+
+ # test withlabels
+ res = client.ts().mrevrange(
+ 0,
+ 200,
+ filters=["Test=This"],
+ with_labels=True
+ )
+ assert {"Test": "This", "team": "ny"} == res[0]["1"][0]
+
+ # test with selected labels
+ res = client.ts().mrevrange(
+ 0,
+ 200,
+ filters=["Test=This"], select_labels=["team"]
+ )
+ assert {"team": "ny"} == res[0]["1"][0]
+ assert {"team": "sf"} == res[1]["2"][0]
+
+ # test filterby
+ res = client.ts().mrevrange(
+ 0,
+ 200,
+ filters=["Test=This"],
+ filter_by_ts=[i for i in range(10, 20)],
+ filter_by_min_value=1,
+ filter_by_max_value=2,
+ )
+ assert [(16, 2.0), (15, 1.0)] == res[0]["1"][1]
+
+ # test groupby
+ res = client.ts().mrevrange(
+ 0, 3, filters=["Test=This"], groupby="Test", reduce="sum"
+ )
+ assert [(3, 6.0), (2, 4.0), (1, 2.0), (0, 0.0)] == res[0]["Test=This"][1]
+ res = client.ts().mrevrange(
+ 0, 3, filters=["Test=This"], groupby="Test", reduce="max"
+ )
+ assert [(3, 3.0), (2, 2.0), (1, 1.0), (0, 0.0)] == res[0]["Test=This"][1]
+ res = client.ts().mrevrange(
+ 0, 3, filters=["Test=This"], groupby="team", reduce="min"
+ )
+ assert 2 == len(res)
+ assert [(3, 3.0), (2, 2.0), (1, 1.0), (0, 0.0)] == res[0]["team=ny"][1]
+ assert [(3, 3.0), (2, 2.0), (1, 1.0), (0, 0.0)] == res[1]["team=sf"][1]
+
+ # test align
+ res = client.ts().mrevrange(
+ 0,
+ 10,
+ filters=["team=ny"],
+ aggregation_type="count",
+ bucket_size_msec=10,
+ align="-",
+ )
+ assert [(10, 1.0), (0, 10.0)] == res[0]["1"][1]
+ res = client.ts().mrevrange(
+ 0,
+ 10,
+ filters=["team=ny"],
+ aggregation_type="count",
+ bucket_size_msec=10,
+ align=1,
+ )
+ assert [(1, 10.0), (-9, 1.0)] == res[0]["1"][1]
+
+
+@pytest.mark.redismod
+def testGet(client):
+ name = "test"
+ client.ts().create(name)
+ assert client.ts().get(name) is None
+ client.ts().add(name, 2, 3)
+ assert 2 == client.ts().get(name)[0]
+ client.ts().add(name, 3, 4)
+ assert 4 == client.ts().get(name)[1]
+
+
+@pytest.mark.redismod
+def testMGet(client):
+ client.ts().create(1, labels={"Test": "This"})
+ client.ts().create(2, labels={"Test": "This", "Taste": "That"})
+ act_res = client.ts().mget(["Test=This"])
+ exp_res = [{"1": [{}, None, None]}, {"2": [{}, None, None]}]
+ assert act_res == exp_res
+ client.ts().add(1, "*", 15)
+ client.ts().add(2, "*", 25)
+ res = client.ts().mget(["Test=This"])
+ assert 15 == res[0]["1"][2]
+ assert 25 == res[1]["2"][2]
+ res = client.ts().mget(["Taste=That"])
+ assert 25 == res[0]["2"][2]
+
+ # test with_labels
+ assert {} == res[0]["2"][0]
+ res = client.ts().mget(["Taste=That"], with_labels=True)
+ assert {"Taste": "That", "Test": "This"} == res[0]["2"][0]
+
+
+@pytest.mark.redismod
+def testInfo(client):
+ client.ts().create(
+ 1,
+ retention_msecs=5,
+ labels={"currentLabel": "currentData"}
+ )
+ info = client.ts().info(1)
+ assert 5 == info.retention_msecs
+ assert info.labels["currentLabel"] == "currentData"
+
+
+@pytest.mark.redismod
+@skip_ifmodversion_lt("1.4.0", "timeseries")
+def testInfoDuplicatePolicy(client):
+ client.ts().create(
+ 1,
+ retention_msecs=5,
+ labels={"currentLabel": "currentData"}
+ )
+ info = client.ts().info(1)
+ assert info.duplicate_policy is None
+
+ client.ts().create("time-serie-2", duplicate_policy="min")
+ info = client.ts().info("time-serie-2")
+ assert "min" == info.duplicate_policy
+
+
+@pytest.mark.redismod
+def testQueryIndex(client):
+ client.ts().create(1, labels={"Test": "This"})
+ client.ts().create(2, labels={"Test": "This", "Taste": "That"})
+ assert 2 == len(client.ts().queryindex(["Test=This"]))
+ assert 1 == len(client.ts().queryindex(["Taste=That"]))
+ assert [2] == client.ts().queryindex(["Taste=That"])
+
+
+#
+# @pytest.mark.redismod
+# @pytest.mark.pipeline
+# def testPipeline(client):
+# pipeline = client.ts().pipeline()
+# pipeline.create("with_pipeline")
+# for i in range(100):
+# pipeline.add("with_pipeline", i, 1.1 * i)
+# pipeline.execute()
+
+# info = client.ts().info("with_pipeline")
+# assert info.lastTimeStamp == 99
+# assert info.total_samples == 100
+# assert client.ts().get("with_pipeline")[1] == 99 * 1.1
+
+
+@pytest.mark.redismod
+def testUncompressed(client):
+ client.ts().create("compressed")
+ client.ts().create("uncompressed", uncompressed=True)
+ compressed_info = client.ts().info("compressed")
+ uncompressed_info = client.ts().info("uncompressed")
+ assert compressed_info.memory_usage != uncompressed_info.memory_usage