Files
LithosAnanake/src/test_runner/modules/stress_tests.c
T
Robert Allan JamesandClaude Sonnet 5 bf59c4916e Fix systemic -Wmissing-field-initializers across src/test_runner/modules/ (3010 -> 0)
TestCase gained a trailing `contract` field (WordContract) at some point
after all 20 test-module files' compound literals were written -- every
single TestCase/WordTestSuite initializer in the tree (sentinels, real
entries, and per-suite entries) omitted it, producing ~3010 warnings on
every build. CLAUDE.md's own documentation claimed this was isolated to
one file (vocabulary_words_test.c); a full audit found it systemic
across all 20 files.

Fixed mechanically: added the missing `{0}` trailing initializer
everywhere. Semantically a no-op -- C99 already zero-fills unlisted
trailing struct fields, so this only silences the diagnostic, changes
no behavior. Verified: all three architectures (amd64/aarch64/riscv64)
build clean, remaining warning count unchanged (30, matching the other
three known -Wno-error-exempted classes: unused-parameter, sign-compare,
plus mkcapsule.c's stringop-truncation which was never actually gated
by this policy -- it's a separate host tool with no -Werror at all).

.claude/CLAUDE.md corrected to describe the actual -Wno-error= exemption
list (four classes, not "build with -Wall -Werror" unconditionally) and
the real current warning inventory.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 21:43:30 -04:00

365 lines
15 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file stress_tests.c
* @brief FORTH-79 Standard Comprehensive Stress Testing Module
*
* This module contains extensive stress tests that verify the interpreter's behavior
* under extreme conditions while remaining within FORTH-79 standard compliance.
*
* Test categories (expanded):
* - Deep nesting of control structures (up to 5 levels)
* - Stack exhaustion and boundary tests (near-limit operations)
* - Numeric boundary conditions (cell_t min/max, overflow)
* - Dictionary pressure (many definitions, long names)
* - Word execution chains (deep call stacks)
* - Control flow edge cases (empty loops, large counts, EXIT)
* - Memory allocation patterns (fragmentation, large blocks)
* - Error recovery (ABORT, stack underflow recovery)
* - Large definitions and word chains
*
* IMPORTANT: These tests only use FORTH-79 standard words. Features from
* later standards (ANS Forth 1994, Forth 2012) are NOT tested here:
* - RECURSE (ANS Forth) - not in FORTH-79
* - Self-referential definitions - not supported in FORTH-79
* - Extended VARIABLE usage - only standard semantics tested
*
* For testing extended/non-standard features, see integration_tests.c
*/
#include <stdio.h>
#include "test_common.h"
#include "test_runner.h"
/* Comprehensive stress test suites */
static WordTestSuite stress_suites[] = {
/* ===== 1. STACK DEPTH TESTS ===== */
{
"STACK_DEPTH", {
{"deep_push", ": PUSH-100 0 100 0 DO I LOOP ; PUSH-100 DEPTH . CR", "Push 100 items", TEST_NORMAL, 0, 1, {0}},
{"deep_math", ": MATH-STRESS 1 100 0 DO 1+ LOOP . CR ; MATH-STRESS", "100 additions", TEST_NORMAL, 0, 1, {0}},
{
"dup_stress", ": DUP-STRESS 42 50 0 DO DUP LOOP DEPTH . CR 51 0 DO DROP LOOP ; DUP-STRESS", "50 DUPs",
TEST_NORMAL, 0, 1, {0}
},
{
"deep_push_200",
": PUSH-200 0 200 0 DO I LOOP ; : CLR-200 200 0 DO DROP LOOP ; PUSH-200 DEPTH . CR CLR-200",
"Push 200 items", TEST_NORMAL, 0, 1, {0}
},
{
"mixed_ops", ": MIXED 1 2 3 4 5 6 7 8 9 10 50 0 DO SWAP ROT LOOP 10 0 DO DROP LOOP ; MIXED",
"Mixed stack ops", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
5, {0}
},
/* ===== 2. STACK BOUNDARY TESTS ===== */
{
"STACK_BOUNDARY", {
{
"near_limit_900",
": PUSH-900 0 900 0 DO I LOOP ; : CLR-900 900 0 DO DROP LOOP ; PUSH-900 DEPTH . CR CLR-900 FORGET CLR-900",
"Push 900 items (near 1024 limit)", TEST_EDGE_CASE, 0, 1, {0}
},
{"underflow_detect", "DROP", "Stack underflow detection", TEST_ERROR_CASE, 1, 1, {0}},
{"dup_underflow", "DUP", "DUP underflow detection", TEST_ERROR_CASE, 1, 1, {0}},
{"swap_underflow", "1 SWAP", "SWAP underflow detection", TEST_ERROR_CASE, 1, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
4, {0}
},
/* ===== 3. RETURN STACK STRESS ===== */
{
"RETURN_STACK", {
{"basic_to_r", "1 2 3 >R >R >R R> R> R> + + . CR", "Basic >R/R> test", TEST_NORMAL, 0, 1, {0}},
{"r_fetch", "42 >R R@ . CR R> DROP", "R@ test", TEST_NORMAL, 0, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 4. DEEP NESTING TESTS ===== */
{
"DEEP_NESTING", {
{
"nested_if_5",
": NEST5 DUP 0> IF DUP 10 > IF DUP 20 > IF DUP 30 > IF DUP 40 > IF 5 ELSE 4 THEN ELSE 3 THEN ELSE 2 THEN ELSE 1 THEN ELSE 0 THEN . CR ; 45 NEST5",
"5-level IF nesting", TEST_NORMAL, 0, 1, {0}
},
{
"nested_loops_4", ": NEST-4 0 2 0 DO 2 0 DO 2 0 DO 2 0 DO 1+ LOOP LOOP LOOP LOOP . CR ; NEST-4",
"4-level DO loop nesting", TEST_NORMAL, 0, 1, {0}
},
{
"mixed_if_do", ": MIX-NEST 0 10 0> IF 5 0 DO 1+ LOOP ELSE 3 0 DO 2 + LOOP THEN . CR ; MIX-NEST",
"IF with DO inside", TEST_NORMAL, 0, 1, {0}
},
{
"begin_simple", ": BEGIN-TEST 5 BEGIN 1- DUP 0= UNTIL DROP ; BEGIN-TEST",
"Simple BEGIN/UNTIL loop", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
4, {0}
},
/* ===== 5. CONTROL FLOW EDGE CASES ===== */
{
"CONTROL_EDGE", {
{"empty_loop", ": EMPTY-LOOP 0 0 DO LOOP ; EMPTY-LOOP", "Empty loop body", TEST_NORMAL, 0, 1, {0}},
{"single_iter", ": SINGLE 1 0 DO 42 . LOOP CR ; SINGLE", "Single iteration", TEST_NORMAL, 0, 1, {0}},
{"large_count", ": BIG-LOOP 0 10000 0 DO 1+ LOOP . CR ; BIG-LOOP", "10000 iterations", TEST_NORMAL, 0, 1, {0}},
{
"nested_exit", ": NEST-EXIT 10 0 DO I 5 = IF EXIT THEN I . LOOP CR ; NEST-EXIT", "EXIT in nested loop",
TEST_NORMAL, 0, 1, {0}
},
{
"begin_while", ": B-W-R 10 BEGIN DUP 0> WHILE DUP . 1- REPEAT DROP CR ; B-W-R", "BEGIN WHILE REPEAT",
TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
5, {0}
},
/* ===== 6. NUMERIC BOUNDARIES ===== */
{
"NUMERIC_BOUNDARY", {
{"max_int", ": MAX-TEST 2147483647 DUP . 1+ . CR ; MAX-TEST", "Max int boundary", TEST_EDGE_CASE, 0, 1, {0}},
{"min_int", ": MIN-TEST -2147483648 DUP . 1- . CR ; MIN-TEST", "Min int boundary", TEST_EDGE_CASE, 0, 1, {0}},
{"large_mult", ": BIG-MULT 10000 10000 * . CR ; BIG-MULT", "Large multiplication", TEST_NORMAL, 0, 1, {0}},
{
"div_edge", ": DIV-TEST 100 1 / 100 2 / 100 3 / . . . CR ; DIV-TEST", "Division edge cases",
TEST_NORMAL, 0, 1, {0}
},
{"mod_edge", ": MOD-TEST 100 7 MOD 100 3 MOD . . CR ; MOD-TEST", "Modulo operations", TEST_NORMAL, 0, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
5, {0}
},
/* ===== 7. WORD EXECUTION CHAINS ===== */
{
"EXEC_CHAINS", {
{
"chain_10",
": C1 1 ; : C2 C1 1+ ; : C3 C2 1+ ; : C4 C3 1+ ; : C5 C4 1+ ; : C6 C5 1+ ; : C7 C6 1+ ; : C8 C7 1+ ; : C9 C8 1+ ; : C10 C9 1+ ; C10 . CR",
"10-word call chain", TEST_NORMAL, 0, 1, {0}
},
{
"chain_20",
": D1 1 ; : D2 D1 1+ ; : D3 D2 1+ ; : D4 D3 1+ ; : D5 D4 1+ ; : D6 D5 1+ ; : D7 D6 1+ ; : D8 D7 1+ ; : D9 D8 1+ ; : D10 D9 1+ ; : D11 D10 1+ ; : D12 D11 1+ ; : D13 D12 1+ ; : D14 D13 1+ ; : D15 D14 1+ ; : D16 D15 1+ ; : D17 D16 1+ ; : D18 D17 1+ ; : D19 D18 1+ ; : D20 D19 1+ ; D20 . CR",
"20-word call chain", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 8. LARGE DEFINITIONS ===== */
{
"LARGE_DEF", {
{
"long_sequence_50",
": LONG50 1 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ 1+ . CR ; LONG50",
"50+ operations", TEST_NORMAL, 0, 1, {0}
},
{
"many_literals",
": LITS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + + + + + + + + + + + + + + + + + + + . CR ; LITS",
"20 literals", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 9. DICTIONARY PRESSURE ===== */
{
"DICT_PRESSURE", {
{
"many_defs",
": T1 1 ; : T2 2 ; : T3 3 ; : T4 4 ; : T5 5 ; : T6 6 ; : T7 7 ; : T8 8 ; : T9 9 ; : T10 10 ; : T11 11 ; : T12 12 ; : T13 13 ; : T14 14 ; : T15 15 ; : T16 16 ; : T17 17 ; : T18 18 ; : T19 19 ; : T20 20 ; T20 . CR",
"20 word definitions", TEST_NORMAL, 0, 1, {0}
},
{
"long_name", ": VERY-LONG-WORD-NAME-TEST-MAX 42 . CR ; VERY-LONG-WORD-NAME-TEST-MAX",
"Long word name (31 chars)", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 10. MEMORY ALLOCATION STRESS ===== */
{
"MEMORY_STRESS", {
{
"allot_100", ": ALLOT-100 HERE 100 ALLOT HERE SWAP - . CR ; ALLOT-100", "ALLOT 100 bytes", TEST_NORMAL, 0, 1, {0}
},
{"allot_1000", ": ALLOT-1K HERE 1000 ALLOT HERE SWAP - . CR ; ALLOT-1K", "ALLOT 1KB", TEST_NORMAL, 0, 1, {0}},
{"allot_8k", ": ALLOT-8K HERE 8192 ALLOT HERE SWAP - . CR ; ALLOT-8K", "ALLOT 8KB", TEST_NORMAL, 0, 1, {0}},
{
"multiple_allots", ": MULTI-ALLOT HERE 10 ALLOT 20 ALLOT 30 ALLOT HERE SWAP - . CR ; MULTI-ALLOT",
"Multiple ALLOTs", TEST_NORMAL, 0, 1, {0}
},
{
"allot_pattern", ": PATTERN 5 0 DO HERE 100 ALLOT DROP LOOP ; PATTERN", "Repeated allot pattern",
TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
5, {0}
},
/* ===== 11. ERROR RECOVERY ===== */
{
"ERROR_RECOVERY", {
{"abort_recovery", ": AB-TEST 1 2 3 ABORT ; AB-TEST DEPTH . CR", "ABORT clears stacks", TEST_NORMAL, 0, 1, {0}},
{"continue_after_abort", "ABORT 42 . CR", "Can continue after ABORT", TEST_NORMAL, 0, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 12. DOUBLE NUMBER STRESS ===== */
{
"DOUBLE_STRESS", {
{"large_double_add", "1000000 0 2000000 0 D+ . . CR", "Large double addition", TEST_NORMAL, 0, 1, {0}},
{"double_chain", "100 200 2DUP D+ . . CR", "Double operation chain", TEST_NORMAL, 0, 1, {0}},
{"double_negate", "100 200 DNEGATE DNEGATE . . CR", "Double negate twice", TEST_NORMAL, 0, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
3, {0}
},
/* ===== 13. MIXED COMPLEXITY ===== */
{
"MIXED_COMPLEX", {
{
"nested_if_do",
": COMPLEX 10 0 DO I DUP 5 > IF 2 * ELSE 3 + THEN . LOOP CR ; COMPLEX",
"Mixed IF/DO", TEST_NORMAL, 0, 1, {0}
},
{
"nested_begin_do",
": NB-DO 5 BEGIN DUP 0> WHILE DUP 3 0 DO I . LOOP CR 1- REPEAT DROP ; NB-DO",
"Nested BEGIN/DO", TEST_NORMAL, 0, 1, {0}
},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
/* ===== 14. STRING/BUFFER EDGE CASES ===== */
{
"STRING_EDGE", {
{"empty_def", ": EMPTY ; EMPTY", "Empty definition", TEST_NORMAL, 0, 1, {0}},
{"single_word", ": SINGLE DUP ; 42 SINGLE . . CR", "Single word def", TEST_NORMAL, 0, 1, {0}},
{NULL, NULL, NULL, TEST_NORMAL, 0, 0, {0}}
},
2, {0}
},
};
/**
* @brief Execute comprehensive stress test suites
*
* Runs an extensive set of stress tests to verify the VM's behavior
* under extreme conditions. Tests include:
* - Stack operations and boundaries
* - Deep nesting and control flow
* - Numeric boundaries and overflow
* - Dictionary pressure
* - Memory allocation patterns
* - Error recovery
* - Mixed complexity scenarios
*
* All tests are FORTH-79 compliant.
*
* @param vm Pointer to the Forth virtual machine instance
*/
void run_stress_tests(VM *vm) {
if (!vm) return;
// Reset global stats for stress tests
extern TestStats global_test_stats;
global_test_stats.total_tests = 0;
global_test_stats.total_pass = 0;
global_test_stats.total_fail = 0;
global_test_stats.total_skip = 0;
global_test_stats.total_error = 0;
log_message(LOG_INFO, "==============================================");
log_message(LOG_INFO, " StarForth Comprehensive Stress Test Suite");
log_message(LOG_INFO, " FORTH-79 Standard Compliance");
log_message(LOG_INFO, "==============================================\n");
for (size_t i = 0; i < sizeof(stress_suites) / sizeof(WordTestSuite); i++) {
log_message(LOG_TEST, "▶ Testing category: %s", stress_suites[i].word_name);
run_test_suite(vm, &stress_suites[i]);
}
log_message(LOG_INFO, "==============================================");
log_message(LOG_INFO, " COMPREHENSIVE STRESS TEST RESULTS");
log_message(LOG_INFO, "==============================================");
log_message(LOG_INFO, " Total tests: %d", global_test_stats.total_tests);
log_message(LOG_INFO, " Passed: %d", global_test_stats.total_pass);
log_message(LOG_INFO, " Failed: %d", global_test_stats.total_fail);
log_message(LOG_INFO, " Skipped: %d", global_test_stats.total_skip);
log_message(LOG_INFO, " Errors: %d", global_test_stats.total_error);
if (global_test_stats.total_fail == 0 && global_test_stats.total_error == 0) {
log_message(LOG_INFO, "\n ✓ ALL STRESS TESTS PASSED!");
log_message(LOG_INFO, " StarForth demonstrates excellent stability");
log_message(LOG_INFO, " under extreme FORTH-79 workload conditions.");
} else {
log_message(LOG_INFO, "\n ✗ SOME TESTS FAILED");
log_message(LOG_INFO, " Review output above for details");
}
log_message(LOG_INFO, "==============================================\n");
}