Skip to content

Commit 75efb1e

Browse files
committed
Rewrite tests using recspecs
Use recspecs expect form to test gcstats output format. Normalize numbers and whitespace for stable comparison.
1 parent dcf65d6 commit 75efb1e

4 files changed

Lines changed: 66 additions & 30 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@ jobs:
1919
version: ${{ matrix.racket-version }}
2020
- name: Install package
2121
run: raco pkg install --auto --name gcstats
22+
- name: Check package dependencies
23+
run: raco setup --check-pkg-deps --pkgs gcstats
2224
- name: Run tests
2325
run: raco test gcstats

gcstats/tests/core-test.rkt

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,63 @@
1-
#lang racket/base
1+
#lang at-exp racket/base
22

3-
(require rackunit
4-
racket/system
5-
racket/port
3+
(require recspecs
4+
recspecs/shell
5+
racket/runtime-path
6+
racket/format
67
racket/string)
78

8-
;; Test that gcstats runs and produces expected output format
9-
(define output
10-
(with-output-to-string
11-
(lambda ()
12-
(parameterize ([current-error-port (current-output-port)])
13-
;; Run a simple program that allocates memory to trigger GC
14-
(system "racket -l gcstats -e '(for ([i 100000]) (cons i i))'")))))
15-
16-
;; Check that output contains expected sections
17-
(check-true (string-contains? output "bytes allocated in the heap")
18-
"Output should contain allocation info")
19-
(check-true (string-contains? output "bytes collected by GC")
20-
"Output should contain collection info")
21-
(check-true (string-contains? output "bytes max heap size")
22-
"Output should contain max heap size")
23-
(check-true (string-contains? output "INIT time")
24-
"Output should contain init time")
25-
(check-true (string-contains? output "MUT time")
26-
"Output should contain mutator time")
27-
(check-true (string-contains? output "GC time")
28-
"Output should contain GC time")
29-
(check-true (string-contains? output "TOTAL time")
30-
"Output should contain total time")
31-
(check-true (string-contains? output "Alloc rate")
32-
"Output should contain allocation rate")
9+
;; Test script that allocates memory to trigger GC
10+
(define-runtime-path test-script "test-script.rkt")
11+
12+
(define cmd (~a "racket -l gcstats -t " test-script))
13+
14+
;; Helper to extract a number from a line matching a pattern
15+
(define (extract-number pattern output)
16+
(define m (regexp-match pattern output))
17+
(and m (string->number (regexp-replace* #rx"," (cadr m) ""))))
18+
19+
;; Test that gcstats produces expected output format
20+
;; We use recspecs-output-filter to normalize numeric values and whitespace
21+
;; AND validate that key metrics are sane
22+
(parameterize ([recspecs-output-filter
23+
(lambda (s)
24+
;; Validate numeric values before normalizing
25+
(define allocated (extract-number #px"([0-9,]+) bytes allocated" s))
26+
(define collected (extract-number #px"([0-9,]+) bytes collected" s))
27+
(define max-heap (extract-number #px"([0-9,]+) bytes max heap" s))
28+
(define gc-pct (extract-number #px"%GC time +([0-9.]+)" s))
29+
30+
(unless (and allocated (> allocated 0))
31+
(error 'gcstats-test "bytes allocated should be positive, got ~a" allocated))
32+
(unless (and collected (>= collected 0))
33+
(error 'gcstats-test "bytes collected should be non-negative, got ~a" collected))
34+
(unless (and max-heap (> max-heap 0))
35+
(error 'gcstats-test "max heap should be positive, got ~a" max-heap))
36+
(unless (and gc-pct (<= gc-pct 100))
37+
(error 'gcstats-test "GC percentage should be <= 100, got ~a" gc-pct))
38+
39+
;; Replace numbers (with optional commas/decimals) with #
40+
(define no-nums (regexp-replace* #px"[0-9][0-9,]*\\.?[0-9]*" s "#"))
41+
;; Collapse multiple spaces to single space
42+
(regexp-replace* #px" +" no-nums " "))])
43+
@expect/shell[cmd]{
44+
45+
# bytes allocated in the heap
46+
# bytes collected by GC
47+
# bytes max heap size
48+
# bytes max slop
49+
# bytes peak total memory use
50+
51+
Generation #: # collections, #ms, #ms elapsed
52+
53+
INIT time # ms
54+
MUT time # ms ( # ms elapsed)
55+
GC time # ms ( # ms elapsed)
56+
TOTAL time # ms ( # ms elapsed)
57+
58+
Max pause time: # ms
59+
%GC time # % ( # % elapsed)
60+
61+
Alloc rate # bytes per MUT second
62+
63+
})

gcstats/tests/test-script.rkt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#lang racket/base
2+
;; Simple script that allocates memory to trigger GC
3+
(for ([i 100000]) (cons i i))

info.rkt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
(define collection 'multi)
44
(define deps '("base"))
5-
(define build-deps '("scribble-lib" "racket-doc" "rackunit-lib"))
5+
(define build-deps '("scribble-lib" "racket-doc" "at-exp-lib" "recspecs-lib"))

0 commit comments

Comments
 (0)