Skip to content

Commit 7ce4f0c

Browse files
committed
Add FlatBuffers/flatc bundling support and smoke tests
Add shared flatc infrastructure from wamp-cicd: - Bump .cicd submodule to include new scripts/flatc/ files - Add src/autobahn/_flatc/ module with get_flatc_path() and run_flatc() - Add scripts/smoke_test.py and scripts/smoke_test_flatc.py - Add justfile recipes: test-smoke, test-wheel-install, test-sdist-install This syncs autobahn-python with zlmdb's FlatBuffers bundling approach, using shared code from wamp-cicd/scripts/flatc/ for DRY. Note: This work was completed with AI assistance (Claude Code).
1 parent 4e490de commit 7ce4f0c

5 files changed

Lines changed: 574 additions & 1 deletion

File tree

justfile

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,180 @@ test-serdes venv="": (install-tools venv) (install-dev venv)
11491149
examples/serdes/tests/test_interrupt.py \
11501150
examples/serdes/tests/test_eventreceived.py
11511151
1152+
# -----------------------------------------------------------------------------
1153+
# -- Smoke tests (package verification)
1154+
# -----------------------------------------------------------------------------
1155+
1156+
# Run smoke tests on an installed autobahn package (verifies FlatBuffers work)
1157+
# This is used by test-wheel-install and test-sdist-install after installation
1158+
test-smoke venv="":
1159+
#!/usr/bin/env bash
1160+
set -e
1161+
VENV_NAME="{{ venv }}"
1162+
if [ -z "${VENV_NAME}" ]; then
1163+
VENV_NAME=$(just --quiet _get-system-venv-name)
1164+
fi
1165+
VENV_PYTHON=$(just --quiet _get-venv-python "${VENV_NAME}")
1166+
VENV_PATH="{{ VENV_DIR }}/${VENV_NAME}"
1167+
1168+
echo "Running smoke tests with Python: $(${VENV_PYTHON} --version)"
1169+
echo "Venv: ${VENV_PATH}"
1170+
echo ""
1171+
1172+
# Run the smoke test Python script
1173+
${VENV_PYTHON} "{{ PROJECT_DIR }}/scripts/smoke_test.py"
1174+
1175+
# Test installing and verifying a built wheel (used in CI for artifact verification)
1176+
# Usage: just test-wheel-install /path/to/autobahn-*.whl
1177+
test-wheel-install wheel_path:
1178+
#!/usr/bin/env bash
1179+
set -e
1180+
WHEEL_PATH="{{ wheel_path }}"
1181+
1182+
if [ ! -f "${WHEEL_PATH}" ]; then
1183+
echo "ERROR: Wheel file not found: ${WHEEL_PATH}"
1184+
exit 1
1185+
fi
1186+
1187+
WHEEL_NAME=$(basename "${WHEEL_PATH}")
1188+
echo "========================================================================"
1189+
echo " WHEEL INSTALL TEST"
1190+
echo "========================================================================"
1191+
echo ""
1192+
echo "Wheel: ${WHEEL_NAME}"
1193+
echo ""
1194+
1195+
# Create ephemeral venv name based on wheel
1196+
EPHEMERAL_VENV="smoke-wheel-$$"
1197+
EPHEMERAL_PATH="{{ VENV_DIR }}/${EPHEMERAL_VENV}"
1198+
1199+
# Extract Python version from wheel filename
1200+
# Wheel format: {name}-{version}-{python tag}-{abi tag}-{platform tag}.whl
1201+
# Python tag examples: cp312, cp311, pp311, py3
1202+
PYTAG=$(echo "${WHEEL_NAME}" | sed -n 's/.*-\(cp[0-9]*\|pp[0-9]*\|py[0-9]*\)-.*/\1/p')
1203+
1204+
if [[ "${PYTAG}" =~ ^cp([0-9])([0-9]+)$ ]]; then
1205+
# CPython wheel (e.g., cp312 -> 3.12)
1206+
MAJOR="${BASH_REMATCH[1]}"
1207+
MINOR="${BASH_REMATCH[2]}"
1208+
PYTHON_SPEC="cpython-${MAJOR}.${MINOR}"
1209+
echo "Detected CPython ${MAJOR}.${MINOR} wheel"
1210+
elif [[ "${PYTAG}" =~ ^pp([0-9])([0-9]+)$ ]]; then
1211+
# PyPy wheel (e.g., pp311 -> pypy-3.11)
1212+
MAJOR="${BASH_REMATCH[1]}"
1213+
MINOR="${BASH_REMATCH[2]}"
1214+
PYTHON_SPEC="pypy-${MAJOR}.${MINOR}"
1215+
echo "Detected PyPy ${MAJOR}.${MINOR} wheel"
1216+
elif [[ "${PYTAG}" =~ ^py([0-9])$ ]]; then
1217+
# Pure Python wheel (e.g., py3) - use system Python
1218+
SYSTEM_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
1219+
PYTHON_SPEC="cpython-${SYSTEM_VERSION}"
1220+
echo "Pure Python wheel, using system Python ${SYSTEM_VERSION}"
1221+
else
1222+
# Fallback to system Python
1223+
SYSTEM_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
1224+
PYTHON_SPEC="cpython-${SYSTEM_VERSION}"
1225+
echo "Could not detect Python version from wheel, using system Python ${SYSTEM_VERSION}"
1226+
fi
1227+
1228+
echo "Creating ephemeral venv with ${PYTHON_SPEC}..."
1229+
1230+
mkdir -p "{{ VENV_DIR }}"
1231+
uv venv --seed --python "${PYTHON_SPEC}" "${EPHEMERAL_PATH}"
1232+
1233+
EPHEMERAL_PYTHON="${EPHEMERAL_PATH}/bin/python3"
1234+
1235+
# Install the wheel
1236+
echo ""
1237+
echo "Installing wheel..."
1238+
${EPHEMERAL_PYTHON} -m pip install "${WHEEL_PATH}"
1239+
1240+
# Run smoke tests
1241+
echo ""
1242+
VENV_DIR="{{ VENV_DIR }}" just test-smoke "${EPHEMERAL_VENV}"
1243+
1244+
# Cleanup
1245+
echo ""
1246+
echo "Cleaning up ephemeral venv..."
1247+
rm -rf "${EPHEMERAL_PATH}"
1248+
1249+
echo ""
1250+
echo "========================================================================"
1251+
echo "WHEEL INSTALL TEST PASSED: ${WHEEL_NAME}"
1252+
echo "========================================================================"
1253+
1254+
# Test installing and verifying a source distribution (used in CI for artifact verification)
1255+
# Usage: just test-sdist-install /path/to/autobahn-*.tar.gz
1256+
test-sdist-install sdist_path:
1257+
#!/usr/bin/env bash
1258+
set -e
1259+
SDIST_PATH="{{ sdist_path }}"
1260+
1261+
if [ ! -f "${SDIST_PATH}" ]; then
1262+
echo "ERROR: Source distribution not found: ${SDIST_PATH}"
1263+
exit 1
1264+
fi
1265+
1266+
SDIST_NAME=$(basename "${SDIST_PATH}")
1267+
echo "========================================================================"
1268+
echo " SOURCE DISTRIBUTION INSTALL TEST"
1269+
echo "========================================================================"
1270+
echo ""
1271+
echo "Source dist: ${SDIST_NAME}"
1272+
echo ""
1273+
1274+
# Check if cmake is available (required for flatc build)
1275+
if command -v cmake >/dev/null 2>&1; then
1276+
echo "cmake: $(cmake --version | head -1)"
1277+
else
1278+
echo "WARNING: cmake not found - flatc binary will not be built"
1279+
echo " Install cmake for full functionality"
1280+
fi
1281+
echo ""
1282+
1283+
# Create ephemeral venv name
1284+
EPHEMERAL_VENV="smoke-sdist-$$"
1285+
EPHEMERAL_PATH="{{ VENV_DIR }}/${EPHEMERAL_VENV}"
1286+
1287+
echo "Creating ephemeral venv: ${EPHEMERAL_VENV}..."
1288+
1289+
# Detect system Python version and create venv
1290+
SYSTEM_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')")
1291+
ENV_NAME="cpy$(echo ${SYSTEM_VERSION} | tr -d '.')"
1292+
PYTHON_SPEC="cpython-${SYSTEM_VERSION}"
1293+
1294+
mkdir -p "{{ VENV_DIR }}"
1295+
uv venv --seed --python "${PYTHON_SPEC}" "${EPHEMERAL_PATH}"
1296+
1297+
EPHEMERAL_PYTHON="${EPHEMERAL_PATH}/bin/python3"
1298+
1299+
# Install build dependencies (required for --no-build-isolation)
1300+
echo ""
1301+
echo "Installing build dependencies..."
1302+
${EPHEMERAL_PYTHON} -m pip install --no-cache-dir setuptools wheel hatchling
1303+
1304+
# Install from source distribution
1305+
# Use --no-build-isolation to allow access to system cmake for building flatc
1306+
# Use --no-cache-dir to disable HTTP download cache
1307+
# Use --no-binary autobahn to force building from source (disable wheel cache)
1308+
echo ""
1309+
echo "Installing from source distribution..."
1310+
${EPHEMERAL_PYTHON} -m pip install --no-build-isolation --no-cache-dir --no-binary autobahn "${SDIST_PATH}"
1311+
1312+
# Run smoke tests
1313+
echo ""
1314+
VENV_DIR="{{ VENV_DIR }}" just test-smoke "${EPHEMERAL_VENV}"
1315+
1316+
# Cleanup
1317+
echo ""
1318+
echo "Cleaning up ephemeral venv..."
1319+
rm -rf "${EPHEMERAL_PATH}"
1320+
1321+
echo ""
1322+
echo "========================================================================"
1323+
echo "SOURCE DISTRIBUTION INSTALL TEST PASSED: ${SDIST_NAME}"
1324+
echo "========================================================================"
1325+
11521326
# -----------------------------------------------------------------------------
11531327
# -- Documentation
11541328
# -----------------------------------------------------------------------------

