Skip to content

Commit e3b37f1

Browse files
authored
Fix 1757 (#1758)
* add audit file for branch * Replace time.clock() with time.perf_counter() in slowsquare examples Fixes #1757 time.clock() was removed in Python 3.8 in favor of time.perf_counter(). This commit updates the slowsquare RPC examples to use the modern API. Changes: - examples/twisted/wamp/rpc/slowsquare/frontend.py: 3 replacements - examples/asyncio/wamp/rpc/slowsquare/frontend.py: 3 replacements time.perf_counter() provides a monotonic clock with the best available resolution for measuring performance, which is the intended behavior for timing RPC call durations. Tested with: just test-integration-ab-examples from crossbar repository * Enhance test runner with comprehensive result summary Add detailed test result reporting with categorization: - Individual example results with ✓/✗ symbols - Aggregation by backend (twisted/asyncio) with pass/fail counts - Aggregation by WAMP feature (overview/pubsub/rpc) with pass/fail counts - Color-coded output (green for pass, red for fail) - Overall summary with total test counts New functions: - categorize_example(): Parse example paths to determine backend and feature type - print_summary(): Display comprehensive test results with categorization Benefits: - Better visibility into test coverage - Easy identification of failures by category - Clear summary statistics for CI/CD integration Fixes #1757
1 parent 7a58118 commit e3b37f1

File tree

4 files changed

+149
-33
lines changed

4 files changed

+149
-33
lines changed

.audit/oberstet_fix_1757.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- [ ] I did **not** use any AI-assistance tools to help create this pull request.
2+
- [x] I **did** use AI-assistance tools to *help* create this pull request.
3+
- [x] I have read, understood and followed the projects' [AI Policy](https://github.com/crossbario/autobahn-python/blob/main/AI_POLICY.md) when creating code, documentation etc. for this pull request.
4+
5+
Submitted by: @oberstet
6+
Date: 2025-11-10
7+
Related issue(s): #1757
8+
Branch: oberstet:fix_1757

examples/asyncio/wamp/rpc/slowsquare/frontend.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ class Component(ApplicationSession):
4040
async def onJoin(self, details):
4141
def got(started, msg, f):
4242
res = f.result()
43-
duration = 1000.0 * (time.clock() - started)
43+
duration = 1000.0 * (time.perf_counter() - started)
4444
print("{}: {} in {}".format(msg, res, duration))
4545

46-
t1 = time.clock()
46+
t1 = time.perf_counter()
4747
d1 = self.call("com.math.slowsquare", 3, 2)
4848
d1.add_done_callback(partial(got, t1, "Slow Square"))
4949

50-
t2 = time.clock()
50+
t2 = time.perf_counter()
5151
d2 = self.call("com.math.square", 3)
5252
d2.add_done_callback(partial(got, t2, "Quick Square"))
5353

examples/run-all-examples.py

Lines changed: 135 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,93 @@ def print_banner(title):
133133
print()
134134

135135

136+
def categorize_example(example_path):
137+
"""Categorize an example by backend and feature type."""
138+
if example_path.startswith("./twisted/"):
139+
backend = "twisted"
140+
path = example_path[len("./twisted/"):]
141+
elif example_path.startswith("./asyncio/"):
142+
backend = "asyncio"
143+
path = example_path[len("./asyncio/"):]
144+
else:
145+
backend = "unknown"
146+
path = example_path
147+
148+
if path.startswith("wamp/overview"):
149+
feature = "overview"
150+
elif path.startswith("wamp/pubsub/"):
151+
feature = "pubsub"
152+
elif path.startswith("wamp/rpc/"):
153+
feature = "rpc"
154+
else:
155+
feature = "unknown"
156+
157+
return backend, feature
158+
159+
160+
def print_summary(results):
161+
"""Print comprehensive test summary with categorization."""
162+
print()
163+
print("=" * 80)
164+
print("Test Results Summary")
165+
print("=" * 80)
166+
print()
167+
168+
# Count totals
169+
total = len(results)
170+
passed = sum(1 for r in results if r["passed"])
171+
failed = total - passed
172+
173+
# Print individual results
174+
print("Individual Examples:")
175+
print("-" * 80)
176+
for result in results:
177+
status_symbol = "✓" if result["passed"] else "✗"
178+
status_color = Fore.GREEN if result["passed"] else Fore.RED
179+
print(f"{status_color}{status_symbol}{Fore.RESET} {result['backend']:8s} {result['feature']:8s} {result['path']}")
180+
print()
181+
182+
# Aggregate by backend
183+
print("By Backend:")
184+
print("-" * 80)
185+
for backend in ["twisted", "asyncio"]:
186+
backend_results = [r for r in results if r["backend"] == backend]
187+
if backend_results:
188+
backend_passed = sum(1 for r in backend_results if r["passed"])
189+
backend_total = len(backend_results)
190+
backend_failed = backend_total - backend_passed
191+
status_symbol = "✓" if backend_failed == 0 else "✗"
192+
status_color = Fore.GREEN if backend_failed == 0 else Fore.RED
193+
print(f"{status_color}{status_symbol}{Fore.RESET} {backend:8s}: {backend_passed}/{backend_total} passed, {backend_failed} failed")
194+
print()
195+
196+
# Aggregate by feature
197+
print("By WAMP Feature:")
198+
print("-" * 80)
199+
for feature in ["overview", "pubsub", "rpc"]:
200+
feature_results = [r for r in results if r["feature"] == feature]
201+
if feature_results:
202+
feature_passed = sum(1 for r in feature_results if r["passed"])
203+
feature_total = len(feature_results)
204+
feature_failed = feature_total - feature_passed
205+
status_symbol = "✓" if feature_failed == 0 else "✗"
206+
status_color = Fore.GREEN if feature_failed == 0 else Fore.RED
207+
print(f"{status_color}{status_symbol}{Fore.RESET} {feature:8s}: {feature_passed}/{feature_total} passed, {feature_failed} failed")
208+
print()
209+
210+
# Overall summary
211+
print("=" * 80)
212+
if failed == 0:
213+
print(f"{Fore.GREEN}✓ ALL TESTS PASSED{Fore.RESET}")
214+
print(f" Total: {passed}/{total} examples completed successfully")
215+
else:
216+
print(f"{Fore.RED}✗ SOME TESTS FAILED{Fore.RESET}")
217+
print(f" Passed: {passed}/{total}")
218+
print(f" Failed: {failed}/{total}")
219+
print("=" * 80)
220+
print()
221+
222+
136223
@inlineCallbacks
137224
def main(reactor):
138225
colorama.init()
@@ -175,9 +262,12 @@ def main(reactor):
175262
if cb_proto.all_done.called:
176263
raise RuntimeError("crossbar exited already")
177264

178-
success = True
265+
results = []
266+
overall_success = True
267+
179268
for exdir in examples:
180269
py = sys.executable
270+
original_exdir = exdir
181271
if exdir.startswith("py3 "):
182272
exdir = exdir[4:]
183273
if sys.version_info.major < 3:
@@ -190,28 +280,45 @@ def main(reactor):
190280
continue
191281

192282
print_banner("Running example: " + exdir)
193-
print(" starting backend")
194-
back_proto = yield start_example(backend, Fore.GREEN, " backend: ", exe=py)
195-
yield sleep(1)
196-
print(" starting frontend")
197-
front_proto = yield start_example(frontend, Fore.BLUE, "frontend: ", exe=py)
198-
yield sleep(3)
199-
200-
for p in [back_proto, front_proto]:
201-
try:
202-
if p.all_done.called:
203-
yield p.all_done
204-
except Exception as e:
205-
print("FAILED:", e)
206-
success = False
207-
208-
for p in [front_proto, back_proto]:
209-
try:
210-
p.transport.signalProcess("KILL")
211-
except ProcessExitedAlready:
212-
pass
213-
214-
if not success:
283+
284+
example_passed = True
285+
try:
286+
print(" starting backend")
287+
back_proto = yield start_example(backend, Fore.GREEN, " backend: ", exe=py)
288+
yield sleep(1)
289+
print(" starting frontend")
290+
front_proto = yield start_example(frontend, Fore.BLUE, "frontend: ", exe=py)
291+
yield sleep(3)
292+
293+
for p in [back_proto, front_proto]:
294+
try:
295+
if p.all_done.called:
296+
yield p.all_done
297+
except Exception as e:
298+
print("FAILED:", e)
299+
example_passed = False
300+
overall_success = False
301+
302+
for p in [front_proto, back_proto]:
303+
try:
304+
p.transport.signalProcess("KILL")
305+
except ProcessExitedAlready:
306+
pass
307+
except Exception as e:
308+
print("EXCEPTION:", e)
309+
example_passed = False
310+
overall_success = False
311+
312+
# Record result
313+
backend_type, feature_type = categorize_example(exdir)
314+
results.append({
315+
"path": exdir,
316+
"backend": backend_type,
317+
"feature": feature_type,
318+
"passed": example_passed
319+
})
320+
321+
if not overall_success:
215322
break
216323
yield sleep(1)
217324

@@ -221,10 +328,11 @@ def main(reactor):
221328
yield cb_proto.all_done
222329
except:
223330
pass
224-
if success:
225-
print()
226-
print("Success!")
227-
print(" ...all the examples neither crashed nor burned...")
331+
332+
# Print comprehensive summary
333+
print_summary(results)
334+
335+
if overall_success:
228336
return 0
229337
return 5
230338

examples/twisted/wamp/rpc/slowsquare/frontend.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ def onJoin(self, details):
4141
print("session attached")
4242

4343
def got(res, started, msg):
44-
duration = 1000.0 * (time.clock() - started)
44+
duration = 1000.0 * (time.perf_counter() - started)
4545
print("{}: {} in {}".format(msg, res, duration))
4646

47-
t1 = time.clock()
47+
t1 = time.perf_counter()
4848
d1 = self.call("com.math.slowsquare", 3)
4949
d1.addCallback(got, t1, "Slow Square")
5050

51-
t2 = time.clock()
51+
t2 = time.perf_counter()
5252
d2 = self.call("com.math.square", 3)
5353
d2.addCallback(got, t2, "Quick Square")
5454

0 commit comments

Comments
 (0)