zupt/sdk/tests/test_python.py
Cristian Cezar Moisés e5f5d32aab v2.2.2
2026-05-01 09:58:47 -03:00

122 lines
3.7 KiB
Python

#!/usr/bin/env python3
"""
zuptsdk Python binding test
SPDX-License-Identifier: AGPL-3.0-or-later
"""
import os
import sys
import tempfile
# Add path so we can import without installing
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
os.environ.setdefault("ZUPTSDK_LIBRARY",
os.path.join(os.path.dirname(__file__), "..", "..", "build", "libzuptsdk.so.1"))
import zuptsdk
PASS = 0
FAIL = 0
def test(name, fn):
global PASS, FAIL
try:
fn()
print(f" {name:<60} PASS")
PASS += 1
except Exception as e:
print(f" {name:<60} FAIL: {e!r}")
FAIL += 1
print(f"\n zuptsdk Python bindings — version {zuptsdk.__version__}\n")
DATA = b"Hello world from Python via cffi!\n" * 10
def t_version():
assert zuptsdk.__version__ == "1.0.0", f"got {zuptsdk.__version__}"
def t_roundtrip_plain():
with zuptsdk.Context() as ctx:
arc = ctx.compress_buffer(DATA, name="hello.txt")
assert isinstance(arc, bytes)
assert len(arc) > 0
out = ctx.extract_buffer(arc)
assert out == DATA
def t_roundtrip_password():
with zuptsdk.Context() as ctx:
arc = ctx.compress_buffer(DATA, name="secret.txt",
password=b"correct horse battery staple")
out = ctx.extract_buffer(arc, password=b"correct horse battery staple")
assert out == DATA
def t_wrong_password():
with zuptsdk.Context() as ctx:
arc = ctx.compress_buffer(DATA, name="x.txt", password=b"good")
try:
ctx.extract_buffer(arc, password=b"bad")
except zuptsdk.ZuptError:
return
raise AssertionError("wrong password was accepted")
def t_secure_buf_password():
with zuptsdk.Context() as ctx, zuptsdk.SecureBuf(b"locked-pw") as pw:
arc = ctx.compress_buffer(DATA, name="x.txt", password=pw)
out = ctx.extract_buffer(arc, password=pw)
assert out == DATA
def t_pq_keypair():
with zuptsdk.Context() as ctx:
kp = ctx.generate_keypair()
with tempfile.TemporaryDirectory() as td:
kp.save(os.path.join(td, "mykey"))
arc = ctx.compress_buffer(DATA, name="pq.txt", public_key=kp.public)
out = ctx.extract_buffer(arc, private_key=kp.private)
assert out == DATA
def t_verify_and_info():
with zuptsdk.Context() as ctx:
arc = ctx.compress_buffer(DATA, name="v.txt")
assert ctx.verify(arc) is True
info = ctx.info(arc)
assert info.format_major >= 1
assert info.is_encrypted is False
assert len(info.uuid) == 36, info.uuid
def t_corrupted_archive():
with zuptsdk.Context() as ctx:
# Use enough data that flipping a byte mid-stream lands in the
# compressed payload, not in a zero-padded region.
big = DATA * 100
arc = bytearray(ctx.compress_buffer(big, name="c.txt"))
# Flip a byte two-thirds of the way through — well into compressed
# data, well before the index/footer.
if len(arc) > 200:
offset = (len(arc) * 2) // 3
arc[offset] ^= 0xFF
try:
ctx.verify(bytes(arc))
except zuptsdk.ZuptError:
return
raise AssertionError("corrupted archive accepted")
test("version constant", t_version)
test("roundtrip plain", t_roundtrip_plain)
test("roundtrip password (bytes)", t_roundtrip_password)
test("wrong password rejected", t_wrong_password)
test("roundtrip with SecureBuf", t_secure_buf_password)
test("PQ keypair generate + roundtrip", t_pq_keypair)
test("verify and info", t_verify_and_info)
test("corrupted archive rejected", t_corrupted_archive)
print(f"\n Results: {PASS} passed, {FAIL} failed\n")
sys.exit(0 if FAIL == 0 else 1)