From 96cd57321cd003dee49dc7688ba081ffbadc0037 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 17:07:37 +0000 Subject: [PATCH 1/3] Initial plan From 06f12ac81ae3aa92b0e0cefe643f2aba02d34b99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 17:21:40 +0000 Subject: [PATCH 2/3] Add load tests for expansion analyzers Co-authored-by: jackfirth <8175575+jackfirth@users.noreply.github.com> --- test/analyzer-load-test.rkt | 165 ++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 test/analyzer-load-test.rkt diff --git a/test/analyzer-load-test.rkt b/test/analyzer-load-test.rkt new file mode 100644 index 0000000..a606358 --- /dev/null +++ b/test/analyzer-load-test.rkt @@ -0,0 +1,165 @@ +#lang racket/base + +(require racket/contract/base + racket/string + rackunit + resyntax/default-recommendations/analyzers/identifier-usage + resyntax/default-recommendations/analyzers/variable-mutability + resyntax/default-recommendations/analyzers/ignored-result-values + resyntax/default-recommendations/analyzers/function-expression-analyzer + resyntax/private/analysis + resyntax/private/source) + +;; Load tests for expansion analyzers to ensure they can handle large files +;; within reasonable timeouts. These tests are designed to catch severe +;; performance regressions where analyzers would take minutes or hang on +;; moderately large files. + +(define timeout-ms 30000) ; 30 second timeout for load tests + +;; Generate a large test file with many definitions and function calls. +;; This creates a file with approximately 300+ lines of code with various +;; constructs that analyzers need to process. The file is large enough to +;; exercise analyzer performance but small enough to complete in reasonable time. +(define (generate-large-test-program) + (string-join + (append + (list "#lang racket/base" + "" + "(require racket/list racket/string)" + "") + ;; Generate many function definitions + (for/list ([i (in-range 25)]) + (format "(define (func~a x y) + (let ([a (+ x y)] + [b (* x y)]) + (if (> a b) + (+ a b) + (* a b))))" i)) + (list "") + ;; Generate many variable definitions + (for/list ([i (in-range 30)]) + (format "(define var~a ~a)" i i)) + (list "") + ;; Generate many mutable variables with assignments + (for/list ([i (in-range 20)]) + (format "(define mut~a 0) +(set! mut~a ~a)" i i i)) + (list "") + ;; Generate function calls with various patterns + (for/list ([i (in-range 25)]) + (format "(void (func~a var~a (+ var~a ~a)))" + (modulo i 25) + (modulo i 30) + (modulo (+ i 1) 30) + i)) + (list "") + ;; Generate nested expressions with ignored results + (for/list ([i (in-range 15)]) + (format "(begin + (+ ~a ~a) + (void ~a))" i (+ i 1) i))) + "\n")) + +(define large-test-source (string-source (generate-large-test-program))) + +(test-case "identifier-usage-analyzer load test" + ;; This test ensures the identifier-usage-analyzer can analyze a large file + ;; within the timeout period. + (define start-time (current-inexact-milliseconds)) + (define analysis + (source-analyze large-test-source + #:analyzers (list identifier-usage-analyzer) + #:timeout-ms timeout-ms)) + (define elapsed-ms (- (current-inexact-milliseconds) start-time)) + + ;; Verify the analysis completed successfully + (check-true (source-code-analysis? analysis)) + + ;; Verify it completed within the timeout (with some margin) + (check-true (< elapsed-ms timeout-ms) + (format "identifier-usage-analyzer took ~a ms, expected < ~a ms" + elapsed-ms + timeout-ms))) + +(test-case "variable-mutability-analyzer load test" + ;; This test ensures the variable-mutability-analyzer can analyze a large file + ;; within the timeout period. + (define start-time (current-inexact-milliseconds)) + (define analysis + (source-analyze large-test-source + #:analyzers (list variable-mutability-analyzer) + #:timeout-ms timeout-ms)) + (define elapsed-ms (- (current-inexact-milliseconds) start-time)) + + ;; Verify the analysis completed successfully + (check-true (source-code-analysis? analysis)) + + ;; Verify it completed within the timeout (with some margin) + (check-true (< elapsed-ms timeout-ms) + (format "variable-mutability-analyzer took ~a ms, expected < ~a ms" + elapsed-ms + timeout-ms))) + +(test-case "ignored-result-values-analyzer load test" + ;; This test ensures the ignored-result-values-analyzer can analyze a large file + ;; within the timeout period. + (define start-time (current-inexact-milliseconds)) + (define analysis + (source-analyze large-test-source + #:analyzers (list ignored-result-values-analyzer) + #:timeout-ms timeout-ms)) + (define elapsed-ms (- (current-inexact-milliseconds) start-time)) + + ;; Verify the analysis completed successfully + (check-true (source-code-analysis? analysis)) + + ;; Verify it completed within the timeout (with some margin) + (check-true (< elapsed-ms timeout-ms) + (format "ignored-result-values-analyzer took ~a ms, expected < ~a ms" + elapsed-ms + timeout-ms))) + +(test-case "function-expression-analyzer load test" + ;; This test ensures the function-expression-analyzer can analyze a large file + ;; within the timeout period. + (define start-time (current-inexact-milliseconds)) + (define analysis + (source-analyze large-test-source + #:analyzers (list function-expression-analyzer) + #:timeout-ms timeout-ms)) + (define elapsed-ms (- (current-inexact-milliseconds) start-time)) + + ;; Verify the analysis completed successfully + (check-true (source-code-analysis? analysis)) + + ;; Verify it completed within the timeout (with some margin) + (check-true (< elapsed-ms timeout-ms) + (format "function-expression-analyzer took ~a ms, expected < ~a ms" + elapsed-ms + timeout-ms))) + +(test-case "all analyzers together load test" + ;; This test ensures all analyzers can work together on a large file + ;; within the timeout period. + (define all-analyzers + (list identifier-usage-analyzer + variable-mutability-analyzer + ignored-result-values-analyzer + function-expression-analyzer)) + + (define start-time (current-inexact-milliseconds)) + (define analysis + (source-analyze large-test-source + #:analyzers all-analyzers + #:timeout-ms timeout-ms)) + (define elapsed-ms (- (current-inexact-milliseconds) start-time)) + + ;; Verify the analysis completed successfully + (check-true (source-code-analysis? analysis)) + + ;; Verify it completed within the timeout (with some margin) + (check-true (< elapsed-ms timeout-ms) + (format "all analyzers together took ~a ms, expected < ~a ms" + elapsed-ms + timeout-ms))) From 1ab6849e445b4488610e4dda955cc5e0b5c68e50 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 14 Nov 2025 07:59:15 +0000 Subject: [PATCH 3/3] Fix analyzer load tests per review feedback - Wrap everything in (module+ test ...) submodule - Use expansion-analyze directly instead of source-analyze - Use time-apply to measure timing - Expand syntax once and reuse for all tests - Remove "all analyzers together" test Co-authored-by: jackfirth <8175575+jackfirth@users.noreply.github.com> --- test/analyzer-load-test.rkt | 245 +++++++++++++++--------------------- 1 file changed, 99 insertions(+), 146 deletions(-) diff --git a/test/analyzer-load-test.rkt b/test/analyzer-load-test.rkt index a606358..74cd9fe 100644 --- a/test/analyzer-load-test.rkt +++ b/test/analyzer-load-test.rkt @@ -1,165 +1,118 @@ #lang racket/base -(require racket/contract/base - racket/string - rackunit - resyntax/default-recommendations/analyzers/identifier-usage - resyntax/default-recommendations/analyzers/variable-mutability - resyntax/default-recommendations/analyzers/ignored-result-values - resyntax/default-recommendations/analyzers/function-expression-analyzer - resyntax/private/analysis - resyntax/private/source) -;; Load tests for expansion analyzers to ensure they can handle large files -;; within reasonable timeouts. These tests are designed to catch severe -;; performance regressions where analyzers would take minutes or hang on -;; moderately large files. +(module+ test + (require racket/string + rackunit + resyntax/default-recommendations/analyzers/identifier-usage + resyntax/default-recommendations/analyzers/variable-mutability + resyntax/default-recommendations/analyzers/ignored-result-values + resyntax/default-recommendations/analyzers/function-expression-analyzer + resyntax/private/analyzer + resyntax/private/source) -(define timeout-ms 30000) ; 30 second timeout for load tests + ;; Load tests for expansion analyzers to ensure they can handle large files + ;; within reasonable timeouts. These tests are designed to catch severe + ;; performance regressions where analyzers would take minutes or hang on + ;; moderately large files. -;; Generate a large test file with many definitions and function calls. -;; This creates a file with approximately 300+ lines of code with various -;; constructs that analyzers need to process. The file is large enough to -;; exercise analyzer performance but small enough to complete in reasonable time. -(define (generate-large-test-program) - (string-join - (append - (list "#lang racket/base" - "" - "(require racket/list racket/string)" - "") - ;; Generate many function definitions - (for/list ([i (in-range 25)]) - (format "(define (func~a x y) + (define timeout-ms 30000) ; 30 second timeout for load tests + + ;; Generate a large test file with many definitions and function calls. + ;; This creates a file with approximately 300+ lines of code with various + ;; constructs that analyzers need to process. The file is large enough to + ;; exercise analyzer performance but small enough to complete in reasonable time. + (define (generate-large-test-program) + (string-join + (append + (list "#lang racket/base" + "" + "(require racket/list racket/string)" + "") + ;; Generate many function definitions + (for/list ([i (in-range 25)]) + (format "(define (func~a x y) (let ([a (+ x y)] [b (* x y)]) (if (> a b) (+ a b) (* a b))))" i)) - (list "") - ;; Generate many variable definitions - (for/list ([i (in-range 30)]) - (format "(define var~a ~a)" i i)) - (list "") - ;; Generate many mutable variables with assignments - (for/list ([i (in-range 20)]) - (format "(define mut~a 0) + (list "") + ;; Generate many variable definitions + (for/list ([i (in-range 30)]) + (format "(define var~a ~a)" i i)) + (list "") + ;; Generate many mutable variables with assignments + (for/list ([i (in-range 20)]) + (format "(define mut~a 0) (set! mut~a ~a)" i i i)) - (list "") - ;; Generate function calls with various patterns - (for/list ([i (in-range 25)]) - (format "(void (func~a var~a (+ var~a ~a)))" - (modulo i 25) - (modulo i 30) - (modulo (+ i 1) 30) - i)) - (list "") - ;; Generate nested expressions with ignored results - (for/list ([i (in-range 15)]) - (format "(begin + (list "") + ;; Generate function calls with various patterns + (for/list ([i (in-range 25)]) + (format "(void (func~a var~a (+ var~a ~a)))" + (modulo i 25) + (modulo i 30) + (modulo (+ i 1) 30) + i)) + (list "") + ;; Generate nested expressions with ignored results + (for/list ([i (in-range 15)]) + (format "(begin (+ ~a ~a) (void ~a))" i (+ i 1) i))) - "\n")) + "\n")) -(define large-test-source (string-source (generate-large-test-program))) + (define large-test-source (string-source (generate-large-test-program))) -(test-case "identifier-usage-analyzer load test" - ;; This test ensures the identifier-usage-analyzer can analyze a large file - ;; within the timeout period. - (define start-time (current-inexact-milliseconds)) - (define analysis - (source-analyze large-test-source - #:analyzers (list identifier-usage-analyzer) - #:timeout-ms timeout-ms)) - (define elapsed-ms (- (current-inexact-milliseconds) start-time)) - - ;; Verify the analysis completed successfully - (check-true (source-code-analysis? analysis)) - - ;; Verify it completed within the timeout (with some margin) - (check-true (< elapsed-ms timeout-ms) - (format "identifier-usage-analyzer took ~a ms, expected < ~a ms" - elapsed-ms - timeout-ms))) + ;; Expand the test source once and reuse for all tests + (define expanded-syntax + (parameterize ([current-namespace (make-base-namespace)]) + (source-expand large-test-source))) -(test-case "variable-mutability-analyzer load test" - ;; This test ensures the variable-mutability-analyzer can analyze a large file - ;; within the timeout period. - (define start-time (current-inexact-milliseconds)) - (define analysis - (source-analyze large-test-source - #:analyzers (list variable-mutability-analyzer) - #:timeout-ms timeout-ms)) - (define elapsed-ms (- (current-inexact-milliseconds) start-time)) - - ;; Verify the analysis completed successfully - (check-true (source-code-analysis? analysis)) - - ;; Verify it completed within the timeout (with some margin) - (check-true (< elapsed-ms timeout-ms) - (format "variable-mutability-analyzer took ~a ms, expected < ~a ms" - elapsed-ms - timeout-ms))) + (test-case "identifier-usage-analyzer load test" + ;; This test ensures the identifier-usage-analyzer can analyze a large file + ;; within the timeout period. + (define-values (result cpu-time real-time gc-time) + (time-apply expansion-analyze (list identifier-usage-analyzer expanded-syntax))) + + ;; Verify it completed within the timeout + (check-true (< real-time timeout-ms) + (format "identifier-usage-analyzer took ~a ms, expected < ~a ms" + real-time + timeout-ms))) -(test-case "ignored-result-values-analyzer load test" - ;; This test ensures the ignored-result-values-analyzer can analyze a large file - ;; within the timeout period. - (define start-time (current-inexact-milliseconds)) - (define analysis - (source-analyze large-test-source - #:analyzers (list ignored-result-values-analyzer) - #:timeout-ms timeout-ms)) - (define elapsed-ms (- (current-inexact-milliseconds) start-time)) - - ;; Verify the analysis completed successfully - (check-true (source-code-analysis? analysis)) - - ;; Verify it completed within the timeout (with some margin) - (check-true (< elapsed-ms timeout-ms) - (format "ignored-result-values-analyzer took ~a ms, expected < ~a ms" - elapsed-ms - timeout-ms))) + (test-case "variable-mutability-analyzer load test" + ;; This test ensures the variable-mutability-analyzer can analyze a large file + ;; within the timeout period. + (define-values (result cpu-time real-time gc-time) + (time-apply expansion-analyze (list variable-mutability-analyzer expanded-syntax))) + + ;; Verify it completed within the timeout + (check-true (< real-time timeout-ms) + (format "variable-mutability-analyzer took ~a ms, expected < ~a ms" + real-time + timeout-ms))) -(test-case "function-expression-analyzer load test" - ;; This test ensures the function-expression-analyzer can analyze a large file - ;; within the timeout period. - (define start-time (current-inexact-milliseconds)) - (define analysis - (source-analyze large-test-source - #:analyzers (list function-expression-analyzer) - #:timeout-ms timeout-ms)) - (define elapsed-ms (- (current-inexact-milliseconds) start-time)) - - ;; Verify the analysis completed successfully - (check-true (source-code-analysis? analysis)) - - ;; Verify it completed within the timeout (with some margin) - (check-true (< elapsed-ms timeout-ms) - (format "function-expression-analyzer took ~a ms, expected < ~a ms" - elapsed-ms - timeout-ms))) + (test-case "ignored-result-values-analyzer load test" + ;; This test ensures the ignored-result-values-analyzer can analyze a large file + ;; within the timeout period. + (define-values (result cpu-time real-time gc-time) + (time-apply expansion-analyze (list ignored-result-values-analyzer expanded-syntax))) + + ;; Verify it completed within the timeout + (check-true (< real-time timeout-ms) + (format "ignored-result-values-analyzer took ~a ms, expected < ~a ms" + real-time + timeout-ms))) -(test-case "all analyzers together load test" - ;; This test ensures all analyzers can work together on a large file - ;; within the timeout period. - (define all-analyzers - (list identifier-usage-analyzer - variable-mutability-analyzer - ignored-result-values-analyzer - function-expression-analyzer)) - - (define start-time (current-inexact-milliseconds)) - (define analysis - (source-analyze large-test-source - #:analyzers all-analyzers - #:timeout-ms timeout-ms)) - (define elapsed-ms (- (current-inexact-milliseconds) start-time)) - - ;; Verify the analysis completed successfully - (check-true (source-code-analysis? analysis)) - - ;; Verify it completed within the timeout (with some margin) - (check-true (< elapsed-ms timeout-ms) - (format "all analyzers together took ~a ms, expected < ~a ms" - elapsed-ms - timeout-ms))) + (test-case "function-expression-analyzer load test" + ;; This test ensures the function-expression-analyzer can analyze a large file + ;; within the timeout period. + (define-values (result cpu-time real-time gc-time) + (time-apply expansion-analyze (list function-expression-analyzer expanded-syntax))) + + ;; Verify it completed within the timeout + (check-true (< real-time timeout-ms) + (format "function-expression-analyzer took ~a ms, expected < ~a ms" + real-time + timeout-ms))))