scripts/smoke_test.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) typedef int GmbH, Germany, 2025. All rights reserved.
3+
#
4+
# Smoke tests for autobahn package verification.
5+
# Used by CI to verify wheels and sdists actually work after building.
6+
7+
"""
8+
Smoke tests for autobahn package.
9+
10+
This script verifies that an autobahn installation is functional by testing:
11+
1. Import autobahn and check version
12+
2. Import autobahn.websocket (WebSocket protocol)
13+
3. Import autobahn.wamp (WAMP protocol)
14+
4. Import autobahn.flatbuffers and check version (shared test)
15+
5. Verify flatc binary is available and executable (shared test)
16+
6. Verify reflection files are present (shared test)
17+
18+
ALL TESTS ARE REQUIRED. Both wheel installs and sdist installs MUST
19+
provide identical functionality including the flatc binary and
20+
reflection.bfbs file.
21+
22+
Note: FlatBuffers/flatc tests use shared functions from smoke_test_flatc.py
23+
(source: wamp-cicd/scripts/flatc/smoke_test_flatc.py)
24+
"""
25+
26+
import sys
27+
28+
# Import shared FlatBuffers test functions
29+
from smoke_test_flatc import (
30+
test_import_flatbuffers,
31+
test_flatc_binary,
32+
test_reflection_files,
33+
)
34+
35+
# Package name for shared tests
36+
PACKAGE_NAME = "autobahn"
37+
38+
39+
def test_import_autobahn():
40+
"""Test 1: Import autobahn and check version."""
41+
print("Test 1: Importing autobahn and checking version...")
42+
try:
43+
import autobahn
44+
print(f" autobahn version: {autobahn.__version__}")
45+
print(" PASS")
46+
return True
47+
except Exception as e:
48+
print(f" FAIL: Could not import autobahn: {e}")
49+
return False
50+
51+
52+
def test_import_websocket():
53+
"""Test 2: Import autobahn.websocket (WebSocket protocol)."""
54+
print("Test 2: Importing autobahn.websocket...")
55+
try:
56+
from autobahn.websocket import protocol
57+
print(" WebSocket protocol module loaded")
58+
print(" PASS")
59+
return True
60+
except Exception as e:
61+
print(f" FAIL: Could not import autobahn.websocket: {e}")
62+
return False
63+
64+
65+
def test_import_wamp():
66+
"""Test 3: Import autobahn.wamp (WAMP protocol)."""
67+
print("Test 3: Importing autobahn.wamp...")
68+
try:
69+
from autobahn.wamp import types
70+
print(" WAMP types module loaded")
71+
print(" PASS")
72+
return True
73+
except Exception as e:
74+
print(f" FAIL: Could not import autobahn.wamp: {e}")
75+
return False
76+
77+
78+
def main():
79+
"""Run all smoke tests."""
80+
print("=" * 72)
81+
print(" SMOKE TESTS - Verifying autobahn installation")
82+
print("=" * 72)
83+
print()
84+
print(f"Python: {sys.version}")
85+
print()
86+
87+
# All tests are REQUIRED - sdist MUST provide same functionality as wheels
88+
# Tests 4-6 use shared functions from smoke_test_flatc.py
89+
tests = [
90+
("Test 1", test_import_autobahn),
91+
("Test 2", test_import_websocket),
92+
("Test 3", test_import_wamp),
93+
("Test 4", lambda: test_import_flatbuffers(PACKAGE_NAME)),
94+
("Test 5", lambda: test_flatc_binary(PACKAGE_NAME)),
95+
("Test 6", lambda: test_reflection_files(PACKAGE_NAME)),
96+
]
97+
98+
failures = 0
99+
passed = 0
100+
101+
for name, test in tests:
102+
result = test()
103+
if result is True:
104+
passed += 1
105+
else:
106+
failures += 1
107+
print()
108+
109+
total = len(tests)
110+
print("=" * 72)
111+
if failures == 0:
112+
print(f"ALL SMOKE TESTS PASSED ({passed}/{total})")
113+
print("=" * 72)
114+
return 0
115+
else:
116+
print(f"SMOKE TESTS FAILED ({passed} passed, {failures} failed)")
117+
print("=" * 72)
118+
return 1
119+
120+
121+
if __name__ == "__main__":
122+
sys.exit(main())

0 commit comments

Comments
 (0)