Files
sdk/python/tests/test_service.py
Neil Movva 9604fd30e1 [BLY-66] direct upload pparams (#28)
* bucket check and async setup
clients perform direct setup by default

* (python) more consistent json for internal api

all requests and response are JSON.
all binary payloads are explicitly encoded as base64
within api.py, and decoded back to bytes before leaving api.py.
User-facing code, e.g. bucket.py and bucket_service.py,
should not see base64 wrangling.

* Support async for all ops

refactor api.py to be async-first
use new asyncio loops to support non-async interface;
cannot call non-async methods from async context

* [js] update client to work with unified service
bump both versions to 0.2.1
disable npm/pypi publish except on manual workflow run

* disable request compression

* fix workflow tests

update standalone Spiral test server to use new JSON interface
2023-09-11 16:55:35 -07:00

210 lines
6.0 KiB
Python

from typing import Optional
import os
import sys
import random
import hashlib
import traceback
import blyss
def key_to_gold_value(key: str, length: int = 512) -> bytes:
h = hashlib.md5()
h.update(key.encode("utf-8"))
value = h.digest()
while len(value) < length:
h.update(b"0")
value += h.digest()
return value[:length]
def verify_read(key: str, value: bytes):
expected = key_to_gold_value(key, len(value))
try:
assert value == expected
except:
print(f"read mismatch for key {key}")
print(f"received {value.hex()[:16]}")
print(f"expected {expected.hex()[:16]}")
print(traceback.format_exc())
raise
def generate_keys(n: int, seed: int = 0) -> list:
return [f"{seed}-{i}" for i in range(n)]
def generateBucketName() -> str:
tag = int(random.random() * 1e6)
return f"api-tester-{tag:#0{6}x}"
async def test_e2e_async(
endpoint: str, api_key: str, N: int = 4000, itemSize: int = 32
):
client = blyss.AsyncClient(api_key, endpoint)
# generate random string for bucket name
bucket_name = generateBucketName()
await client.create(bucket_name, usage_hints={"maxItemSize": 40_000})
print("Created bucket")
bucket = await client.connect(bucket_name)
print(await bucket.info())
# generate N random keys
local_keys = generate_keys(N, 0)
# write all N keys
await bucket.write({k: key_to_gold_value(k, itemSize) for k in local_keys})
print(f"Wrote {N} keys")
# read a random key
testKey = random.choice(local_keys)
value = (await bucket.private_read([testKey]))[0]
assert value is not None
verify_read(testKey, value)
print(f"Read key {testKey}, got {value.hex()[:8]}[...]")
# delete testKey from the bucket, and localData.
await bucket.delete_key(testKey)
local_keys.remove(testKey)
value = (await bucket.private_read([testKey]))[0]
def _test_delete(key: str, value: Optional[bytes]):
if value is None:
print(f"Deleted key {key}")
else:
# this happens only sometimes??
print("ERROR: delete not reflected in read!")
print(f"Read deleted key {key} and got {value.hex()[:8]}[...]")
_test_delete(testKey, value)
# clear all keys
await bucket.clear_entire_bucket()
local_keys = []
print("Cleared bucket")
# write a new set of N keys
local_keys = generate_keys(N, 2)
await bucket.write({k: key_to_gold_value(k, itemSize) for k in local_keys})
print(f"Wrote {N} keys")
# read a random key
testKey = random.choice(local_keys)
value = (await bucket.private_read([testKey]))[0]
assert value is not None
verify_read(testKey, value)
# rename the bucket
new_bucket_name = bucket_name + "-rn"
await bucket.rename(new_bucket_name)
print("Renamed bucket")
print(await bucket.info())
# read a random key
testKey = random.choice(local_keys)
value = (await bucket.private_read([testKey]))[0]
assert value is not None
verify_read(testKey, value)
print(f"Read key {testKey}")
# destroy the bucket
await bucket.destroy_entire_bucket()
print("Destroyed bucket")
def test_e2e(endpoint: str, api_key: str, N: int = 4000, itemSize: int = 32):
client = blyss.Client(api_key, endpoint)
# generate random string for bucket name
bucket_name = generateBucketName()
client.create(bucket_name, usage_hints={"maxItemSize": 40_000})
print("Created bucket")
bucket = client.connect(bucket_name)
print(bucket.info())
# generate N random keys
local_keys = generate_keys(N, 0)
# write all N keys
bucket.write({k: key_to_gold_value(k, itemSize) for k in local_keys})
print(f"Wrote {N} keys")
# read a random key
testKey = random.choice(local_keys)
value = bucket.private_read([testKey])[0]
assert value is not None
verify_read(testKey, value)
print(f"Read key {testKey}, got {value.hex()[:8]}[...]")
# delete testKey from the bucket, and localData.
bucket.delete_key(testKey)
local_keys.remove(testKey)
value = bucket.private_read([testKey])[0]
def _test_delete(key: str, value: Optional[bytes]):
if value is None:
print(f"Deleted key {key}")
else:
# this happens only sometimes??
print("ERROR: delete not reflected in read!")
print(f"Read deleted key {key} and got {value.hex()[:8]}[...]")
_test_delete(testKey, value)
# clear all keys
bucket.clear_entire_bucket()
local_keys = []
print("Cleared bucket")
# write a new set of N keys
local_keys = generate_keys(N, 2)
bucket.write({k: key_to_gold_value(k, itemSize) for k in local_keys})
print(f"Wrote {N} keys")
# read a random key
testKey = random.choice(local_keys)
value = bucket.private_read([testKey])[0]
assert value is not None
verify_read(testKey, value)
# rename the bucket
new_bucket_name = bucket_name + "-rn"
bucket.rename(new_bucket_name)
print("Renamed bucket")
print(bucket.info())
# read a random key
testKey = random.choice(local_keys)
value = bucket.private_read([testKey])[0]
assert value is not None
verify_read(testKey, value)
print(f"Read key {testKey}")
# destroy the bucket
bucket.destroy_entire_bucket()
print("Destroyed bucket")
if __name__ == "__main__":
import asyncio
api_key = os.environ.get("BLYSS_STAGING_API_KEY", None)
endpoint = os.environ.get("BLYSS_STAGING_SERVER", None)
if len(sys.argv) > 1:
print("Using endpoint from command line")
endpoint = sys.argv[1]
if len(sys.argv) > 2:
print("Using api_key from command line")
api_key = sys.argv[2]
if api_key == "none":
api_key = None
print("DEBUG", api_key, endpoint)
assert endpoint is not None
assert api_key is not None
print(f"testing Blyss endpoint at {endpoint}")
asyncio.run(test_e2e_async(endpoint, api_key))
print("async ✅")
test_e2e(endpoint, api_key)
print("sync ✅")