From 9226b1bcb5ef46c8658530598d57ae22b411fe07 Mon Sep 17 00:00:00 2001 From: James Casey Date: Sat, 28 Feb 2026 14:23:54 +0000 Subject: [PATCH 1/2] style: fix lint violations in stdlib/test/ and stdlib/bootstrap-test/ BT-964 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove 1974 unnecessary trailing `.` statement separators - Remove 662 unnecessary parentheses - Remove ~47 trailing `^` on last expressions (implicit returns) - Fix 5 non-self cascade candidates (arr/bus/c receivers) - Fix multi_expr_calc.bt fixture: replace effect-free non-last expressions - Lint: skip module-level expressions in effect_free_statement check (bootstrap-test files use module-level expressions as test assertions) - Lint: exempt `self` from cascade_candidate — consecutive sends to self (e.g. BUnit assertions) should remain as separate statements for readability and debuggability Co-Authored-By: Claude Sonnet 4.6 --- .../src/lint/cascade_candidate.rs | 116 +++++---------- .../src/semantic_analysis/validators.rs | 32 +++-- stdlib/bootstrap-test/arithmetic.bt | 2 +- stdlib/bootstrap-test/array_ops.bt | 4 +- stdlib/bootstrap-test/equality.bt | 4 +- stdlib/bootstrap-test/erlang_exceptions.bt | 2 +- stdlib/bootstrap-test/errors.bt | 20 +-- stdlib/bootstrap-test/exceptions.bt | 2 +- stdlib/bootstrap-test/symbol.bt | 2 +- stdlib/test/abstract_classes_test.bt | 6 +- stdlib/test/actor_class_local_var_test.bt | 8 +- .../test/actor_conditional_mutations_test.bt | 94 ++++++------ stdlib/test/actor_coordination_test.bt | 27 ++-- stdlib/test/actor_deadlock_test.bt | 16 +-- stdlib/test/actor_lifecycle_test.bt | 34 ++--- stdlib/test/actor_local_mutations_test.bt | 36 ++--- stdlib/test/actor_message_chaining_test.bt | 40 +++--- stdlib/test/actor_non_local_return_test.bt | 52 +++---- stdlib/test/actor_self_send_collect_test.bt | 66 ++++----- stdlib/test/actor_slot_test.bt | 128 ++++++++--------- stdlib/test/architecture_doc_examples_test.bt | 8 +- stdlib/test/arithmetic_operations_test.bt | 38 ++--- stdlib/test/arithmetic_test.bt | 2 +- stdlib/test/array_test.bt | 82 +++++------ stdlib/test/association_test.bt | 38 ++--- stdlib/test/beamtalk_interface_test.bt | 2 +- stdlib/test/block_evaluation_test.bt | 20 +-- stdlib/test/blocks_test.bt | 50 +++---- stdlib/test/cast_send_test.bt | 20 +-- stdlib/test/character_test.bt | 58 ++++---- stdlib/test/class_builder_test.bt | 2 +- stdlib/test/class_hierarchy_query_test.bt | 44 +++--- stdlib/test/class_method_self_new_test.bt | 4 +- stdlib/test/class_object_dispatch_test.bt | 44 +++--- stdlib/test/class_reflection_test.bt | 42 +++--- stdlib/test/class_self_dispatch_test.bt | 2 +- stdlib/test/class_state_test.bt | 44 +++--- stdlib/test/class_variables_singleton_test.bt | 16 +-- stdlib/test/class_variables_test.bt | 14 +- stdlib/test/closures_advanced_test.bt | 70 ++++----- stdlib/test/codegen_doc_test.bt | 6 +- stdlib/test/collection_mutations_test.bt | 24 ++-- stdlib/test/collection_protocol_test.bt | 64 ++++----- stdlib/test/collections_test.bt | 136 +++++++++--------- stdlib/test/compiled_method_test.bt | 26 ++-- stdlib/test/counter_test.bt | 4 +- stdlib/test/custom_collection_test.bt | 58 ++++---- stdlib/test/custom_exceptions_test.bt | 26 ++-- stdlib/test/datetime_test.bt | 114 +++++++-------- stdlib/test/dictionary_test.bt | 68 ++++----- stdlib/test/display_string_test.bt | 32 ++--- stdlib/test/doc_test_example.bt | 6 +- stdlib/test/empty_method_self_test.bt | 10 +- stdlib/test/erlang_interop_test.bt | 40 +++--- stdlib/test/error_message_test.bt | 24 ++-- stdlib/test/error_method_test.bt | 20 +-- stdlib/test/exception_mutations_test.bt | 28 ++-- stdlib/test/field_mutations_do_test.bt | 40 +++--- stdlib/test/file_io_test.bt | 34 ++--- stdlib/test/file_stream_test.bt | 74 +++++----- stdlib/test/fixtures/abstract_shape.bt | 2 +- .../test/fixtures/actor_chaining_fixture.bt | 2 +- stdlib/test/fixtures/actor_class_local_var.bt | 10 +- stdlib/test/fixtures/actor_collect_counter.bt | 30 ++-- .../fixtures/actor_coordination_fixture.bt | 4 +- stdlib/test/fixtures/actor_nlr_basic.bt | 2 +- stdlib/test/fixtures/actor_nlr_computed.bt | 2 +- stdlib/test/fixtures/actor_nlr_local_var.bt | 2 +- stdlib/test/fixtures/actor_nlr_mutate.bt | 2 +- stdlib/test/fixtures/actor_nlr_on_do.bt | 2 +- stdlib/test/fixtures/actor_nlr_recursive.bt | 2 +- stdlib/test/fixtures/actor_slot_fixture.bt | 34 ++--- stdlib/test/fixtures/circle.bt | 2 +- stdlib/test/fixtures/class_method_self_new.bt | 4 +- stdlib/test/fixtures/class_state_actor.bt | 20 +-- .../fixtures/conditional_mutation_counter.bt | 16 +-- stdlib/test/fixtures/counter.bt | 2 +- stdlib/test/fixtures/deadlock_a.bt | 4 +- stdlib/test/fixtures/deadlock_b.bt | 6 +- stdlib/test/fixtures/error_counter.bt | 6 +- stdlib/test/fixtures/error_message_helper.bt | 8 +- stdlib/test/fixtures/event_bus_fixture.bt | 4 +- .../fixtures/field_mutation_accumulator.bt | 22 +-- .../test/fixtures/field_mutation_counter.bt | 8 +- stdlib/test/fixtures/field_mutation_nested.bt | 6 +- .../test/fixtures/hom_composability_actor.bt | 54 +++---- stdlib/test/fixtures/local_mutation_actor.bt | 58 ++++---- stdlib/test/fixtures/logging_counter.bt | 2 +- stdlib/test/fixtures/math_helper.bt | 2 +- stdlib/test/fixtures/mixed_call_site_actor.bt | 18 +-- stdlib/test/fixtures/multi_expr_calc.bt | 6 +- stdlib/test/fixtures/multi_keyword.bt | 12 +- .../test/fixtures/mutation_return_values.bt | 8 +- stdlib/test/fixtures/nlr_bar.bt | 2 +- stdlib/test/fixtures/nlr_baz.bt | 6 +- stdlib/test/fixtures/nlr_doubler.bt | 2 +- stdlib/test/fixtures/nlr_field_mutation.bt | 42 +++--- stdlib/test/fixtures/nlr_foo.bt | 2 +- stdlib/test/fixtures/nlr_nested_hom.bt | 42 +++--- stdlib/test/fixtures/nlr_on_do.bt | 4 +- stdlib/test/fixtures/nlr_return_test.bt | 2 +- stdlib/test/fixtures/nlr_skipper.bt | 2 +- .../fixtures/non_literal_callable_actor.bt | 18 +-- stdlib/test/fixtures/number_list.bt | 10 +- stdlib/test/fixtures/recursive_actor.bt | 2 +- stdlib/test/fixtures/removal_test_child.bt | 4 +- stdlib/test/fixtures/removal_test_parent.bt | 4 +- stdlib/test/fixtures/sealed_counter.bt | 4 +- stdlib/test/fixtures/self_ref_actor.bt | 6 +- stdlib/test/fixtures/string_formatter.bt | 4 +- .../test/fixtures/tier2_block_test_actor.bt | 62 ++++---- stdlib/test/fixtures/typed_account.bt | 14 +- stdlib/test/fixtures/typed_counter.bt | 4 +- stdlib/test/fixtures/typed_ledger.bt | 2 +- stdlib/test/fixtures/untyped_container.bt | 4 +- stdlib/test/fixtures/value_point.bt | 4 +- stdlib/test/fixtures/value_type_builder.bt | 22 +-- stdlib/test/future_auto_await_test.bt | 24 ++-- stdlib/test/hom_composability_test.bt | 36 ++--- stdlib/test/instance_class_var_access_test.bt | 18 +-- ...stance_class_var_access_value_type_test.bt | 18 +-- stdlib/test/integer_bitwise_test.bt | 30 ++-- stdlib/test/json_test.bt | 50 +++---- stdlib/test/keyword_messages_test.bt | 42 +++--- stdlib/test/language_features_doc_test.bt | 94 ++++++------ stdlib/test/list_literals_test.bt | 20 +-- stdlib/test/math_test.bt | 68 ++++----- stdlib/test/metaclass_test.bt | 78 +++++----- stdlib/test/method_resolver_hierarchy_test.bt | 22 +-- stdlib/test/mixed_call_site_test.bt | 22 +-- stdlib/test/mutation_return_values_test.bt | 28 ++-- stdlib/test/nested_to_do_test.bt | 8 +- stdlib/test/nil_protocol_test.bt | 54 +++---- stdlib/test/nlr_state_threading_test.bt | 108 +++++++------- stdlib/test/non_literal_callable_test.bt | 14 +- stdlib/test/number_methods_test.bt | 70 ++++----- stdlib/test/object_protocol_test.bt | 82 +++++------ stdlib/test/pattern_matching_test.bt | 28 ++-- stdlib/test/protoobject_actors_test.bt | 48 +++---- stdlib/test/protoobject_manual_test.bt | 14 +- stdlib/test/random_test.bt | 88 ++++++------ stdlib/test/recursion_test.bt | 32 ++--- stdlib/test/reflection_basic_test.bt | 38 ++--- stdlib/test/regex_test.bt | 42 +++--- stdlib/test/remove_from_system_test.bt | 18 +-- stdlib/test/runtime_doc_test.bt | 24 ++-- stdlib/test/sealed_class_test.bt | 20 +-- stdlib/test/self_reference_test.bt | 26 ++-- stdlib/test/semantic_scope_test.bt | 34 ++--- stdlib/test/set_test.bt | 88 ++++++------ stdlib/test/setup_state_test.bt | 6 +- stdlib/test/source_file_reload_test.bt | 20 +-- stdlib/test/species_test.bt | 92 ++++++------ stdlib/test/stack_frame_test.bt | 30 ++-- stdlib/test/stream_collections_test.bt | 132 ++++++++--------- stdlib/test/stream_test.bt | 112 +++++++-------- stdlib/test/string_advanced_methods_test.bt | 22 +-- stdlib/test/string_interpolation_test.bt | 42 +++--- stdlib/test/string_new_methods_test.bt | 42 +++--- stdlib/test/string_operations_test.bt | 30 ++-- stdlib/test/string_quote_escape_test.bt | 10 +- stdlib/test/system_test.bt | 38 ++--- stdlib/test/test_case_assertion_test.bt | 56 ++++---- stdlib/test/test_runner_test.bt | 24 ++-- stdlib/test/tier2_block_round_trip_test.bt | 38 ++--- stdlib/test/times_repeat_simple_test.bt | 30 ++-- stdlib/test/tuple_test.bt | 34 ++--- stdlib/test/typed_classes_test.bt | 56 ++++---- stdlib/test/unary_messages_test.bt | 58 ++++---- stdlib/test/unicode_test.bt | 30 ++-- stdlib/test/value_object_self_send_test.bt | 14 +- stdlib/test/value_object_test.bt | 110 +++++++------- stdlib/test/value_subclass_test.bt | 58 ++++---- stdlib/test/value_type_local_vars_test.bt | 12 +- stdlib/test/value_type_multi_expr_test.bt | 16 +-- .../test/value_type_non_local_return_test.bt | 28 ++-- stdlib/test/value_type_update_test.bt | 36 ++--- stdlib/test/workspace_interface_test.bt | 2 +- 178 files changed, 2641 insertions(+), 2678 deletions(-) diff --git a/crates/beamtalk-core/src/lint/cascade_candidate.rs b/crates/beamtalk-core/src/lint/cascade_candidate.rs index 53f6b9fce..0f3be82a4 100644 --- a/crates/beamtalk-core/src/lint/cascade_candidate.rs +++ b/crates/beamtalk-core/src/lint/cascade_candidate.rs @@ -22,7 +22,6 @@ //! into a single cascade receiver. use crate::ast::{Block, Expression, Identifier, Module}; -use crate::ast_walker::for_each_expr_seq; use crate::lint::LintPass; use crate::source_analysis::Diagnostic; @@ -32,7 +31,19 @@ pub(crate) struct CascadeCandidatePass; impl LintPass for CascadeCandidatePass { fn check(&self, module: &Module, diagnostics: &mut Vec) { - for_each_expr_seq(module, |seq| check_sequence(seq, diagnostics)); + // Skip module.expressions — top-level sequences are used in bootstrap-test + // files as individual test assertions (each paired with its own `// =>` + // comment). Converting those to a cascade would change the semantics + // because only the last send's result would be asserted. Only check + // method bodies and standalone method definitions. + for class in &module.classes { + for method in class.methods.iter().chain(class.class_methods.iter()) { + check_sequence(&method.body, diagnostics); + } + } + for standalone in &module.method_definitions { + check_sequence(&standalone.method.body, diagnostics); + } } } @@ -70,7 +81,13 @@ fn check_sequence(exprs: &[Expression], diagnostics: &mut Vec) { i += 1; } let run_len = i - run_start; - if run_len >= 3 { + // Skip `self` — consecutive sends to `self` in method bodies are + // typically independent assertions or setup steps (e.g. BUnit's + // `self assert:…`) that should remain as separate statements for + // readability and debuggability. Cascading them would merge + // logically-distinct operations and make test failures harder to + // isolate. + if run_len >= 3 && recv != "self" { let first_span = exprs[run_start].span(); let last_span = exprs[i - 1].span(); let span = first_span.merge(last_span); @@ -212,11 +229,7 @@ mod tests { #[test] fn three_consecutive_sends_flagged() { let diags = lint( - "Object subclass: Foo\n\ - add: arr =>\n\ - arr add: 1.\n\ - arr add: 2.\n\ - arr add: 3\n", + "Object subclass: Foo\n add: arr =>\n arr add: 1\n arr add: 2\n arr add: 3\n", ); assert_eq!( diags.len(), @@ -234,12 +247,7 @@ mod tests { #[test] fn four_consecutive_sends_flagged_once() { let diags = lint( - "Object subclass: Foo\n\ - add: arr =>\n\ - arr add: 1.\n\ - arr add: 2.\n\ - arr add: 3.\n\ - arr add: 4\n", + "Object subclass: Foo\n add: arr =>\n arr add: 1\n arr add: 2\n arr add: 3\n arr add: 4\n", ); assert_eq!( diags.len(), @@ -255,12 +263,7 @@ mod tests { #[test] fn two_consecutive_sends_not_flagged() { - let diags = lint( - "Object subclass: Foo\n\ - add: arr =>\n\ - arr add: 1.\n\ - arr add: 2\n", - ); + let diags = lint("Object subclass: Foo\n add: arr =>\n arr add: 1\n arr add: 2\n"); assert!( diags.is_empty(), "two sends should not be flagged, got: {diags:?}" @@ -270,12 +273,7 @@ mod tests { #[test] fn interleaved_sends_not_flagged() { let diags = lint( - "Object subclass: Foo\n\ - add: arr with: other =>\n\ - arr add: 1.\n\ - other add: 99.\n\ - arr add: 2.\n\ - arr add: 3\n", + "Object subclass: Foo\n add: arr with: other =>\n arr add: 1\n other add: 99\n arr add: 2\n arr add: 3\n", ); assert!( diags.is_empty(), @@ -286,11 +284,7 @@ mod tests { #[test] fn lint_has_category_and_hint() { let diags = lint( - "Object subclass: Foo\n\ - add: arr =>\n\ - arr add: 1.\n\ - arr add: 2.\n\ - arr add: 3\n", + "Object subclass: Foo\n add: arr =>\n arr add: 1\n arr add: 2\n arr add: 3\n", ); assert_eq!(diags.len(), 1); assert_eq!(diags[0].category, Some(DiagnosticCategory::Lint)); @@ -298,34 +292,22 @@ mod tests { } #[test] - fn self_receiver_flagged() { - let diags = lint( - "Object subclass: Foo\n\ - run =>\n\ - self doA.\n\ - self doB.\n\ - self doC\n", - ); - assert_eq!( - diags.len(), - 1, - "self sends should be flagged, got: {diags:?}" - ); + fn self_receiver_not_flagged() { + // Consecutive sends to `self` (e.g. BUnit assertions) are intentionally + // exempt from the cascade lint — they represent independent operations + // that should remain as separate statements for debuggability. + let diags = + lint("Object subclass: Foo\n run =>\n self doA\n self doB\n self doC\n"); assert!( - diags[0].message.contains("self"), - "message: {}", - diags[0].message + diags.is_empty(), + "self sends should NOT be flagged, got: {diags:?}" ); } #[test] fn complex_receiver_not_flagged() { let diags = lint( - "Object subclass: Foo\n\ - run: x =>\n\ - (x builder) add: 1.\n\ - (x builder) add: 2.\n\ - (x builder) add: 3\n", + "Object subclass: Foo\n run: x =>\n (x builder) add: 1\n (x builder) add: 2\n (x builder) add: 3\n", ); assert!( diags.is_empty(), @@ -336,9 +318,7 @@ mod tests { #[test] fn cascade_in_block_body_flagged() { let diags = lint( - "Object subclass: Foo\n\ - run: arr =>\n\ - [:x | arr add: 1. arr add: 2. arr add: 3]\n", + "Object subclass: Foo\n run: arr =>\n [:x | arr add: 1. arr add: 2. arr add: 3]\n", ); assert_eq!( diags.len(), @@ -351,11 +331,7 @@ mod tests { fn mixed_selector_types_flagged() { // Unary + keyword sends to the same receiver are still a cascade candidate. let diags = lint( - "Object subclass: Foo\n\ - run: arr =>\n\ - arr add: 1.\n\ - arr sort.\n\ - arr add: 2\n", + "Object subclass: Foo\n run: arr =>\n arr add: 1\n arr sort\n arr add: 2\n", ); assert_eq!( diags.len(), @@ -368,11 +344,7 @@ mod tests { fn cast_send_breaks_run() { // Cast sends (`!`) cannot appear in a cascade, so they break the run. let diags = lint( - "Object subclass: Foo\n\ - run: arr =>\n\ - arr add: 1.\n\ - arr fire!\n\ - arr add: 2\n", + "Object subclass: Foo\n run: arr =>\n arr add: 1\n arr fire!\n arr add: 2\n", ); assert!( diags.is_empty(), @@ -385,12 +357,7 @@ mod tests { // `@expect` directives are separate expression nodes that break runs. // This is correct: an @expect-annotated send has different semantics. let diags = lint( - "Object subclass: Foo\n\ - run: arr =>\n\ - arr add: 1.\n\ - @expect dnu\n\ - arr add: 2.\n\ - arr add: 3\n", + "Object subclass: Foo\n run: arr =>\n arr add: 1\n @expect dnu\n arr add: 2\n arr add: 3\n", ); assert!( diags.is_empty(), @@ -401,12 +368,7 @@ mod tests { #[test] fn class_method_body_flagged() { let diags = lint( - "Object subclass: Foo\n\ - class\n\ - setup: arr =>\n\ - arr add: 1.\n\ - arr add: 2.\n\ - arr add: 3\n", + "Object subclass: Foo\n class\n setup: arr =>\n arr add: 1\n arr add: 2\n arr add: 3\n", ); assert_eq!( diags.len(), diff --git a/crates/beamtalk-core/src/semantic_analysis/validators.rs b/crates/beamtalk-core/src/semantic_analysis/validators.rs index 14498e7e6..e5a8d6abf 100644 --- a/crates/beamtalk-core/src/semantic_analysis/validators.rs +++ b/crates/beamtalk-core/src/semantic_analysis/validators.rs @@ -14,7 +14,7 @@ //! - Empty method bodies (BT-631) use crate::ast::{Block, Expression, Identifier, Module}; -use crate::ast_walker::{for_each_expr_seq, walk_expression, walk_module}; +use crate::ast_walker::{walk_expression, walk_module}; use crate::semantic_analysis::block_context::{classify_block, is_collection_hof_selector}; use crate::semantic_analysis::{BlockContext, ClassHierarchy}; #[cfg(test)] @@ -1077,14 +1077,27 @@ fn check_seq_for_effect_free(exprs: &[Expression], diagnostics: &mut Vec` comments) and these are evaluated intentionally. +/// /// Effect-free expressions include literals, variable references, and pure /// binary arithmetic / comparison expressions composed from pure sub-expressions. /// /// Uses `Severity::Lint` so the warning is suppressed during normal compilation /// and only surfaces when running `beamtalk lint`. pub(crate) fn check_effect_free_statements(module: &Module, diagnostics: &mut Vec) { - for_each_expr_seq(module, |seq| check_seq_for_effect_free(seq, diagnostics)); + // Skip module.expressions — those are intentional top-level test assertions. + // Only check method bodies and standalone method definitions. + for class in &module.classes { + for method in class.methods.iter().chain(class.class_methods.iter()) { + check_seq_for_effect_free(&method.body, diagnostics); + } + } + for standalone in &module.method_definitions { + check_seq_for_effect_free(&standalone.method.body, diagnostics); + } } /// BT-919: Error when `!` (cast) is used on a statically-known value type. @@ -1479,21 +1492,20 @@ mod tests { ); } - /// Module-level expressions: non-last literal triggers lint. + /// Module-level expressions: NOT linted, because bootstrap-test files use + /// top-level expressions as intentional test assertions (paired with `// =>`). #[test] - fn module_level_effect_free_emits_lint() { + fn module_level_effect_free_not_linted() { let src = "42.\nself doSomething"; let tokens = lex_with_eof(src); let (module, parse_diags) = parse(tokens); assert!(parse_diags.is_empty(), "Parse failed: {parse_diags:?}"); let mut diagnostics = Vec::new(); check_effect_free_statements(&module, &mut diagnostics); - assert_eq!( - diagnostics.len(), - 1, - "Expected 1 lint for discarded literal at module level, got: {diagnostics:?}" + assert!( + diagnostics.is_empty(), + "Expected no lint for module-level expressions (they are intentional test assertions), got: {diagnostics:?}" ); - assert_eq!(diagnostics[0].severity, Severity::Lint); } /// Standalone method definition: non-last literal triggers lint. diff --git a/stdlib/bootstrap-test/arithmetic.bt b/stdlib/bootstrap-test/arithmetic.bt index a23f104a3..5d68d51b8 100644 --- a/stdlib/bootstrap-test/arithmetic.bt +++ b/stdlib/bootstrap-test/arithmetic.bt @@ -101,7 +101,7 @@ // => 5 // Double negative -0 - (-5) +0 - -5 // => 5 // Zero division operand (numerator) diff --git a/stdlib/bootstrap-test/array_ops.bt b/stdlib/bootstrap-test/array_ops.bt index 0a2b38688..6dab00085 100644 --- a/stdlib/bootstrap-test/array_ops.bt +++ b/stdlib/bootstrap-test/array_ops.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Bootstrap-level smoke tests for the Array type (BT-822). -// Tests literal syntax, basic access, and core operations. +// Bootstrap-level smoke tests for the Array type (BT-822) +// Tests literal syntax, basic access, and core operations // =========================================================================== // ARRAY LITERALS diff --git a/stdlib/bootstrap-test/equality.bt b/stdlib/bootstrap-test/equality.bt index 530fefc50..4ad59f833 100644 --- a/stdlib/bootstrap-test/equality.bt +++ b/stdlib/bootstrap-test/equality.bt @@ -48,8 +48,8 @@ true /= false // Strict vs loose equality // Note: 1.0 compiles to integer 1 in Core Erlang (Rust format! truncates .0) -// so 1.0 =:= 1 is true due to compilation artifact. -// Use values like 1.5 to demonstrate real strict equality behavior. +// so 1.0 =:= 1 is true due to compilation artifact +// Use values like 1.5 to demonstrate real strict equality behavior 1.5 =:= 1 // => false diff --git a/stdlib/bootstrap-test/erlang_exceptions.bt b/stdlib/bootstrap-test/erlang_exceptions.bt index 7a408f48c..2b9f19076 100644 --- a/stdlib/bootstrap-test/erlang_exceptions.bt +++ b/stdlib/bootstrap-test/erlang_exceptions.bt @@ -3,7 +3,7 @@ // Tests for BEAM interop exception classes (BT-678) // Verifies BEAMError, ExitError, ThrowError class hierarchy -// and exception catching behavior. +// and exception catching behavior // =========================================================================== // BEAM ERROR HIERARCHY — SIGNAL AND CATCH diff --git a/stdlib/bootstrap-test/errors.bt b/stdlib/bootstrap-test/errors.bt index 4e794982a..0fd0b8b25 100644 --- a/stdlib/bootstrap-test/errors.bt +++ b/stdlib/bootstrap-test/errors.bt @@ -5,9 +5,9 @@ // Tests that runtime errors produce correct error kinds // Validates BT-458: ERROR: assertion support in stdlib test framework // -// These tests were migrated from E2E where they don't need REPL features. +// These tests were migrated from E2E where they don't need REPL features // Stdlib tests match #beamtalk_error{kind} structurally (more precise than -// E2E substring matching). +// E2E substring matching) // =========================================================================== // ARITHMETIC ERRORS @@ -65,8 +65,8 @@ nil nonExistentMethod // =========================================================================== // PRIMITIVE TYPE INSTANTIATION ERRORS (BT-422) // =========================================================================== -// Primitive types are backed by native BEAM values, not maps. -// Calling `new` on them should raise an instantiation_error. +// Primitive types are backed by native BEAM values, not maps +// Calling `new` on them should raise an instantiation_error Integer new // => ERROR: instantiation_error @@ -96,8 +96,8 @@ Block new // => ERROR: instantiation_error // new: on non-instantiable primitives still raises instantiation_error -// because the class can't be constructed at all (BT-473: checked first). -// BT-422: gen_server crash fix ensures class process survives the error. +// because the class can't be constructed at all (BT-473: checked first) +// BT-422: gen_server crash fix ensures class process survives the error Integer new: 42 // => ERROR: instantiation_error @@ -109,7 +109,7 @@ String new: "hello" // NON-MAP ARGUMENT TO new: (BT-473) // =========================================================================== // Passing a non-Dictionary argument to new: should raise type_error, -// not silently fall back to new/0. +// not silently fall back to new/0 Dictionary new: 42 // => ERROR: type_error @@ -124,9 +124,9 @@ Dictionary new: true // FILE I/O ERRORS // =========================================================================== // NOTE: File I/O error tests temporarily removed — the underlying File -// operations raise function_clause instead of structured beamtalk_errors. -// See pre-existing failures in file_io.bt E2E tests. -// TODO: Re-add when beamtalk_file.erl properly handles these error paths. +// operations raise function_clause instead of structured beamtalk_errors +// See pre-existing failures in file_io.bt E2E tests +// TODO: Re-add when beamtalk_file.erl properly handles these error paths // =========================================================================== // ACTOR INSTANTIATION ERRORS (BT-623) diff --git a/stdlib/bootstrap-test/exceptions.bt b/stdlib/bootstrap-test/exceptions.bt index c76cee36a..33c082e7d 100644 --- a/stdlib/bootstrap-test/exceptions.bt +++ b/stdlib/bootstrap-test/exceptions.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // E2E tests for exception handling (BT-338) -// Tests Block on:do:, ensure:, and Exception object inspection. +// Tests Block on:do:, ensure:, and Exception object inspection // =========================================================================== // BLOCK on:do: — BASIC EXCEPTION CATCHING diff --git a/stdlib/bootstrap-test/symbol.bt b/stdlib/bootstrap-test/symbol.bt index 54da0362b..5a58b5d6b 100644 --- a/stdlib/bootstrap-test/symbol.bt +++ b/stdlib/bootstrap-test/symbol.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // Symbol primitive tests (BT-273) -// Symbols are atoms — interned identifiers used as selectors and names. +// Symbols are atoms — interned identifiers used as selectors and names // Class #foo class diff --git a/stdlib/test/abstract_classes_test.bt b/stdlib/test/abstract_classes_test.bt index 3ac213beb..86a36b7d5 100644 --- a/stdlib/test/abstract_classes_test.bt +++ b/stdlib/test/abstract_classes_test.bt @@ -7,9 +7,9 @@ TestCase subclass: AbstractClassesTest testConcreteSubclassWorksNormally => - c := Circle spawn. - self assert: (c setRadius: 5) equals: 5. - self assert: (c area) equals: 25 + c := Circle spawn + self assert: (c setRadius: 5) equals: 5 + self assert: c area equals: 25 testAbstractMethodRaisesSubclassResponsibility => // Calling subclassResponsibility raises a user_error diff --git a/stdlib/test/actor_class_local_var_test.bt b/stdlib/test/actor_class_local_var_test.bt index 530695b35..f1a9398df 100644 --- a/stdlib/test/actor_class_local_var_test.bt +++ b/stdlib/test/actor_class_local_var_test.bt @@ -2,14 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // BT-741: Tests that Actor class methods can use local variables (arithmetic, -// block literals, dictionaries) without referencing actor State fields. +// block literals, dictionaries) without referencing actor State fields TestCase subclass: ActorClassLocalVarTest testClassMethodsWithLocalVariables => - self assert: (ActorClassLocalVar buildDict) equals: #{#key => 42}. + self assert: ActorClassLocalVar buildDict equals: #{#key => 42} // BT-741: Class method with arithmetic on local variables - self assert: (ActorClassLocalVar computeSum) equals: 30. + self assert: ActorClassLocalVar computeSum equals: 30 // BT-741: Class method with block literal as local variable - self assert: (ActorClassLocalVar applyBlock) equals: 42 + self assert: ActorClassLocalVar applyBlock equals: 42 diff --git a/stdlib/test/actor_conditional_mutations_test.bt b/stdlib/test/actor_conditional_mutations_test.bt index 85349ebc9..ff20913bc 100644 --- a/stdlib/test/actor_conditional_mutations_test.bt +++ b/stdlib/test/actor_conditional_mutations_test.bt @@ -2,100 +2,98 @@ // SPDX-License-Identifier: Apache-2.0 // BT-915: Tests that self.slot := inside ifTrue:, ifFalse:, and -// ifTrue:ifFalse: correctly mutates actor state. +// ifTrue:ifFalse: correctly mutates actor state // // Without the fix, mutations inside conditional blocks are lost because // the block executes as a pure closure and the mutated state is local -// to the closure and never returned to handle_call. +// to the closure and never returned to handle_call TestCase subclass: ActorConditionalMutationsTest testIfTrueWithTrueFlag => // Verify flag=true causes the increment to be applied - c := ConditionalMutationCounter spawn. - self assert: (c conditionalIncrement: true) equals: 1. + c := ConditionalMutationCounter spawn + self assert: (c conditionalIncrement: true) equals: 1 self assert: (c conditionalIncrement: true) equals: 2 testIfTrueWithFalseFlag => // Verify flag=false leaves state unchanged - c := ConditionalMutationCounter spawn. - result := c conditionalIncrement: false. - self assert: result equals: 0. - self assert: (c getCount) equals: 0 + c := ConditionalMutationCounter spawn + result := c conditionalIncrement: false + self assert: result equals: 0 + self assert: c getCount equals: 0 testIfFalseWithFalseFlag => // Verify flag=false causes the decrement to be applied - c := ConditionalMutationCounter spawn. - self assert: (c conditionalDecrement: false) equals: -1. - self assert: (c getCount) equals: -1 + c := ConditionalMutationCounter spawn + self assert: (c conditionalDecrement: false) equals: -1 + self assert: c getCount equals: -1 testIfFalseWithTrueFlag => // Verify flag=true leaves state unchanged - c := ConditionalMutationCounter spawn. - result := c conditionalDecrement: true. - self assert: result equals: 0. - self assert: (c getCount) equals: 0 + c := ConditionalMutationCounter spawn + result := c conditionalDecrement: true + self assert: result equals: 0 + self assert: c getCount equals: 0 testIfTrueIfFalseWithTrueFlag => // Verify true branch of ifTrue:ifFalse: is taken - c := ConditionalMutationCounter spawn. - result := c conditionalToggle: true. - self assert: result equals: 10. - self assert: (c getCount) equals: 10 + c := ConditionalMutationCounter spawn + result := c conditionalToggle: true + self assert: result equals: 10 + self assert: c getCount equals: 10 testIfTrueIfFalseWithFalseFlag => // Verify false branch of ifTrue:ifFalse: is taken - c := ConditionalMutationCounter spawn. - result := c conditionalToggle: false. - self assert: result equals: -1. - self assert: (c getCount) equals: -1 + c := ConditionalMutationCounter spawn + result := c conditionalToggle: false + self assert: result equals: -1 + self assert: c getCount equals: -1 testStatePersistedAcrossCalls => // Verify state accumulates across multiple conditional calls - c := ConditionalMutationCounter spawn. - c conditionalIncrement: true. - c conditionalIncrement: true. - c conditionalIncrement: false. - self assert: (c getCount) equals: 2 + c := ConditionalMutationCounter spawn + c conditionalIncrement: true; conditionalIncrement: true; conditionalIncrement: false + self assert: c getCount equals: 2 testSequentialConditionals => // Verify two sequential conditionals in one method both thread state - c := ConditionalMutationCounter spawn. + c := ConditionalMutationCounter spawn // a=true, b=true => count = 0 + 1 + 10 = 11 - self assert: (c doubleConditional: true and: true) equals: 11. - c reset. + self assert: (c doubleConditional: true and: true) equals: 11 + c reset // a=true, b=false => count = 0 + 1 = 1 - self assert: (c doubleConditional: true and: false) equals: 1. - c reset. + self assert: (c doubleConditional: true and: false) equals: 1 + c reset // a=false, b=true => count = 0 + 10 = 10 - self assert: (c doubleConditional: false and: true) equals: 10. - c reset. + self assert: (c doubleConditional: false and: true) equals: 10 + c reset // a=false, b=false => count = 0 self assert: (c doubleConditional: false and: false) equals: 0 testNestedConditionals => // Verify nested ifTrue: with mutations threads state correctly - c := ConditionalMutationCounter spawn. + c := ConditionalMutationCounter spawn // outer=true, inner=true => count = 0 + 100 = 100 - self assert: (c nestedConditional: true and: true) equals: 100. - c reset. + self assert: (c nestedConditional: true and: true) equals: 100 + c reset // outer=true, inner=false => count = 0 (inner not taken) - self assert: (c nestedConditional: true and: false) equals: 0. - c reset. + self assert: (c nestedConditional: true and: false) equals: 0 + c reset // outer=false => count = 0 (outer not taken) self assert: (c nestedConditional: false and: true) equals: 0 testConditionalAsLastExpression => // Verify conditional as the last expression in a method - c := ConditionalMutationCounter spawn. + c := ConditionalMutationCounter spawn // flag=true returns the assigned value (5) and mutates state - result := c conditionalLast: true. - self assert: result equals: 5. - self assert: (c getCount) equals: 5. - c reset. + result := c conditionalLast: true + self assert: result equals: 5 + self assert: c getCount equals: 5 + c reset // flag=false returns nil and leaves state unchanged - result2 := c conditionalLast: false. - self assert: result2 equals: nil. - self assert: (c getCount) equals: 0 + result2 := c conditionalLast: false + self assert: result2 equals: nil + self assert: c getCount equals: 0 diff --git a/stdlib/test/actor_coordination_test.bt b/stdlib/test/actor_coordination_test.bt index 5349b5f64..4561a3f4d 100644 --- a/stdlib/test/actor_coordination_test.bt +++ b/stdlib/test/actor_coordination_test.bt @@ -1,28 +1,25 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-898: Tests actor-to-actor coordination with sync-by-default dispatch. +// BT-898: Tests actor-to-actor coordination with sync-by-default dispatch // bus notify: calls receive: on the collector synchronously — when notify: -// returns, the collector has already processed the event. +// returns, the collector has already processed the event TestCase subclass: ActorCoordinationTest testSyncEventDelivery => - col := EventCollector spawn. - bus := EventBus spawn. - bus subscribe: col. - bus notify: "hello". + col := EventCollector spawn + bus := EventBus spawn + bus subscribe: col + bus notify: "hello" // notify: is synchronous; no barriers needed - self assert: (col eventCount) equals: 1 + self assert: col eventCount equals: 1 // Multiple events delivered in order testMultipleEventsDelivered => - col := EventCollector spawn. - bus := EventBus spawn. - bus subscribe: col. - bus notify: "first". - bus notify: "second". - bus notify: "third". - self assert: (col eventCount) equals: 3. - self assert: (col events) equals: #("first", "second", "third") + col := EventCollector spawn + bus := EventBus spawn + bus subscribe: col; notify: "first"; notify: "second"; notify: "third" + self assert: col eventCount equals: 3 + self assert: col events equals: #("first", "second", "third") diff --git a/stdlib/test/actor_deadlock_test.bt b/stdlib/test/actor_deadlock_test.bt index 86931d828..f7f7947ba 100644 --- a/stdlib/test/actor_deadlock_test.bt +++ b/stdlib/test/actor_deadlock_test.bt @@ -2,17 +2,17 @@ // SPDX-License-Identifier: Apache-2.0 // Tests that mutual actor calls (A calls B, B calls back A) produce a -// clear #timeout error after the default 5000ms gen_server:call timeout. +// clear #timeout error after the default 5000ms gen_server:call timeout // -// NOTE: This test intentionally triggers a 5000ms deadlock timeout. -// It verifies deadlock detection behavior per ADR 0043. +// NOTE: This test intentionally triggers a 5000ms deadlock timeout +// It verifies deadlock detection behavior per ADR 0043 TestCase subclass: ActorDeadlockTest - // Two actors calling each other synchronously creates a deadlock. - // The gen_server:call timeout (5000ms) raises a #timeout error. + // Two actors calling each other synchronously creates a deadlock + // The gen_server:call timeout (5000ms) raises a #timeout error testMutualCallDeadlockRaisesTimeout => - a := DeadlockA spawn. - b := DeadlockB spawn. - a setPeer: b. + a := DeadlockA spawn + b := DeadlockB spawn + a setPeer: b self should: [a callPeer] raise: #timeout diff --git a/stdlib/test/actor_lifecycle_test.bt b/stdlib/test/actor_lifecycle_test.bt index d05744f3c..796f19bfa 100644 --- a/stdlib/test/actor_lifecycle_test.bt +++ b/stdlib/test/actor_lifecycle_test.bt @@ -2,44 +2,44 @@ // SPDX-License-Identifier: Apache-2.0 // BT-172, BT-397: Tests actor lifecycle — isAlive, stop, idempotent stop, -// and error behaviour when sending to a stopped actor. +// and error behaviour when sending to a stopped actor TestCase subclass: ActorLifecycleTest testIsAliveAndStop => - counter := Counter spawn. + counter := Counter spawn // isAlive returns true for a running actor - self assert: (counter isAlive). + self assert: counter isAlive // Actor still works after isAlive check - self assert: (counter increment) equals: 1. + self assert: counter increment equals: 1 // isAlive still true after message processing - self assert: (counter isAlive). + self assert: counter isAlive // Stop the actor gracefully - self assert: (counter stop) equals: #ok. + self assert: counter stop equals: #ok // Stopping an already-stopped actor is idempotent - self assert: (counter stop) equals: #ok. + self assert: counter stop equals: #ok // isAlive returns false after stop - self deny: (counter isAlive). + self deny: counter isAlive // Sending a message to a stopped actor raises an error self should: [counter increment] raise: #actor_dead testNonMapArgumentToSpawnwith => - // not silently fall back to spawn/0. - self should: [Counter spawnWith: 42] raise: #type_error. + // not silently fall back to spawn/0 + self should: [Counter spawnWith: 42] raise: #type_error // Passing a non-Dictionary argument to spawnWith: should raise type_error, - self should: [Counter spawnWith: "hello"] raise: #type_error. + self should: [Counter spawnWith: "hello"] raise: #type_error self should: [Counter spawnWith: true] raise: #type_error testSpawnwithWithBareIdentifierKeys => // Bare identifier keys in map literals work as implicit symbols - c3 := Counter spawnWith: #{value => 10}. - self assert: (c3 getValue) equals: 10. - self assert: (c3 increment) equals: 11 + c3 := Counter spawnWith: #{value => 10} + self assert: c3 getValue equals: 10 + self assert: c3 increment equals: 11 testPrintstringActorInstanceAndClassObject => // Actor instance printString returns "a ClassName" - c2 := Counter spawn. - self assert: (c2 printString) equals: "a Counter". + c2 := Counter spawn + self assert: c2 printString equals: "a Counter" // Class object printString returns class name - self assert: (Counter printString) equals: "Counter" + self assert: Counter printString equals: "Counter" diff --git a/stdlib/test/actor_local_mutations_test.bt b/stdlib/test/actor_local_mutations_test.bt index a98c8254d..2cd605bc5 100644 --- a/stdlib/test/actor_local_mutations_test.bt +++ b/stdlib/test/actor_local_mutations_test.bt @@ -2,27 +2,27 @@ // SPDX-License-Identifier: Apache-2.0 // BT-598: Tests that local variables inside actor method blocks are correctly -// mutated and scoped — covering do:, inject:into:, to:do:, and whileFalse:. +// mutated and scoped — covering do:, inject:into:, to:do:, and whileFalse: TestCase subclass: ActorLocalMutationsTest testLocalMutationsInActorBlocks => - a := LocalMutationActor spawn. - self assert: (a sumWithDo: #(1, 2, 3, 4, 5)) equals: 15. - b := LocalMutationActor spawn. - self assert: (b sumWithInject: #(10, 20, 30)) equals: #{#count => 3, #result => 60}. - c := LocalMutationActor spawn. - self assert: (c countToN: 5) equals: 5. - d := LocalMutationActor spawn. - self assert: (d sumRange: 5) equals: 15. - e := LocalMutationActor spawn. - self assert: (e countDownFrom: 3) equals: 3. - h := LocalMutationActor spawn. - self assert: (h countUpWithWhileFalseFrom: 3) equals: 3. - i := LocalMutationActor spawn. - self assert: (i sumEvens: 10) equals: 30. - f := LocalMutationActor spawn. - self assert: (f processWithTracking: #(5, 10, 15)) equals: #{#localCount => 3, #log => 30}. - g := FieldMutationAccumulator spawn. + a := LocalMutationActor spawn + self assert: (a sumWithDo: #(1, 2, 3, 4, 5)) equals: 15 + b := LocalMutationActor spawn + self assert: (b sumWithInject: #(10, 20, 30)) equals: #{#count => 3, #result => 60} + c := LocalMutationActor spawn + self assert: (c countToN: 5) equals: 5 + d := LocalMutationActor spawn + self assert: (d sumRange: 5) equals: 15 + e := LocalMutationActor spawn + self assert: (e countDownFrom: 3) equals: 3 + h := LocalMutationActor spawn + self assert: (h countUpWithWhileFalseFrom: 3) equals: 3 + i := LocalMutationActor spawn + self assert: (i sumEvens: 10) equals: 30 + f := LocalMutationActor spawn + self assert: (f processWithTracking: #(5, 10, 15)) equals: #{#localCount => 3, #log => 30} + g := FieldMutationAccumulator spawn self assert: (g processWithLocal: #(10, 20, 30)) equals: #{#localSum => 3, #sum => 60} diff --git a/stdlib/test/actor_message_chaining_test.bt b/stdlib/test/actor_message_chaining_test.bt index 9764b089f..8444afe40 100644 --- a/stdlib/test/actor_message_chaining_test.bt +++ b/stdlib/test/actor_message_chaining_test.bt @@ -3,55 +3,53 @@ // Tests that chained message sends on actors work correctly with sync-by-default // dispatch. When `actor method1 method2` is written, method1 returns the value -// directly (sync gen_server:call), and method2 is dispatched on that value. +// directly (sync gen_server:call), and method2 is dispatched on that value TestCase subclass: ActorMessageChainingTest // Chained send: actor method returning a primitive, chained with printString testChainedPrimitiveMethodResult => - a := ActorChainingFixture spawn. + a := ActorChainingFixture spawn // getValue returns 0 directly; printString dispatches on 0 - self assert: (a getValue printString) equals: "0" + self assert: a getValue printString equals: "0" // Chained send: method on actor returning itself testChainedSelfReturn => - a := ActorChainingFixture spawn. + a := ActorChainingFixture spawn // getSelf returns the actor directly; getValue dispatches on the actor - self assert: (a getSelf getValue) equals: 0 + self assert: a getSelf getValue equals: 0 // String interpolation with actor values testStringInterpolationWithActorValues => - a := ActorChainingFixture spawn. - a increment. + a := ActorChainingFixture spawn + a increment self assert: "val={a getValue}" equals: "val=1" // Multiple sequential sends testSequentialSends => - a := ActorChainingFixture spawn. - a increment. - a increment. - a increment. - self assert: (a getValue) equals: 3 + a := ActorChainingFixture spawn + a increment; increment; increment + self assert: a getValue equals: 3 // Chained send: method dispatched on actor-method result testChainedSendOnActorMethodResult => - a := ActorChainingFixture spawnWith: #{value => 42}. + a := ActorChainingFixture spawnWith: #{value => 42} // getName returns a string directly; size is dispatched on the string - self assert: (a getName size) equals: 7 + self assert: a getName size equals: 7 // Chained send: getValue → printString (sync dispatch, no intermediary Future) testImplicitChaining => - a := ActorChainingFixture spawn. - self assert: (a getValue printString) equals: "0" + a := ActorChainingFixture spawn + self assert: a getValue printString equals: "0" // Chained send on string result testChainedOnStringResult => - a := ActorChainingFixture spawn. - self assert: (a getName size) equals: 7 + a := ActorChainingFixture spawn + self assert: a getName size equals: 7 // Multi-step chaining (actor → actor → primitive) testMultiStepChaining => - a := ActorChainingFixture spawn. - // getSelf returns the actor; getValue returns 0; printString dispatches on 0. - self assert: (a getSelf getValue printString) equals: "0" + a := ActorChainingFixture spawn + // getSelf returns the actor; getValue returns 0; printString dispatches on 0 + self assert: a getSelf getValue printString equals: "0" diff --git a/stdlib/test/actor_non_local_return_test.bt b/stdlib/test/actor_non_local_return_test.bt index b6544b39b..d9174109b 100644 --- a/stdlib/test/actor_non_local_return_test.bt +++ b/stdlib/test/actor_non_local_return_test.bt @@ -3,39 +3,39 @@ // BT-761: Tests non-local return (^) inside block arguments in Actor subclass // methods — empty/non-empty, classify, local var storage, mutation, recursion, -// on:do: with NLR, and NLR with persistent state. +// on:do: with NLR, and NLR with persistent state TestCase subclass: ActorNonLocalReturnTest testNonLocalReturnInActorBlocks => - a := ActorNlrBasic spawn. - self assert: (a test: #()) equals: "empty". - self assert: (a test: #(1)) equals: "not empty". - self assert: (a classify: 5) equals: "positive". - self assert: (a classify: -1) equals: "non-positive". - self assert: (a classify: 0) equals: "non-positive". - self assert: (a checkFalse: #()) equals: "empty". - self assert: (a checkFalse: #(1)) equals: "not empty". - b := ActorNlrLocalVar spawn. - b store: "x" val: 42. - self assert: (b fetch: "x") equals: 42. - self assert: (b fetch: "y") equals: "not found". - c := ActorNlrComputed spawn. - self assert: (c doubleIfPositive: 5) equals: 10. - self assert: (c doubleIfPositive: -1) equals: 0. - d := ActorNlrRecursive spawn. - self assert: (d countDown: 3) equals: "done". - self assert: (d countDown: 0) equals: "done". - e := ActorNlrOnDo spawn. - self assert: (e test: #()) equals: "early". - self assert: (e test: #(1)) equals: "not early". - f := ActorNlrMutate spawn. + a := ActorNlrBasic spawn + self assert: (a test: #()) equals: "empty" + self assert: (a test: #(1)) equals: "not empty" + self assert: (a classify: 5) equals: "positive" + self assert: (a classify: -1) equals: "non-positive" + self assert: (a classify: 0) equals: "non-positive" + self assert: (a checkFalse: #()) equals: "empty" + self assert: (a checkFalse: #(1)) equals: "not empty" + b := ActorNlrLocalVar spawn + b store: "x" val: 42 + self assert: (b fetch: "x") equals: 42 + self assert: (b fetch: "y") equals: "not found" + c := ActorNlrComputed spawn + self assert: (c doubleIfPositive: 5) equals: 10 + self assert: (c doubleIfPositive: -1) equals: 0 + d := ActorNlrRecursive spawn + self assert: (d countDown: 3) equals: "done" + self assert: (d countDown: 0) equals: "done" + e := ActorNlrOnDo spawn + self assert: (e test: #()) equals: "early" + self assert: (e test: #(1)) equals: "not early" + f := ActorNlrMutate spawn // count starts at 0; incAndCheck: 1 sets count=1, 1>=1 triggers NLR - self assert: (f incAndCheck: 1) equals: 1. + self assert: (f incAndCheck: 1) equals: 1 // count is now 1 (mutation was preserved); incAndCheck: 5 sets count=2, 2<5 falls through - self assert: (f incAndCheck: 5) equals: "not yet". + self assert: (f incAndCheck: 5) equals: "not yet" // count is now 2; incAndCheck: 3 sets count=3, 3>=3 triggers NLR - self assert: (f incAndCheck: 3) equals: 3. + self assert: (f incAndCheck: 3) equals: 3 // count is now 3 (verified mutation persisted across NLR and non-NLR paths) self assert: (f incAndCheck: 10) equals: "not yet" diff --git a/stdlib/test/actor_self_send_collect_test.bt b/stdlib/test/actor_self_send_collect_test.bt index e49d709c3..6363f16b0 100644 --- a/stdlib/test/actor_self_send_collect_test.bt +++ b/stdlib/test/actor_self_send_collect_test.bt @@ -2,54 +2,54 @@ // SPDX-License-Identifier: Apache-2.0 // BT-904: Tests that collect:, select:, reject:, and do: with self-sends -// work correctly in actor methods (state threading through blocks). +// work correctly in actor methods (state threading through blocks) TestCase subclass: ActorSelfSendCollectTest testCollectWithSelfSend => - c := ActorCollectCounter spawn. - result := c doubleAll: #(1, 2, 3). - self assert: result equals: #(2, 4, 6). - self assert: (c getCount) equals: 3 + c := ActorCollectCounter spawn + result := c doubleAll: #(1, 2, 3) + self assert: result equals: #(2, 4, 6) + self assert: c getCount equals: 3 testCollectWithFieldMutation => - c := ActorCollectCounter spawn. - result := c doubleAllWithFieldMutation: #(1, 2, 3). - self assert: result equals: #(2, 4, 6). - self assert: (c getCount) equals: 3 + c := ActorCollectCounter spawn + result := c doubleAllWithFieldMutation: #(1, 2, 3) + self assert: result equals: #(2, 4, 6) + self assert: c getCount equals: 3 testCollectWithSelfSendImplicitReturn => - c := ActorCollectCounter spawn. - result := c doubleAllImplicit: #(1, 2, 3). - self assert: result equals: #(2, 4, 6). - self assert: (c getCount) equals: 3 + c := ActorCollectCounter spawn + result := c doubleAllImplicit: #(1, 2, 3) + self assert: result equals: #(2, 4, 6) + self assert: c getCount equals: 3 testDoWithSelfSend => - c := ActorCollectCounter spawn. - result := c countAll: #(10, 20, 30). - self assert: result equals: 3. - self assert: (c getCount) equals: 3 + c := ActorCollectCounter spawn + result := c countAll: #(10, 20, 30) + self assert: result equals: 3 + self assert: c getCount equals: 3 testSelectWithSelfSend => - c := ActorCollectCounter spawn. - result := c selectPositive: #(-1, 2, -3, 4). - self assert: result equals: #(2, 4). - self assert: (c getCount) equals: 4 + c := ActorCollectCounter spawn + result := c selectPositive: #(-1, 2, -3, 4) + self assert: result equals: #(2, 4) + self assert: c getCount equals: 4 testRejectWithSelfSend => - c := ActorCollectCounter spawn. - result := c rejectNegative: #(-1, 2, -3, 4). - self assert: result equals: #(2, 4). - self assert: (c getCount) equals: 4 + c := ActorCollectCounter spawn + result := c rejectNegative: #(-1, 2, -3, 4) + self assert: result equals: #(2, 4) + self assert: c getCount equals: 4 testCollectWithSelfSendEmptyList => - c := ActorCollectCounter spawn. - result := c doubleAll: #(). - self assert: result equals: #(). - self assert: (c getCount) equals: 0 + c := ActorCollectCounter spawn + result := c doubleAll: #() + self assert: result equals: #() + self assert: c getCount equals: 0 testSelectWithSelfSendEmptyList => - c := ActorCollectCounter spawn. - result := c selectPositive: #(). - self assert: result equals: #(). - self assert: (c getCount) equals: 0 + c := ActorCollectCounter spawn + result := c selectPositive: #() + self assert: result equals: #() + self assert: c getCount equals: 0 diff --git a/stdlib/test/actor_slot_test.bt b/stdlib/test/actor_slot_test.bt index aecb35411..d02c766de 100644 --- a/stdlib/test/actor_slot_test.bt +++ b/stdlib/test/actor_slot_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-916: Tests for self.slot := assignment in actor methods. +// BT-916: Tests for self.slot := assignment in actor methods // Verifies that state is correctly threaded through: // - multiple slot assignments in one method // - slot assignment inside ifTrue:ifFalse: conditional @@ -10,124 +10,122 @@ // // Compile-time checks (value type error, withSlot: bypass warning) are // validated by Rust unit tests in semantic_analysis/validators.rs (BT-914) -// and by the E2E @load-error test in tests/e2e/cases/actor_slot.bt. +// and by the E2E @load-error test in tests/e2e/cases/actor_slot.bt TestCase subclass: ActorSlotTest testMultipleSlotAssignmentsInOneMethod => // Both count and total are updated and persist correctly - c := ActorSlotCounter spawn. - result := c incrementBoth: 10. - self assert: result equals: #{#count => 1, #total => 10}. - result2 := c incrementBoth: 5. + c := ActorSlotCounter spawn + result := c incrementBoth: 10 + self assert: result equals: #{#count => 1, #total => 10} + result2 := c incrementBoth: 5 self assert: result2 equals: #{#count => 2, #total => 15} testMultipleAssignmentsToSameSlot => // Three sequential assignments to the same slot accumulate correctly - c := ActorSlotCounter spawn. - self assert: (c addThrice: 3) equals: 9. + c := ActorSlotCounter spawn + self assert: (c addThrice: 3) equals: 9 self assert: (c addThrice: 1) equals: 12 testSlotAssignmentInsideConditional => // Slot assignment inside ifTrue: is applied when condition is true - c := ConditionalMutationCounter spawn. - self assert: (c conditionalIncrement: true) equals: 1. - self assert: (c conditionalIncrement: true) equals: 2. + c := ConditionalMutationCounter spawn + self assert: (c conditionalIncrement: true) equals: 1 + self assert: (c conditionalIncrement: true) equals: 2 // Slot assignment is NOT applied when condition is false self assert: (c conditionalIncrement: false) equals: 2 testSlotAssignmentInsideIfTrueIfFalse => // Both branches of ifTrue:ifFalse: correctly thread state - c := ConditionalMutationCounter spawn. - self assert: (c conditionalToggle: true) equals: 10. - c reset. + c := ConditionalMutationCounter spawn + self assert: (c conditionalToggle: true) equals: 10 + c reset self assert: (c conditionalToggle: false) equals: -1 testSlotAssignmentInsideDoBlock => // do: with self.slot := accumulates correctly - c := ActorSlotCounter spawn. - self assert: (c sumItems: #(1, 2, 3, 4, 5)) equals: 15. + c := ActorSlotCounter spawn + self assert: (c sumItems: #(1, 2, 3, 4, 5)) equals: 15 // State persists after the method completes - self assert: (c getTotal) equals: 15 + self assert: c getTotal equals: 15 testSlotAssignmentInsideDoBlockTwoSlots => // do: with mutations to two different slots both thread correctly - c := ActorSlotCounter spawn. - result := c countAndSum: #(10, 20, 30). - self assert: result equals: #{#count => 3, #total => 60}. - self assert: (c getCount) equals: 3. - self assert: (c getTotal) equals: 60 + c := ActorSlotCounter spawn + result := c countAndSum: #(10, 20, 30) + self assert: result equals: #{#count => 3, #total => 60} + self assert: c getCount equals: 3 + self assert: c getTotal equals: 60 testSlotAssignmentInsideCollectBlock => // collect: with self.slot := in block: result is correct and state is updated - c := ActorSlotCounter spawn. - result := c collectDoubled: #(1, 2, 3). - self assert: result equals: #(2, 4, 6). + c := ActorSlotCounter spawn + result := c collectDoubled: #(1, 2, 3) + self assert: result equals: #(2, 4, 6) // count was incremented once per element - self assert: (c getCount) equals: 3 + self assert: c getCount equals: 3 testSlotAssignmentWithEarlyReturn => // Slot assignment before ifTrue:[^value] preserves the updated state - c := ActorSlotCounter spawn. + c := ActorSlotCounter spawn // count=0+1=1 >= 1, so early return fires - result := c addAndCheckLimit: 1. - self assert: result equals: #reached. - self assert: (c getCount) equals: 1 + result := c addAndCheckLimit: 1 + self assert: result equals: #reached + self assert: c getCount equals: 1 testSlotAssignmentWithEarlyReturnNotFired => // When the limit is not reached, normal path runs and state is still updated - c := ActorSlotCounter spawn. + c := ActorSlotCounter spawn // count=0+1=1 < 5, so early return does NOT fire - result := c addAndCheckLimit: 5. - self assert: result equals: #not_yet. - self assert: (c getCount) equals: 1. + result := c addAndCheckLimit: 5 + self assert: result equals: #not_yet + self assert: c getCount equals: 1 // count=1+1=2 < 5, still not reached - result2 := c addAndCheckLimit: 5. - self assert: result2 equals: #not_yet. - self assert: (c getCount) equals: 2. + result2 := c addAndCheckLimit: 5 + self assert: result2 equals: #not_yet + self assert: c getCount equals: 2 // count=2+1=3 < 5, still not reached - result3 := c addAndCheckLimit: 5. - self assert: result3 equals: #not_yet. - self assert: (c getCount) equals: 3. + result3 := c addAndCheckLimit: 5 + self assert: result3 equals: #not_yet + self assert: c getCount equals: 3 // count=3+1=4 < 5, still not reached - result4 := c addAndCheckLimit: 5. - self assert: result4 equals: #not_yet. - self assert: (c getCount) equals: 4. + result4 := c addAndCheckLimit: 5 + self assert: result4 equals: #not_yet + self assert: c getCount equals: 4 // count=4+1=5 >= 5, early return fires - result5 := c addAndCheckLimit: 5. - self assert: result5 equals: #reached. - self assert: (c getCount) equals: 5 + result5 := c addAndCheckLimit: 5 + self assert: result5 equals: #reached + self assert: c getCount equals: 5 testSlotAssignmentBeforeEarlyReturnValue => // total is incremented before the ^ so the returned value reflects the new state - c := ActorSlotCounter spawn. + c := ActorSlotCounter spawn // total=0+1=1 > 0, so returns total=1 - result := c addAndReturnIfAbove: 0. - self assert: result equals: 1. - self assert: (c getTotal) equals: 1 + result := c addAndReturnIfAbove: 0 + self assert: result equals: 1 + self assert: c getTotal equals: 1 testSlotAssignmentBeforeEarlyReturnFallthrough => // When threshold not exceeded, falls through to -1 but state is still updated - c := ActorSlotCounter spawn. + c := ActorSlotCounter spawn // total=0+1=1, 1 > 100? No, returns -1 - result := c addAndReturnIfAbove: 100. - self assert: result equals: -1. - self assert: (c getTotal) equals: 1 + result := c addAndReturnIfAbove: 100 + self assert: result equals: -1 + self assert: c getTotal equals: 1 testStatePersistedAcrossMultipleCalls => // State accumulates correctly across independent method calls - c := ActorSlotCounter spawn. - c incrementBoth: 10. - c incrementBoth: 20. - c incrementBoth: 30. - self assert: (c getCount) equals: 3. - self assert: (c getTotal) equals: 60 + c := ActorSlotCounter spawn + c incrementBoth: 10; incrementBoth: 20; incrementBoth: 30 + self assert: c getCount equals: 3 + self assert: c getTotal equals: 60 testResetClearsBothSlots => // reset clears both slots back to 0 - c := ActorSlotCounter spawn. - c incrementBoth: 42. - c reset. - self assert: (c getCount) equals: 0. - self assert: (c getTotal) equals: 0 + c := ActorSlotCounter spawn + c incrementBoth: 42 + c reset + self assert: c getCount equals: 0 + self assert: c getTotal equals: 0 diff --git a/stdlib/test/architecture_doc_examples_test.bt b/stdlib/test/architecture_doc_examples_test.bt index 61de85814..c8b8e464a 100644 --- a/stdlib/test/architecture_doc_examples_test.bt +++ b/stdlib/test/architecture_doc_examples_test.bt @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 // Tests that the code examples in docs/beamtalk-architecture.md compile and -// produce correct results — collect: with multiplication, binary math precedence. +// produce correct results — collect: with multiplication, binary math precedence TestCase subclass: ArchitectureDocExamplesTest testCollectAndMathPrecedence => - doubled := #(1, 2, 3) collect: [:x | x * 2]. - self assert: doubled equals: #(2, 4, 6). + doubled := #(1, 2, 3) collect: [:x | x * 2] + self assert: doubled equals: #(2, 4, 6) // --- Math precedence (doc: "Binary Operations with Math Precedence" section) --- - result := 2 + 3 * 4. + result := 2 + 3 * 4 self assert: result equals: 14 diff --git a/stdlib/test/arithmetic_operations_test.bt b/stdlib/test/arithmetic_operations_test.bt index 63d512551..328e362df 100644 --- a/stdlib/test/arithmetic_operations_test.bt +++ b/stdlib/test/arithmetic_operations_test.bt @@ -7,62 +7,62 @@ TestCase subclass: ArithmeticOperationsTest testModulo => // Basic modulo - self assert: (10 % 3) equals: 1. + self assert: (10 % 3) equals: 1 // Modulo with no remainder - self assert: (9 % 3) equals: 0. + self assert: (9 % 3) equals: 0 // Modulo with zero dividend self assert: (0 % 5) equals: 0 testExponentiation => // Basic exponentiation - self assert: (2 ** 10) equals: 1024. + self assert: (2 ** 10) equals: 1024 // Exponent of zero - self assert: (5 ** 0) equals: 1. + self assert: (5 ** 0) equals: 1 // Exponent of one - self assert: (7 ** 1) equals: 7. + self assert: (7 ** 1) equals: 7 // Small exponentiation - self assert: (3 ** 3) equals: 27. + self assert: (3 ** 3) equals: 27 // Exponentiation has higher precedence than multiplication - self assert: (3 * 2 ** 3) equals: 24. + self assert: (3 * 2 ** 3) equals: 24 // Zero to the power of zero (mathematical convention: 1) - self assert: (0 ** 0) equals: 1. + self assert: (0 ** 0) equals: 1 // Negative base self assert: (-2 ** 2) equals: 4 testGreaterThan => - self assert: (5 > 3). + self assert: (5 > 3) self deny: (3 > 5) testLessThan => - self assert: (5 < 10). + self assert: (5 < 10) self deny: (10 < 5) testEqual => - self assert: (5 == 5). + self assert: (5 == 5) self deny: (5 == 6) testLessOrEqual => // Less than or equal (true - equal) - self assert: (5 <= 5). + self assert: (5 <= 5) // Less than or equal (true - less) - self assert: (3 <= 5). + self assert: (3 <= 5) // Less than or equal (false) self deny: (7 <= 5) testGreaterOrEqual => // Greater than or equal (true - equal) - self assert: (5 >= 5). + self assert: (5 >= 5) // Greater than or equal (true - greater) - self assert: (7 >= 5). + self assert: (7 >= 5) // Greater than or equal (false) self deny: (3 >= 5) testAsString => - self assert: (42 asString) equals: "42" + self assert: 42 asString equals: "42" testAsFloat => // Test integer to float conversion - f := 42 asFloat. - self assert: (f class) equals: Float. - self assert: (f > 41.9). + f := 42 asFloat + self assert: f class equals: Float + self assert: (f > 41.9) self assert: (f < 42.1) diff --git a/stdlib/test/arithmetic_test.bt b/stdlib/test/arithmetic_test.bt index 06b81232f..b2fcbf50f 100644 --- a/stdlib/test/arithmetic_test.bt +++ b/stdlib/test/arithmetic_test.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // ADR 0014 Phase 2: Tests basic arithmetic operations — addition, subtraction, -// negation, equality, and denial — as a canonical BUnit TestCase example. +// negation, equality, and denial — as a canonical BUnit TestCase example TestCase subclass: ArithmeticTest diff --git a/stdlib/test/array_test.bt b/stdlib/test/array_test.bt index 75b84bc14..32ac3e76e 100644 --- a/stdlib/test/array_test.bt +++ b/stdlib/test/array_test.bt @@ -1,94 +1,94 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BUnit tests for the Array collection type (BT-822). +// BUnit tests for the Array collection type (BT-822) TestCase subclass: ArrayTest testClassAndCreation => - self assert: (#[1, 2, 3] class) equals: Array. - self assert: (#[] class) equals: Array + self assert: #[1, 2, 3] class equals: Array + self assert: #[] class equals: Array testSizeAndIsEmpty => - self assert: (#[] size) equals: 0. - self assert: (#[1, 2, 3] size) equals: 3. - self assert: (#[] isEmpty). - self deny: (#[1] isEmpty). - self assert: (#[1] isNotEmpty) + self assert: #[] size equals: 0 + self assert: #[1, 2, 3] size equals: 3 + self assert: #[] isEmpty + self deny: #[1] isEmpty + self assert: #[1] isNotEmpty testAtIndexedAccess => - a := #[10, 20, 30]. - self assert: (a at: 1) equals: 10. - self assert: (a at: 2) equals: 20. + a := #[10, 20, 30] + self assert: (a at: 1) equals: 10 + self assert: (a at: 2) equals: 20 self assert: (a at: 3) equals: 30 testAtPutFunctionalUpdate => - a := #[1, 2, 3]. - b := a at: 2 put: 99. - self assert: (b at: 2) equals: 99. + a := #[1, 2, 3] + b := a at: 2 put: 99 + self assert: (b at: 2) equals: 99 // Original is unchanged (immutable) self assert: (a at: 2) equals: 2 testIncludes => - a := #[1, 2, 3]. - self assert: (a includes: 2). - self deny: (a includes: 9). + a := #[1, 2, 3] + self assert: (a includes: 2) + self deny: (a includes: 9) self deny: (#[] includes: 1) testDo => // do: returns nil - self assert: (#[1, 2, 3] do: [:x | x + 1]) equals: nil. + self assert: (#[1, 2, 3] do: [:x | x + 1]) equals: nil // do: on empty array also returns nil self assert: (#[] do: [:x | x]) equals: nil testCollect => - self assert: (#[1, 2, 3] collect: [:x | x * 2]) equals: #[2, 4, 6]. - self assert: (#[] collect: [:x | x * 2]) equals: #[]. + self assert: (#[1, 2, 3] collect: [:x | x * 2]) equals: #[2, 4, 6] + self assert: (#[] collect: [:x | x * 2]) equals: #[] // collect: preserves order self assert: (#[3, 1, 2] collect: [:x | x + 10]) equals: #[13, 11, 12] testCollectReturnsArray => - result := #[1, 2, 3] collect: [:x | x * 2]. - self assert: (result class) equals: Array + result := #[1, 2, 3] collect: [:x | x * 2] + self assert: result class equals: Array testSelect => - self assert: (#[1, 2, 3, 4] select: [:x | x > 2]) equals: #[3, 4]. - self assert: (#[1, 2, 3] select: [:x | x > 10]) equals: #[]. + self assert: (#[1, 2, 3, 4] select: [:x | x > 2]) equals: #[3, 4] + self assert: (#[1, 2, 3] select: [:x | x > 10]) equals: #[] self assert: (#[1, 2, 3] select: [:x | true]) equals: #[1, 2, 3] testSelectReturnsArray => - result := #[1, 2, 3, 4] select: [:x | x > 2]. - self assert: (result class) equals: Array + result := #[1, 2, 3, 4] select: [:x | x > 2] + self assert: result class equals: Array testReject => - self assert: (#[1, 2, 3, 4] reject: [:x | x > 2]) equals: #[1, 2]. + self assert: (#[1, 2, 3, 4] reject: [:x | x > 2]) equals: #[1, 2] self assert: (#[1, 2, 3] reject: [:x | false]) equals: #[1, 2, 3] testInjectInto => - self assert: (#[1, 2, 3] inject: 0 into: [:acc :x | acc + x]) equals: 6. - self assert: (#[1, 2, 3, 4] inject: 1 into: [:acc :x | acc * x]) equals: 24. + self assert: (#[1, 2, 3] inject: 0 into: [:acc :x | acc + x]) equals: 6 + self assert: (#[1, 2, 3, 4] inject: 1 into: [:acc :x | acc * x]) equals: 24 self assert: (#[] inject: 0 into: [:acc :x | acc + x]) equals: 0 testPrintString => - self assert: (#[1, 2, 3] printString) equals: "#[1, 2, 3]". - self assert: (#[] printString) equals: "#[]". - self assert: (#["a", "b"] printString) equals: "#[""a"", ""b""]" + self assert: #[1, 2, 3] printString equals: "#[1, 2, 3]" + self assert: #[] printString equals: "#[]" + self assert: #["a", "b"] printString equals: "#[""a"", ""b""]" testWithAll => - a := Array withAll: #(1, 2, 3). - self assert: (a class) equals: Array. - self assert: (a size) equals: 3. - self assert: (a at: 1) equals: 1. + a := Array withAll: #(1, 2, 3) + self assert: a class equals: Array + self assert: a size equals: 3 + self assert: (a at: 1) equals: 1 self assert: (a at: 3) equals: 3 testEmptyArray => - self assert: (#[] size) equals: 0. - self assert: (#[] isEmpty). - self assert: (#[] printString) equals: "#[]" + self assert: #[] size equals: 0 + self assert: #[] isEmpty + self assert: #[] printString equals: "#[]" testLiteralEquality => - self assert: (#[1, 2, 3]) equals: #[1, 2, 3]. + self assert: #[1, 2, 3] equals: #[1, 2, 3] @expect dnu - self deny: (#[1, 2, 3] =:= #[1, 2, 4]). + self deny: (#[1, 2, 3] =:= #[1, 2, 4]) @expect dnu self deny: (#[1, 2] =:= #[1, 2, 3]) diff --git a/stdlib/test/association_test.bt b/stdlib/test/association_test.bt index 84597d31b..8088adc7d 100644 --- a/stdlib/test/association_test.bt +++ b/stdlib/test/association_test.bt @@ -6,36 +6,36 @@ TestCase subclass: AssociationTest testCreationBinaryMessage => - a := #name -> "James". - self assert: (a class) equals: Association. + a := #name -> "James" + self assert: a class equals: Association // Integer key with Integer value - self assert: ((42 -> "answer") class) equals: Association. + self assert: (42 -> "answer") class equals: Association // String key - self assert: (("city" -> "London") class) equals: Association + self assert: ("city" -> "London") class equals: Association testAccessorsKeyAndValue => - a := #name -> "James". - self assert: (a key) equals: #name. - self assert: (a value) equals: "James". - b := 1 -> 2. - self assert: (b key) equals: 1. - self assert: (b value) equals: 2 + a := #name -> "James" + self assert: a key equals: #name + self assert: a value equals: "James" + b := 1 -> 2 + self assert: b key equals: 1 + self assert: b value equals: 2 testDisplayAsstringPrintstring => // asString uses displayString (user-facing: no # prefix, no string quotes) - self assert: ((#name -> "James") asString) equals: "name -> James". - self assert: ((42 -> "answer") asString) equals: "42 -> answer". - self assert: (("count" -> 5) asString) equals: "count -> 5". + self assert: (#name -> "James") asString equals: "name -> James" + self assert: (42 -> "answer") asString equals: "42 -> answer" + self assert: ("count" -> 5) asString equals: "count -> 5" // printString uses printString for each part (developer: # prefix, string quoted) - self assert: ((#name -> "James") printString) equals: "#name -> ""James""" + self assert: (#name -> "James") printString equals: "#name -> ""James""" testReflection => - self assert: ((#name -> "James") class) equals: Association. - self assert: ((#name -> "James") respondsTo: #key). + self assert: (#name -> "James") class equals: Association + self assert: ((#name -> "James") respondsTo: #key) self assert: ((#name -> "James") respondsTo: #value) testUsageInCollections => - assocs := #(#a -> 1, #b -> 2, #c -> 3). - self assert: (assocs size) equals: 3. - self assert: (assocs collect: [:assoc | assoc key]) equals: #(#a, #b, #c). + assocs := #(#a -> 1, #b -> 2, #c -> 3) + self assert: assocs size equals: 3 + self assert: (assocs collect: [:assoc | assoc key]) equals: #(#a, #b, #c) self assert: (assocs collect: [:assoc | assoc value]) equals: #(1, 2, 3) diff --git a/stdlib/test/beamtalk_interface_test.bt b/stdlib/test/beamtalk_interface_test.bt index ac5a76d9e..c3507885b 100644 --- a/stdlib/test/beamtalk_interface_test.bt +++ b/stdlib/test/beamtalk_interface_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BUnit tests for BeamtalkInterface facade API (BT-849 / ADR 0040 Phase 6). +// BUnit tests for BeamtalkInterface facade API (BT-849 / ADR 0040 Phase 6) // // Tests use class-level introspection (includesSelector:, inheritsFrom:) since // the Beamtalk workspace singleton is not available in the BUnit test context diff --git a/stdlib/test/block_evaluation_test.bt b/stdlib/test/block_evaluation_test.bt index 1df397799..b5207cf65 100644 --- a/stdlib/test/block_evaluation_test.bt +++ b/stdlib/test/block_evaluation_test.bt @@ -3,35 +3,35 @@ // Tests block evaluation — basic value/value:/value:value: dispatch, nested // blocks, blocks used as conditionals, and variable persistence across -// expressions in a test method. +// expressions in a test method TestCase subclass: BlockEvaluationTest testBlockEvaluationBasic => - self assert: ([5 + 3] value) equals: 8. + self assert: [5 + 3] value equals: 8 // Block with argument that returns computed value - self assert: ([:x | x * 2] value: 7) equals: 14. + self assert: ([:x | x * 2] value: 7) equals: 14 // Block with two arguments self assert: ([:a :b | a + b] value: 10 value: 20) equals: 30 testBlockEvaluationNested => // Nested block evaluation - self assert: ([[:x | x * 3] value: 4] value) equals: 12. + self assert: [[:x | x * 3] value: 4] value equals: 12 // Block returning a block, then evaluating it - self assert: ([[100]] value value) equals: 100 + self assert: [[100]] value value equals: 100 testBlockWithConditionals => // Block with comparison (returns boolean for conditional use) - self assert: ([:x | x > 5] value: 10). - self deny: ([:x | x > 5] value: 3). + self assert: ([:x | x > 5] value: 10) + self deny: ([:x | x > 5] value: 3) // Block with arithmetic comparison self assert: ([:x :y | x + y > 10] value: 5 value: 10) testVariablePersistenceAcrossExpressions => // Set up a value - baseValue := 100. - self assert: baseValue equals: 100. + baseValue := 100 + self assert: baseValue equals: 100 // Use it in a block - self assert: ([:x | x + baseValue] value: 50) equals: 150. + self assert: ([:x | x + baseValue] value: 50) equals: 150 // Value still accessible self assert: baseValue equals: 100 diff --git a/stdlib/test/blocks_test.bt b/stdlib/test/blocks_test.bt index fc6d01943..1f169b2d3 100644 --- a/stdlib/test/blocks_test.bt +++ b/stdlib/test/blocks_test.bt @@ -2,70 +2,70 @@ // SPDX-License-Identifier: Apache-2.0 // Tests for block (closure) evaluation — argument passing, arity, whileTrue/False, -// valueWithArguments:, closure variable capture, and early return with ^. +// valueWithArguments:, closure variable capture, and early return with ^ TestCase subclass: BlocksTest testBlockEvaluation => - self assert: ([:x | x + 1] value: 5) equals: 6. + self assert: ([:x | x + 1] value: 5) equals: 6 // Block with two arguments - self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7. + self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7 // Block with no arguments (value message) - self assert: ([42] value) equals: 42. + self assert: [42] value equals: 42 // Block with expression body - self assert: ([:n | n * n] value: 5) equals: 25. + self assert: ([:n | n * n] value: 5) equals: 25 // Nested arithmetic in block - self assert: ([:a | a + a * 2] value: 3) equals: 9. + self assert: ([:a | a + a * 2] value: 3) equals: 9 // Block returning constant - self assert: ([:x | 100] value: 999) equals: 100. + self assert: ([:x | 100] value: 999) equals: 100 // Block with subtraction - self assert: ([:a :b | a - b] value: 10 value: 3) equals: 7. + self assert: ([:a :b | a - b] value: 10 value: 3) equals: 7 // Block with three arguments - self assert: ([:x :y :z | x + y + z] value: 1 value: 2 value: 3) equals: 6. + self assert: ([:x :y :z | x + y + z] value: 1 value: 2 value: 3) equals: 6 // Nested blocks - outer returns inner block that captures x - self assert: ([[:x | [:y | x + y]] value: 10] value value: 5) equals: 15. + self assert: ([[:x | [:y | x + y]] value: 10] value value: 5) equals: 15 // Higher-order block (makeAdder pattern) - self assert: ([[:n | [:x | x + n]] value: 5] value value: 10) equals: 15. + self assert: ([[:n | [:x | x + n]] value: 5] value value: 10) equals: 15 // Complex expression in block body self assert: ([:x | x * 2 + 1] value: 5) equals: 11 testReturnStatements => // Explicit return with ^ (returns from block) - self assert: ([:x | ^x + 10] value: 5) equals: 15. + self assert: ([:x | ^x + 10] value: 5) equals: 15 // Explicit return of literal - self assert: ([^42] value) equals: 42. + self assert: [^42] value equals: 42 // Implicit return (last expression) - same behavior - self assert: ([:x | x + 10] value: 5) equals: 15. + self assert: ([:x | x + 10] value: 5) equals: 15 // whileTrue: with false condition (returns immediately) self assert: ([false] whileTrue: [42]) equals: nil testBasicClosureCapture => // Simple closure capturing outer variable - outerVar := 10. - self assert: outerVar equals: 10. - self assert: ([:x | x + outerVar] value: 5) equals: 15. + outerVar := 10 + self assert: outerVar equals: 10 + self assert: ([:x | x + outerVar] value: 5) equals: 15 // Nested closure with capture - makeAdder := [:n | [:x | x + n]]. - addFive := makeAdder value: 5. + makeAdder := [:n | [:x | x + n]] + addFive := makeAdder value: 5 self assert: (addFive value: 10) equals: 15 testBlockValuewitharguments => // Block with array of arguments - self assert: ([:x :y | x + y] valueWithArguments: #(3, 4)) equals: 7. + self assert: ([:x :y | x + y] valueWithArguments: #(3, 4)) equals: 7 // Zero-arg block - self assert: ([42] valueWithArguments: #()) equals: 42. + self assert: ([42] valueWithArguments: #()) equals: 42 // Single-arg block self assert: ([:x | x * 2] valueWithArguments: #(5)) equals: 10 testBlockArity => // Zero-argument block arity - self assert: ([42] arity) equals: 0. + self assert: [42] arity equals: 0 // One-argument block arity - self assert: ([:x | x + 1] arity) equals: 1. + self assert: [:x | x + 1] arity equals: 1 // Two-argument block arity - self assert: ([:x :y | x + y] arity) equals: 2. + self assert: [:x :y | x + y] arity equals: 2 // Three-argument block arity - self assert: ([:x :y :z | x + y + z] arity) equals: 3 + self assert: [:x :y :z | x + y + z] arity equals: 3 testWhilefalse => // whileFalse: with true condition (returns immediately) diff --git a/stdlib/test/cast_send_test.bt b/stdlib/test/cast_send_test.bt index ecd9c0ef3..80c304de9 100644 --- a/stdlib/test/cast_send_test.bt +++ b/stdlib/test/cast_send_test.bt @@ -1,35 +1,35 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-920: Tests fire-and-forget cast sends (! suffix). +// BT-920: Tests fire-and-forget cast sends (! suffix) // Cast sends route through beamtalk_actor:cast_send/3 via gen_server:cast, // delivering messages asynchronously. A subsequent sync send acts as a -// barrier ensuring the cast was processed before asserting. +// barrier ensuring the cast was processed before asserting TestCase subclass: CastSendTest testCastSendIncrements => // Cast send fires and forgets; sync getValue acts as ordering barrier - c := Counter spawn. + c := Counter spawn c increment! // Sync barrier: forces ordering — cast must be processed before getValue reply - self assert: (c getValue) equals: 1 + self assert: c getValue equals: 1 testMultipleCastSendsAreProcessed => - c := Counter spawn. + c := Counter spawn c increment! c increment! c increment! // Sync barrier ensures all three casts were processed - self assert: (c getValue) equals: 3 + self assert: c getValue equals: 3 testCastSendDoesNotBlockCaller => - // Cast sends are fire-and-forget: multiple casts return immediately. - // The sync getValue at the end acts as an ordering barrier. - c := Counter spawn. + // Cast sends are fire-and-forget: multiple casts return immediately + // The sync getValue at the end acts as an ordering barrier + c := Counter spawn c increment! c decrement! c increment! // Net effect: +1 -1 +1 = 1 - self assert: (c getValue) equals: 1 + self assert: c getValue equals: 1 diff --git a/stdlib/test/character_test.bt b/stdlib/test/character_test.bt index 318ebe480..3bfdc2172 100644 --- a/stdlib/test/character_test.bt +++ b/stdlib/test/character_test.bt @@ -3,36 +3,36 @@ // BT-339: Tests for the Character class — integer codes, equality, comparison, // predicates (isLetter, isDigit, isUppercase, isLowercase, isWhitespace), -// arithmetic on char codes, and conversions (asString, asFloat). +// arithmetic on char codes, and conversions (asString, asFloat) TestCase subclass: CharacterTest testCharacterOperations => - self assert: ($A) equals: 65. - self assert: ($a) equals: 97. - self assert: ($0) equals: 48. - self assert: ($\n) equals: 10. - self assert: ($\t) equals: 9. - self assert: ($A =:= $A). - self deny: ($A =:= $B). - self assert: ($A /= $B). - self assert: ($A < $B). - self assert: ($B > $A). - self assert: ($A <= $A). - self assert: ($B >= $A). - self assert: ($A isLetter). - self assert: ($z isLetter). - self deny: ($0 isLetter). - self assert: ($5 isDigit). - self deny: ($A isDigit). - self assert: ($A isUppercase). - self deny: ($a isUppercase). - self assert: ($a isLowercase). - self deny: ($A isLowercase). - self assert: ($\n isWhitespace). - self assert: ($\t isWhitespace). - self deny: ($A isWhitespace). - self assert: ($A + 1) equals: 66. - self assert: ($z - $a) equals: 25. - self assert: ($A asString) equals: "65". - self assert: ($A asFloat) equals: 65 asFloat + self assert: $A equals: 65 + self assert: $a equals: 97 + self assert: $0 equals: 48 + self assert: $\n equals: 10 + self assert: $\t equals: 9 + self assert: ($A =:= $A) + self deny: ($A =:= $B) + self assert: ($A /= $B) + self assert: ($A < $B) + self assert: ($B > $A) + self assert: ($A <= $A) + self assert: ($B >= $A) + self assert: $A isLetter + self assert: $z isLetter + self deny: $0 isLetter + self assert: $5 isDigit + self deny: $A isDigit + self assert: $A isUppercase + self deny: $a isUppercase + self assert: $a isLowercase + self deny: $A isLowercase + self assert: $\n isWhitespace + self assert: $\t isWhitespace + self deny: $A isWhitespace + self assert: ($A + 1) equals: 66 + self assert: ($z - $a) equals: 25 + self assert: $A asString equals: "65" + self assert: $A asFloat equals: 65 asFloat diff --git a/stdlib/test/class_builder_test.bt b/stdlib/test/class_builder_test.bt index 951d3de33..5885613ca 100644 --- a/stdlib/test/class_builder_test.bt +++ b/stdlib/test/class_builder_test.bt @@ -4,7 +4,7 @@ // ClassBuilder validation tests (ADR 0038) // // Tests ClassBuilder error cases: validation failures caught before class -// registration. Exercises the validate/2 logic in beamtalk_class_builder.erl. +// registration. Exercises the validate/2 logic in beamtalk_class_builder.erl TestCase subclass: ClassBuilderTest state: cls = nil diff --git a/stdlib/test/class_hierarchy_query_test.bt b/stdlib/test/class_hierarchy_query_test.bt index 276745d76..6d195934b 100644 --- a/stdlib/test/class_hierarchy_query_test.bt +++ b/stdlib/test/class_hierarchy_query_test.bt @@ -8,57 +8,57 @@ TestCase subclass: ClassHierarchyQueryTest testNumberSubclasses => // Number has Integer and Float as direct subclasses - numSubs := Number subclasses. - self assert: (numSubs includes: Integer). + numSubs := Number subclasses + self assert: (numSubs includes: Integer) self assert: (numSubs includes: Float) testBooleanSubclasses => // Boolean has True and False as direct subclasses - boolSubs := Boolean subclasses. - self assert: (boolSubs includes: True). + boolSubs := Boolean subclasses + self assert: (boolSubs includes: True) self assert: (boolSubs includes: False) testFloatIsSealed => // Float is sealed — always a leaf - self assert: (Float subclasses isEmpty). - self assert: (True subclasses isEmpty) + self assert: Float subclasses isEmpty + self assert: True subclasses isEmpty testActorSubclassesNotEmpty => // Actor should have some subclasses - actorSubs := Actor subclasses. - self deny: (actorSubs isEmpty) + actorSubs := Actor subclasses + self deny: actorSubs isEmpty testNumberAllSubclasses => // Number allSubclasses includes Integer and Float - numAllSubs := Number allSubclasses. - self assert: (numAllSubs includes: Integer). + numAllSubs := Number allSubclasses + self assert: (numAllSubs includes: Integer) self assert: (numAllSubs includes: Float) testBooleanAllSubclasses => // Boolean allSubclasses includes True and False - boolAllSubs := Boolean allSubclasses. - self assert: (boolAllSubs includes: True). + boolAllSubs := Boolean allSubclasses + self assert: (boolAllSubs includes: True) self assert: (boolAllSubs includes: False) testCollectionAllSubclasses => // Collection allSubclasses includes List and Dictionary - collSubs := Collection allSubclasses. - self assert: (collSubs includes: List). + collSubs := Collection allSubclasses + self assert: (collSubs includes: List) self assert: (collSubs includes: Dictionary) testFloatAllSubclassesEmpty => // Float is sealed — always a leaf, allSubclasses returns empty - self assert: (Float allSubclasses isEmpty) + self assert: Float allSubclasses isEmpty testClassOnPrimitives => // class returns the class name for primitives - self assert: (42 class) equals: Integer. - self assert: ("hello" class) equals: String. - self assert: (true class) equals: True. - self assert: (nil class) equals: UndefinedObject. - self assert: (3.14 class) equals: Float + self assert: 42 class equals: Integer + self assert: "hello" class equals: String + self assert: true class equals: True + self assert: nil class equals: UndefinedObject + self assert: 3.14 class equals: Float testClassOnClassObject => // class on a class object returns something - classObj := Integer class. - self assert: (classObj isNil) equals: false + classObj := Integer class + self assert: classObj isNil equals: false diff --git a/stdlib/test/class_method_self_new_test.bt b/stdlib/test/class_method_self_new_test.bt index 2782cded8..5788c4d3d 100644 --- a/stdlib/test/class_method_self_new_test.bt +++ b/stdlib/test/class_method_self_new_test.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-893: Class method self-sends (self new:) should not deadlock. -// Tests the factory pattern where class methods create instances via self new:. +// BT-893: Class method self-sends (self new:) should not deadlock +// Tests the factory pattern where class methods create instances via self new: TestCase subclass: ClassMethodSelfNewTest diff --git a/stdlib/test/class_object_dispatch_test.bt b/stdlib/test/class_object_dispatch_test.bt index 65288fee9..c99f407e9 100644 --- a/stdlib/test/class_object_dispatch_test.bt +++ b/stdlib/test/class_object_dispatch_test.bt @@ -2,33 +2,33 @@ // SPDX-License-Identifier: Apache-2.0 // BT-753: Class objects correctly dispatch Object base class methods -// and pure Beamtalk Behaviour methods. +// and pure Beamtalk Behaviour methods TestCase subclass: ClassObjectDispatchTest // --- Object base class methods on class objects (BT-753 core fix) --- // Note: respondsTo: on class objects is a known limitation (virtual metaclass - // tag isn't registered in the class registry). Tracked in BT-776. + // tag isn't registered in the class registry). Tracked in BT-776 testClassObjectYourself => - self assert: (Counter yourself) equals: Counter + self assert: Counter yourself equals: Counter testClassObjectHash => - h := Counter hash. + h := Counter hash self assert: (h > 0) testClassObjectIsNilNotNil => - self deny: (Counter isNil). - self assert: (Counter notNil) + self deny: Counter isNil + self assert: Counter notNil testClassObjectPrintString => - ps := Counter printString. - self deny: (ps isEmpty) + ps := Counter printString + self deny: ps isEmpty testClassObjectInspect => - i := Counter inspect. - self deny: (i isEmpty) + i := Counter inspect + self deny: i isEmpty testClassObjectPerform => self assert: (Counter perform: #name) equals: #Counter @@ -36,29 +36,29 @@ TestCase subclass: ClassObjectDispatchTest // --- Primitive class objects also work --- testPrimitiveClassObjectReflection => - self assert: (Integer respondsTo: #isNil). - self assert: (Integer yourself) equals: Integer. - self assert: (Integer notNil) + self assert: (Integer respondsTo: #isNil) + self assert: Integer yourself equals: Integer + self assert: Integer notNil // --- Pure Beamtalk Behaviour methods (BT-753 converted from @primitive) --- testInheritsFrom => - self assert: (Counter inheritsFrom: Actor). - self assert: (Counter inheritsFrom: Object). - self deny: (Counter inheritsFrom: Counter). + self assert: (Counter inheritsFrom: Actor) + self assert: (Counter inheritsFrom: Object) + self deny: (Counter inheritsFrom: Counter) self deny: (Counter inheritsFrom: Integer) testIncludesBehaviour => - self assert: (Counter includesBehaviour: Counter). - self assert: (Counter includesBehaviour: Actor). - self assert: (Counter includesBehaviour: Object). + self assert: (Counter includesBehaviour: Counter) + self assert: (Counter includesBehaviour: Actor) + self assert: (Counter includesBehaviour: Object) self deny: (Counter includesBehaviour: Integer) testCanUnderstand => - self assert: (Counter canUnderstand: #increment). - self assert: (Counter canUnderstand: #isNil). + self assert: (Counter canUnderstand: #increment) + self assert: (Counter canUnderstand: #isNil) self deny: (Counter canUnderstand: #bogus) testWhichClassIncludesSelector => - self assert: (Counter whichClassIncludesSelector: #increment) equals: Counter. + self assert: (Counter whichClassIncludesSelector: #increment) equals: Counter self assert: (Counter whichClassIncludesSelector: #bogus) equals: nil diff --git a/stdlib/test/class_reflection_test.bt b/stdlib/test/class_reflection_test.bt index 28bb76a50..6ac6e465a 100644 --- a/stdlib/test/class_reflection_test.bt +++ b/stdlib/test/class_reflection_test.bt @@ -3,48 +3,48 @@ // BT-510, BT-776, ADR 0032 Phase 2: Tests class method reflection — methods // returns only methods defined directly on the class, allMethods returns the full -// inheritance chain, and respondsTo: works on class objects. +// inheritance chain, and respondsTo: works on class objects TestCase subclass: ClassReflectionTest testLocalAndFullMethodLists => - counterLocal := Counter methods. - self deny: (counterLocal isEmpty). + counterLocal := Counter methods + self deny: counterLocal isEmpty // Counter defines increment, decrement, getValue locally - self assert: (counterLocal includes: #increment). - self assert: (counterLocal includes: #decrement). - self assert: (counterLocal includes: #getValue). + self assert: (counterLocal includes: #increment) + self assert: (counterLocal includes: #decrement) + self assert: (counterLocal includes: #getValue) // Inherited methods are NOT in methods - self deny: (counterLocal includes: #isNil). - self deny: (counterLocal includes: #respondsTo:). + self deny: (counterLocal includes: #isNil) + self deny: (counterLocal includes: #respondsTo:) // --------------------------------------------------------------------------- - counterMethods := Counter allMethods. + counterMethods := Counter allMethods // Counter allMethods — full inheritance chain - self deny: (counterMethods isEmpty). + self deny: counterMethods isEmpty // Local methods are present - self assert: (counterMethods includes: #increment). + self assert: (counterMethods includes: #increment) // --------------------------------------------------------------------------- - self assert: (counterMethods includes: #getValue). + self assert: (counterMethods includes: #getValue) // Inherited methods ARE in allMethods (full chain) - self assert: (counterMethods includes: #isNil). - self assert: (counterMethods includes: #respondsTo:). + self assert: (counterMethods includes: #isNil) + self assert: (counterMethods includes: #respondsTo:) // --------------------------------------------------------------------------- - intMethods := Integer allMethods. + intMethods := Integer allMethods // Primitive class — full chain still works - self deny: (intMethods isEmpty). + self deny: intMethods isEmpty // isNil is inherited from Object/ProtoObject — included in full chain - self assert: (intMethods includes: #isNil). + self assert: (intMethods includes: #isNil) // --------------------------------------------------------------------------- // BT-776: respondsTo: on class objects (virtual metaclass tag fix) // Class methods defined on Class/Behaviour should be found - self assert: (Counter respondsTo: #name). - self assert: (Counter respondsTo: #superclass). + self assert: (Counter respondsTo: #name) + self assert: (Counter respondsTo: #superclass) // Inherited Object methods should be found - self assert: (Counter respondsTo: #isNil). + self assert: (Counter respondsTo: #isNil) // Non-existent methods should return false self deny: (Counter respondsTo: #bogus) // BT-942: superclass returns correct value via __beamtalk_meta/0 fast path testActorSuperclassReflection => - self assert: (Counter superclass) equals: Actor + self assert: Counter superclass equals: Actor diff --git a/stdlib/test/class_self_dispatch_test.bt b/stdlib/test/class_self_dispatch_test.bt index e8ef39347..53286c434 100644 --- a/stdlib/test/class_self_dispatch_test.bt +++ b/stdlib/test/class_self_dispatch_test.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // BT-773: self and explicit class name in class methods should both use -// direct dispatch (not actor message send) to avoid deadlock. +// direct dispatch (not actor message send) to avoid deadlock TestCase subclass: ClassSelfDispatchTest diff --git a/stdlib/test/class_state_test.bt b/stdlib/test/class_state_test.bt index 5711b919c..407e193f9 100644 --- a/stdlib/test/class_state_test.bt +++ b/stdlib/test/class_state_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-927: BUnit tests for classState declaration and codegen. +// BT-927: BUnit tests for classState declaration and codegen // // Verifies that class-side state declared with `classState:` is correctly: // - Initialized to the declared default value at class registration time @@ -9,48 +9,46 @@ // - Writable via class-side setter methods // - Persistent across multiple class method calls // -// Uses the ClassStateActor fixture (stdlib/test/fixtures/class_state_actor.bt). +// Uses the ClassStateActor fixture (stdlib/test/fixtures/class_state_actor.bt) TestCase subclass: ClassStateTest setUp => - // Reset class state before each test to ensure isolation. - ClassStateActor reset. + // Reset class state before each test to ensure isolation + ClassStateActor reset self testGetterReturnsDefaultValue => - // After reset, counter should be 0 (the declared default). + // After reset, counter should be 0 (the declared default) self assert: ClassStateActor counter equals: 0 testSetterPersistsValue => - // Setting counter to 42 and reading it back should return 42. - ClassStateActor counter: 42. + // Setting counter to 42 and reading it back should return 42 + ClassStateActor counter: 42 self assert: ClassStateActor counter equals: 42 testSetterOverwritesPreviousValue => - // Overwriting the counter value should return the new value. - ClassStateActor counter: 10. - ClassStateActor counter: 99. + // Overwriting the counter value should return the new value + ClassStateActor counter: 10 + ClassStateActor counter: 99 self assert: ClassStateActor counter equals: 99 testMultipleClassStateVariables => - // Both class state variables are independently settable and readable. - ClassStateActor counter: 7. - ClassStateActor label: "hello". - self assert: ClassStateActor counter equals: 7. + // Both class state variables are independently settable and readable + ClassStateActor counter: 7 + ClassStateActor label: "hello" + self assert: ClassStateActor counter equals: 7 self assert: ClassStateActor label equals: "hello" testClassStateIsolatedFromInstanceState => - // Mutating instance state on a spawned actor does not affect class state. - ClassStateActor counter: 55. - actor := ClassStateActor spawn. - actor increment. + // Mutating instance state on a spawned actor does not affect class state + ClassStateActor counter: 55 + actor := ClassStateActor spawn + actor increment self assert: ClassStateActor counter equals: 55 testResetRestoresDefaultValues => - // After setting values, reset should restore declared defaults. - ClassStateActor counter: 999. - ClassStateActor label: "modified". - ClassStateActor reset. - self assert: ClassStateActor counter equals: 0. + // After setting values, reset should restore declared defaults + ClassStateActor counter: 999; label: "modified"; reset + self assert: ClassStateActor counter equals: 0 self assert: ClassStateActor label equals: "unset" diff --git a/stdlib/test/class_variables_singleton_test.bt b/stdlib/test/class_variables_singleton_test.bt index 503e9ecf6..4bd7c7c5c 100644 --- a/stdlib/test/class_variables_singleton_test.bt +++ b/stdlib/test/class_variables_singleton_test.bt @@ -3,22 +3,22 @@ // BT-488, ADR 0019 Phase 1: Tests that singleton classes (BeamtalkInterface, // TranscriptStream, WorkspaceInterface) expose a current accessor that -// returns nil before initialization. +// returns nil before initialization TestCase subclass: ClassVariablesSingletonTest testSingletonCurrentAccessors => - self assert: (BeamtalkInterface current) equals: nil. + self assert: BeamtalkInterface current equals: nil // TranscriptStream has current accessor - self assert: (TranscriptStream current) equals: nil. + self assert: TranscriptStream current equals: nil // WorkspaceInterface has current accessor - self assert: (WorkspaceInterface current) equals: nil + self assert: WorkspaceInterface current equals: nil testSetAndGetCurrent => // Set a BeamtalkInterface instance as current and verify retrieval - prev := BeamtalkInterface current. - sd := BeamtalkInterface spawn. - BeamtalkInterface current: sd. - self assert: (BeamtalkInterface current) equals: sd. + prev := BeamtalkInterface current + sd := BeamtalkInterface spawn + BeamtalkInterface current: sd + self assert: BeamtalkInterface current equals: sd // Restore previous value to avoid affecting other tests BeamtalkInterface current: prev diff --git a/stdlib/test/class_variables_test.bt b/stdlib/test/class_variables_test.bt index be792ec76..080aab0f3 100644 --- a/stdlib/test/class_variables_test.bt +++ b/stdlib/test/class_variables_test.bt @@ -2,20 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 // BT-412: Tests that class variables persist across instance creation and are -// shared by all instances, including when accessed via class-side self-sends. +// shared by all instances, including when accessed via class-side self-sends TestCase subclass: ClassVariablesTest testClassVariablePersistence => - self assert: (ClassVarCounter getCount) equals: 0. + self assert: ClassVarCounter getCount equals: 0 // Create an instance via class method that increments counter - ClassVarCounter create. + ClassVarCounter create // Class variable was incremented - self assert: (ClassVarCounter getCount) equals: 1. + self assert: ClassVarCounter getCount equals: 1 // Create another instance - ClassVarCounter create. + ClassVarCounter create // Class variable persists across calls - self assert: (ClassVarCounter getCount) equals: 2. + self assert: ClassVarCounter getCount equals: 2 // Class method calling another class method (self-send routing) - self assert: (ClassVarCounter createAndReport) equals: 3 + self assert: ClassVarCounter createAndReport equals: 3 diff --git a/stdlib/test/closures_advanced_test.bt b/stdlib/test/closures_advanced_test.bt index 8dbf0d402..8cc0ef970 100644 --- a/stdlib/test/closures_advanced_test.bt +++ b/stdlib/test/closures_advanced_test.bt @@ -6,70 +6,70 @@ TestCase subclass: ClosuresAdvancedTest testBasicClosureCapture => - outer := 10. - self assert: outer equals: 10. - closure := [:x | x + outer]. - self assert: (closure value: 5) equals: 15. + outer := 10 + self assert: outer equals: 10 + closure := [:x | x + outer] + self assert: (closure value: 5) equals: 15 // Verify outer variable unchanged self assert: outer equals: 10 testMultipleCaptures => // Closure capturing multiple variables - base := 100. - self assert: base equals: 100. - multiplier := 2. - self assert: multiplier equals: 2. - compute := [:x | (x + base) * multiplier]. + base := 100 + self assert: base equals: 100 + multiplier := 2 + self assert: multiplier equals: 2 + compute := [:x | (x + base) * multiplier] self assert: (compute value: 50) equals: 300 testNestedClosures => // Closure returning closure (currying pattern) - makeAdder := [:amount | [:value | value + amount]]. - add10 := makeAdder value: 10. - self assert: (add10 value: 5) equals: 15. - self assert: (add10 value: 20) equals: 30. + makeAdder := [:amount | [:value | value + amount]] + add10 := makeAdder value: 10 + self assert: (add10 value: 5) equals: 15 + self assert: (add10 value: 20) equals: 30 // Different closure from same factory - add100 := makeAdder value: 100. + add100 := makeAdder value: 100 self assert: (add100 value: 5) equals: 105 testClosureChains => // Multiple levels of nesting - makeMultiplier := [:factor | [:makeAdder | [:value | (value + makeAdder) * factor]]]. - times2 := makeMultiplier value: 2. - times2Plus10 := times2 value: 10. + makeMultiplier := [:factor | [:makeAdder | [:value | (value + makeAdder) * factor]]] + times2 := makeMultiplier value: 2 + times2Plus10 := times2 value: 10 self assert: (times2Plus10 value: 5) equals: 30 testClosureWithOperators => // Closure using binary operators - threshold := 100. - self assert: threshold equals: 100. - isAboveThreshold := [:n | n > threshold]. - self assert: (isAboveThreshold value: 150). + threshold := 100 + self assert: threshold equals: 100 + isAboveThreshold := [:n | n > threshold] + self assert: (isAboveThreshold value: 150) self deny: (isAboveThreshold value: 50) testSharedCaptures => // Multiple closures sharing same captured variable - shared := 1000. - self assert: shared equals: 1000. - addShared := [:x | x + shared]. - subtractShared := [:x | x - shared]. - multiplyShared := [:x | x * shared]. - self assert: (addShared value: 500) equals: 1500. - self assert: (subtractShared value: 1200) equals: 200. + shared := 1000 + self assert: shared equals: 1000 + addShared := [:x | x + shared] + subtractShared := [:x | x - shared] + multiplyShared := [:x | x * shared] + self assert: (addShared value: 500) equals: 1500 + self assert: (subtractShared value: 1200) equals: 200 self assert: (multiplyShared value: 2) equals: 2000 testClosureComposition => // Using one closure's result as input to another - double := [:x | x * 2]. - addOne := [:x | x + 1]. + double := [:x | x * 2] + addOne := [:x | x + 1] // Apply double first, then addOne - doubleResult := double value: 5. - self assert: doubleResult equals: 10. + doubleResult := double value: 5 + self assert: doubleResult equals: 10 self assert: (addOne value: doubleResult) equals: 11 testDeepNesting => // Three levels deep - level1 := [:a | [:b | [:c | a + b + c]]]. - level2 := level1 value: 1. - level3 := level2 value: 2. + level1 := [:a | [:b | [:c | a + b + c]]] + level2 := level1 value: 1 + level3 := level2 value: 2 self assert: (level3 value: 3) equals: 6 diff --git a/stdlib/test/codegen_doc_test.bt b/stdlib/test/codegen_doc_test.bt index a2e7d7276..34a7df895 100644 --- a/stdlib/test/codegen_doc_test.bt +++ b/stdlib/test/codegen_doc_test.bt @@ -13,15 +13,15 @@ TestCase subclass: CodegenDocTest // --- Method docs from /// comments --- testMethodDocFromTripleSlash => - m := DocCounter >> #increment. + m := DocCounter >> #increment self assert: m doc equals: "Increment the counter by one." testValueMethodDoc => - m := DocCounter >> #value. + m := DocCounter >> #value self assert: m doc equals: "Return the current count." // --- Method without doc comment has nil doc --- testMethodWithoutDocHasNilDoc => - m := DocCounter >> #reset. + m := DocCounter >> #reset self assert: m doc equals: nil diff --git a/stdlib/test/collection_mutations_test.bt b/stdlib/test/collection_mutations_test.bt index 75dc36ea9..cc6472c8e 100644 --- a/stdlib/test/collection_mutations_test.bt +++ b/stdlib/test/collection_mutations_test.bt @@ -2,20 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 // BT-524: Tests that the is_list guard in mutation-threading codegen works -// correctly when actor methods iterate over List, Set, and Dictionary arguments. +// correctly when actor methods iterate over List, Set, and Dictionary arguments TestCase subclass: CollectionMutationsTest testActorMutatingCollections => - counter := CollectionMutationCounter spawn. - self assert: (counter getTotal) equals: 0. - self assert: (counter sumSet: #(1, 2, 3)) equals: 6. - self assert: (counter getTotal) equals: 6. - counter2 := CollectionMutationCounter spawn. - s := (Set new) fromList: #(1, 2, 3). - self assert: (counter2 sumSet: s) equals: 6. - self assert: (counter2 getTotal) equals: 6. - counter3 := CollectionMutationCounter spawn. - self assert: (counter3 sumDictValues: (Dictionary new: #{#a => 10, #b => 20, #c => 30})) equals: 60. - self assert: (counter3 getTotal) equals: 60 + counter := CollectionMutationCounter spawn + self assert: counter getTotal equals: 0 + self assert: (counter sumSet: #(1, 2, 3)) equals: 6 + self assert: counter getTotal equals: 6 + counter2 := CollectionMutationCounter spawn + s := (Set new) fromList: #(1, 2, 3) + self assert: (counter2 sumSet: s) equals: 6 + self assert: counter2 getTotal equals: 6 + counter3 := CollectionMutationCounter spawn + self assert: (counter3 sumDictValues: (Dictionary new: #{#a => 10, #b => 20, #c => 30})) equals: 60 + self assert: counter3 getTotal equals: 60 diff --git a/stdlib/test/collection_protocol_test.bt b/stdlib/test/collection_protocol_test.bt index 469d0333f..8aea9e175 100644 --- a/stdlib/test/collection_protocol_test.bt +++ b/stdlib/test/collection_protocol_test.bt @@ -7,65 +7,65 @@ TestCase subclass: CollectionProtocolTest testSetSharedCollectionProtocolInheritedFromCollection => // Set isEmpty - self assert: (Set new isEmpty). - self deny: ((Set new add: 1) isEmpty). + self assert: Set new isEmpty + self deny: (Set new add: 1) isEmpty // Set isNotEmpty - self assert: ((Set new add: 1) isNotEmpty). - self deny: (Set new isNotEmpty). + self assert: (Set new add: 1) isNotEmpty + self deny: Set new isNotEmpty // Set includes: - self assert: ((Set new add: 1) includes: 1). - self deny: ((Set new add: 1) includes: 2). + self assert: ((Set new add: 1) includes: 1) + self deny: ((Set new add: 1) includes: 2) // Set collect: (inherited from Collection) - self assert: (((Set new add: 1) add: 2) collect: [:x | x * 10]) size equals: 2. + self assert: (((Set new add: 1) add: 2) collect: [:x | x * 10]) size equals: 2 // Set select: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) select: [:x | x > 1]) size equals: 2. + self assert: ((((Set new add: 1) add: 2) add: 3) select: [:x | x > 1]) size equals: 2 // Set reject: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) reject: [:x | x > 2]) size equals: 2. + self assert: ((((Set new add: 1) add: 2) add: 3) reject: [:x | x > 2]) size equals: 2 // Set inject:into: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) inject: 0 into: [:sum :x | sum + x]) equals: 6. + self assert: ((((Set new add: 1) add: 2) add: 3) inject: 0 into: [:sum :x | sum + x]) equals: 6 // Set detect: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) detect: [:x | x > 1]) notNil. + self assert: ((((Set new add: 1) add: 2) add: 3) detect: [:x | x > 1]) notNil // Set detect:ifNone: (inherited from Collection) - self assert: ((Set new add: 1) detect: [:x | x > 5] ifNone: [0]) equals: 0. + self assert: ((Set new add: 1) detect: [:x | x > 5] ifNone: [0]) equals: 0 // Set anySatisfy: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) anySatisfy: [:x | x > 2]). - self deny: (((Set new add: 1) add: 2) anySatisfy: [:x | x > 5]). + self assert: ((((Set new add: 1) add: 2) add: 3) anySatisfy: [:x | x > 2]) + self deny: (((Set new add: 1) add: 2) anySatisfy: [:x | x > 5]) // Set allSatisfy: (inherited from Collection) - self assert: ((((Set new add: 1) add: 2) add: 3) allSatisfy: [:x | x > 0]). + self assert: ((((Set new add: 1) add: 2) add: 3) allSatisfy: [:x | x > 0]) self deny: ((((Set new add: 1) add: 2) add: 3) allSatisfy: [:x | x > 2]) testDictionaryCollectionProtocol => // Dictionary isEmpty (inherited from Collection via size) - self assert: (#{} isEmpty). - self deny: (#{#a => 1} isEmpty). + self assert: #{} isEmpty + self deny: #{#a => 1} isEmpty // Dictionary do: iterates over values - self assert: (#{#a => 10, #b => 20} do: [:v | v + 1]) equals: nil. + self assert: (#{#a => 10, #b => 20} do: [:v | v + 1]) equals: nil // Dictionary includes: checks values - self assert: (#{#a => 1, #b => 2} includes: 1). - self deny: (#{#a => 1, #b => 2} includes: 99). + self assert: (#{#a => 1, #b => 2} includes: 1) + self deny: (#{#a => 1, #b => 2} includes: 99) // Dictionary collect: (inherited from Collection via do:) - self assert: (#{#a => 1, #b => 2} collect: [:v | v * 10]) size equals: 2. + self assert: (#{#a => 1, #b => 2} collect: [:v | v * 10]) size equals: 2 // Dictionary select: (inherited from Collection via do:) - self assert: (#{#a => 1, #b => 2, #c => 3} select: [:v | v > 1]) size equals: 2. + self assert: (#{#a => 1, #b => 2, #c => 3} select: [:v | v > 1]) size equals: 2 // Dictionary inject:into: (inherited from Collection via do:) - self assert: (#{#a => 1, #b => 2, #c => 3} inject: 0 into: [:sum :v | sum + v]) equals: 6. + self assert: (#{#a => 1, #b => 2, #c => 3} inject: 0 into: [:sum :v | sum + v]) equals: 6 // Dictionary detect: (inherited from Collection via do:) - self assert: (#{#a => 1, #b => 5, #c => 3} detect: [:v | v > 4]) equals: 5. + self assert: (#{#a => 1, #b => 5, #c => 3} detect: [:v | v > 4]) equals: 5 // Dictionary detect:ifNone: - self assert: (#{#a => 1} detect: [:v | v > 10] ifNone: [0]) equals: 0. + self assert: (#{#a => 1} detect: [:v | v > 10] ifNone: [0]) equals: 0 // Dictionary anySatisfy: (inherited from Collection) - self assert: (#{#a => 1, #b => 5} anySatisfy: [:v | v > 3]). - self deny: (#{#a => 1, #b => 2} anySatisfy: [:v | v > 5]). + self assert: (#{#a => 1, #b => 5} anySatisfy: [:v | v > 3]) + self deny: (#{#a => 1, #b => 2} anySatisfy: [:v | v > 5]) // Dictionary allSatisfy: (inherited from Collection) - self assert: (#{#a => 2, #b => 4} allSatisfy: [:v | v isEven]). + self assert: (#{#a => 2, #b => 4} allSatisfy: [:v | v isEven]) self deny: (#{#a => 1, #b => 2} allSatisfy: [:v | v isEven]) testTupleCollectionProtocol => // Tuple empty creation - self assert: (Tuple new class) equals: Tuple + self assert: Tuple new class equals: Tuple testClassHierarchyVerification => // Verify superclass chain - self assert: (#(1, 2, 3) class) equals: List. - self assert: (Set new class) equals: Set. - self assert: (#{} class) equals: Dictionary + self assert: #(1, 2, 3) class equals: List + self assert: Set new class equals: Set + self assert: #{} class equals: Dictionary diff --git a/stdlib/test/collections_test.bt b/stdlib/test/collections_test.bt index 4c83a6e7c..777da7864 100644 --- a/stdlib/test/collections_test.bt +++ b/stdlib/test/collections_test.bt @@ -4,136 +4,136 @@ // BT-44, BT-75: Tests List methods — creation, literals, mutation (add:, remove:), // iteration (do:, collect:, select:, reject:, inject:into:), sort, advanced // methods (zip:, groupBy:, partition:), and new methods (++, from:to:, indexOf:, -// eachWithIndex:, intersperse:). +// eachWithIndex:, intersperse:) TestCase subclass: CollectionsTest testCreation => - self assert: (List new) equals: #(). - self assert: ((List new) size) equals: 0. - self assert: ((List new) class) equals: List. + self assert: List new equals: #() + self assert: (List new) size equals: 0 + self assert: (List new) class equals: List // List new: is not supported (no meaningful init-from-map) self should: [List new: #{#a => 1}] raise: #instantiation_error testTier1EssentialMethods => // --- last --- - self assert: (#(1, 2, 3) last) equals: 3. - self assert: (#(42) last) equals: 42. + self assert: #(1, 2, 3) last equals: 3 + self assert: #(42) last equals: 42 // --- at: --- - self assert: (#(10, 20, 30) at: 1) equals: 10. - self assert: (#(10, 20, 30) at: 3) equals: 30. + self assert: (#(10, 20, 30) at: 1) equals: 10 + self assert: (#(10, 20, 30) at: 3) equals: 30 // --- includes: --- - self assert: (#(1, 2, 3) includes: 2). - self deny: (#(1, 2, 3) includes: 5). - self deny: (#() includes: 1). + self assert: (#(1, 2, 3) includes: 2) + self deny: (#(1, 2, 3) includes: 5) + self deny: (#() includes: 1) // --- sort --- - self assert: (#(3, 1, 2) sort) equals: #(1, 2, 3). - self assert: (#() sort) equals: #(). + self assert: #(3, 1, 2) sort equals: #(1, 2, 3) + self assert: #() sort equals: #() // --- reversed --- - self assert: (#(1, 2, 3) reversed) equals: #(3, 2, 1). - self assert: (#() reversed) equals: #(). + self assert: #(1, 2, 3) reversed equals: #(3, 2, 1) + self assert: #() reversed equals: #() // --- detect: --- - self assert: (#(1, 2, 3, 4) detect: [:x | x > 2]) equals: 3. + self assert: (#(1, 2, 3, 4) detect: [:x | x > 2]) equals: 3 // --- detect:ifNone: --- - self assert: (#(1, 2, 3) detect: [:x | x > 10] ifNone: [0]) equals: 0. + self assert: (#(1, 2, 3) detect: [:x | x > 10] ifNone: [0]) equals: 0 self assert: (#(1, 2, 3) detect: [:x | x > 1] ifNone: [0]) equals: 2 testTier2FunctionalMethods => // --- take: --- - self assert: (#(1, 2, 3, 4, 5) take: 3) equals: #(1, 2, 3). - self assert: (#(1, 2) take: 5) equals: #(1, 2). + self assert: (#(1, 2, 3, 4, 5) take: 3) equals: #(1, 2, 3) + self assert: (#(1, 2) take: 5) equals: #(1, 2) // --- drop: --- - self assert: (#(1, 2, 3, 4, 5) drop: 2) equals: #(3, 4, 5). - self assert: (#(1, 2) drop: 5) equals: #(). + self assert: (#(1, 2, 3, 4, 5) drop: 2) equals: #(3, 4, 5) + self assert: (#(1, 2) drop: 5) equals: #() // --- flatten --- - self assert: (#(#(1, 2), #(3, 4)) flatten) equals: #(1, 2, 3, 4). + self assert: #(#(1, 2), #(3, 4)) flatten equals: #(1, 2, 3, 4) // --- flatMap: --- - self assert: (#(1, 2, 3) flatMap: [:x | #(x, (x * 10))]) equals: #(1, 10, 2, 20, 3, 30). + self assert: (#(1, 2, 3) flatMap: [:x | #(x, (x * 10))]) equals: #(1, 10, 2, 20, 3, 30) // --- count: --- - self assert: (#(1, 2, 3, 4, 5) count: [:x | x > 2]) equals: 3. + self assert: (#(1, 2, 3, 4, 5) count: [:x | x > 2]) equals: 3 // --- anySatisfy: --- - self assert: (#(1, 2, 3) anySatisfy: [:x | x > 2]). - self deny: (#(1, 2, 3) anySatisfy: [:x | x > 5]). + self assert: (#(1, 2, 3) anySatisfy: [:x | x > 2]) + self deny: (#(1, 2, 3) anySatisfy: [:x | x > 5]) // --- allSatisfy: --- - self assert: (#(1, 2, 3) allSatisfy: [:x | x > 0]). + self assert: (#(1, 2, 3) allSatisfy: [:x | x > 0]) self deny: (#(1, 2, 3) allSatisfy: [:x | x > 1]) testAddFirst => // --- addFirst: (O(1) cons prepend) --- - self assert: (#(2, 3) addFirst: 1) equals: #(1, 2, 3). + self assert: (#(2, 3) addFirst: 1) equals: #(1, 2, 3) self assert: (#() addFirst: "x") equals: #("x") testTier3AdvancedMethods => // --- unique --- - self assert: (#(3, 1, 2, 1, 3) unique) equals: #(1, 2, 3). + self assert: #(3, 1, 2, 1, 3) unique equals: #(1, 2, 3) // --- takeWhile: --- - self assert: (#(1, 2, 3, 4, 5) takeWhile: [:x | x < 4]) equals: #(1, 2, 3). + self assert: (#(1, 2, 3, 4, 5) takeWhile: [:x | x < 4]) equals: #(1, 2, 3) // --- dropWhile: --- - self assert: (#(1, 2, 3, 4, 5) dropWhile: [:x | x < 3]) equals: #(3, 4, 5). + self assert: (#(1, 2, 3, 4, 5) dropWhile: [:x | x < 3]) equals: #(3, 4, 5) // --- intersperse: --- - self assert: (#(1, 2, 3) intersperse: 0) equals: #(1, 0, 2, 0, 3). - self assert: (#() intersperse: 0) equals: #(). + self assert: (#(1, 2, 3) intersperse: 0) equals: #(1, 0, 2, 0, 3) + self assert: (#() intersperse: 0) equals: #() // --- add: --- - self assert: (#(1, 2, 3) add: 4) equals: #(1, 2, 3, 4). + self assert: (#(1, 2, 3) add: 4) equals: #(1, 2, 3, 4) self assert: (#() add: 1) equals: #(1) testAdvancedMethods => // --- zip: --- - zipped := #(1, 2, 3) zip: #(4, 5, 6). - self assert: (zipped size) equals: 3. + zipped := #(1, 2, 3) zip: #(4, 5, 6) + self assert: zipped size equals: 3 // --- groupBy: --- - grouped := #(1, 2, 3, 4, 5, 6) groupBy: [:x | x isEven]. - self assert: (grouped size) equals: 2. + grouped := #(1, 2, 3, 4, 5, 6) groupBy: [:x | x isEven] + self assert: grouped size equals: 2 // --- partition: --- - partitioned := #(1, 2, 3, 4) partition: [:x | x > 2]. - self assert: (partitioned size) equals: 2. + partitioned := #(1, 2, 3, 4) partition: [:x | x > 2] + self assert: partitioned size equals: 2 // --- sort: (with comparator) --- self assert: (#(3, 1, 2) sort: [:a :b | a >= b]) equals: #(3, 2, 1) testFromToAndIndexOf => // --- ++ (concatenation) --- - self assert: (#(1, 2) ++ #(3, 4)) equals: #(1, 2, 3, 4). - self assert: (#() ++ #(1, 2)) equals: #(1, 2). - self assert: (#(1, 2) ++ #()) equals: #(1, 2). - self assert: (#() ++ #()) equals: #(). + self assert: (#(1, 2) ++ #(3, 4)) equals: #(1, 2, 3, 4) + self assert: (#() ++ #(1, 2)) equals: #(1, 2) + self assert: (#(1, 2) ++ #()) equals: #(1, 2) + self assert: (#() ++ #()) equals: #() // --- from:to: (subsequence, 1-based inclusive) --- - self assert: (#(1, 2, 3, 4, 5) from: 2 to: 4) equals: #(2, 3, 4). + self assert: (#(1, 2, 3, 4, 5) from: 2 to: 4) equals: #(2, 3, 4) // Wildcard for single-element result (Erlang printable_list ambiguity with small integers) - self assert: (#(1, 2, 3, 4, 5) from: 1 to: 1) equals: #(1). + self assert: (#(1, 2, 3, 4, 5) from: 1 to: 1) equals: #(1) // Two-element subsequence verifies inclusive bounds - self assert: (#(1, 2, 3, 4, 5) from: 1 to: 2) equals: #(1, 2). - self assert: (#(1, 2, 3, 4, 5) from: 1 to: 5) equals: #(1, 2, 3, 4, 5). - self assert: (#(1, 2, 3) from: 3 to: 2) equals: #(). + self assert: (#(1, 2, 3, 4, 5) from: 1 to: 2) equals: #(1, 2) + self assert: (#(1, 2, 3, 4, 5) from: 1 to: 5) equals: #(1, 2, 3, 4, 5) + self assert: (#(1, 2, 3) from: 3 to: 2) equals: #() // from:to: beyond list end returns available elements - self assert: (#(1, 2, 3) from: 2 to: 10) equals: #(2, 3). + self assert: (#(1, 2, 3) from: 2 to: 10) equals: #(2, 3) // --- indexOf: (1-based, nil if not found) --- - self assert: (#(10, 20, 30) indexOf: 20) equals: 2. - self assert: (#(10, 20, 30) indexOf: 10) equals: 1. - self assert: (#(10, 20, 30) indexOf: 30) equals: 3. - self assert: (#(10, 20, 30) indexOf: 99) equals: nil. + self assert: (#(10, 20, 30) indexOf: 20) equals: 2 + self assert: (#(10, 20, 30) indexOf: 10) equals: 1 + self assert: (#(10, 20, 30) indexOf: 30) equals: 3 + self assert: (#(10, 20, 30) indexOf: 99) equals: nil // indexOf: returns first match when duplicates exist - self assert: (#(1, 2, 3, 2) indexOf: 2) equals: 2. - self assert: (#() indexOf: 1) equals: nil. + self assert: (#(1, 2, 3, 2) indexOf: 2) equals: 2 + self assert: (#() indexOf: 1) equals: nil // eachWithIndex: returns nil after iterating - self assert: (#(10, 20, 30) eachWithIndex: [:elem :idx | elem + idx]) equals: nil. + self assert: (#(10, 20, 30) eachWithIndex: [:elem :idx | elem + idx]) equals: nil // Verify eachWithIndex: iterates (empty list is a no-op) - self assert: (#() eachWithIndex: [:elem :idx | elem]) equals: nil. + self assert: (#() eachWithIndex: [:elem :idx | elem]) equals: nil // The block receives (elem, idx) — verify it doesn't error with 2-arg block: - self assert: (#(100, 200, 300) eachWithIndex: [:elem :idx | elem + idx]) equals: nil. + self assert: (#(100, 200, 300) eachWithIndex: [:elem :idx | elem + idx]) equals: nil // --- ++ with variables --- - a := #(1, 2, 3). - self assert: a equals: #(1, 2, 3). - // Direct index assertion not possible in E2E since blocks can't accumulate results. + a := #(1, 2, 3) + self assert: a equals: #(1, 2, 3) + // Direct index assertion not possible in E2E since blocks can't accumulate results self assert: (a ++ #(4, 5)) equals: #(1, 2, 3, 4, 5) testJoin => // BT-895: join and join: caused infinite dispatch loop // --- join (no separator) --- - self assert: (#("hello", "world") join) equals: "helloworld". - self assert: (#("a", "b", "c") join) equals: "abc". - self assert: (#() join) equals: "". + self assert: #("hello", "world") join equals: "helloworld" + self assert: #("a", "b", "c") join equals: "abc" + self assert: #() join equals: "" // --- join: (with separator) --- - self assert: (#("a", "b", "c") join: ", ") equals: "a, b, c". - self assert: (#("hello", "world") join: " ") equals: "hello world". - self assert: (#("x") join: ", ") equals: "x". + self assert: (#("a", "b", "c") join: ", ") equals: "a, b, c" + self assert: (#("hello", "world") join: " ") equals: "hello world" + self assert: (#("x") join: ", ") equals: "x" self assert: (#() join: ", ") equals: "" diff --git a/stdlib/test/compiled_method_test.bt b/stdlib/test/compiled_method_test.bt index cdf6019df..319265001 100644 --- a/stdlib/test/compiled_method_test.bt +++ b/stdlib/test/compiled_method_test.bt @@ -7,32 +7,32 @@ TestCase subclass: CompiledMethodTest testMethodLookup => - self assert: (Counter >> #getValue) notNil. + self assert: (Counter >> #getValue) notNil self assert: (Counter >> #nonExistent) equals: nil testMethodLookupOnVariableReceivers => - cls := Counter. - self assert: cls equals: Counter. - self assert: (cls >> #getValue) notNil. - self assert: ((cls >> #getValue) selector) equals: #getValue. + cls := Counter + self assert: cls equals: Counter + self assert: (cls >> #getValue) notNil + self assert: (cls >> #getValue) selector equals: #getValue self assert: (cls >> #nonExistent) equals: nil testClass => - self assert: ((Counter >> #getValue) class) equals: CompiledMethod + self assert: (Counter >> #getValue) class equals: CompiledMethod testSelector => - self assert: ((Counter >> #getValue) selector) equals: #getValue. - self assert: ((Counter >> #increment) selector) equals: #increment + self assert: (Counter >> #getValue) selector equals: #getValue + self assert: (Counter >> #increment) selector equals: #increment testArgumentCount => - self assert: ((Counter >> #getValue) argumentCount) equals: 0. - self assert: ((Counter >> #increment) argumentCount) equals: 0 + self assert: (Counter >> #getValue) argumentCount equals: 0 + self assert: (Counter >> #increment) argumentCount equals: 0 testSource => - self assert: ((Counter >> #getValue) source) equals: "getValue => ^self.value" + self assert: (Counter >> #getValue) source equals: "getValue => self.value" testPrintString => - self assert: ((Counter >> #getValue) printString) equals: "a CompiledMethod(getValue)" + self assert: (Counter >> #getValue) printString equals: "a CompiledMethod(getValue)" testLookupOnNonClass => // >> on non-class value produces type_error @@ -40,4 +40,4 @@ TestCase subclass: CompiledMethodTest self should: [42 >> #foo] raise: #type_error testAsString => - self assert: ((Counter >> #getValue) asString) equals: "a CompiledMethod(getValue)" + self assert: (Counter >> #getValue) asString equals: "a CompiledMethod(getValue)" diff --git a/stdlib/test/counter_test.bt b/stdlib/test/counter_test.bt index 1394aa677..670b84f60 100644 --- a/stdlib/test/counter_test.bt +++ b/stdlib/test/counter_test.bt @@ -7,7 +7,7 @@ TestCase subclass: CounterTest testInitialValue => - self assert: (Counter spawn getValue) equals: 0 + self assert: Counter spawn getValue equals: 0 testIncrement => - self assert: (Counter spawn increment) equals: 1 + self assert: Counter spawn increment equals: 1 diff --git a/stdlib/test/custom_collection_test.bt b/stdlib/test/custom_collection_test.bt index 6dd4845b9..61480ea20 100644 --- a/stdlib/test/custom_collection_test.bt +++ b/stdlib/test/custom_collection_test.bt @@ -2,67 +2,67 @@ // SPDX-License-Identifier: Apache-2.0 // BT-815: Tests that a user-defined Collection subclass (implementing only -// do: and size) correctly inherits the abstract Collection protocol. +// do: and size) correctly inherits the abstract Collection protocol TestCase subclass: CustomCollectionTest testInheritedInjectInto => - col := NumberList new: #{#items => #(1, 2, 3)}. - self assert: (col inject: 0 into: [:sum :x | sum + x]) equals: 6. - // Non-commutative: verifies block arg order is (accumulator, element). + col := NumberList new: #{#items => #(1, 2, 3)} + self assert: (col inject: 0 into: [:sum :x | sum + x]) equals: 6 + // Non-commutative: verifies block arg order is (accumulator, element) self assert: (col inject: #() into: [:acc :x | acc addFirst: x]) equals: #(3, 2, 1) testInheritedCollect => - col := NumberList new: #{#items => #(1, 2, 3)}. + col := NumberList new: #{#items => #(1, 2, 3)} self assert: (col collect: [:x | x * 2]) equals: #(2, 4, 6) testInheritedSelect => - col := NumberList new: #{#items => #(1, 2, 3, 4)}. + col := NumberList new: #{#items => #(1, 2, 3, 4)} self assert: (col select: [:x | x > 2]) equals: #(3, 4) testInheritedReject => - col := NumberList new: #{#items => #(1, 2, 3, 4)}. + col := NumberList new: #{#items => #(1, 2, 3, 4)} self assert: (col reject: [:x | x > 2]) equals: #(1, 2) testInheritedIncludes => - col := NumberList new: #{#items => #(1, 2, 3)}. - self assert: (col includes: 2). + col := NumberList new: #{#items => #(1, 2, 3)} + self assert: (col includes: 2) self deny: (col includes: 9) testInheritedIsEmpty => - empty := NumberList new: #{#items => #()}. - self assert: empty isEmpty. - self deny: empty isNotEmpty. - col := NumberList new: #{#items => #(1)}. - self deny: col isEmpty. + empty := NumberList new: #{#items => #()} + self assert: empty isEmpty + self deny: empty isNotEmpty + col := NumberList new: #{#items => #(1)} + self deny: col isEmpty self assert: col isNotEmpty testInheritedDetect => - col := NumberList new: #{#items => #(1, 2, 3)}. + col := NumberList new: #{#items => #(1, 2, 3)} self assert: (col detect: [:x | x > 1]) equals: 2 testInheritedDetectIfNone => - col := NumberList new: #{#items => #(1, 2, 3)}. + col := NumberList new: #{#items => #(1, 2, 3)} self assert: (col detect: [:x | x > 10] ifNone: [0]) equals: 0 testInheritedAnySatisfy => - col := NumberList new: #{#items => #(1, 2, 3)}. - self assert: (col anySatisfy: [:x | x > 2]). + col := NumberList new: #{#items => #(1, 2, 3)} + self assert: (col anySatisfy: [:x | x > 2]) self deny: (col anySatisfy: [:x | x > 5]) testInheritedAllSatisfy => - col := NumberList new: #{#items => #(1, 2, 3)}. - self assert: (col allSatisfy: [:x | x > 0]). + col := NumberList new: #{#items => #(1, 2, 3)} + self assert: (col allSatisfy: [:x | x > 0]) self deny: (col allSatisfy: [:x | x > 1]) testEmptyCollectionEdgeCases => - empty := NumberList new: #{#items => #()}. - self assert: (empty inject: 0 into: [:acc :x | acc + x]) equals: 0. - self assert: (empty collect: [:x | x * 2]) equals: #(). - self assert: (empty select: [:x | x > 0]) equals: #(). - self assert: (empty reject: [:x | x > 0]) equals: #(). - self deny: (empty includes: 1). - self assert: (empty detect: [:x | x > 0]) equals: nil. - self assert: (empty detect: [:x | x > 0] ifNone: [42]) equals: 42. - self deny: (empty anySatisfy: [:x | x > 0]). + empty := NumberList new: #{#items => #()} + self assert: (empty inject: 0 into: [:acc :x | acc + x]) equals: 0 + self assert: (empty collect: [:x | x * 2]) equals: #() + self assert: (empty select: [:x | x > 0]) equals: #() + self assert: (empty reject: [:x | x > 0]) equals: #() + self deny: (empty includes: 1) + self assert: (empty detect: [:x | x > 0]) equals: nil + self assert: (empty detect: [:x | x > 0] ifNone: [42]) equals: 42 + self deny: (empty anySatisfy: [:x | x > 0]) self assert: (empty allSatisfy: [:x | x > 0]) diff --git a/stdlib/test/custom_exceptions_test.bt b/stdlib/test/custom_exceptions_test.bt index eaa77f007..b79a375dc 100644 --- a/stdlib/test/custom_exceptions_test.bt +++ b/stdlib/test/custom_exceptions_test.bt @@ -6,62 +6,62 @@ TestCase subclass: CustomExceptionsTest testSignalFromCustomErrorRaisesWithCorrectClass => - result := [MyCustomError new signal: "oops"] on: Exception do: [:e | e class]. + result := [MyCustomError new signal: "oops"] on: Exception do: [:e | e class] self assert: result equals: MyCustomError testSignalNoArgsOnCustomErrorRaisesWithClassName => - result := [MyCustomError new signal] on: Exception do: [:e | e class]. + result := [MyCustomError new signal] on: Exception do: [:e | e class] self assert: result equals: MyCustomError testSignalNoArgsMessageIsClassName => - result := [MyCustomError new signal] on: Exception do: [:e | e message]. + result := [MyCustomError new signal] on: Exception do: [:e | e message] self assert: result equals: "MyCustomError" testSignalPreservesMessage => - result := [MyCustomError new signal: "custom message"] on: Exception do: [:e | e message]. + result := [MyCustomError new signal: "custom message"] on: Exception do: [:e | e message] self assert: result equals: "custom message" testSignalPreservesKind => - result := [MyCustomError new signal: "test"] on: Exception do: [:e | e kind]. + result := [MyCustomError new signal: "test"] on: Exception do: [:e | e kind] self assert: result equals: #signal testCatchByExactClass => // on: MyCustomError do: catches MyCustomError - result := [MyCustomError new signal: "caught"] on: MyCustomError do: [:e | e message]. + result := [MyCustomError new signal: "caught"] on: MyCustomError do: [:e | e message] self assert: result equals: "caught" testCatchByParentClass => // on: Error do: catches MyCustomError (Error is superclass) - result := [MyCustomError new signal: "err"] on: Error do: [:e | "caught by Error"]. + result := [MyCustomError new signal: "err"] on: Error do: [:e | "caught by Error"] self assert: result equals: "caught by Error" testCatchByRootException => // on: Exception do: catches MyCustomError (Exception is root) - result := [MyCustomError new signal: "exc"] on: Exception do: [:e | "caught by Exception"]. + result := [MyCustomError new signal: "exc"] on: Exception do: [:e | "caught by Exception"] self assert: result equals: "caught by Exception" testNonMatchingClassTypeError => // on: TypeError do: does NOT catch MyCustomError - result := [[MyCustomError new signal: "no"] on: TypeError do: [:e | "wrong"]] on: Exception do: [:e | "correct"]. + result := [[MyCustomError new signal: "no"] on: TypeError do: [:e | "wrong"]] on: Exception do: [:e | "correct"] self assert: result equals: "correct" testNonMatchingClassRuntimeError => // on: RuntimeError do: does NOT catch MyCustomError - result := [[MyCustomError new signal: "no"] on: RuntimeError do: [:e | "wrong"]] on: Exception do: [:e | "correct"]. + result := [[MyCustomError new signal: "no"] on: RuntimeError do: [:e | "wrong"]] on: Exception do: [:e | "correct"] self assert: result equals: "correct" testBuiltInDoesNotUnderstandStillWorks => // Built-in does_not_understand still maps to RuntimeError @expect dnu - result := [42 noSuchMethod] on: RuntimeError do: [:e | e class]. + result := [42 noSuchMethod] on: RuntimeError do: [:e | e class] self assert: result equals: RuntimeError testBuiltInDivisionByZero => // Built-in division by zero raises an exception - result := [1 / 0] on: Exception do: [:e | "caught"]. + result := [1 / 0] on: Exception do: [:e | "caught"] self assert: result equals: "caught" testReSignalingCaughtCustomException => // Re-signaling a caught custom exception preserves its class - result := [[MyCustomError new signal: "re-test"] on: MyCustomError do: [:e | e signal: "forwarded"]] on: MyCustomError do: [:e | e message]. + result := [[MyCustomError new signal: "re-test"] on: MyCustomError do: [:e | e signal: "forwarded"]] on: MyCustomError do: [:e | e message] self assert: result equals: "forwarded" diff --git a/stdlib/test/datetime_test.bt b/stdlib/test/datetime_test.bt index 8bd886e97..9d7009c81 100644 --- a/stdlib/test/datetime_test.bt +++ b/stdlib/test/datetime_test.bt @@ -6,35 +6,35 @@ TestCase subclass: DateTimeTest testConstructionYearMonthDay => - dt := DateTime year: 2026 month: 2 day: 18. - self assert: (dt class) equals: DateTime + dt := DateTime year: 2026 month: 2 day: 18 + self assert: dt class equals: DateTime testConstructionYearMonthDayHourMinuteSecond => // Construct a full DateTime - dt2 := DateTime year: 2026 month: 2 day: 18 hour: 10 minute: 30 second: 0. - self assert: (dt2 class) equals: DateTime + dt2 := DateTime year: 2026 month: 2 day: 18 hour: 10 minute: 30 second: 0 + self assert: dt2 class equals: DateTime testConstructionFromtimestamp => // Unix epoch is 1970-01-01 - epoch := DateTime fromTimestamp: 0. - self assert: (epoch year) equals: 1970. - self assert: (epoch month) equals: 1. - self assert: (epoch day) equals: 1. - self assert: (epoch hour) equals: 0 + epoch := DateTime fromTimestamp: 0 + self assert: epoch year equals: 1970 + self assert: epoch month equals: 1 + self assert: epoch day equals: 1 + self assert: epoch hour equals: 0 testConstructionFromstring => // Parse ISO 8601 string - parsed := DateTime fromString: "2026-02-18T10:30:00Z". - self assert: (parsed year) equals: 2026. - self assert: (parsed month) equals: 2. - self assert: (parsed day) equals: 18. - self assert: (parsed hour) equals: 10. - self assert: (parsed minute) equals: 30. - self assert: (parsed second) equals: 0 + parsed := DateTime fromString: "2026-02-18T10:30:00Z" + self assert: parsed year equals: 2026 + self assert: parsed month equals: 2 + self assert: parsed day equals: 18 + self assert: parsed hour equals: 10 + self assert: parsed minute equals: 30 + self assert: parsed second equals: 0 testConstructionNow => // DateTime now returns a DateTime - self assert: ((DateTime now) class) equals: DateTime. + self assert: (DateTime now) class equals: DateTime // now has a year >= 2026 self assert: ((DateTime now) year >= 2026) @@ -43,81 +43,81 @@ TestCase subclass: DateTimeTest self assert: ((DateTime monotonicNow) class =:= Integer) testAccessors => - a := DateTime year: 2026 month: 3 day: 15 hour: 14 minute: 45 second: 30. - self assert: (a year) equals: 2026. - self assert: (a month) equals: 3. - self assert: (a day) equals: 15. - self assert: (a hour) equals: 14. - self assert: (a minute) equals: 45. - self assert: (a second) equals: 30 + a := DateTime year: 2026 month: 3 day: 15 hour: 14 minute: 45 second: 30 + self assert: a year equals: 2026 + self assert: a month equals: 3 + self assert: a day equals: 15 + self assert: a hour equals: 14 + self assert: a minute equals: 45 + self assert: a second equals: 30 testConversionAstimestamp => // Unix epoch round-trip - self assert: ((DateTime fromTimestamp: 0) asTimestamp) equals: 0. + self assert: (DateTime fromTimestamp: 0) asTimestamp equals: 0 // Known timestamp round-trip - ts := (DateTime year: 2026 month: 1 day: 1) asTimestamp. - self assert: ((DateTime fromTimestamp: ts) year) equals: 2026. - self assert: ((DateTime fromTimestamp: ts) month) equals: 1. - self assert: ((DateTime fromTimestamp: ts) day) equals: 1 + ts := (DateTime year: 2026 month: 1 day: 1) asTimestamp + self assert: (DateTime fromTimestamp: ts) year equals: 2026 + self assert: (DateTime fromTimestamp: ts) month equals: 1 + self assert: (DateTime fromTimestamp: ts) day equals: 1 testConversionAsstring => // Date-only formats with zero time - self assert: ((DateTime year: 2026 month: 2 day: 18) asString) equals: "2026-02-18T00:00:00Z". + self assert: (DateTime year: 2026 month: 2 day: 18) asString equals: "2026-02-18T00:00:00Z" // Full datetime format - self assert: ((DateTime year: 2026 month: 2 day: 18 hour: 10 minute: 30 second: 0) asString) equals: "2026-02-18T10:30:00Z" + self assert: (DateTime year: 2026 month: 2 day: 18 hour: 10 minute: 30 second: 0) asString equals: "2026-02-18T10:30:00Z" testConversionPrintstring => self assert: ((DateTime year: 2026 month: 2 day: 18) printString) notNil testArithmeticAddseconds => // Add one hour - self assert: (((DateTime year: 2026 month: 1 day: 1) addSeconds: 3600) hour) equals: 1. + self assert: ((DateTime year: 2026 month: 1 day: 1) addSeconds: 3600) hour equals: 1 // Add negative seconds (subtract) - self assert: (((DateTime year: 2026 month: 1 day: 1 hour: 1 minute: 0 second: 0) addSeconds: -3600) hour) equals: 0 + self assert: ((DateTime year: 2026 month: 1 day: 1 hour: 1 minute: 0 second: 0) addSeconds: -3600) hour equals: 0 testArithmeticAdddays => // Add 7 days - self assert: (((DateTime year: 2026 month: 1 day: 1) addDays: 7) day) equals: 8. + self assert: ((DateTime year: 2026 month: 1 day: 1) addDays: 7) day equals: 8 // Add days across month boundary - self assert: (((DateTime year: 2026 month: 1 day: 30) addDays: 3) month) equals: 2. - self assert: (((DateTime year: 2026 month: 1 day: 30) addDays: 3) day) equals: 2 + self assert: ((DateTime year: 2026 month: 1 day: 30) addDays: 3) month equals: 2 + self assert: ((DateTime year: 2026 month: 1 day: 30) addDays: 3) day equals: 2 testArithmeticDiffseconds => // One day difference - b := DateTime year: 2026 month: 1 day: 2. - c := DateTime year: 2026 month: 1 day: 1. - self assert: (b diffSeconds: c) equals: 86400. + b := DateTime year: 2026 month: 1 day: 2 + c := DateTime year: 2026 month: 1 day: 1 + self assert: (b diffSeconds: c) equals: 86400 // Negative difference (reverse) - self assert: (c diffSeconds: b) equals: -86400. + self assert: (c diffSeconds: b) equals: -86400 // Zero difference self assert: (c diffSeconds: c) equals: 0 testComparison => - d := DateTime year: 2026 month: 1 day: 1. - e := DateTime year: 2026 month: 1 day: 2. - self assert: (d < e). - self deny: (e < d). - self deny: (d > e). - self assert: (e > d). - self assert: (d <= e). - self assert: (d <= d). - self deny: (d >= e). - self assert: (d >= d). - self assert: (d =:= d). - self deny: (d =:= e). - self assert: (d /= e). + d := DateTime year: 2026 month: 1 day: 1 + e := DateTime year: 2026 month: 1 day: 2 + self assert: (d < e) + self deny: (e < d) + self deny: (d > e) + self assert: (e > d) + self assert: (d <= e) + self assert: (d <= d) + self deny: (d >= e) + self assert: (d >= d) + self assert: (d =:= d) + self deny: (d =:= e) + self assert: (d /= e) self deny: (d /= d) testErrorHandling => // Invalid date raises error - self should: [DateTime year: 2026 month: 13 day: 1] raise: #type_error. + self should: [DateTime year: 2026 month: 13 day: 1] raise: #type_error // Invalid time raises error - self should: [DateTime year: 2026 month: 1 day: 1 hour: 25 minute: 0 second: 0] raise: #type_error. + self should: [DateTime year: 2026 month: 1 day: 1 hour: 25 minute: 0 second: 0] raise: #type_error // Invalid string format raises error - self should: [DateTime fromString: "not-a-date"] raise: #type_error. + self should: [DateTime fromString: "not-a-date"] raise: #type_error // Non-integer argument raises error @expect type - self should: [DateTime fromTimestamp: "hello"] raise: #type_error. + self should: [DateTime fromTimestamp: "hello"] raise: #type_error // diffSeconds: with non-DateTime raises error @expect type self should: [(DateTime year: 2026 month: 1 day: 1) diffSeconds: "hello"] raise: #type_error diff --git a/stdlib/test/dictionary_test.bt b/stdlib/test/dictionary_test.bt index 2ca7b15d9..fd062cbeb 100644 --- a/stdlib/test/dictionary_test.bt +++ b/stdlib/test/dictionary_test.bt @@ -6,81 +6,81 @@ TestCase subclass: DictionaryTest testCreation => - self assert: (Dictionary new) equals: #{}. - self assert: ((Dictionary new) size) equals: 0. - self assert: ((Dictionary new) class) equals: Dictionary. + self assert: Dictionary new equals: #{} + self assert: (Dictionary new) size equals: 0 + self assert: (Dictionary new) class equals: Dictionary // Dictionary new: initializes with given entries - self assert: (Dictionary new: #{#x => 10, #y => 20}) equals: #{#x => 10, #y => 20}. - self assert: ((Dictionary new: #{#x => 10, #y => 20}) size) equals: 2. - self assert: ((Dictionary new: #{#x => 10}) at: #x) equals: 10. - self assert: ((Dictionary new: #{#x => 10}) class) equals: Dictionary + self assert: (Dictionary new: #{#x => 10, #y => 20}) equals: #{#x => 10, #y => 20} + self assert: (Dictionary new: #{#x => 10, #y => 20}) size equals: 2 + self assert: ((Dictionary new: #{#x => 10}) at: #x) equals: 10 + self assert: (Dictionary new: #{#x => 10}) class equals: Dictionary testClass => - self assert: (#{#a => 1} class) equals: Dictionary. - self assert: (#{} class) equals: Dictionary + self assert: #{#a => 1} class equals: Dictionary + self assert: #{} class equals: Dictionary testSize => - self assert: (#{#a => 1, #b => 2, #c => 3} size) equals: 3. - self assert: (#{} size) equals: 0 + self assert: #{#a => 1, #b => 2, #c => 3} size equals: 3 + self assert: #{} size equals: 0 testKeysValues => - self assert: (#{#x => 10} keys) equals: #(#x). - self assert: (#{#x => 10} values) equals: #(10) + self assert: #{#x => 10} keys equals: #(#x) + self assert: #{#x => 10} values equals: #(10) testAtLookup => - self assert: (#{#name => "Alice", #age => 30} at: #name) equals: "Alice". + self assert: (#{#name => "Alice", #age => 30} at: #name) equals: "Alice" self assert: (#{#x => 42} at: #x) equals: 42 testAtPutInsertUpdateReturnsNewDictionary => - d := #{#x => 1}. - self assert: d equals: #{#x => 1}. - self assert: (d at: #y put: 2) equals: #{#x => 1, #y => 2}. - self assert: ((#{#a => 1} at: #b put: 2) size) equals: 2. + d := #{#x => 1} + self assert: d equals: #{#x => 1} + self assert: (d at: #y put: 2) equals: #{#x => 1, #y => 2} + self assert: (#{#a => 1} at: #b put: 2) size equals: 2 self assert: ((#{#a => 1} at: #a put: 99) at: #a) equals: 99 testAtIfabsentLookupWithDefault => - self assert: (#{#a => 1} at: #a ifAbsent: [42]) equals: 1. + self assert: (#{#a => 1} at: #a ifAbsent: [42]) equals: 1 self assert: (#{#a => 1} at: #b ifAbsent: [42]) equals: 42 testIncludeskey => - self assert: (#{#a => 1, #b => 2} includesKey: #a). - self deny: (#{#a => 1, #b => 2} includesKey: #c). + self assert: (#{#a => 1, #b => 2} includesKey: #a) + self deny: (#{#a => 1, #b => 2} includesKey: #c) self deny: (#{} includesKey: #x) testRemovekey => - self assert: ((#{#a => 1, #b => 2} removeKey: #a) size) equals: 1. + self assert: (#{#a => 1, #b => 2} removeKey: #a) size equals: 1 self deny: ((#{#a => 1, #b => 2} removeKey: #a) includesKey: #a) testMerge => - d1 := #{#a => 1, #b => 2}. - self assert: d1 equals: #{#a => 1, #b => 2}. - d2 := #{#b => 20, #c => 3}. - self assert: d2 equals: #{#b => 20, #c => 3}. - self assert: (d1 merge: d2) equals: #{#a => 1, #b => 20, #c => 3}. + d1 := #{#a => 1, #b => 2} + self assert: d1 equals: #{#a => 1, #b => 2} + d2 := #{#b => 20, #c => 3} + self assert: d2 equals: #{#b => 20, #c => 3} + self assert: (d1 merge: d2) equals: #{#a => 1, #b => 20, #c => 3} self assert: ((#{#a => 1} merge: #{#a => 99}) at: #a) equals: 99 testKeysandvaluesdo => // Returns nil - self assert: (#{#a => 1} keysAndValuesDo: [:k :v | nil]) equals: nil. + self assert: (#{#a => 1} keysAndValuesDo: [:k :v | nil]) equals: nil // Works for empty dictionary - self assert: (#{} keysAndValuesDo: [:k :v | nil]) equals: nil. + self assert: (#{} keysAndValuesDo: [:k :v | nil]) equals: nil // Works for multi-entry dictionary - self assert: (#{#a => 1, #b => 2} keysAndValuesDo: [:k :v | nil]) equals: nil. + self assert: (#{#a => 1, #b => 2} keysAndValuesDo: [:k :v | nil]) equals: nil // Block receives correct key (#a) and value (99) — raises if wrong values passed self assert: (#{#a => 99} keysAndValuesDo: [:k :v | - (k =:= #a) ifFalse: [k error: "unexpected key"]. + (k =:= #a) ifFalse: [k error: "unexpected key"] (v =:= 99) ifFalse: [v error: "unexpected value"]]) equals: nil testNestedDictionaries => // Nested dictionaries display correctly - self assert: #{#a => #{#x => 1}} equals: #{#a => #{#x => 1}}. + self assert: #{#a => #{#x => 1}} equals: #{#a => #{#x => 1}} // Empty nested dictionary self assert: #{#a => #{}} equals: #{#a => #{}} testBinaryExpressionsInMapValues => // Simple arithmetic in map value - self assert: #{#x => 1 + 2} equals: #{#x => 3}. + self assert: #{#x => 1 + 2} equals: #{#x => 3} // Multiple binary expressions in values - self assert: #{#x => 1 + 2, #y => 3 * 4} equals: #{#x => 3, #y => 12}. + self assert: #{#x => 1 + 2, #y => 3 * 4} equals: #{#x => 3, #y => 12} // Subtraction in map value self assert: #{#result => 10 - 3} equals: #{#result => 7} diff --git a/stdlib/test/display_string_test.bt b/stdlib/test/display_string_test.bt index cd3cd6191..9fdd0ab23 100644 --- a/stdlib/test/display_string_test.bt +++ b/stdlib/test/display_string_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-929: Tests for displayString / printString two-protocol distinction. +// BT-929: Tests for displayString / printString two-protocol distinction // printString = developer representation (unambiguous, quoted strings, #symbol) // displayString = user-facing representation (no quotes, no # prefix) @@ -9,29 +9,29 @@ TestCase subclass: DisplayStringTest testStringPrintString => // printString adds surrounding quotes for developer inspection - self assert: ("hello" printString) equals: """hello""" + self assert: "hello" printString equals: """hello""" testStringDisplayString => // displayString returns the raw string (no quotes) - self assert: ("hello" displayString) equals: "hello" + self assert: "hello" displayString equals: "hello" testStringPrintStringIsDifferentFromDisplayString => // The two should differ for strings (printString adds quotes) self deny: ("hello" printString =:= "hello" displayString) testEmptyStringPrintString => - self assert: ("" printString) equals: """""" + self assert: "" printString equals: """""" testEmptyStringDisplayString => - self assert: ("" displayString) equals: "" + self assert: "" displayString equals: "" testSymbolPrintString => // printString includes the # prefix - self assert: (#hello printString) equals: "#hello" + self assert: #hello printString equals: "#hello" testSymbolDisplayString => // displayString omits the # prefix - self assert: (#hello displayString) equals: "hello" + self assert: #hello displayString equals: "hello" testSymbolPrintStringIsDifferentFromDisplayString => // The two should differ for symbols @@ -39,28 +39,28 @@ TestCase subclass: DisplayStringTest testIntegerDisplayString => // Integer inherits displayString from Object, delegates to printString - self assert: (42 displayString) equals: "42" + self assert: 42 displayString equals: "42" testIntegerDisplayStringNegative => - self assert: (-7 displayString) equals: "-7" + self assert: -7 displayString equals: "-7" testObjectDisplayStringDelegatesToPrintString => // Object.displayString delegates to printString by default - self assert: (42 displayString) equals: (42 printString) + self assert: 42 displayString equals: 42 printString - // BT-933: printString must escape embedded double-quote characters by doubling them. + // BT-933: printString must escape embedded double-quote characters by doubling them testStringWithEmbeddedQuotePrintString => - // "a""b" is the string a"b; printString doubles the embedded " and wraps in outer quotes. + // "a""b" is the string a"b; printString doubles the embedded " and wraps in outer quotes // Result is "a""b" (6 chars), written as Beamtalk literal: """a""""b""" - self assert: ("a""b" printString) equals: """a""""b""" + self assert: "a""b" printString equals: """a""""b""" testStringThatIsJustAQuotePrintString => // """" is the string containing one "; printString produces """" (4 chars: " "" ") // That 4-char string as a Beamtalk literal is: """""""""" - self assert: ("""" printString) equals: """""""""" + self assert: """" printString equals: """""""""" testStringWithMultipleEmbeddedQuotesPrintString => - // "a""b""c" is the string a"b"c; printString doubles each " and wraps. + // "a""b""c" is the string a"b"c; printString doubles each " and wraps // Result: "a""b""c" (8 chars), as Beamtalk: """a""""b""""c""" - self assert: ("a""b""c" printString) equals: """a""""b""""c""" + self assert: "a""b""c" printString equals: """a""""b""""c""" diff --git a/stdlib/test/doc_test_example.bt b/stdlib/test/doc_test_example.bt index 4c88aef6e..bb9ac0211 100644 --- a/stdlib/test/doc_test_example.bt +++ b/stdlib/test/doc_test_example.bt @@ -3,7 +3,7 @@ // BUnit test: verify doc test extraction from /// doc comments (BT-441) -/// A simple calculator for testing doc test extraction. +/// A simple calculator for testing doc test extraction /// /// ## Examples /// ```beamtalk @@ -12,14 +12,14 @@ /// ``` Object subclass: DocTestExample - /// Compute the answer to life, the universe, and everything. + /// Compute the answer to life, the universe, and everything /// /// ```beamtalk /// 42 // => 42 /// ``` answer => 42 - /// Demonstrate stateful doc examples with variables. + /// Demonstrate stateful doc examples with variables /// /// ```beamtalk /// x := 10 diff --git a/stdlib/test/empty_method_self_test.bt b/stdlib/test/empty_method_self_test.bt index e1ea41c22..a4151d288 100644 --- a/stdlib/test/empty_method_self_test.bt +++ b/stdlib/test/empty_method_self_test.bt @@ -2,16 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 // BT-631/BT-859: Tests that an actor method explicitly returning self -// returns the actor reference and that reference is usable for further messages. +// returns the actor reference and that reference is usable for further messages TestCase subclass: EmptyMethodSelfTest testDoNothingReturnsSelf => - a := EmptyMethodActor spawn. + a := EmptyMethodActor spawn // Call method that explicitly returns self - ref := a doNothing. + ref := a doNothing // Returned reference should be the same actor - self assert: (ref =:= a). + self assert: (ref =:= a) // Verify by reading state through the returned reference - self assert: (ref getValue) equals: 42 + self assert: ref getValue equals: 42 diff --git a/stdlib/test/erlang_interop_test.bt b/stdlib/test/erlang_interop_test.bt index ba8276a18..d0fa8a2fd 100644 --- a/stdlib/test/erlang_interop_test.bt +++ b/stdlib/test/erlang_interop_test.bt @@ -7,17 +7,17 @@ TestCase subclass: ErlangInteropTest testModuleProxyConstruction => // Unary message on Erlang constructs ErlangModule proxy - self assert: ((Erlang lists) class) equals: ErlangModule. - self assert: ((Erlang maps) class) equals: ErlangModule. - self assert: ((Erlang erlang) class) equals: ErlangModule + self assert: (Erlang lists) class equals: ErlangModule + self assert: (Erlang maps) class equals: ErlangModule + self assert: (Erlang erlang) class equals: ErlangModule testErlangFunctionCallsKeywordMessages => // Single keyword: lists:reverse/1 - self assert: (Erlang lists reverse: #(3, 2, 1)) equals: #(1, 2, 3). + self assert: (Erlang lists reverse: #(3, 2, 1)) equals: #(1, 2, 3) // Multi-keyword: maps:merge/2 - self assert: (Erlang maps merge: #{#a => 1} with: #{#b => 2}) equals: #{#a => 1, #b => 2}. + self assert: (Erlang maps merge: #{#a => 1} with: #{#b => 2}) equals: #{#a => 1, #b => 2} // lists:seq/2 - self assert: (Erlang lists seq: 1 with: 5) equals: #(1, 2, 3, 4, 5). + self assert: (Erlang lists seq: 1 with: 5) equals: #(1, 2, 3, 4, 5) // lists:nth/2 self assert: (Erlang lists nth: 2 with: #(10, 20, 30)) equals: 20 @@ -27,8 +27,8 @@ TestCase subclass: ErlangInteropTest testCachedProxy => // Store proxy in variable and reuse - proxy := Erlang lists. - self assert: (proxy reverse: #(1, 2, 3)) equals: #(3, 2, 1). + proxy := Erlang lists + self assert: (proxy reverse: #(1, 2, 3)) equals: #(3, 2, 1) self assert: (proxy reverse: #(#a, #b, #c)) equals: #(#c, #b, #a) testClassProtocolOnErlang => @@ -37,21 +37,21 @@ TestCase subclass: ErlangInteropTest self assert: (Erlang class) isMeta equals: true testProxyObjectProtocol => - proxy := Erlang lists. - self assert: (proxy class) equals: ErlangModule. - self assert: (proxy == proxy). - self deny: (proxy isNil). - self assert: (proxy notNil) + proxy := Erlang lists + self assert: proxy class equals: ErlangModule + self assert: (proxy == proxy) + self deny: proxy isNil + self assert: proxy notNil testBt682DirectCallVsProxyEquivalence => // Single-arg keyword: direct vs proxy - directResult := Erlang lists reverse: #(1, 2, 3). - // produce identical results. - proxyLists := Erlang lists. + directResult := Erlang lists reverse: #(1, 2, 3) + // produce identical results + proxyLists := Erlang lists // Verify optimized (direct call) and unoptimized (cached proxy) paths - proxyResult := proxyLists reverse: #(1, 2, 3). - self assert: (directResult =:= proxyResult). + proxyResult := proxyLists reverse: #(1, 2, 3) + self assert: (directResult =:= proxyResult) // Multi-arg keyword: direct vs proxy - directSeq := Erlang lists seq: 1 with: 5. - proxySeq := proxyLists seq: 1 with: 5. + directSeq := Erlang lists seq: 1 with: 5 + proxySeq := proxyLists seq: 1 with: 5 self assert: (directSeq =:= proxySeq) diff --git a/stdlib/test/error_message_test.bt b/stdlib/test/error_message_test.bt index 42fe031a3..adf3abb5b 100644 --- a/stdlib/test/error_message_test.bt +++ b/stdlib/test/error_message_test.bt @@ -2,27 +2,27 @@ // SPDX-License-Identifier: Apache-2.0 // BT-932: BUnit failure messages — verify raw BEAM errors are decoded -// into human-readable messages instead of raw Erlang term formatting. +// into human-readable messages instead of raw Erlang term formatting // // ErrorMessageHelperTest defines methods that intentionally trigger raw BEAM // errors. They are NOT prefixed with "test" so BUnit will not auto-discover // them. ErrorMessageTest runs each helper method via TestRunner run:method: -// and checks that the resulting failure messages are human-readable. +// and checks that the resulting failure messages are human-readable TestCase subclass: ErrorMessageTest testBadkeyMessageIsReadable => - result := TestRunner run: ErrorMessageHelperTest method: #triggerBadkey. - self assert: (result failed) equals: 1. - failures := result failures. - errorMsg := (failures first) at: #error. + result := TestRunner run: ErrorMessageHelperTest method: #triggerBadkey + self assert: result failed equals: 1 + failures := result failures + errorMsg := (failures first) at: #error // Should say "not found in dictionary" instead of raw {badkey,...} - self assert: (errorMsg includesSubstring: "not found in dictionary"). + self assert: (errorMsg includesSubstring: "not found in dictionary") testBadarithMessageIsReadable => - result := TestRunner run: ErrorMessageHelperTest method: #triggerBadarith. - self assert: (result failed) equals: 1. - failures := result failures. - errorMsg := (failures first) at: #error. + result := TestRunner run: ErrorMessageHelperTest method: #triggerBadarith + self assert: result failed equals: 1 + failures := result failures + errorMsg := (failures first) at: #error // Should say "bad arithmetic" instead of raw badarith atom - self assert: (errorMsg includesSubstring: "bad arithmetic"). + self assert: (errorMsg includesSubstring: "bad arithmetic") diff --git a/stdlib/test/error_method_test.bt b/stdlib/test/error_method_test.bt index 6ee833354..975aaeec1 100644 --- a/stdlib/test/error_method_test.bt +++ b/stdlib/test/error_method_test.bt @@ -7,33 +7,33 @@ TestCase subclass: ErrorMethodTest testBasicErrorOnPrimitives => - self assert: ([42 error: "too big"] on: Exception do: [:e | e message]) equals: "too big". + self assert: ([42 error: "too big"] on: Exception do: [:e | e message]) equals: "too big" // Integer error: has user_error kind - self assert: ([42 error: "too big"] on: Exception do: [:e | e kind]) equals: #user_error. + self assert: ([42 error: "too big"] on: Exception do: [:e | e kind]) equals: #user_error // Integer error: has correct class - self assert: ([42 error: "too big"] on: Exception do: [:e | e errorClass]) equals: #Integer. + self assert: ([42 error: "too big"] on: Exception do: [:e | e errorClass]) equals: #Integer // String error: works - self assert: (["hello" error: "bad string"] on: Exception do: [:e | e message]) equals: "bad string". + self assert: (["hello" error: "bad string"] on: Exception do: [:e | e message]) equals: "bad string" // String error: has correct class self assert: (["hello" error: "bad string"] on: Exception do: [:e | e errorClass]) equals: #String testErrorOnValueTypes => // Value type error: is catchable - v := Validator new. - self assert: ([v check: -1] on: Exception do: [:e | e message]) equals: "must be non-negative". + v := Validator new + self assert: ([v check: -1] on: Exception do: [:e | e message]) equals: "must be non-negative" // Value type error: has correct class - self assert: ([v check: -1] on: Exception do: [:e | e errorClass]) equals: #Validator. + self assert: ([v check: -1] on: Exception do: [:e | e errorClass]) equals: #Validator // Value type error: has user_error kind - self assert: ([v check: -1] on: Exception do: [:e | e kind]) equals: #user_error. + self assert: ([v check: -1] on: Exception do: [:e | e kind]) equals: #user_error // No error when valid self assert: (v check: 5) equals: 5 testErrorWithNonStringArgument => // Integer error message is coerced — raises user_error not type_error @expect type - self should: [42 error: 99] raise: #user_error. + self should: [42 error: 99] raise: #user_error // Verify kind and errorClass via on:do: @expect type - self assert: ([42 error: 99] on: Exception do: [:e | e kind]) equals: #user_error. + self assert: ([42 error: 99] on: Exception do: [:e | e kind]) equals: #user_error @expect type self assert: ([42 error: 99] on: Exception do: [:e | e errorClass]) equals: #Integer diff --git a/stdlib/test/exception_mutations_test.bt b/stdlib/test/exception_mutations_test.bt index e0ad7ec1d..af375a996 100644 --- a/stdlib/test/exception_mutations_test.bt +++ b/stdlib/test/exception_mutations_test.bt @@ -3,30 +3,30 @@ // BT-410: Tests that actor state mutations inside on:do: error handlers and // ensure: cleanup blocks are correctly threaded — mutations accumulate across -// multiple calls and both try-body and cleanup mutations are preserved. +// multiple calls and both try-body and cleanup mutations are preserved TestCase subclass: ExceptionMutationsTest testMutationsInOnDoAndEnsure => - c := ErrorCounter spawn. - c riskyIncrement. + c := ErrorCounter spawn + c riskyIncrement // Verify errorCount was mutated by the handler - self assert: (c getErrorCount) equals: 1. + self assert: c getErrorCount equals: 1 // Value should be unchanged (try body failed before mutation completed) - self assert: (c getValue) equals: 0. - c riskyIncrement. + self assert: c getValue equals: 0 + c riskyIncrement // Call again to verify mutation accumulates - self assert: (c getErrorCount) equals: 2. + self assert: c getErrorCount equals: 2 // Spawn a fresh actor - d := ErrorCounter spawn. - d safeIncrementWithCleanup. + d := ErrorCounter spawn + d safeIncrementWithCleanup // Value should be incremented by the try body - self assert: (d getValue) equals: 1. + self assert: d getValue equals: 1 // errorCount should be incremented by the cleanup block - self assert: (d getErrorCount) equals: 1. - d safeIncrementWithCleanup. + self assert: d getErrorCount equals: 1 + d safeIncrementWithCleanup // Call again to verify both accumulate - self assert: (d getValue) equals: 2. + self assert: d getValue equals: 2 // safeIncrementWithCleanup: body increments value, cleanup increments errorCount - self assert: (d getErrorCount) equals: 2 + self assert: d getErrorCount equals: 2 diff --git a/stdlib/test/field_mutations_do_test.bt b/stdlib/test/field_mutations_do_test.bt index 2449e31e0..93484fd02 100644 --- a/stdlib/test/field_mutations_do_test.bt +++ b/stdlib/test/field_mutations_do_test.bt @@ -3,28 +3,28 @@ // BT-98: Tests that actor field mutations inside do: loops and inject:into: blocks // are correctly threaded through the state monad — setValue, sumArray via do:, -// sumWithInject:, and multi-field accumulation (sum, count, product). +// sumWithInject:, and multi-field accumulation (sum, count, product) TestCase subclass: FieldMutationsDoTest testFieldMutationsWithSetAndDo => - counter := FieldMutationCounter spawn. - self assert: (counter getValue) equals: 0. - self assert: (counter setValue: 5) equals: 5. - self assert: (counter getValue) equals: 5. - self assert: (counter setValue: 10) equals: 10. - self assert: (counter getValue) equals: 10. - self assert: (counter setValue: 0) equals: 0. - self assert: (counter sumArray: #(1, 2, 3)) equals: 6. - self assert: (counter getValue) equals: 6. - self assert: (counter setValue: 0) equals: 0. - self assert: (counter sumArray: #(10, 20, 30)) equals: 60. - self assert: (counter getValue) equals: 60. - self assert: (counter sumWithInject: #(1, 2, 3)) equals: 6. - self assert: (counter sumWithInject: #(100, 200, 300)) equals: 600. - acc := FieldMutationAccumulator spawn. - self assert: (acc processArray: #(2, 3, 4)) equals: #{#count => 3, #product => 24, #sum => 9}. - self assert: (acc getSum) equals: 9. - self assert: (acc getProduct) equals: 24. - self assert: (acc getCount) equals: 3 + counter := FieldMutationCounter spawn + self assert: counter getValue equals: 0 + self assert: (counter setValue: 5) equals: 5 + self assert: counter getValue equals: 5 + self assert: (counter setValue: 10) equals: 10 + self assert: counter getValue equals: 10 + self assert: (counter setValue: 0) equals: 0 + self assert: (counter sumArray: #(1, 2, 3)) equals: 6 + self assert: counter getValue equals: 6 + self assert: (counter setValue: 0) equals: 0 + self assert: (counter sumArray: #(10, 20, 30)) equals: 60 + self assert: counter getValue equals: 60 + self assert: (counter sumWithInject: #(1, 2, 3)) equals: 6 + self assert: (counter sumWithInject: #(100, 200, 300)) equals: 600 + acc := FieldMutationAccumulator spawn + self assert: (acc processArray: #(2, 3, 4)) equals: #{#count => 3, #product => 24, #sum => 9} + self assert: acc getSum equals: 9 + self assert: acc getProduct equals: 24 + self assert: acc getCount equals: 3 diff --git a/stdlib/test/file_io_test.bt b/stdlib/test/file_io_test.bt index ae988456b..5f2504eca 100644 --- a/stdlib/test/file_io_test.bt +++ b/stdlib/test/file_io_test.bt @@ -9,59 +9,59 @@ TestCase subclass: FileIoTest self deny: (File exists: "target/bt-test-tmp/nonexistent_xyzzy.txt") testFileWritingAndReading => - self assert: (File writeAll: "target/bt-test-tmp/test.txt" contents: "Hello, Beamtalk!") equals: nil. - self assert: (File readAll: "target/bt-test-tmp/test.txt") equals: "Hello, Beamtalk!". + self assert: (File writeAll: "target/bt-test-tmp/test.txt" contents: "Hello, Beamtalk!") equals: nil + self assert: (File readAll: "target/bt-test-tmp/test.txt") equals: "Hello, Beamtalk!" self assert: (File exists: "target/bt-test-tmp/test.txt") testOverwriteExistingFile => - self assert: (File writeAll: "target/bt-test-tmp/test.txt" contents: "New content") equals: nil. + self assert: (File writeAll: "target/bt-test-tmp/test.txt" contents: "New content") equals: nil self assert: (File readAll: "target/bt-test-tmp/test.txt") equals: "New content" testSpecialCharacters => - self assert: (File writeAll: "target/bt-test-tmp/special.txt" contents: "Hello, World! @#$%") equals: nil. + self assert: (File writeAll: "target/bt-test-tmp/special.txt" contents: "Hello, World! @#$%") equals: nil self assert: (File readAll: "target/bt-test-tmp/special.txt") equals: "Hello, World! @#$%" testEmptyFile => - self assert: (File writeAll: "target/bt-test-tmp/empty.txt" contents: "") equals: nil. - self assert: (File readAll: "target/bt-test-tmp/empty.txt") equals: "". + self assert: (File writeAll: "target/bt-test-tmp/empty.txt" contents: "") equals: nil + self assert: (File readAll: "target/bt-test-tmp/empty.txt") equals: "" self assert: (File exists: "target/bt-test-tmp/empty.txt") testSecurityPathValidation => - self deny: (File exists: "/etc/passwd"). - self deny: (File exists: "../passwords.txt"). + self deny: (File exists: "/etc/passwd") + self deny: (File exists: "../passwords.txt") // Windows-style absolute paths - self deny: (File exists: "C:\\Windows\\system32"). + self deny: (File exists: "C:\\Windows\\system32") // Backslash absolute paths self deny: (File exists: "\\\\server\\share") testErrorPathsReadall => // readAll: nonexistent file - self should: [File readAll: "target/bt-test-tmp/no_such_file_xyz.txt"] raise: #file_not_found. + self should: [File readAll: "target/bt-test-tmp/no_such_file_xyz.txt"] raise: #file_not_found // readAll: non-string path @expect type - self should: [File readAll: 42] raise: #type_error. + self should: [File readAll: 42] raise: #type_error // readAll: absolute path - self should: [File readAll: "/etc/passwd"] raise: #invalid_path. + self should: [File readAll: "/etc/passwd"] raise: #invalid_path // readAll: directory traversal self should: [File readAll: "../secret.txt"] raise: #invalid_path testErrorPathsWriteallContents => // writeAll: non-string path @expect type - self should: [File writeAll: 42 contents: "data"] raise: #type_error. + self should: [File writeAll: 42 contents: "data"] raise: #type_error // writeAll: non-string contents @expect type - self should: [File writeAll: "target/bt-test-tmp/test.txt" contents: 42] raise: #type_error. + self should: [File writeAll: "target/bt-test-tmp/test.txt" contents: 42] raise: #type_error // writeAll: absolute path - self should: [File writeAll: "/tmp/evil.txt" contents: "data"] raise: #invalid_path. + self should: [File writeAll: "/tmp/evil.txt" contents: "data"] raise: #invalid_path // writeAll: directory traversal self should: [File writeAll: "../evil.txt" contents: "data"] raise: #invalid_path testSubdirectoryCreation => // writeAll: creates parent directories automatically - self assert: (File writeAll: "target/bt-test-tmp/subdir/nested.txt" contents: "nested") equals: nil. + self assert: (File writeAll: "target/bt-test-tmp/subdir/nested.txt" contents: "nested") equals: nil self assert: (File readAll: "target/bt-test-tmp/subdir/nested.txt") equals: "nested" testUnicodeContent => - self assert: (File writeAll: "target/bt-test-tmp/unicode.txt" contents: "Hello 世界 🌍") equals: nil. + self assert: (File writeAll: "target/bt-test-tmp/unicode.txt" contents: "Hello 世界 🌍") equals: nil self assert: (File readAll: "target/bt-test-tmp/unicode.txt") equals: "Hello 世界 🌍" diff --git a/stdlib/test/file_stream_test.bt b/stdlib/test/file_stream_test.bt index e22e3905c..2cc04ab00 100644 --- a/stdlib/test/file_stream_test.bt +++ b/stdlib/test/file_stream_test.bt @@ -6,58 +6,58 @@ TestCase subclass: FileStreamTest testFileLinesBasicReading => - self assert: ((File lines: "test/fixtures/stream_test.txt") asList) equals: #("line one", "line two", "line three"). + self assert: (File lines: "test/fixtures/stream_test.txt") asList equals: #("line one", "line two", "line three") // Take first N lines - self assert: ((File lines: "test/fixtures/stream_test.txt") take: 2) equals: #("line one", "line two"). + self assert: ((File lines: "test/fixtures/stream_test.txt") take: 2) equals: #("line one", "line two") // Take more lines than exist - self assert: ((File lines: "test/fixtures/stream_test.txt") take: 100) equals: #("line one", "line two", "line three"). + self assert: ((File lines: "test/fixtures/stream_test.txt") take: 100) equals: #("line one", "line two", "line three") // Single line file (no trailing newline) - self assert: ((File lines: "test/fixtures/stream_single.txt") asList) equals: #("only line"). + self assert: (File lines: "test/fixtures/stream_single.txt") asList equals: #("only line") // File without trailing newline - self assert: ((File lines: "test/fixtures/stream_no_trailing.txt") asList) equals: #("first", "second") + self assert: (File lines: "test/fixtures/stream_no_trailing.txt") asList equals: #("first", "second") testEmptyFile => // Empty file returns empty stream - self assert: ((File lines: "test/fixtures/stream_empty.txt") asList) equals: #(). + self assert: (File lines: "test/fixtures/stream_empty.txt") asList equals: #() self assert: ((File lines: "test/fixtures/stream_empty.txt") take: 5) equals: #() testStreamPipelineComposition => // Select lines matching a pattern - self assert: (((File lines: "test/fixtures/stream_test.txt") select: [:l | l includesSubstring:"two"]) asList) equals: #("line two"). + self assert: ((File lines: "test/fixtures/stream_test.txt") select: [:l | l includesSubstring:"two"]) asList equals: #("line two") // Collect (transform) lines - self assert: (((File lines: "test/fixtures/stream_test.txt") collect: [:l | l size]) asList) equals: #(8, 8, 10). + self assert: ((File lines: "test/fixtures/stream_test.txt") collect: [:l | l size]) asList equals: #(8, 8, 10) // Drop first line - self assert: (((File lines: "test/fixtures/stream_test.txt") drop: 1) asList) equals: #("line two", "line three"). + self assert: ((File lines: "test/fixtures/stream_test.txt") drop: 1) asList equals: #("line two", "line three") // Inject (fold) - count lines - self assert: ((File lines: "test/fixtures/stream_test.txt") inject: 0 into: [:count :line | count + 1]) equals: 3. + self assert: ((File lines: "test/fixtures/stream_test.txt") inject: 0 into: [:count :line | count + 1]) equals: 3 // Detect first matching line - self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"three"]) equals: "line three". + self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"three"]) equals: "line three" // Detect returns nil when no match - self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"four"]) equals: nil. + self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"four"]) equals: nil // anySatisfy - self assert: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"one"]). - self deny: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"four"]). + self assert: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"one"]) + self deny: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"four"]) // allSatisfy - self assert: ((File lines: "test/fixtures/stream_test.txt") allSatisfy: [:l | l includesSubstring:"line"]). + self assert: ((File lines: "test/fixtures/stream_test.txt") allSatisfy: [:l | l includesSubstring:"line"]) self deny: ((File lines: "test/fixtures/stream_test.txt") allSatisfy: [:l | l includesSubstring:"one"]) testFileOpenDoBlockScopedHandle => // Read lines through handle - self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines asList]) equals: #("line one", "line two", "line three"). + self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines asList]) equals: #("line one", "line two", "line three") // Take lines through handle - self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines take: 1]) equals: #("line one"). + self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines take: 1]) equals: #("line one") // Pipeline through handle - self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | (handle lines select: [:l | l includesSubstring:"two"]) asList]) equals: #("line two"). + self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | (handle lines select: [:l | l includesSubstring:"two"]) asList]) equals: #("line two") // Block returns result - self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines inject: 0 into: [:count :line | count + 1]]) equals: 3. + self assert: (File open: "test/fixtures/stream_test.txt" do: [:handle | handle lines inject: 0 into: [:count :line | count + 1]]) equals: 3 // Empty file through handle self assert: (File open: "test/fixtures/stream_empty.txt" do: [:handle | handle lines asList]) equals: #() testLazyEvaluationConstantMemory => // take: only reads needed lines (lazy) - self assert: ((File lines: "test/fixtures/stream_large.txt") take: 3) equals: #("a", "b", "c"). + self assert: ((File lines: "test/fixtures/stream_large.txt") take: 3) equals: #("a", "b", "c") // Chained lazy operations - self assert: (((File lines: "test/fixtures/stream_large.txt") drop: 5) take: 3) equals: #("f", "g", "h"). + self assert: (((File lines: "test/fixtures/stream_large.txt") drop: 5) take: 3) equals: #("f", "g", "h") // reject: with lazy evaluation self assert: (((File lines: "test/fixtures/stream_large.txt") reject: [:l | l =:= "e"]) take: 5) equals: #("a", "b", "c", "d", "f") @@ -70,50 +70,50 @@ TestCase subclass: FileStreamTest testStreamFinalizerPartialConsumption => // take: on file stream closes handle via finalizer - self assert: ((File lines: "test/fixtures/stream_test.txt") take: 1) equals: #("line one"). + self assert: ((File lines: "test/fixtures/stream_test.txt") take: 1) equals: #("line one") // detect: on file stream closes handle via finalizer - self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"two"]) equals: "line two". + self assert: ((File lines: "test/fixtures/stream_test.txt") detect: [:l | l includesSubstring:"two"]) equals: "line two" // anySatisfy: on file stream closes handle via finalizer - self assert: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"one"]). + self assert: ((File lines: "test/fixtures/stream_test.txt") anySatisfy: [:l | l includesSubstring:"one"]) // allSatisfy: on file stream with early exit closes handle via finalizer - self deny: ((File lines: "test/fixtures/stream_large.txt") allSatisfy: [:l | l =:= "a"]). + self deny: ((File lines: "test/fixtures/stream_large.txt") allSatisfy: [:l | l =:= "a"]) // Pipeline with finalizer propagation: select + take - self assert: (((File lines: "test/fixtures/stream_test.txt") select: [:l | l includesSubstring:"line"]) take: 2) equals: #("line one", "line two"). + self assert: (((File lines: "test/fixtures/stream_test.txt") select: [:l | l includesSubstring:"line"]) take: 2) equals: #("line one", "line two") // Pipeline with finalizer propagation: collect + take - self assert: (((File lines: "test/fixtures/stream_large.txt") collect: [:l | l size]) take: 3) equals: #(1, 1, 1). + self assert: (((File lines: "test/fixtures/stream_large.txt") collect: [:l | l size]) take: 3) equals: #(1, 1, 1) // Pipeline with finalizer propagation: drop + take - self assert: (((File lines: "test/fixtures/stream_large.txt") drop: 2) take: 2) equals: #("c", "d"). + self assert: (((File lines: "test/fixtures/stream_large.txt") drop: 2) take: 2) equals: #("c", "d") // Pipeline with finalizer propagation: reject + detect self assert: (((File lines: "test/fixtures/stream_test.txt") reject: [:l | l includesSubstring:"one"]) detect: [:l | l includesSubstring:"two"]) equals: "line two" testErrorPaths => // File not found - self should: [File lines: "test/fixtures/nonexistent.txt"] raise: #file_not_found. + self should: [File lines: "test/fixtures/nonexistent.txt"] raise: #file_not_found // Type error: non-string path @expect type - self should: [File lines: 42] raise: #type_error. + self should: [File lines: 42] raise: #type_error // File not found with open:do: self should: [File open: "test/fixtures/nonexistent.txt" do: [:h | h lines asList]] raise: #file_not_found testErrorPathsTypeErrors => // Type errors that produce compile-time warnings but still run correctly @expect type - self should: [File open: 42 do: [:h | h lines asList]] raise: #type_error. + self should: [File open: 42 do: [:h | h lines asList]] raise: #type_error @expect type - self should: [File open: "test/fixtures/stream_test.txt" do: "not a block"] raise: #type_error. + self should: [File open: "test/fixtures/stream_test.txt" do: "not a block"] raise: #type_error // lines: with absolute path (security) - self should: [File lines: "/etc/passwd"] raise: #invalid_path. + self should: [File lines: "/etc/passwd"] raise: #invalid_path // lines: with directory traversal - self should: [File lines: "../secret.txt"] raise: #invalid_path. + self should: [File lines: "../secret.txt"] raise: #invalid_path // open:do: with absolute path - self should: [File open: "/etc/passwd" do: [:h | h lines asList]] raise: #invalid_path. + self should: [File open: "/etc/passwd" do: [:h | h lines asList]] raise: #invalid_path // open:do: with directory traversal self should: [File open: "../secret.txt" do: [:h | h lines asList]] raise: #invalid_path testWindowsStyleLineEndingsRN => // Windows CRLF line endings are stripped correctly - self assert: ((File lines: "test/fixtures/stream_crlf.txt") asList) equals: #("alpha", "beta", "gamma") + self assert: (File lines: "test/fixtures/stream_crlf.txt") asList equals: #("alpha", "beta", "gamma") testUnicodeFileContent => // Unicode content (multi-byte UTF-8) reads correctly through streams - self assert: ((File lines: "test/fixtures/stream_unicode.txt") asList) equals: #("Hello 世界", "café", "über") + self assert: (File lines: "test/fixtures/stream_unicode.txt") asList equals: #("Hello 世界", "café", "über") diff --git a/stdlib/test/fixtures/abstract_shape.bt b/stdlib/test/fixtures/abstract_shape.bt index 7066b8bbe..da62f5115 100644 --- a/stdlib/test/fixtures/abstract_shape.bt +++ b/stdlib/test/fixtures/abstract_shape.bt @@ -10,4 +10,4 @@ abstract Actor subclass: Shape // Abstract method — subclasses must override area => self subclassResponsibility - getName => ^self.name + getName => self.name diff --git a/stdlib/test/fixtures/actor_chaining_fixture.bt b/stdlib/test/fixtures/actor_chaining_fixture.bt index b961ce09e..d62b10b12 100644 --- a/stdlib/test/fixtures/actor_chaining_fixture.bt +++ b/stdlib/test/fixtures/actor_chaining_fixture.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-840: Fixture actor for message chaining tests. +// BT-840: Fixture actor for message chaining tests Actor subclass: ActorChainingFixture state: value = 0 diff --git a/stdlib/test/fixtures/actor_class_local_var.bt b/stdlib/test/fixtures/actor_class_local_var.bt index c8c0e75d4..b18b6e7f6 100644 --- a/stdlib/test/fixtures/actor_class_local_var.bt +++ b/stdlib/test/fixtures/actor_class_local_var.bt @@ -1,26 +1,26 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-741: Test fixture for class methods on Actor subclasses with local variables. -// Class methods must NOT inject the actor State parameter. +// BT-741: Test fixture for class methods on Actor subclasses with local variables +// Class methods must NOT inject the actor State parameter Actor subclass: ActorClassLocalVar state: value = 0 - // BT-741: Class method with local variable creation and method calls on it. + // BT-741: Class method with local variable creation and method calls on it // Previously triggered: {unbound_var, 'State', {class_buildDict, 2}} class buildDict => d := #{} d2 := d at: #key put: 42 d2 - // BT-741: Class method with arithmetic on local variables. + // BT-741: Class method with arithmetic on local variables class computeSum => x := 10 y := 20 x + y - // BT-741: Class method with block literal as local variable. + // BT-741: Class method with block literal as local variable class applyBlock => transform := [:x | x * 2] transform value: 21 diff --git a/stdlib/test/fixtures/actor_collect_counter.bt b/stdlib/test/fixtures/actor_collect_counter.bt index fbd3931bf..e6b7c3467 100644 --- a/stdlib/test/fixtures/actor_collect_counter.bt +++ b/stdlib/test/fixtures/actor_collect_counter.bt @@ -3,34 +3,34 @@ // BT-904: Actor fixture for testing self-sends inside collect:/select:/reject: // blocks. Self-sends in actor blocks need state threading because they may -// mutate actor state. +// mutate actor state Actor subclass: ActorCollectCounter state: count = 0 - getCount => ^self.count + getCount => self.count // Helper: increments count and returns formatted item processItem: item => - self.count := self.count + 1. - ^item * 2 + self.count := self.count + 1 + item * 2 // collect: with self-send — needs state threading doubleAll: items => - ^items collect: [:item | self processItem: item] + items collect: [:item | self processItem: item] // select: with self-send — needs state threading selectPositive: items => - ^items select: [:item | self checkPositive: item] + items select: [:item | self checkPositive: item] // reject: with self-send — needs state threading rejectNegative: items => - ^items reject: [:item | self checkNegative: item] + items reject: [:item | self checkNegative: item] // collect: with field assignment in block — direct field mutation doubleAllWithFieldMutation: items => - ^items collect: [:item | - self.count := self.count + 1. + items collect: [:item | + self.count := self.count + 1 item * 2 ] @@ -40,15 +40,15 @@ Actor subclass: ActorCollectCounter // do: with self-send — already works (has state threading) countAll: items => - items do: [:item | self processItem: item]. - ^self.count + items do: [:item | self processItem: item] + self.count // Helper for select: checkPositive: item => - self.count := self.count + 1. - ^item > 0 + self.count := self.count + 1 + item > 0 // Helper for reject: checkNegative: item => - self.count := self.count + 1. - ^item < 0 + self.count := self.count + 1 + item < 0 diff --git a/stdlib/test/fixtures/actor_coordination_fixture.bt b/stdlib/test/fixtures/actor_coordination_fixture.bt index 681713585..ff0a2d14d 100644 --- a/stdlib/test/fixtures/actor_coordination_fixture.bt +++ b/stdlib/test/fixtures/actor_coordination_fixture.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-898: Fixture actor for actor-to-actor coordination tests. -// EventCollector receives events forwarded by EventBus. +// BT-898: Fixture actor for actor-to-actor coordination tests +// EventCollector receives events forwarded by EventBus Actor subclass: EventCollector state: events = #() diff --git a/stdlib/test/fixtures/actor_nlr_basic.bt b/stdlib/test/fixtures/actor_nlr_basic.bt index 0c7858586..44b3b7ebf 100644 --- a/stdlib/test/fixtures/actor_nlr_basic.bt +++ b/stdlib/test/fixtures/actor_nlr_basic.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrBasic — ifTrue: non-local return in Actor method. +// BT-761: ActorNlrBasic — ifTrue: non-local return in Actor method Actor subclass: ActorNlrBasic state: x = 0 diff --git a/stdlib/test/fixtures/actor_nlr_computed.bt b/stdlib/test/fixtures/actor_nlr_computed.bt index 972b03c62..fa043614b 100644 --- a/stdlib/test/fixtures/actor_nlr_computed.bt +++ b/stdlib/test/fixtures/actor_nlr_computed.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrComputed — NLR with computed return values in Actor methods. +// BT-761: ActorNlrComputed — NLR with computed return values in Actor methods Actor subclass: ActorNlrComputed state: x = 0 diff --git a/stdlib/test/fixtures/actor_nlr_local_var.bt b/stdlib/test/fixtures/actor_nlr_local_var.bt index 995de1a1f..91481f7ef 100644 --- a/stdlib/test/fixtures/actor_nlr_local_var.bt +++ b/stdlib/test/fixtures/actor_nlr_local_var.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrLocalVar — NLR with local variable bindings in Actor methods. +// BT-761: ActorNlrLocalVar — NLR with local variable bindings in Actor methods Actor subclass: ActorNlrLocalVar state: data = #{} diff --git a/stdlib/test/fixtures/actor_nlr_mutate.bt b/stdlib/test/fixtures/actor_nlr_mutate.bt index e7559ae24..cd93f04a9 100644 --- a/stdlib/test/fixtures/actor_nlr_mutate.bt +++ b/stdlib/test/fixtures/actor_nlr_mutate.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrMutate — NLR after field mutation preserves updated state. +// BT-761: ActorNlrMutate — NLR after field mutation preserves updated state Actor subclass: ActorNlrMutate state: count = 0 diff --git a/stdlib/test/fixtures/actor_nlr_on_do.bt b/stdlib/test/fixtures/actor_nlr_on_do.bt index 8c8634c73..84d0367ba 100644 --- a/stdlib/test/fixtures/actor_nlr_on_do.bt +++ b/stdlib/test/fixtures/actor_nlr_on_do.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrOnDo — NLR throw propagates through on:do: in Actor methods. +// BT-761: ActorNlrOnDo — NLR throw propagates through on:do: in Actor methods Actor subclass: ActorNlrOnDo state: x = 0 diff --git a/stdlib/test/fixtures/actor_nlr_recursive.bt b/stdlib/test/fixtures/actor_nlr_recursive.bt index c3046b093..16a8ba855 100644 --- a/stdlib/test/fixtures/actor_nlr_recursive.bt +++ b/stdlib/test/fixtures/actor_nlr_recursive.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-761: ActorNlrRecursive — NLR in recursive Actor methods. +// BT-761: ActorNlrRecursive — NLR in recursive Actor methods Actor subclass: ActorNlrRecursive state: count = 0 diff --git a/stdlib/test/fixtures/actor_slot_fixture.bt b/stdlib/test/fixtures/actor_slot_fixture.bt index c452375e9..3b5d112e7 100644 --- a/stdlib/test/fixtures/actor_slot_fixture.bt +++ b/stdlib/test/fixtures/actor_slot_fixture.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-916: Actor fixture for testing self.slot := assignment patterns. -// Covers: multiple slots, do: blocks, collect: blocks, and early return (^). +// BT-916: Actor fixture for testing self.slot := assignment patterns +// Covers: multiple slots, do: blocks, collect: blocks, and early return (^) Actor subclass: ActorSlotCounter state: count = 0 @@ -14,51 +14,51 @@ Actor subclass: ActorSlotCounter // Multiple slot assignments in one method incrementBoth: n => - self.count := self.count + 1. - self.total := self.total + n. + self.count := self.count + 1 + self.total := self.total + n #{#count => self.count, #total => self.total} // Multiple sequential assignments to same slot addThrice: n => - self.count := self.count + n. - self.count := self.count + n. - self.count := self.count + n. + self.count := self.count + n + self.count := self.count + n + self.count := self.count + n self.count // Slot assignment inside do: block sumItems: items => - items do: [:item | self.total := self.total + item]. + items do: [:item | self.total := self.total + item] self.total // Slot assignment inside do: block with two slot mutations per iteration countAndSum: items => items do: [:item | - self.count := self.count + 1. + self.count := self.count + 1 self.total := self.total + item - ]. + ] #{#count => self.count, #total => self.total} // Slot assignment inside collect: block (count tracks each element processed) collectDoubled: items => result := items collect: [:item | - self.count := self.count + 1. + self.count := self.count + 1 item * 2 - ]. + ] result // Slot assignment then early return (^) from method body via ifTrue: // Pattern: mutate slot, check condition, return early if met addAndCheckLimit: limit => - self.count := self.count + 1. - self.count >= limit ifTrue: [^#reached]. + self.count := self.count + 1 + self.count >= limit ifTrue: [^#reached] #not_yet // Slot assignment before an early return with a computed value addAndReturnIfAbove: threshold => - self.total := self.total + 1. - self.total > threshold ifTrue: [^self.total]. + self.total := self.total + 1 + self.total > threshold ifTrue: [^self.total] -1 reset => - self.count := 0. + self.count := 0 self.total := 0 diff --git a/stdlib/test/fixtures/circle.bt b/stdlib/test/fixtures/circle.bt index bbf2e51d5..a09dee1cd 100644 --- a/stdlib/test/fixtures/circle.bt +++ b/stdlib/test/fixtures/circle.bt @@ -6,6 +6,6 @@ Actor subclass: Circle state: radius = 0 - area => ^self.radius * self.radius + area => self.radius * self.radius setRadius: r => self.radius := r diff --git a/stdlib/test/fixtures/class_method_self_new.bt b/stdlib/test/fixtures/class_method_self_new.bt index a5f3ffb54..b13373811 100644 --- a/stdlib/test/fixtures/class_method_self_new.bt +++ b/stdlib/test/fixtures/class_method_self_new.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-893: Test fixture for class method self-sends (new/new:/spawn). -// Factory pattern: class methods that call self new: to create instances. +// BT-893: Test fixture for class method self-sends (new/new:/spawn) +// Factory pattern: class methods that call self new: to create instances Object subclass: Shape state: kind = #unknown state: sides = 0 diff --git a/stdlib/test/fixtures/class_state_actor.bt b/stdlib/test/fixtures/class_state_actor.bt index 296da159c..bdd7c275a 100644 --- a/stdlib/test/fixtures/class_state_actor.bt +++ b/stdlib/test/fixtures/class_state_actor.bt @@ -1,33 +1,33 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-927: Test fixture for classState declaration and codegen. +// BT-927: Test fixture for classState declaration and codegen // -// Provides an Actor subclass with classState variables for round-trip testing. +// Provides an Actor subclass with classState variables for round-trip testing // Tests: initial value, setter, getter, multiple independent class variables, -// and independence from instance-level state mutations. +// and independence from instance-level state mutations Actor subclass: ClassStateActor classState: counter = 0 classState: label = "unset" state: value = 0 - /// Return the class-level counter value. + /// Return the class-level counter value class counter => self.counter - /// Set the class-level counter. + /// Set the class-level counter class counter: n => self.counter := n - /// Return the class-level label value. + /// Return the class-level label value class label => self.label - /// Set the class-level label. + /// Set the class-level label class label: s => self.label := s - /// Increment the instance-level value (independent from class state). + /// Increment the instance-level value (independent from class state) increment => self.value := self.value + 1 - /// Reset all class state to defaults. + /// Reset all class state to defaults class reset => - self.counter := 0. + self.counter := 0 self.label := "unset" diff --git a/stdlib/test/fixtures/conditional_mutation_counter.bt b/stdlib/test/fixtures/conditional_mutation_counter.bt index 1758b0e2a..f64436f67 100644 --- a/stdlib/test/fixtures/conditional_mutation_counter.bt +++ b/stdlib/test/fixtures/conditional_mutation_counter.bt @@ -1,39 +1,39 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-915: Actor fixture for testing self.slot := inside conditional blocks. -// Exercises ifTrue:, ifFalse:, and ifTrue:ifFalse: with field mutation threading. +// BT-915: Actor fixture for testing self.slot := inside conditional blocks +// Exercises ifTrue:, ifFalse:, and ifTrue:ifFalse: with field mutation threading Actor subclass: ConditionalMutationCounter state: count = 0 // Increment count only when flag is true conditionalIncrement: flag => - flag ifTrue: [self.count := self.count + 1]. + flag ifTrue: [self.count := self.count + 1] self.count // Decrement count only when flag is false conditionalDecrement: flag => - flag ifFalse: [self.count := self.count - 1]. + flag ifFalse: [self.count := self.count - 1] self.count // Two-branch conditional: +10 if true, -1 if false conditionalToggle: flag => flag ifTrue: [self.count := self.count + 10] - ifFalse: [self.count := self.count - 1]. + ifFalse: [self.count := self.count - 1] self.count // Method with two sequential conditional mutations doubleConditional: a and: b => - a ifTrue: [self.count := self.count + 1]. - b ifTrue: [self.count := self.count + 10]. + a ifTrue: [self.count := self.count + 1] + b ifTrue: [self.count := self.count + 10] self.count // Nested conditionals: outer and inner both have mutations nestedConditional: outer and: inner => outer ifTrue: [ inner ifTrue: [self.count := self.count + 100] - ]. + ] self.count // Conditional as last expression (no trailing self.count) diff --git a/stdlib/test/fixtures/counter.bt b/stdlib/test/fixtures/counter.bt index 094c68ebf..52565c354 100644 --- a/stdlib/test/fixtures/counter.bt +++ b/stdlib/test/fixtures/counter.bt @@ -9,4 +9,4 @@ Actor subclass: Counter increment => self.value := self.value + 1 decrement => self.value := self.value - 1 - getValue => ^self.value + getValue => self.value diff --git a/stdlib/test/fixtures/deadlock_a.bt b/stdlib/test/fixtures/deadlock_a.bt index 8c7847f22..b1a50ee85 100644 --- a/stdlib/test/fixtures/deadlock_a.bt +++ b/stdlib/test/fixtures/deadlock_a.bt @@ -1,9 +1,9 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// DeadlockA fixture for actor_deadlock_test.bt. +// DeadlockA fixture for actor_deadlock_test.bt // When callPeer is called, it synchronously calls respondToA: on DeadlockB, -// which calls back callPeer on this actor — creating a circular deadlock. +// which calls back callPeer on this actor — creating a circular deadlock Actor subclass: DeadlockA state: peer = nil diff --git a/stdlib/test/fixtures/deadlock_b.bt b/stdlib/test/fixtures/deadlock_b.bt index cb4609bd5..7946d27b3 100644 --- a/stdlib/test/fixtures/deadlock_b.bt +++ b/stdlib/test/fixtures/deadlock_b.bt @@ -1,14 +1,14 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// DeadlockB fixture for actor_deadlock_test.bt. +// DeadlockB fixture for actor_deadlock_test.bt // respondToA: calls back callPeer on the caller (DeadlockA), which is -// already busy handling its own callPeer — creating a circular deadlock. +// already busy handling its own callPeer — creating a circular deadlock Actor subclass: DeadlockB respondToA: caller => // This call back to caller (DeadlockA) creates a deadlock: // caller is busy handling callPeer, so this gen_server:call blocks, - // and after 5000ms the gen_server:call timeout fires. + // and after 5000ms the gen_server:call timeout fires caller callPeer diff --git a/stdlib/test/fixtures/error_counter.bt b/stdlib/test/fixtures/error_counter.bt index 2267e57f3..852aad6b9 100644 --- a/stdlib/test/fixtures/error_counter.bt +++ b/stdlib/test/fixtures/error_counter.bt @@ -1,4 +1,4 @@ -// Actor for testing state mutation threading in exception handling blocks. +// Actor for testing state mutation threading in exception handling blocks // Used by tests/stdlib/exception_mutations.bt (BT-410) Actor subclass: ErrorCounter @@ -13,5 +13,5 @@ Actor subclass: ErrorCounter safeIncrementWithCleanup => [self.value := self.value + 1] ensure: [self.errorCount := self.errorCount + 1] - getValue => ^self.value - getErrorCount => ^self.errorCount + getValue => self.value + getErrorCount => self.errorCount diff --git a/stdlib/test/fixtures/error_message_helper.bt b/stdlib/test/fixtures/error_message_helper.bt index b22530842..3f90ed1ac 100644 --- a/stdlib/test/fixtures/error_message_helper.bt +++ b/stdlib/test/fixtures/error_message_helper.bt @@ -1,18 +1,18 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-932: Helper test class that triggers raw BEAM errors. +// BT-932: Helper test class that triggers raw BEAM errors // ErrorMessageHelperTest defines methods that intentionally trigger raw BEAM // errors. They are NOT prefixed with "test" so BUnit will not auto-discover // them. ErrorMessageTest runs each helper method via TestRunner run:method: -// and checks that the resulting failure messages are human-readable. +// and checks that the resulting failure messages are human-readable TestCase subclass: ErrorMessageHelperTest - // Triggers {badkey, Key} BEAM error: maps:get/2 with absent key. + // Triggers {badkey, Key} BEAM error: maps:get/2 with absent key triggerBadkey => Erlang maps get: #missingKey with: #{#other => 1} - // Triggers badarith BEAM error: division by zero. + // Triggers badarith BEAM error: division by zero triggerBadarith => 1 / 0 diff --git a/stdlib/test/fixtures/event_bus_fixture.bt b/stdlib/test/fixtures/event_bus_fixture.bt index 40dc73171..9f60c4660 100644 --- a/stdlib/test/fixtures/event_bus_fixture.bt +++ b/stdlib/test/fixtures/event_bus_fixture.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-898: Fixture actor for actor-to-actor coordination tests. -// EventBus forwards notifications to a subscribed EventCollector. +// BT-898: Fixture actor for actor-to-actor coordination tests +// EventBus forwards notifications to a subscribed EventCollector Actor subclass: EventBus state: collector = nil diff --git a/stdlib/test/fixtures/field_mutation_accumulator.bt b/stdlib/test/fixtures/field_mutation_accumulator.bt index 69320a544..166eb09b0 100644 --- a/stdlib/test/fixtures/field_mutation_accumulator.bt +++ b/stdlib/test/fixtures/field_mutation_accumulator.bt @@ -9,24 +9,24 @@ Actor subclass: FieldMutationAccumulator state: product = 1 state: count = 0 - getSum => ^self.sum - getProduct => ^self.product - getCount => ^self.count + getSum => self.sum + getProduct => self.product + getCount => self.count // Multiple fields mutated in do: processArray: items => items do: [:item | - self.sum := self.sum + item. - self.product := self.product * item. + self.sum := self.sum + item + self.product := self.product * item self.count := self.count + 1 - ]. - ^#{#sum => self.sum, #product => self.product, #count => self.count} + ] + #{#sum => self.sum, #product => self.product, #count => self.count} // BT-598: Local variable mutation in actor method blocks processWithLocal: items => - localSum := 0. + localSum := 0 items do: [:item | - localSum := localSum + 1. + localSum := localSum + 1 self.sum := self.sum + item - ]. - ^#{#localSum => localSum, #sum => self.sum} + ] + #{#localSum => localSum, #sum => self.sum} diff --git a/stdlib/test/fixtures/field_mutation_counter.bt b/stdlib/test/fixtures/field_mutation_counter.bt index 011947c35..4fd2545d3 100644 --- a/stdlib/test/fixtures/field_mutation_counter.bt +++ b/stdlib/test/fixtures/field_mutation_counter.bt @@ -8,15 +8,15 @@ Actor subclass: FieldMutationCounter state: value = 0 - getValue => ^self.value + getValue => self.value setValue: v => self.value := v // do: with field mutation (accumulate sum) sumArray: items => - items do: [:item | self.value := self.value + item]. - ^self.value + items do: [:item | self.value := self.value + item] + self.value // inject:into: without field mutation (pure functional) sumWithInject: items => - ^items inject: 0 into: [:sum :item | sum + item] + items inject: 0 into: [:sum :item | sum + item] diff --git a/stdlib/test/fixtures/field_mutation_nested.bt b/stdlib/test/fixtures/field_mutation_nested.bt index 66c6a7f65..350369439 100644 --- a/stdlib/test/fixtures/field_mutation_nested.bt +++ b/stdlib/test/fixtures/field_mutation_nested.bt @@ -7,7 +7,7 @@ Actor subclass: FieldMutationNested state: value = 0 - getValue => ^self.value + getValue => self.value // Nested to:do: with field mutation nestedIncrement: outer inner: inner => @@ -15,5 +15,5 @@ Actor subclass: FieldMutationNested 1 to: inner do: [:j | self.value := self.value + 1 ] - ]. - ^self.value + ] + self.value diff --git a/stdlib/test/fixtures/hom_composability_actor.bt b/stdlib/test/fixtures/hom_composability_actor.bt index cb0177c98..54f956e3c 100644 --- a/stdlib/test/fixtures/hom_composability_actor.bt +++ b/stdlib/test/fixtures/hom_composability_actor.bt @@ -1,65 +1,65 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-857: HOM composability fixture (ADR 0041 Phase 5 testing). +// BT-857: HOM composability fixture (ADR 0041 Phase 5 testing) // Verifies that user-defined HOMs calling blocks in loops thread state // correctly across multiple invocations, and that nested HOMs -// propagate mutations back to the caller. +// propagate mutations back to the caller // // Implementation note: The Tier 2 protocol for block calls inside a do: loop // body is activated when the loop body has at least one local write (which // triggers the stateful do: codegen path). The HOMs below include a `last` // variable assignment to activate this path, matching the ADR 0041 design -// where HOMs naturally have their own local state (e.g. index tracking). +// where HOMs naturally have their own local state (e.g. index tracking) Actor subclass: HomComposabilityActor - // User-defined HOM: calls aBlock for each element in #(1, 2, 3, 4, 5). + // User-defined HOM: calls aBlock for each element in #(1, 2, 3, 4, 5) // The `last :=` write activates the stateful do: path so that - // aBlock value: each is called via the Tier 2 protocol with StateAcc threading. + // aBlock value: each is called via the Tier 2 protocol with StateAcc threading eachItem: aBlock => - last := nil. + last := nil #(1, 2, 3, 4, 5) do: [:each | last := aBlock value: each - ]. + ] last - // Nested HOM: outer delegates to inner, testing two-layer state threading. + // Nested HOM: outer delegates to inner, testing two-layer state threading outerEachItem: aBlock => self eachItem: aBlock - // Returns sum of (aBlock value: each) for each item in items. - // Used to test pure block correctness via a loop HOM. + // Returns sum of (aBlock value: each) for each item in items + // Used to test pure block correctness via a loop HOM sumOf: aBlock over: items => - total := 0. - items do: [:each | total := total + (aBlock value: each)]. + total := 0 + items do: [:each | total := total + (aBlock value: each)] total // --- Test methods (called from BUnit via actor await) --- - // Test: user-defined HOM with mutating block — mutations accumulate. - // Block captures local `count`; HOM calls it for 1..5; count should be 15. + // Test: user-defined HOM with mutating block — mutations accumulate + // Block captures local `count`; HOM calls it for 1..5; count should be 15 testMutatingBlockInCustomLoop => - count := 0. - self eachItem: [:x | count := count + x]. + count := 0 + self eachItem: [:x | count := count + x] count - // Test: nested HOMs — outer calls inner, both thread state correctly. - // Same block, same items, same expected result as above. + // Test: nested HOMs — outer calls inner, both thread state correctly + // Same block, same items, same expected result as above testNestedHOMsAccumulate => - count := 0. - self outerEachItem: [:x | count := count + x]. + count := 0 + self outerEachItem: [:x | count := count + x] count - // Test: pure block passed to HOM — correct result, no crash. - // sumOf:over: loops with a pure block [:x | x * 2]; result = 2+4+6+8+10 = 30. + // Test: pure block passed to HOM — correct result, no crash + // sumOf:over: loops with a pure block [:x | x * 2]; result = 2+4+6+8+10 = 30 testPureBlockViaHOM => self sumOf: [:x | x * 2] over: #(1, 2, 3, 4, 5) - // Test: block stored in local variable, then passed to user-defined HOM. - // Mutations from the stored block must propagate back to the caller. + // Test: block stored in local variable, then passed to user-defined HOM + // Mutations from the stored block must propagate back to the caller testStoredBlockPassedToHOM => - count := 0. - addBlock := [:x | count := count + x]. - self eachItem: addBlock. + count := 0 + addBlock := [:x | count := count + x] + self eachItem: addBlock count diff --git a/stdlib/test/fixtures/local_mutation_actor.bt b/stdlib/test/fixtures/local_mutation_actor.bt index a05c79f3a..fea52f82e 100644 --- a/stdlib/test/fixtures/local_mutation_actor.bt +++ b/stdlib/test/fixtures/local_mutation_actor.bt @@ -7,72 +7,72 @@ Actor subclass: LocalMutationActor state: log = 0 - getLog => ^self.log + getLog => self.log // Local mutation in do: (lists:foldl path) sumWithDo: items => - total := 0. + total := 0 items do: [:item | total := total + item - ]. - ^total + ] + total // Local mutation in inject:into: sumWithInject: items => - count := 0. + count := 0 result := items inject: 0 into: [:acc :item | - count := count + 1. + count := count + 1 acc + item - ]. - ^#{#result => result, #count => count} + ] + #{#result => result, #count => count} // Local mutation in timesRepeat: countToN: n => - counter := 0. + counter := 0 n timesRepeat: [ counter := counter + 1 - ]. - ^counter + ] + counter // Local mutation in to:do: sumRange: n => - total := 0. + total := 0 1 to: n do: [:i | total := total + i - ]. - ^total + ] + total // Local mutation in whileTrue: countDownFrom: n => - counter := n. - steps := 0. + counter := n + steps := 0 [counter > 0] whileTrue: [ - counter := counter - 1. + counter := counter - 1 steps := steps + 1 - ]. - ^steps + ] + steps // Local mutation in whileFalse: countUpWithWhileFalseFrom: n => - counter := 0. + counter := 0 [counter >= n] whileFalse: [ counter := counter + 1 - ]. - ^counter + ] + counter // Local mutation in to:by:do: sumEvens: n => - total := 0. + total := 0 2 to: n by: 2 do: [:i | total := total + i - ]. - ^total + ] + total // Mixed local + field mutation processWithTracking: items => - localCount := 0. + localCount := 0 items do: [:item | - localCount := localCount + 1. + localCount := localCount + 1 self.log := self.log + item - ]. - ^#{#localCount => localCount, #log => self.log} + ] + #{#localCount => localCount, #log => self.log} diff --git a/stdlib/test/fixtures/logging_counter.bt b/stdlib/test/fixtures/logging_counter.bt index d1b1c4906..3290c543f 100644 --- a/stdlib/test/fixtures/logging_counter.bt +++ b/stdlib/test/fixtures/logging_counter.bt @@ -10,7 +10,7 @@ Counter subclass: LoggingCounter // Override increment to add logging, then call super increment => - self.logCount := self.logCount + 1. + self.logCount := self.logCount + 1 super increment // New method to get log count diff --git a/stdlib/test/fixtures/math_helper.bt b/stdlib/test/fixtures/math_helper.bt index 0e2e7034c..336ef368f 100644 --- a/stdlib/test/fixtures/math_helper.bt +++ b/stdlib/test/fixtures/math_helper.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // MathHelper - value type with recursive methods for testing BT-330 -// Value types use direct function calls, so recursive self-dispatch works. +// Value types use direct function calls, so recursive self-dispatch works Object subclass: MathHelper diff --git a/stdlib/test/fixtures/mixed_call_site_actor.bt b/stdlib/test/fixtures/mixed_call_site_actor.bt index bf3480105..6f406a5e8 100644 --- a/stdlib/test/fixtures/mixed_call_site_actor.bt +++ b/stdlib/test/fixtures/mixed_call_site_actor.bt @@ -1,27 +1,27 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-870: Mixed Tier 1/Tier 2 call site fixture. +// BT-870: Mixed Tier 1/Tier 2 call site fixture // Tests that a HOM called from two different methods — one with a plain Tier 1 // block and one with a Tier 2 (captured-mutation) block — compiles and runs -// correctly for both call sites. +// correctly for both call sites Actor subclass: MixedCallSiteActor - // HOM called with both Tier 1 and Tier 2 blocks depending on the caller. + // HOM called with both Tier 1 and Tier 2 blocks depending on the caller // BT-870: The method body is compiled as Tier 2. Tier 1 call sites must - // promote their blocks to the Tier 2 calling convention (StateAcc passthrough). + // promote their blocks to the Tier 2 calling convention (StateAcc passthrough) applyBlock: aBlock to: anItem => aBlock value: anItem - // Tier 1 call site: block has no captured mutations. + // Tier 1 call site: block has no captured mutations // BT-870: Prior to the fix this caused a wrong-arity crash because the block - // was compiled as arity 1 but the Tier 2 method body calls it with arity 2. + // was compiled as arity 1 but the Tier 2 method body calls it with arity 2 testTier1CallSite => self applyBlock: [:x | x + 1] to: 10 - // Tier 2 call site: block captures and mutates `total`. + // Tier 2 call site: block captures and mutates `total` testTier2CallSite => - total := 0. - self applyBlock: [:x | total := total + x] to: 7. + total := 0 + self applyBlock: [:x | total := total + x] to: 7 total diff --git a/stdlib/test/fixtures/multi_expr_calc.bt b/stdlib/test/fixtures/multi_expr_calc.bt index ddf469578..f3d04fd0e 100644 --- a/stdlib/test/fixtures/multi_expr_calc.bt +++ b/stdlib/test/fixtures/multi_expr_calc.bt @@ -9,11 +9,11 @@ Object subclass: MultiExprCalc // Two-expression method: first expression is discarded, second is returned doubleAfterAdd: x => - x + 100 + x abs x * 2 // Three-expression method: first two are discarded, third is returned compute: a with: b => - a + b - a - b + a abs + b abs a * b diff --git a/stdlib/test/fixtures/multi_keyword.bt b/stdlib/test/fixtures/multi_keyword.bt index a2757c0eb..6cb07e41a 100644 --- a/stdlib/test/fixtures/multi_keyword.bt +++ b/stdlib/test/fixtures/multi_keyword.bt @@ -9,16 +9,16 @@ Actor subclass: MultiKeyword // 4-keyword method: sum four arguments add: a and: b and: c and: d => - self.result := a + b + c + d. - ^self.result + self.result := a + b + c + d + self.result // 5-keyword method: sum five arguments add: a and: b and: c and: d and: e => - self.result := a + b + c + d + e. - ^self.result + self.result := a + b + c + d + e + self.result // 4-keyword method: verify argument order by weighted sum first: a second: b third: c fourth: d => - ^a * 1000 + b * 100 + c * 10 + d + a * 1000 + b * 100 + c * 10 + d - getResult => ^self.result + getResult => self.result diff --git a/stdlib/test/fixtures/mutation_return_values.bt b/stdlib/test/fixtures/mutation_return_values.bt index 8f29ef541..feca151eb 100644 --- a/stdlib/test/fixtures/mutation_return_values.bt +++ b/stdlib/test/fixtures/mutation_return_values.bt @@ -3,19 +3,19 @@ // BT-483: Tests that mutation-threaded control flow returns {Result, State} // When control flow is the last expression in a method, the method should -// return the Result part of the tuple, not nil. +// return the Result part of the tuple, not nil Actor subclass: MutationReturnValues state: value = 0 - getValue => ^self.value + getValue => self.value setValue: v => self.value := v // inject:into: should return the accumulator result // Block receives (accumulator, element) matching Beamtalk convention (BT-820) sumViaInject: items => items inject: 0 into: [:acc :elem | - self.value := self.value + elem. + self.value := self.value + elem acc + elem ] @@ -26,7 +26,7 @@ Actor subclass: MutationReturnValues // on:do: should return the handler result on exception failingAdd => [self.value := self.value + (1 / 0). self.value] on: Exception do: [:e | - self.value := self.value + 100. + self.value := self.value + 100 -999 ] diff --git a/stdlib/test/fixtures/nlr_bar.bt b/stdlib/test/fixtures/nlr_bar.bt index f3c1b78c3..2166c305e 100644 --- a/stdlib/test/fixtures/nlr_bar.bt +++ b/stdlib/test/fixtures/nlr_bar.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrBar — ifFalse: non-local return fixture. +// BT-754: NlrBar — ifFalse: non-local return fixture Object subclass: NlrBar check: x => diff --git a/stdlib/test/fixtures/nlr_baz.bt b/stdlib/test/fixtures/nlr_baz.bt index faabfc685..926eeef76 100644 --- a/stdlib/test/fixtures/nlr_baz.bt +++ b/stdlib/test/fixtures/nlr_baz.bt @@ -1,9 +1,9 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrBaz — top-level ^ regression guard fixture. +// BT-754: NlrBaz — top-level ^ regression guard fixture // Intentional: ^ on last expression tests that top-level ^ still works -// after NLR changes. Do not simplify to `x + x`. +// after NLR changes. Do not simplify to `x + x` Object subclass: NlrBaz - double: x => ^x + x + double: x => x + x diff --git a/stdlib/test/fixtures/nlr_doubler.bt b/stdlib/test/fixtures/nlr_doubler.bt index 75d3716a7..dc81b1f49 100644 --- a/stdlib/test/fixtures/nlr_doubler.bt +++ b/stdlib/test/fixtures/nlr_doubler.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrDoubler — non-local return with computed value fixture. +// BT-754: NlrDoubler — non-local return with computed value fixture Object subclass: NlrDoubler test: x => diff --git a/stdlib/test/fixtures/nlr_field_mutation.bt b/stdlib/test/fixtures/nlr_field_mutation.bt index 776faba6e..7ca295c76 100644 --- a/stdlib/test/fixtures/nlr_field_mutation.bt +++ b/stdlib/test/fixtures/nlr_field_mutation.bt @@ -1,58 +1,58 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-854/BT-857: Fixture for testing NLR state threading in value types. +// BT-854/BT-857: Fixture for testing NLR state threading in value types // When ^ fires inside a block, the throw now carries Self as state -// in a 4-tuple: {$bt_nlr, Token, Value, Self{N}}. -// The method returns {Result, Self{N}} which dispatch/3 unwraps. +// in a 4-tuple: {$bt_nlr, Token, Value, Self{N}} +// The method returns {Result, Self{N}} which dispatch/3 unwraps // // Note: Field mutations inside do: blocks for value types are not // yet supported (BT-860). Tests here use field mutations in the -// method body BEFORE the block that contains ^. +// method body BEFORE the block that contains ^ Object subclass: NlrFieldMutation state: lastQuery = nil - // Field mutation happens before the block with ^. - // The NLR throw carries Self1 (with lastQuery set). + // Field mutation happens before the block with ^ + // The NLR throw carries Self1 (with lastQuery set) findFirst: item in: items => - self.lastQuery := item. + self.lastQuery := item items do: [:each | each =:= item ifTrue: [^each] - ]. + ] nil - // Returns self via ^, making field mutations visible to the caller. - // self.lastQuery is set before the block, then ^self returns the updated Self. + // Returns self via ^, making field mutations visible to the caller + // self.lastQuery is set before the block, then ^self returns the updated Self findAndReturnSelf: item in: items => - self.lastQuery := item. + self.lastQuery := item items do: [:each | each =:= item ifTrue: [^self] - ]. + ] self - // Normal NLR with no field mutations — exercises the tuple return format. + // Normal NLR with no field mutations — exercises the tuple return format detect: aBlock in: items => items do: [:each | (aBlock value: each) ifTrue: [^each] - ]. + ] nil - // Tests the non-NLR path: the body returns {Result, Self{N}}. + // Tests the non-NLR path: the body returns {Result, Self{N}} findNone: items => items do: [:each | false ifTrue: [^each] - ]. + ] nil - // BT-857: Returns true if any element satisfies aBlock (early return via ^). - // Field mutation (lastQuery := size) happens before the block that may ^. - // Verifies NLR state preservation: anySatisfy: pattern (bool return). + // BT-857: Returns true if any element satisfies aBlock (early return via ^) + // Field mutation (lastQuery := size) happens before the block that may ^ + // Verifies NLR state preservation: anySatisfy: pattern (bool return) anySatisfy: aBlock in: items => - self.lastQuery := items size. + self.lastQuery := items size items do: [:each | (aBlock value: each) ifTrue: [^true] - ]. + ] false lastQuery => self.lastQuery diff --git a/stdlib/test/fixtures/nlr_foo.bt b/stdlib/test/fixtures/nlr_foo.bt index 84f30e019..0306d4448 100644 --- a/stdlib/test/fixtures/nlr_foo.bt +++ b/stdlib/test/fixtures/nlr_foo.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrFoo — ifTrue:ifFalse: non-local return fixture. +// BT-754: NlrFoo — ifTrue:ifFalse: non-local return fixture Object subclass: NlrFoo classify: x => diff --git a/stdlib/test/fixtures/nlr_nested_hom.bt b/stdlib/test/fixtures/nlr_nested_hom.bt index 3daf54d96..36b878294 100644 --- a/stdlib/test/fixtures/nlr_nested_hom.bt +++ b/stdlib/test/fixtures/nlr_nested_hom.bt @@ -1,47 +1,47 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-857: Fixture for testing NLR state preservation through nested HOMs. +// BT-857: Fixture for testing NLR state preservation through nested HOMs // Verifies that when ^ fires inside a block passed through multiple HOMs, // the accumulated state (field mutations) is correctly preserved in the -// NLR 4-tuple as it propagates through each HOM frame. +// NLR 4-tuple as it propagates through each HOM frame // -// Pattern: field mutation in method body BEFORE block invocation. -// Methods return `^self` (updated self) so the caller can verify visitCount. +// Pattern: field mutation in method body BEFORE block invocation +// Methods return `^self` (updated self) so the caller can verify visitCount // // Note: Field mutations inside do: blocks for value types are not // yet supported (BT-860). Field mutations here occur in the METHOD BODY -// before the block invocation. +// before the block invocation Object subclass: NlrNestedHom state: visitCount = 0 - // Inner HOM: calls aBlock for each element. Has no ^ of its own. - // When aBlock throws NLR, it propagates out of this method. + // Inner HOM: calls aBlock for each element. Has no ^ of its own + // When aBlock throws NLR, it propagates out of this method applyBlock: aBlock forEach: items => items do: [:each | aBlock value: each] - // Outer HOM: delegates to inner HOM. Adds a second frame of indirection. - // When aBlock throws NLR through applyBlock:forEach:, it also propagates here. + // Outer HOM: delegates to inner HOM. Adds a second frame of indirection + // When aBlock throws NLR through applyBlock:forEach:, it also propagates here applyBlockNested: aBlock forEach: items => self applyBlock: aBlock forEach: items - // Searches items for an element equal to target, through one HOM layer. - // Field mutation (visitCount := 1) happens before the block with ^. - // Uses ^self to return the updated self so callers can verify visitCount. - // Verifies state (visitCount) is preserved after NLR through one HOM frame. + // Searches items for an element equal to target, through one HOM layer + // Field mutation (visitCount := 1) happens before the block with ^ + // Uses ^self to return the updated self so callers can verify visitCount + // Verifies state (visitCount) is preserved after NLR through one HOM frame findViaSingleHOM: target in: items => - self.visitCount := 1. - self applyBlock: [:x | x =:= target ifTrue: [^self]] forEach: items. + self.visitCount := 1 + self applyBlock: [:x | x =:= target ifTrue: [^self]] forEach: items self - // Searches items for an element equal to target, through TWO HOM layers. - // Field mutation (visitCount := 2) happens before the block with ^. - // Uses ^self to return the updated self so callers can verify visitCount. - // Verifies state (visitCount) is preserved after NLR through two HOM frames. + // Searches items for an element equal to target, through TWO HOM layers + // Field mutation (visitCount := 2) happens before the block with ^ + // Uses ^self to return the updated self so callers can verify visitCount + // Verifies state (visitCount) is preserved after NLR through two HOM frames findViaNestedHOM: target in: items => - self.visitCount := 2. - self applyBlockNested: [:x | x =:= target ifTrue: [^self]] forEach: items. + self.visitCount := 2 + self applyBlockNested: [:x | x =:= target ifTrue: [^self]] forEach: items self visitCount => self.visitCount diff --git a/stdlib/test/fixtures/nlr_on_do.bt b/stdlib/test/fixtures/nlr_on_do.bt index d8d5923a1..5d133ad65 100644 --- a/stdlib/test/fixtures/nlr_on_do.bt +++ b/stdlib/test/fixtures/nlr_on_do.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrOnDo — NLR throw propagates through on:do: fixture. -// Verifies that on:do: does NOT swallow NLR throws (re-raises them). +// BT-754: NlrOnDo — NLR throw propagates through on:do: fixture +// Verifies that on:do: does NOT swallow NLR throws (re-raises them) Object subclass: NlrOnDo test: x => diff --git a/stdlib/test/fixtures/nlr_return_test.bt b/stdlib/test/fixtures/nlr_return_test.bt index eab899f2e..f749e5251 100644 --- a/stdlib/test/fixtures/nlr_return_test.bt +++ b/stdlib/test/fixtures/nlr_return_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrReturnTest — ifTrue: non-local return fixture. +// BT-754: NlrReturnTest — ifTrue: non-local return fixture Object subclass: NlrReturnTest test: x => diff --git a/stdlib/test/fixtures/nlr_skipper.bt b/stdlib/test/fixtures/nlr_skipper.bt index 53e8bd8d5..d77961c8e 100644 --- a/stdlib/test/fixtures/nlr_skipper.bt +++ b/stdlib/test/fixtures/nlr_skipper.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrSkipper — early return skips later expressions fixture. +// BT-754: NlrSkipper — early return skips later expressions fixture Object subclass: NlrSkipper test: x => diff --git a/stdlib/test/fixtures/non_literal_callable_actor.bt b/stdlib/test/fixtures/non_literal_callable_actor.bt index 9a6366176..19e7d4d7e 100644 --- a/stdlib/test/fixtures/non_literal_callable_actor.bt +++ b/stdlib/test/fixtures/non_literal_callable_actor.bt @@ -1,27 +1,27 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-909: Actor that passes block variables (non-literal callables) to list ops. +// BT-909: Actor that passes block variables (non-literal callables) to list ops // This triggers the runtime arity normalization wrapper because the compiler -// cannot statically determine the block's tier when it's referenced by identifier. +// cannot statically determine the block's tier when it's referenced by identifier Actor subclass: NonLiteralCallableActor // collect: with a Tier-1 block stored in a variable collectWithTier1Block => - blk := [:x | x * 10]. + blk := [:x | x * 10] #(1, 2, 3) collect: blk // select: with a Tier-1 block stored in a variable selectWithTier1Block => - blk := [:x | x > 2]. + blk := [:x | x > 2] #(1, 2, 3, 4, 5) select: blk - // do: with a Tier-2 (stateful) block stored in a variable. + // do: with a Tier-2 (stateful) block stored in a variable // Mutations are silently dropped at the Erlang boundary (expected), - // but the call must not crash with badarity. + // but the call must not crash with badarity doWithTier2Block => - total := 0. - blk := [:x | total := total + x]. - #(1, 2, 3) do: blk. + total := 0 + blk := [:x | total := total + x] + #(1, 2, 3) do: blk "done" diff --git a/stdlib/test/fixtures/number_list.bt b/stdlib/test/fixtures/number_list.bt index da0371e56..be3c45e71 100644 --- a/stdlib/test/fixtures/number_list.bt +++ b/stdlib/test/fixtures/number_list.bt @@ -1,18 +1,18 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// NumberList — a user-defined Collection subclass for testing BT-815. +// NumberList — a user-defined Collection subclass for testing BT-815 // Implements only do:, size, and printString; all higher-order collection -// methods (collect:, select:, inject:into:, etc.) are inherited from Collection. +// methods (collect:, select:, inject:into:, etc.) are inherited from Collection Collection subclass: NumberList state: items = #() - // Return number of elements. + // Return number of elements size -> Integer => self.items size - // Iterate over each element, evaluating block with each one. + // Iterate over each element, evaluating block with each one do: block: Block -> Nil => self.items do: block - // Return a developer-readable string representation. + // Return a developer-readable string representation printString -> String => "NumberList" diff --git a/stdlib/test/fixtures/recursive_actor.bt b/stdlib/test/fixtures/recursive_actor.bt index bdebdba41..0dbbec3d0 100644 --- a/stdlib/test/fixtures/recursive_actor.bt +++ b/stdlib/test/fixtures/recursive_actor.bt @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // RecursiveActor - Actor with recursive methods for testing BT-330 -// Actor self-sends use synchronous direct dispatch (BT-330 fix). +// Actor self-sends use synchronous direct dispatch (BT-330 fix) Actor subclass: RecursiveActor state: result = 0 diff --git a/stdlib/test/fixtures/removal_test_child.bt b/stdlib/test/fixtures/removal_test_child.bt index 7ee1e6d4b..6555f17c6 100644 --- a/stdlib/test/fixtures/removal_test_child.bt +++ b/stdlib/test/fixtures/removal_test_child.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Fixture for removeFromSystem subclass rejection test (BT-785). -// Extending RemovalTestParent makes it impossible to remove the parent. +// Fixture for removeFromSystem subclass rejection test (BT-785) +// Extending RemovalTestParent makes it impossible to remove the parent RemovalTestParent subclass: RemovalTestChild diff --git a/stdlib/test/fixtures/removal_test_parent.bt b/stdlib/test/fixtures/removal_test_parent.bt index 7b3829a88..7e1189a4b 100644 --- a/stdlib/test/fixtures/removal_test_parent.bt +++ b/stdlib/test/fixtures/removal_test_parent.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Fixture for removeFromSystem subclass rejection test (BT-785). -// RemovalTestChild extends this class, so removeFromSystem should raise an error. +// Fixture for removeFromSystem subclass rejection test (BT-785) +// RemovalTestChild extends this class, so removeFromSystem should raise an error Object subclass: RemovalTestParent diff --git a/stdlib/test/fixtures/sealed_counter.bt b/stdlib/test/fixtures/sealed_counter.bt index 26f782095..0ebafb4af 100644 --- a/stdlib/test/fixtures/sealed_counter.bt +++ b/stdlib/test/fixtures/sealed_counter.bt @@ -1,9 +1,9 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Sealed counter class for testing sealed class codegen optimization (BT-403). +// Sealed counter class for testing sealed class codegen optimization (BT-403) // Self-sends in sealed classes use direct dispatch (skip safe_dispatch try/catch) -// and direct function calls to __sealed_* methods. +// and direct function calls to __sealed_* methods sealed Actor subclass: SealedCounter state: value = 0 diff --git a/stdlib/test/fixtures/self_ref_actor.bt b/stdlib/test/fixtures/self_ref_actor.bt index 289f774ec..e9d7b4220 100644 --- a/stdlib/test/fixtures/self_ref_actor.bt +++ b/stdlib/test/fixtures/self_ref_actor.bt @@ -8,12 +8,12 @@ Actor subclass: SelfRefActor state: value = 0 // Returns self (the actor's object reference) - returnSelf => ^self + returnSelf => self // Returns self's class from inside a block - classInBlock => ^[self class] value + classInBlock => [self class] value // Keyword message setter setValue: v => self.value := v - getValue => ^self.value + getValue => self.value diff --git a/stdlib/test/fixtures/string_formatter.bt b/stdlib/test/fixtures/string_formatter.bt index 4bed6bfe4..40dae29ff 100644 --- a/stdlib/test/fixtures/string_formatter.bt +++ b/stdlib/test/fixtures/string_formatter.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-892: Value object fixture for testing inject:into: with self sends. -// Self sends in value-object blocks should NOT trigger state threading. +// BT-892: Value object fixture for testing inject:into: with self sends +// Self sends in value-object blocks should NOT trigger state threading Object subclass: StringFormatter state: prefix = "" diff --git a/stdlib/test/fixtures/tier2_block_test_actor.bt b/stdlib/test/fixtures/tier2_block_test_actor.bt index 90e2c5f8f..29f4e03c5 100644 --- a/stdlib/test/fixtures/tier2_block_test_actor.bt +++ b/stdlib/test/fixtures/tier2_block_test_actor.bt @@ -1,65 +1,65 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-851/BT-852/BT-853: Tier 2 block round-trip test fixture (ADR 0041 Phase 1). +// BT-851/BT-852/BT-853: Tier 2 block round-trip test fixture (ADR 0041 Phase 1) // Tests that a block with captured mutations can be passed to a HOM via -// self-send and the mutation propagates back to the caller through state threading. +// self-send and the mutation propagates back to the caller through state threading Actor subclass: Tier2BlockTestActor - // BT-851: HOM that receives a block and calls it with the Tier 2 protocol. + // BT-851: HOM that receives a block and calls it with the Tier 2 protocol // The block parameter `aBlock` is compiled with the stateful calling convention - // when the compiler detects it receives a Tier 2 (captured-mutation) block. + // when the compiler detects it receives a Tier 2 (captured-mutation) block applyBlock: aBlock to: anItem => aBlock value: anItem - // BT-853: HOM where the block call is NOT the last expression. + // BT-853: HOM where the block call is NOT the last expression // After calling the block (which mutates count via StateAcc), this method - // returns a fixed sentinel value. The state update must still propagate back. + // returns a fixed sentinel value. The state update must still propagate back applyBlockNonLast: aBlock to: anItem => - aBlock value: anItem. + aBlock value: anItem 99 - // BT-853: HOM where the block result is captured in a local variable. - // The block returns (count + x) and this HOM adds an extra offset to it. + // BT-853: HOM where the block result is captured in a local variable + // The block returns (count + x) and this HOM adds an extra offset to it applyBlockGetResult: aBlock to: anItem addend: extra => - result := aBlock value: anItem. + result := aBlock value: anItem result + extra - // BT-852/BT-853 new_state ordering: HOM with TWO sequential Tier 2 assignment calls. - // Verifies state is correctly threaded across multiple Tier 2 assignments. + // BT-852/BT-853 new_state ordering: HOM with TWO sequential Tier 2 assignment calls + // Verifies state is correctly threaded across multiple Tier 2 assignments // If new_state were pre-computed before expression_doc, duplicate StateN bindings - // in generated Core Erlang would cause an Erlang compile-time failure. + // in generated Core Erlang would cause an Erlang compile-time failure applyTwoBlocks: aBlock1 and: aBlock2 to: anItem => - r1 := aBlock1 value: anItem. - r2 := aBlock2 value: r1. + r1 := aBlock1 value: anItem + r2 := aBlock2 value: r1 r2 - // BT-851: Self-sends applyBlock:to: with a Tier 2 block. - // The block `[:x | count := count + x]` captures and mutates `count`. - // After the self-send, `count` should reflect the mutation. + // BT-851: Self-sends applyBlock:to: with a Tier 2 block + // The block `[:x | count := count + x]` captures and mutates `count` + // After the self-send, `count` should reflect the mutation testRoundTrip => - count := 0. - self applyBlock: [:x | count := count + x] to: 5. + count := 0 + self applyBlock: [:x | count := count + x] to: 5 count - // BT-853: Non-last Tier 2 value: call — block mutates count, HOM returns sentinel. - // The state update (count=3) must propagate back through the self-send. + // BT-853: Non-last Tier 2 value: call — block mutates count, HOM returns sentinel + // The state update (count=3) must propagate back through the self-send testNonLastTier2ValueCall => - count := 0. - self applyBlockNonLast: [:x | count := count + x] to: 3. + count := 0 + self applyBlockNonLast: [:x | count := count + x] to: 3 count - // BT-853: Tier 2 block result captured in local variable in the HOM. - // Block computes (count + x) = (0 + 4) = 4, HOM returns result + 10 = 14. + // BT-853: Tier 2 block result captured in local variable in the HOM + // Block computes (count + x) = (0 + 4) = 4, HOM returns result + 10 = 14 testTier2ResultCapture => - count := 0. + count := 0 self applyBlockGetResult: [:x | count := count + x. count] to: 4 addend: 10 - // BT-852/BT-853 new_state ordering: Two sequential Tier 2 assignments in HOM. - // block1 adds x to count, block2 multiplies count by x. - // applyTwoBlocks:and:to: passes r1 as arg to block2. + // BT-852/BT-853 new_state ordering: Two sequential Tier 2 assignments in HOM + // block1 adds x to count, block2 multiplies count by x + // applyTwoBlocks:and:to: passes r1 as arg to block2 // count=0 -> block1(2) -> count=2, r1=2 -> block2(2) -> count=4, r2=4 testTwoBlocks => - count := 0. + count := 0 self applyTwoBlocks: [:x | count := count + x. count] and: [:x | count := count * x. count] to: 2 diff --git a/stdlib/test/fixtures/typed_account.bt b/stdlib/test/fixtures/typed_account.bt index 9c39bc746..f31684c33 100644 --- a/stdlib/test/fixtures/typed_account.bt +++ b/stdlib/test/fixtures/typed_account.bt @@ -4,7 +4,7 @@ // TypedAccount — test fixture for typed actor features // // A typed actor with multiple typed state fields (Integer, String), -// typed parameters, and return annotations. +// typed parameters, and return annotations typed Actor subclass: TypedAccount state: balance: Integer = 0 @@ -13,24 +13,24 @@ typed Actor subclass: TypedAccount deposit: amount: Integer -> Integer => amount < 0 ifTrue: [ self error: "Amount must be non-negative" - ]. - self.balance := self.balance + amount. + ] + self.balance := self.balance + amount self.balance withdraw: amount: Integer -> Integer => amount < 0 ifTrue: [ self error: "Amount must be non-negative" - ]. + ] self.balance < amount ifTrue: [ self error: "Insufficient funds (balance: " ++ self.balance printString ++ ", requested: " ++ amount printString ++ ")" - ]. - self.balance := self.balance - amount. + ] + self.balance := self.balance - amount self.balance balance -> Integer => self.balance setOwner: name: String -> String => - self.owner := name. + self.owner := name self.owner getOwner -> String => self.owner diff --git a/stdlib/test/fixtures/typed_counter.bt b/stdlib/test/fixtures/typed_counter.bt index 5d6e34ee0..0193d7411 100644 --- a/stdlib/test/fixtures/typed_counter.bt +++ b/stdlib/test/fixtures/typed_counter.bt @@ -5,11 +5,11 @@ typed Actor subclass: TypedCounter state: value: Integer = 0 increment -> Integer => - self.value := self.value + 1. + self.value := self.value + 1 self.value add: amount: Integer -> Integer => - self.value := self.value + amount. + self.value := self.value + amount self.value current -> Integer => self.value diff --git a/stdlib/test/fixtures/typed_ledger.bt b/stdlib/test/fixtures/typed_ledger.bt index 16201fa8d..7285c3953 100644 --- a/stdlib/test/fixtures/typed_ledger.bt +++ b/stdlib/test/fixtures/typed_ledger.bt @@ -5,5 +5,5 @@ typed Actor subclass: TypedLedger state: amount: Integer = 0 addOne -> Integer => - self.amount := self.amount + 1. + self.amount := self.amount + 1 self.amount diff --git a/stdlib/test/fixtures/untyped_container.bt b/stdlib/test/fixtures/untyped_container.bt index 603fcb5ad..31dd1bdee 100644 --- a/stdlib/test/fixtures/untyped_container.bt +++ b/stdlib/test/fixtures/untyped_container.bt @@ -5,5 +5,5 @@ Actor subclass: UntypedContainer state: item = nil setItem: value => - self.item := value. - ^self.item + self.item := value + self.item diff --git a/stdlib/test/fixtures/value_point.bt b/stdlib/test/fixtures/value_point.bt index 6be19c898..da47666fa 100644 --- a/stdlib/test/fixtures/value_point.bt +++ b/stdlib/test/fixtures/value_point.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// ValuePoint — a Point class declared with `Value subclass:` (BT-923). -// Tests auto-generated getters, with*: setters, and keyword constructor. +// ValuePoint — a Point class declared with `Value subclass:` (BT-923) +// Tests auto-generated getters, with*: setters, and keyword constructor Value subclass: ValuePoint state: x = 0 diff --git a/stdlib/test/fixtures/value_type_builder.bt b/stdlib/test/fixtures/value_type_builder.bt index d2733691e..6ad8509af 100644 --- a/stdlib/test/fixtures/value_type_builder.bt +++ b/stdlib/test/fixtures/value_type_builder.bt @@ -1,8 +1,8 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// ValueTypeBuilder - demonstrates immutable-update semantics via Self-threading (BT-833). -// Field assignments produce new Self snapshots rather than mutating in place. +// ValueTypeBuilder - demonstrates immutable-update semantics via Self-threading (BT-833) +// Field assignments produce new Self snapshots rather than mutating in place Object subclass: ValueTypeBuilder state: x = 0 @@ -10,24 +10,24 @@ Object subclass: ValueTypeBuilder // Fluent setter: assigns one field and returns updated self withX: newX => - self.x := newX. - ^self + self.x := newX + self // Fluent setter: assigns one field and returns updated self withY: newY => - self.y := newY. - ^self + self.y := newY + self // Setter that assigns multiple fields sequentially (BT-833: sequential threading) setX: newX y: newY => - self.x := newX. - self.y := newY. - ^self + self.x := newX + self.y := newY + self // Read-then-write: reads current field value, adds delta, writes back (BT-833) incrementX: delta => - self.x := self.x + delta. - ^self + self.x := self.x + delta + self // Getters getX => self.x diff --git a/stdlib/test/future_auto_await_test.bt b/stdlib/test/future_auto_await_test.bt index c823d090e..93e374047 100644 --- a/stdlib/test/future_auto_await_test.bt +++ b/stdlib/test/future_auto_await_test.bt @@ -5,42 +5,42 @@ // with sync-by-default dispatch. Actor method calls return values directly // (via gen_server:call), so binary ops (+, ==, <, >, etc.) receive the // resolved value, not a Future. The codegen wraps operands with -// beamtalk_future:maybe_await/1 for backward compatibility during migration. +// beamtalk_future:maybe_await/1 for backward compatibility during migration TestCase subclass: FutureAutoAwaitTest // Equality: actor method result used in == comparison testEqualityWithActorMethod => - a := ActorChainingFixture spawn. + a := ActorChainingFixture spawn self assert: (a getValue == 0) equals: true // Arithmetic: actor method result used in + operation testArithmeticAddWithActorMethod => - a := ActorChainingFixture spawn. + a := ActorChainingFixture spawn self assert: (a getValue + 1) equals: 1 // Comparison: actor method result used in > comparison testGreaterThanWithActorMethod => - a := ActorChainingFixture spawn. - a increment. + a := ActorChainingFixture spawn + a increment self assert: (a getValue > 0) equals: true // Comparison: actor method result used in < comparison testLessThanWithActorMethod => - a := ActorChainingFixture spawn. + a := ActorChainingFixture spawn self assert: (a getValue < 10) equals: true // Arithmetic: actor method result used in * operation testArithmeticAfterIncrement => - a := ActorChainingFixture spawn. - a increment. - a increment. + a := ActorChainingFixture spawn + a increment + a increment self assert: (a getValue * 3) equals: 6 // Both operands are actor method results testBothOperandsAreActorResults => - a := ActorChainingFixture spawn. - b := ActorChainingFixture spawn. - a increment. + a := ActorChainingFixture spawn + b := ActorChainingFixture spawn + a increment self assert: (a getValue + b getValue) equals: 1 diff --git a/stdlib/test/hom_composability_test.bt b/stdlib/test/hom_composability_test.bt index 6cecfe1f6..dc0be7907 100644 --- a/stdlib/test/hom_composability_test.bt +++ b/stdlib/test/hom_composability_test.bt @@ -1,40 +1,40 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-857: Tests for HOM composability (ADR 0041 Phase 5). +// BT-857: Tests for HOM composability (ADR 0041 Phase 5) // -// BT-912: Tier 2 block StateAcc threading through stateful do: loop bodies. +// BT-912: Tier 2 block StateAcc threading through stateful do: loop bodies // // The BT-912 bug: when `last := aBlock value: each` is in a stateful do: // loop body, the Tier 2 block's NewStateAcc was discarded by codegen, so -// mutations to captured variables (e.g., `count`) were not propagated back. +// mutations to captured variables (e.g., `count`) were not propagated back // // Fixed by: // 1. generate_local_var_assignment_in_loop: unpack {Result, NewStateAcc} from -// Tier 2 block calls and thread NewStateAcc into the maps:put. +// Tier 2 block calls and thread NewStateAcc into the maps:put // 2. detect_tier2_self_send: treat identifier Tier 2 block parameters as Tier 2 -// HOM arguments, enabling state threading through nested HOM delegation chains. +// HOM arguments, enabling state threading through nested HOM delegation chains // // Stored blocks passed to HOMs (testStoredBlockPassedToCustomHOM) require -// type-level tracking of block variables (BT-909) and are not yet tested. +// type-level tracking of block variables (BT-909) and are not yet tested TestCase subclass: HomComposabilityTest - // Test: pure block passed to user-defined HOM — no state overhead, correct result. - // sumOf:over: with [:x | x * 2] over #(1,2,3,4,5) = 30. + // Test: pure block passed to user-defined HOM — no state overhead, correct result + // sumOf:over: with [:x | x * 2] over #(1,2,3,4,5) = 30 testPureBlockViaHOMCorrectResult => - actor := HomComposabilityActor spawn. - self assert: (actor testPureBlockViaHOM) equals: 30 + actor := HomComposabilityActor spawn + self assert: actor testPureBlockViaHOM equals: 30 - // BT-912: Mutating block passed to user-defined HOM accumulates correctly. - // [:x | count := count + x] over 1..5 → count = 15. + // BT-912: Mutating block passed to user-defined HOM accumulates correctly + // [:x | count := count + x] over 1..5 → count = 15 testMutatingBlockViaMutatingHOM => - actor := HomComposabilityActor spawn. - self assert: (actor testMutatingBlockInCustomLoop) equals: 15 + actor := HomComposabilityActor spawn + self assert: actor testMutatingBlockInCustomLoop equals: 15 - // BT-912: Nested HOMs — outer delegates to inner, state threads through both layers. - // Same block, same items, same expected result as above. + // BT-912: Nested HOMs — outer delegates to inner, state threads through both layers + // Same block, same items, same expected result as above testNestedHOMsThreadState => - actor := HomComposabilityActor spawn. - self assert: (actor testNestedHOMsAccumulate) equals: 15 + actor := HomComposabilityActor spawn + self assert: actor testNestedHOMsAccumulate equals: 15 diff --git a/stdlib/test/instance_class_var_access_test.bt b/stdlib/test/instance_class_var_access_test.bt index 3eb6c7389..700824b2b 100644 --- a/stdlib/test/instance_class_var_access_test.bt +++ b/stdlib/test/instance_class_var_access_test.bt @@ -3,23 +3,23 @@ // BT-413: Tests that actor instances can read class variables via self class — // verifying that the class variable is shared across all instances and reflects -// the total count of created objects. +// the total count of created objects TestCase subclass: InstanceClassVarAccessTest testInstanceAccessToClassVariable => - self assert: (InstanceAccessCounter instanceCount) equals: 0. + self assert: InstanceAccessCounter instanceCount equals: 0 // Create an instance via class method (increments instanceCount) - c := InstanceAccessCounter create. + c := InstanceAccessCounter create // Class variable was incremented (verify via class method) - self assert: (InstanceAccessCounter instanceCount) equals: 1. + self assert: InstanceAccessCounter instanceCount equals: 1 // Instance reads class variable via self class (the key BT-413 feature) - self assert: (c totalCounters) equals: 1. + self assert: c totalCounters equals: 1 // Create another instance - d := InstanceAccessCounter create. + d := InstanceAccessCounter create // Class variable reflects both creations - self assert: (InstanceAccessCounter instanceCount) equals: 2. + self assert: InstanceAccessCounter instanceCount equals: 2 // Both instances see the same class variable - self assert: (c totalCounters) equals: 2. - self assert: (d totalCounters) equals: 2 + self assert: c totalCounters equals: 2 + self assert: d totalCounters equals: 2 diff --git a/stdlib/test/instance_class_var_access_value_type_test.bt b/stdlib/test/instance_class_var_access_value_type_test.bt index 6e70f3ecb..d48969591 100644 --- a/stdlib/test/instance_class_var_access_value_type_test.bt +++ b/stdlib/test/instance_class_var_access_value_type_test.bt @@ -3,23 +3,23 @@ // BT-413: Tests that value-type (Object subclass) instances can read class // variables via self class — same BT-413 invariant as actors but for -// non-actor classes (e.g. ClassVarPoint). +// non-actor classes (e.g. ClassVarPoint) TestCase subclass: InstanceClassVarAccessValueTypeTest testValueTypeInstanceAccessToClassVariable => - self assert: (ClassVarPoint instanceCount) equals: 0. + self assert: ClassVarPoint instanceCount equals: 0 // Create a point via class method (increments instanceCount) - p1 := ClassVarPoint create: #{#x => 3, #y => 4}. + p1 := ClassVarPoint create: #{#x => 3, #y => 4} // Verify it's a value type (has x field) - self assert: (p1 x) equals: 3. + self assert: p1 x equals: 3 // Class variable was incremented - self assert: (ClassVarPoint instanceCount) equals: 1. + self assert: ClassVarPoint instanceCount equals: 1 // Instance reads class variable via self class (the key BT-413 feature) - self assert: (p1 totalPoints) equals: 1. + self assert: p1 totalPoints equals: 1 // Create another point - p2 := ClassVarPoint create: #{#x => 1, #y => 2}. + p2 := ClassVarPoint create: #{#x => 1, #y => 2} // Both instances see updated class variable - self assert: (p1 totalPoints) equals: 2. - self assert: (p2 totalPoints) equals: 2 + self assert: p1 totalPoints equals: 2 + self assert: p2 totalPoints equals: 2 diff --git a/stdlib/test/integer_bitwise_test.bt b/stdlib/test/integer_bitwise_test.bt index f487ef220..bbfe18343 100644 --- a/stdlib/test/integer_bitwise_test.bt +++ b/stdlib/test/integer_bitwise_test.bt @@ -6,30 +6,30 @@ TestCase subclass: IntegerBitwiseTest testBitwiseOperations => - self assert: (12 bitAnd: 10) equals: 8. - self assert: (255 bitAnd: 15) equals: 15. + self assert: (12 bitAnd: 10) equals: 8 + self assert: (255 bitAnd: 15) equals: 15 // --- bitOr: --- - self assert: (12 bitOr: 10) equals: 14. - self assert: (0 bitOr: 255) equals: 255. + self assert: (12 bitOr: 10) equals: 14 + self assert: (0 bitOr: 255) equals: 255 // --- bitXor: --- - self assert: (12 bitXor: 10) equals: 6. - self assert: (255 bitXor: 255) equals: 0. + self assert: (12 bitXor: 10) equals: 6 + self assert: (255 bitXor: 255) equals: 0 // --- bitNot --- - self assert: (0 bitNot) equals: -1. + self assert: 0 bitNot equals: -1 // --- bitShift: (positive = left) --- - self assert: (1 bitShift: 4) equals: 16. + self assert: (1 bitShift: 4) equals: 16 // --- bitShift: (negative = right) --- self assert: (16 bitShift: -2) equals: 4 testMathMethods => // --- factorial --- - self assert: (0 factorial) equals: 1. - self assert: (1 factorial) equals: 1. - self assert: (5 factorial) equals: 120. + self assert: 0 factorial equals: 1 + self assert: 1 factorial equals: 1 + self assert: 5 factorial equals: 120 // --- gcd: --- - self assert: (12 gcd: 8) equals: 4. - self assert: (7 gcd: 5) equals: 1. - self assert: (0 gcd: 5) equals: 5. + self assert: (12 gcd: 8) equals: 4 + self assert: (7 gcd: 5) equals: 1 + self assert: (0 gcd: 5) equals: 5 // --- lcm: --- - self assert: (4 lcm: 6) equals: 12. + self assert: (4 lcm: 6) equals: 12 self assert: (3 lcm: 5) equals: 15 diff --git a/stdlib/test/json_test.bt b/stdlib/test/json_test.bt index bd2bca0f3..1e30bd62b 100644 --- a/stdlib/test/json_test.bt +++ b/stdlib/test/json_test.bt @@ -6,77 +6,77 @@ TestCase subclass: JsonTest testParsingPrimitiveValues => - self assert: (JSON parse: "42") equals: 42. + self assert: (JSON parse: "42") equals: 42 // Parse a JSON float - self assert: (JSON parse: "3.14") equals: 3.14. + self assert: (JSON parse: "3.14") equals: 3.14 // Parse JSON true - self assert: (JSON parse: "true"). + self assert: (JSON parse: "true") // Parse JSON false - self deny: (JSON parse: "false"). + self deny: (JSON parse: "false") // Parse JSON null to nil self assert: (JSON parse: "null") equals: nil testParsingArrays => // Parse a JSON array of integers - self assert: (JSON parse: "[1, 2, 3]") equals: #(1, 2, 3). + self assert: (JSON parse: "[1, 2, 3]") equals: #(1, 2, 3) // Parse a nested array - self assert: (JSON parse: "[[1, 2], [3, 4]]") equals: #(#(1, 2), #(3, 4)). + self assert: (JSON parse: "[[1, 2], [3, 4]]") equals: #(#(1, 2), #(3, 4)) // Parse a mixed array — verify size and individual access - self assert: ((JSON parse: "[1, true, null]") size) equals: 3. + self assert: (JSON parse: "[1, true, null]") size equals: 3 // Parse an empty array self assert: (JSON parse: "[]") equals: #() testGeneratingBeamtalkValueToJsonString => // Generate JSON from a List - self assert: (JSON generate: #(1, 2, 3)) equals: "[1,2,3]". + self assert: (JSON generate: #(1, 2, 3)) equals: "[1,2,3]" // Generate JSON from an Integer - self assert: (JSON generate: 42) equals: "42". + self assert: (JSON generate: 42) equals: "42" // Generate JSON from true - self assert: (JSON generate: true) equals: "true". + self assert: (JSON generate: true) equals: "true" // Generate JSON from false - self assert: (JSON generate: false) equals: "false". + self assert: (JSON generate: false) equals: "false" // Generate JSON from nil (becomes null) - self assert: (JSON generate: nil) equals: "null". + self assert: (JSON generate: nil) equals: "null" // Generate JSON from an empty List self assert: (JSON generate: #()) equals: "[]" testRoundTripGenerateThenParse => // Round-trip an integer - self assert: (JSON parse: (JSON generate: 42)) equals: 42. + self assert: (JSON parse: (JSON generate: 42)) equals: 42 // Round-trip a boolean - self assert: (JSON parse: (JSON generate: true)). + self assert: (JSON parse: (JSON generate: true)) // Round-trip null - self assert: (JSON parse: (JSON generate: nil)) equals: nil. + self assert: (JSON parse: (JSON generate: nil)) equals: nil // Round-trip an array - self assert: (JSON parse: (JSON generate: #(1, 2, 3))) equals: #(1, 2, 3). + self assert: (JSON parse: (JSON generate: #(1, 2, 3))) equals: #(1, 2, 3) // Round-trip a Dictionary - self assert: ((JSON parse: (JSON generate: #{"name" => "Ada"})) at: "name") equals: "Ada". + self assert: ((JSON parse: (JSON generate: #{"name" => "Ada"})) at: "name") equals: "Ada" // Round-trip nested structures self assert: (((JSON parse: (JSON generate: #{"user" => #{"age" => 36}})) at: "user") at: "age") equals: 36 testDictionaryGenerateAndParse => // Generate JSON from a Dictionary, then verify structure - self assert: ((JSON generate: #{"a" => 1}) size > 2). + self assert: ((JSON generate: #{"a" => 1}) size > 2) // Generate and re-parse a Dictionary - self assert: ((JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) at: "x") equals: 10. - self assert: ((JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) at: "y") equals: 20. - self assert: ((JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) size) equals: 2. + self assert: ((JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) at: "x") equals: 10 + self assert: ((JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) at: "y") equals: 20 + self assert: (JSON parse: (JSON generate: #{"x" => 10, "y" => 20})) size equals: 2 // Dictionary with nested List - self assert: ((JSON parse: (JSON generate: #{"items" => #(1, 2, 3)})) at: "items") equals: #(1, 2, 3). + self assert: ((JSON parse: (JSON generate: #{"items" => #(1, 2, 3)})) at: "items") equals: #(1, 2, 3) // Dictionary with boolean values - self assert: ((JSON parse: (JSON generate: #{"active" => true})) at: "active"). + self assert: ((JSON parse: (JSON generate: #{"active" => true})) at: "active") // Dictionary with null value self assert: ((JSON parse: (JSON generate: #{"value" => nil})) at: "value") equals: nil testPrettyPrinting => // Pretty print produces a non-empty string - self assert: ((JSON prettyPrint: #{"a" => 1}) size > 0). + self assert: ((JSON prettyPrint: #{"a" => 1}) size > 0) // Pretty print produces same data as generate when re-parsed self assert: ((JSON parse: (JSON prettyPrint: #{"a" => 1})) at: "a") equals: 1 testErrorHandling => // Parse invalid JSON produces a parse_error - self should: [JSON parse: "not json"] raise: #parse_error. + self should: [JSON parse: "not json"] raise: #parse_error // Parse with non-string argument produces type_error @expect type self should: [JSON parse: 42] raise: #type_error diff --git a/stdlib/test/keyword_messages_test.bt b/stdlib/test/keyword_messages_test.bt index 693eec8a8..00b9ac5e5 100644 --- a/stdlib/test/keyword_messages_test.bt +++ b/stdlib/test/keyword_messages_test.bt @@ -7,62 +7,62 @@ TestCase subclass: KeywordMessagesTest testSingleKeywordMessages => - self assert: ([:x | x] value: 42) equals: 42. - self assert: ([:x | x + 10] value: 5) equals: 15. + self assert: ([:x | x] value: 42) equals: 42 + self assert: ([:x | x + 10] value: 5) equals: 15 self assert: ([:n | n * n] value: 4) equals: 16 testMultiKeywordMessages => - self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7. - self assert: ([:a :b | a - b] value: 10 value: 3) equals: 7. + self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7 + self assert: ([:a :b | a - b] value: 10 value: 3) equals: 7 self assert: ([:x :y | x * y] value: 6 value: 7) equals: 42 testThreeKeywordMessages => - self assert: ([:a :b :c | a + b + c] value: 1 value: 2 value: 3) equals: 6. + self assert: ([:a :b :c | a + b + c] value: 1 value: 2 value: 3) equals: 6 self assert: ([:x :y :z | x * y + z] value: 2 value: 3 value: 4) equals: 10 testNestedKeywordMessages => - self assert: ([:x | [:y | x + y] value: 10] value: 5) equals: 15. + self assert: ([:x | [:y | x + y] value: 10] value: 5) equals: 15 self assert: ([:a | [:b | [:c | a + b + c] value: 3] value: 2] value: 1) equals: 6 testKeywordMessagesWithLiterals => - self assert: ([:s | s] value: "test") equals: "test". - self assert: ([:n | n * 10] value: 0) equals: 0. + self assert: ([:s | s] value: "test") equals: "test" + self assert: ([:n | n * 10] value: 0) equals: 0 self assert: ([:x | 0 - x] value: 5) equals: -5 testComplexExpressionsAsArguments => - self assert: ([:x | x * 2] value: 3 + 2) equals: 10. + self assert: ([:x | x * 2] value: 3 + 2) equals: 10 self assert: ([:a :b | a + b] value: 2 * 3 value: 4 + 1) equals: 11 testHigherOrderBlocksVariablePersistenceAcrossExpressions => // Block that returns a block - makeMultiplier := [:factor | [:n | n * factor]]. - times3 := makeMultiplier value: 3. - self assert: (times3 value: 7) equals: 21. + makeMultiplier := [:factor | [:n | n * factor]] + times3 := makeMultiplier value: 3 + self assert: (times3 value: 7) equals: 21 // Passing block as argument - applyBlock := [:block :arg | block value: arg]. + applyBlock := [:block :arg | block value: arg] self assert: (applyBlock value: [:x | x + 100] value: 42) equals: 142 testMultiLineKeywordMessage => // BT-890: keyword messages should continue across newlines result := true ifTrue: [42] - ifFalse: [0]. + ifFalse: [0] self assert: result equals: 42 testMultiLineInjectInto => // BT-890: multi-line inject:into: keyword message sum := #(1, 2, 3) inject: 0 - into: [:acc :each | acc + each]. + into: [:acc :each | acc + each] self assert: sum equals: 6 test4KeywordMessagesOnObjects => - mk := MultiKeyword spawn. + mk := MultiKeyword spawn // 4-keyword method: sum four arguments - self assert: (mk add: 1 and: 2 and: 3 and: 4) equals: 10. + self assert: (mk add: 1 and: 2 and: 3 and: 4) equals: 10 // 4-keyword method: verify argument order (weighted sum) - self assert: (mk first: 1 second: 2 third: 3 fourth: 4) equals: 1234. + self assert: (mk first: 1 second: 2 third: 3 fourth: 4) equals: 1234 // Different argument values to confirm ordering - self assert: (mk first: 9 second: 0 third: 5 fourth: 7) equals: 9057. + self assert: (mk first: 9 second: 0 third: 5 fourth: 7) equals: 9057 // 5-keyword method: sum five arguments - self assert: (mk add: 10 and: 20 and: 30 and: 40 and: 50) equals: 150. + self assert: (mk add: 10 and: 20 and: 30 and: 40 and: 50) equals: 150 // Verify state was updated by add:and:and:and:and: - self assert: (mk getResult) equals: 150 + self assert: mk getResult equals: 150 diff --git a/stdlib/test/language_features_doc_test.bt b/stdlib/test/language_features_doc_test.bt index 63dfdb624..2fce19e0a 100644 --- a/stdlib/test/language_features_doc_test.bt +++ b/stdlib/test/language_features_doc_test.bt @@ -7,94 +7,94 @@ TestCase subclass: LanguageFeaturesDocTest testStringEncodingAndUtf8 => - self assert: ("Hello" length) equals: 5. - self assert: ("世界" length) equals: 2. + self assert: "Hello" length equals: 5 + self assert: "世界" length equals: 2 // Slicing by grapheme - self assert: ("Hello" at: 1) equals: "H". - self assert: ("世界" at: 1) equals: "世". + self assert: ("Hello" at: 1) equals: "H" + self assert: ("世界" at: 1) equals: "世" // Case conversion - self assert: ("HELLO" lowercase) equals: "hello". - self assert: ("straße" uppercase) equals: "STRASSE" + self assert: "HELLO" lowercase equals: "hello" + self assert: "straße" uppercase equals: "STRASSE" testCoreSyntaxBinaryOperators => // Exponentiation - self assert: (2 ** 10) equals: 1024. + self assert: (2 ** 10) equals: 1024 // Multiplicative - self assert: (3 * 4) equals: 12. - self assert: (10 / 2) equals: 5 asFloat. - self assert: (17 % 5) equals: 2. + self assert: (3 * 4) equals: 12 + self assert: (10 / 2) equals: 5 asFloat + self assert: (17 % 5) equals: 2 // Additive - self assert: (3 + 4) equals: 7. - self assert: (10 - 3) equals: 7. - self assert: "Hello" ++ " World" equals: "Hello World". + self assert: (3 + 4) equals: 7 + self assert: (10 - 3) equals: 7 + self assert: "Hello" ++ " World" equals: "Hello World" // Comparison - self assert: (3 < 5). - self assert: (5 > 3). - self assert: (3 <= 3). - self assert: (5 >= 3). + self assert: (3 < 5) + self assert: (5 > 3) + self assert: (3 <= 3) + self assert: (5 >= 3) // Equality - self assert: (5 =:= 5). - self assert: (5 == 5.0). - self assert: (5 /= 6). + self assert: (5 =:= 5) + self assert: (5 == 5.0) + self assert: (5 /= 6) @expect dnu self assert: (5 =/= 6) testGradualTyping => - typedDocMath := TypedMath new. - self assert: (typedDocMath identity: 7) equals: 7. - self assert: (typedDocMath sum: 2 with: 5) equals: 7. - self assert: (typedDocMath maybeName: false) equals: "none". - typedDocAccount := TypedAccount spawn. - self assert: (typedDocAccount deposit: 8) equals: 8. - self assert: (typedDocAccount balance) equals: 8 + typedDocMath := TypedMath new + self assert: (typedDocMath identity: 7) equals: 7 + self assert: (typedDocMath sum: 2 with: 5) equals: 7 + self assert: (typedDocMath maybeName: false) equals: "none" + typedDocAccount := TypedAccount spawn + self assert: (typedDocAccount deposit: 8) equals: 8 + self assert: typedDocAccount balance equals: 8 testBlocksClosures => // Block with arguments - self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7. + self assert: ([:x :y | x + y] value: 3 value: 4) equals: 7 // Block with local variables - myBlock := [:x | temp := x * 2. temp + 1]. + myBlock := [:x | temp := x * 2. temp + 1] self assert: (myBlock value: 5) equals: 11 testPatternMatchingMatchExpression => // Variable binding in patterns - self assert: (42 match: [n -> n + 1]) equals: 43. + self assert: (42 match: [n -> n + 1]) equals: 43 // Match on computed expression - self assert: ((3 + 4) match: [7 -> "correct"; _ -> "wrong"]) equals: "correct". + self assert: ((3 + 4) match: [7 -> "correct"; _ -> "wrong"]) equals: "correct" // Integer literal matching - self assert: (1 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "one". - self assert: (2 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "two". - self assert: (3 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "other". + self assert: (1 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "one" + self assert: (2 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "two" + self assert: (3 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "other" // Symbol matching - self assert: (#ok match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "success". + self assert: (#ok match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "success" // String matching - self assert: ("hello" match: ["hello" -> "hi"; _ -> "huh?"]) equals: "hi". + self assert: ("hello" match: ["hello" -> "hi"; _ -> "huh?"]) equals: "hi" // Negative number patterns - self assert: (-1 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "minus one". - self assert: (0 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "zero". + self assert: (-1 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "minus one" + self assert: (0 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "zero" // Guard clauses with when: - self assert: (10 match: [n when: [n > 100] -> "big"; n when: [n > 5] -> "medium"; _ -> "small"]) equals: "medium". + self assert: (10 match: [n when: [n > 100] -> "big"; n when: [n > 5] -> "medium"; _ -> "small"]) equals: "medium" // Wildcard match self assert: (42 match: [_ -> "matched"]) equals: "matched" testDestructuringInMatchArms => // Variable captures the matched value - self assert: (42 match: [x -> x + 1]) equals: 43. + self assert: (42 match: [x -> x + 1]) equals: 43 // Multiple arms with variable binding self assert: ("hello" match: [s -> s size]) equals: 5 testStandardLibraryStream => // Terminal forces computation through the pipeline - self assert: (((Stream from: 1) select: [:n | n isEven]) take: 5) equals: #(2, 4, 6, 8, 10). - self assert: ((Stream on: #(1, 2, 3, 4)) inject: 0 into: [:sum :n | sum + n]) equals: 10. + self assert: (((Stream from: 1) select: [:n | n isEven]) take: 5) equals: #(2, 4, 6, 8, 10) + self assert: ((Stream on: #(1, 2, 3, 4)) inject: 0 into: [:sum :n | sum + n]) equals: 10 // Stream printString — pipeline inspection - self assert: ((Stream from: 1) printString) notNil. - self assert: ((Stream on: #(1, 2, 3)) printString) notNil. - self assert: (((Stream from: 1) select: [:n | n isEven]) printString) notNil. + self assert: ((Stream from: 1) printString) notNil + self assert: ((Stream on: #(1, 2, 3)) printString) notNil + self assert: (((Stream from: 1) select: [:n | n isEven]) printString) notNil // Eager vs Lazy boundary self assert: (#(1, 2, 3, 4, 5) select: [:n | n > 2]) equals: #(3, 4, 5) testTestingFrameworkExpressionTests => // From the expression tests example - self assert: (1 + 2) equals: 3. - self assert: ("hello" size) equals: 5. + self assert: (1 + 2) equals: 3 + self assert: "hello" size equals: 5 self assert: "hello" ++ " world" equals: "hello world" diff --git a/stdlib/test/list_literals_test.bt b/stdlib/test/list_literals_test.bt index f99737bbb..9bc08b331 100644 --- a/stdlib/test/list_literals_test.bt +++ b/stdlib/test/list_literals_test.bt @@ -6,25 +6,25 @@ TestCase subclass: ListLiteralsTest testEmptyList => - self assert: #() equals: #(). - self assert: (#() size) equals: 0. - self assert: (#() isEmpty) + self assert: #() equals: #() + self assert: #() size equals: 0 + self assert: #() isEmpty testSingleElementList => - self assert: #(256) equals: #(256). - self assert: (#(256) size) equals: 1. - self deny: (#(256) isEmpty) + self assert: #(256) equals: #(256) + self assert: #(256) size equals: 1 + self deny: #(256) isEmpty testMultipleElementList => - self assert: #(1, 2, 3) equals: #(1, 2, 3). - self assert: (#(1, 2, 3) size) equals: 3 + self assert: #(1, 2, 3) equals: #(1, 2, 3) + self assert: #(1, 2, 3) size equals: 3 testNestedLists => self assert: #(#(1, 2), #(3, 4)) equals: #(#(1, 2), #(3, 4)) testListMethods => - self assert: (#(1, 2, 3) first) equals: 1. - self assert: (#(1, 2, 3) rest) equals: #(2, 3) + self assert: #(1, 2, 3) first equals: 1 + self assert: #(1, 2, 3) rest equals: #(2, 3) testTrailingComma => self assert: #(10, 20, 30,) equals: #(10, 20, 30) diff --git a/stdlib/test/math_test.bt b/stdlib/test/math_test.bt index c459d545d..c30fb07f5 100644 --- a/stdlib/test/math_test.bt +++ b/stdlib/test/math_test.bt @@ -6,85 +6,85 @@ TestCase subclass: MathTest testFloatClassSideConstants => - self assert: (Float pi) equals: 3.141592653589793. + self assert: Float pi equals: 3.141592653589793 // Euler's number - self assert: (Float e) equals: 2.718281828459045 + self assert: Float e equals: 2.718281828459045 testTrigonometricMethodsFloatInstance => // sin of pi/2 - self assert: ((Float pi / 2) sin) equals: 1 asFloat. + self assert: (Float pi / 2) sin equals: 1 asFloat // cos of pi - self assert: ((Float pi) cos) equals: -1 asFloat. + self assert: (Float pi) cos equals: -1 asFloat // tan of pi/4 (should be close to 1.0) - self assert: ((Float pi / 4) tan) equals: 0.9999999999999999. + self assert: (Float pi / 4) tan equals: 0.9999999999999999 // asin of 0.5 - self assert: (0.5 asin) equals: 0.5235987755982989. + self assert: 0.5 asin equals: 0.5235987755982989 // acos of 0.5 - self assert: (0.5 acos) equals: 1.0471975511965979. + self assert: 0.5 acos equals: 1.0471975511965979 // atan of 0.5 - self assert: (0.5 atan) equals: 0.4636476090008061. + self assert: 0.5 atan equals: 0.4636476090008061 // atan2 - self assert: (0.5 atan2: 0.5) equals: 0.7853981633974483. + self assert: (0.5 atan2: 0.5) equals: 0.7853981633974483 // atan2 with Integer argument - self assert: ((1 asFloat) atan2: 2) equals: 0.4636476090008061. + self assert: ((1 asFloat) atan2: 2) equals: 0.4636476090008061 // sin of small value - self assert: (0.5 sin) equals: 0.479425538604203. + self assert: 0.5 sin equals: 0.479425538604203 // cos of small value - self assert: (0.5 cos) equals: 0.8775825618903728 + self assert: 0.5 cos equals: 0.8775825618903728 testExponentialLogarithmicMethodsFloatInstance => // sqrt of 4.0 - self assert: (4.0 sqrt) equals: 2 asFloat. + self assert: 4.0 sqrt equals: 2 asFloat // sqrt of 2.0 - self assert: (2.0 sqrt) equals: 1.4142135623730951. + self assert: 2.0 sqrt equals: 1.4142135623730951 // log of e (natural) - self assert: ((Float e) log) equals: 1 asFloat. + self assert: (Float e) log equals: 1 asFloat // ln of e (alias for log) - self assert: ((Float e) ln) equals: 1 asFloat. + self assert: (Float e) ln equals: 1 asFloat // log2 - self assert: (8.0 log2) equals: 3 asFloat. + self assert: 8.0 log2 equals: 3 asFloat // log10 - self assert: (100.0 log10) equals: 2 asFloat. + self assert: 100.0 log10 equals: 2 asFloat // exp of 0.5 - self assert: (0.5 exp) equals: 1.6487212707001282. + self assert: 0.5 exp equals: 1.6487212707001282 // raisedTo: - self assert: (2.0 raisedTo: 10) equals: 1024 asFloat. + self assert: (2.0 raisedTo: 10) equals: 1024 asFloat // raisedTo: with float exponent self assert: (4.0 raisedTo: 0.5) equals: 2 asFloat testExponentialLogarithmicMethodsIntegerInstance => // Integer sqrt - self assert: (16 sqrt) equals: 4 asFloat. + self assert: 16 sqrt equals: 4 asFloat // Integer sqrt non-perfect - self assert: (2 sqrt) equals: 1.4142135623730951. + self assert: 2 sqrt equals: 1.4142135623730951 // Integer log2 - self assert: (8 log2) equals: 3 asFloat. + self assert: 8 log2 equals: 3 asFloat // Integer log10 - self assert: (100 log10) equals: 2 asFloat. + self assert: 100 log10 equals: 2 asFloat // Integer exp of 2 - self assert: (2 exp) equals: 7.38905609893065. + self assert: 2 exp equals: 7.38905609893065 // Integer raisedTo: self assert: (2 raisedTo: 10) equals: 1024 asFloat testTrigonometricIdentities => // sin^2 + cos^2 = 1 (within float precision) - x := 0.5. - self assert: ((x sin) * (x sin)) + ((x cos) * (x cos)) equals: 1 asFloat + x := 0.5 + self assert: ((x sin) * x sin) + ((x cos) * x cos) equals: 1 asFloat testDomainErrorHandling => // sqrt of negative number - self should: [(-1 asFloat) sqrt] raise: #badarith. + self should: [(-1 asFloat) sqrt] raise: #badarith // log of zero - self should: [(0 asFloat) log] raise: #badarith. + self should: [(0 asFloat) log] raise: #badarith // log of negative - self should: [(-1 asFloat) log] raise: #badarith. + self should: [(-1 asFloat) log] raise: #badarith // ln of zero (alias for log) - self should: [(0 asFloat) ln] raise: #badarith. + self should: [(0 asFloat) ln] raise: #badarith // log2 of zero - self should: [(0 asFloat) log2] raise: #badarith. + self should: [(0 asFloat) log2] raise: #badarith // log10 of zero - self should: [(0 asFloat) log10] raise: #badarith. + self should: [(0 asFloat) log10] raise: #badarith // asin outside [-1, 1] range - self should: [(2 asFloat) asin] raise: #badarith. + self should: [(2 asFloat) asin] raise: #badarith // acos outside [-1, 1] range self should: [(2 asFloat) acos] raise: #badarith diff --git a/stdlib/test/metaclass_test.bt b/stdlib/test/metaclass_test.bt index f4c900736..acb0d75e7 100644 --- a/stdlib/test/metaclass_test.bt +++ b/stdlib/test/metaclass_test.bt @@ -3,82 +3,82 @@ // BT-412, BT-803, ADR 0036 Phase 2: Tests the metaclass tower — primitive class // identity (42 class == Integer), isMeta/isClass predicates, metaclass name, -// thisClass, superclass hierarchy, self-grounding fixed point, and sealed Metaclass. +// thisClass, superclass hierarchy, self-grounding fixed point, and sealed Metaclass TestCase subclass: MetaclassTest testPrimitiveClassIdentityAndTower => - self assert: (42 class) equals: Integer. - self assert: (3.14 class) equals: Float. - self assert: ("hello" class) equals: String. - self assert: (true class) equals: True. - self assert: (false class) equals: False. - self assert: (nil class) equals: UndefinedObject. - self assert: (#symbol class) equals: Symbol. + self assert: 42 class equals: Integer + self assert: 3.14 class equals: Float + self assert: "hello" class equals: String + self assert: true class equals: True + self assert: false class equals: False + self assert: nil class equals: UndefinedObject + self assert: #symbol class equals: Symbol // BT-802 (ADR 0036 Phase 1): Metaclass objects replace the #Metaclass sentinel - self assert: (42 class class) isMeta equals: true. - self assert: ("hello" class class) isMeta equals: true. - self assert: (true class class) isMeta equals: true. + self assert: (42 class class) isMeta equals: true + self assert: ("hello" class class) isMeta equals: true + self assert: (true class class) isMeta equals: true // Metaclass objects are not plain classes - self assert: (42 class class) isClass equals: false. + self assert: (42 class class) isClass equals: false // Metaclass tower terminates: self-grounding invariant (class class class == class class) - self assert: (42 class class class) equals: (42 class class) + self assert: 42 class class class equals: 42 class class // BT-803: isMetaclass predicate testIsMetaclass => - self assert: (42 class class) isMetaclass equals: true. - self assert: ("hello" class class) isMetaclass equals: true. - self assert: (true class class) isMetaclass equals: true. - self assert: (nil class class) isMetaclass equals: true. + self assert: (42 class class) isMetaclass equals: true + self assert: ("hello" class class) isMetaclass equals: true + self assert: (true class class) isMetaclass equals: true + self assert: (nil class class) isMetaclass equals: true // isBehaviour is inherited from Behaviour - self assert: (42 class class) isBehaviour equals: true. + self assert: (42 class class) isBehaviour equals: true // Regular class objects are not metaclasses - self assert: (42 class) isMetaclass equals: false. + self assert: (42 class) isMetaclass equals: false self assert: Integer isMetaclass equals: false // BT-803: name — e.g. 42 class class name == 'Integer class' testName => - self assert: (42 class class) name equals: "Integer class". - self assert: (3.14 class class) name equals: "Float class". - self assert: ("hello" class class) name equals: "String class". - self assert: (true class class) name equals: "True class". - self assert: (false class class) name equals: "False class". - self assert: (nil class class) name equals: "UndefinedObject class". + self assert: (42 class class) name equals: "Integer class" + self assert: (3.14 class class) name equals: "Float class" + self assert: ("hello" class class) name equals: "String class" + self assert: (true class class) name equals: "True class" + self assert: (false class class) name equals: "False class" + self assert: (nil class class) name equals: "UndefinedObject class" self assert: (#sym class class) name equals: "Symbol class" // BT-803: thisClass — e.g. 42 class class thisClass == Integer testThisClass => - self assert: (42 class class) thisClass equals: Integer. - self assert: (3.14 class class) thisClass equals: Float. - self assert: ("hello" class class) thisClass equals: String. - self assert: (true class class) thisClass equals: True. - self assert: (false class class) thisClass equals: False. + self assert: (42 class class) thisClass equals: Integer + self assert: (3.14 class class) thisClass equals: Float + self assert: ("hello" class class) thisClass equals: String + self assert: (true class class) thisClass equals: True + self assert: (false class class) thisClass equals: False self assert: (nil class class) thisClass equals: UndefinedObject // BT-803: printString — same as name testPrintString => - self assert: (42 class class) printString equals: "Integer class". - self assert: (3.14 class class) printString equals: "Float class". + self assert: (42 class class) printString equals: "Integer class" + self assert: (3.14 class class) printString equals: "Float class" self assert: ("hello" class class) printString equals: "String class" // BT-803: superclass invariant — Counter class superclass == Actor class testSuperclassInvariant => // Parallel hierarchy: Counter class class superclass == Actor class class - self assert: (Counter class class superclass) equals: (Actor class class). + self assert: Counter class class superclass equals: Actor class class // Actor's metaclass superclass is Object's metaclass - self assert: (Actor class class superclass) equals: (Object class class). + self assert: Actor class class superclass equals: Object class class // Object's metaclass superclass is ProtoObject's metaclass - self assert: (Object class class superclass) equals: (ProtoObject class class) + self assert: Object class class superclass equals: ProtoObject class class // BT-803: self-grounding fixed point — Metaclass class class == Metaclass class testSelfGrounding => - self assert: (Metaclass class class) equals: (Metaclass class). + self assert: Metaclass class class equals: Metaclass class // Three-deep also terminates - self assert: (Metaclass class class class) equals: (Metaclass class class) + self assert: Metaclass class class class equals: Metaclass class class // BT-803: Metaclass allSubclasses returns [] (sealed) testAllSubclassesSealed => - self assert: (Metaclass allSubclasses isEmpty) + self assert: Metaclass allSubclasses isEmpty // BT-803: Metaclass new raises error testNewRaisesError => @@ -87,6 +87,6 @@ TestCase subclass: MetaclassTest // Class identity tests for domain classes testClassIdentityForDomainClasses => // Random class isMeta returns true (BT-802 / ADR 0036) - self assert: (Random class) isMeta equals: true. + self assert: (Random class) isMeta equals: true // Regex class isMeta returns true (BT-802 / ADR 0036) self assert: (Regex class) isMeta equals: true diff --git a/stdlib/test/method_resolver_hierarchy_test.bt b/stdlib/test/method_resolver_hierarchy_test.bt index 78013fd74..051a459ae 100644 --- a/stdlib/test/method_resolver_hierarchy_test.bt +++ b/stdlib/test/method_resolver_hierarchy_test.bt @@ -4,7 +4,7 @@ // BUnit tests for >> hierarchy walking (ADR 0033, BT-770) // // Verifies that >> walks the superclass chain to find inherited methods, -// matching Pharo's semantics. +// matching Pharo's semantics TestCase subclass: MethodResolverHierarchyTest @@ -12,29 +12,29 @@ TestCase subclass: MethodResolverHierarchyTest testInheritedMethodReturnsCompiledMethod => // greetParent is defined on HierarchyParent, inherited by HierarchyChild - m := HierarchyChild >> #greetParent. - self assert: m class equals: CompiledMethod. + m := HierarchyChild >> #greetParent + self assert: m class equals: CompiledMethod self assert: m selector equals: #greetParent testInheritedMethodFromObject => // isNil is defined on Object, inherited by HierarchyChild - m := HierarchyChild >> #isNil. - self assert: m class equals: CompiledMethod. + m := HierarchyChild >> #isNil + self assert: m class equals: CompiledMethod self assert: m selector equals: #isNil // --- Local methods still work --- testLocalMethodStillReturnsCompiledMethod => - m := HierarchyChild >> #greetChild. - self assert: m class equals: CompiledMethod. + m := HierarchyChild >> #greetChild + self assert: m class equals: CompiledMethod self assert: m selector equals: #greetChild // --- Local method takes precedence over inherited --- testLocalMethodShadowsInherited => // sharedMethod is defined on both parent and child - m := HierarchyChild >> #sharedMethod. - self assert: m class equals: CompiledMethod. + m := HierarchyChild >> #sharedMethod + self assert: m class equals: CompiledMethod self assert: m selector equals: #sharedMethod // --- Non-existent methods still return nil --- @@ -45,6 +45,6 @@ TestCase subclass: MethodResolverHierarchyTest // --- Inherited method carries doc from defining class --- testInheritedMethodDocFromParent => - HierarchyParent setDocForMethod: #greetParent to: "Parent greeting". - m := HierarchyChild >> #greetParent. + HierarchyParent setDocForMethod: #greetParent to: "Parent greeting" + m := HierarchyChild >> #greetParent self assert: m doc equals: "Parent greeting" diff --git a/stdlib/test/mixed_call_site_test.bt b/stdlib/test/mixed_call_site_test.bt index 3acbbeef4..3458de26d 100644 --- a/stdlib/test/mixed_call_site_test.bt +++ b/stdlib/test/mixed_call_site_test.bt @@ -1,23 +1,23 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-870: Mixed Tier 1/Tier 2 call site test (ADR 0041). +// BT-870: Mixed Tier 1/Tier 2 call site test (ADR 0041) // Verifies that a HOM called from one method with a plain Tier 1 block and from -// another method with a Tier 2 (captured-mutation) block works correctly for both. +// another method with a Tier 2 (captured-mutation) block works correctly for both // // The Tier 1 call site was previously a runtime crash: the Tier 2 method body -// calls blocks with arity 2 but the un-promoted block had arity 1. +// calls blocks with arity 2 but the un-promoted block had arity 1 TestCase subclass: MixedCallSiteTest testTier1BlockAtTier2HOM => - // A plain block (no captured mutations) at a known Tier 2 HOM position. - // BT-870: Must not crash. Result should be 10 + 1 = 11. - actor := MixedCallSiteActor spawn. - self assert: (actor testTier1CallSite) equals: 11 + // A plain block (no captured mutations) at a known Tier 2 HOM position + // BT-870: Must not crash. Result should be 10 + 1 = 11 + actor := MixedCallSiteActor spawn + self assert: actor testTier1CallSite equals: 11 testTier2BlockAtTier2HOM => - // A captured-mutation block at a Tier 2 HOM position. - // State threading must still work: total should be 0 + 7 = 7. - actor := MixedCallSiteActor spawn. - self assert: (actor testTier2CallSite) equals: 7 + // A captured-mutation block at a Tier 2 HOM position + // State threading must still work: total should be 0 + 7 = 7 + actor := MixedCallSiteActor spawn + self assert: actor testTier2CallSite equals: 7 diff --git a/stdlib/test/mutation_return_values_test.bt b/stdlib/test/mutation_return_values_test.bt index 7a8eb3606..33823fbae 100644 --- a/stdlib/test/mutation_return_values_test.bt +++ b/stdlib/test/mutation_return_values_test.bt @@ -3,31 +3,31 @@ // BT-483: Tests that mutation-threaded control flow correctly returns the // computed value (not nil) from inject:into:, on:do:, and ensure: when -// combined with actor field mutations. +// combined with actor field mutations TestCase subclass: MutationReturnValuesTest testMutationReturnValues => - actor := MutationReturnValues spawn. - self assert: (actor setValue: 0) equals: 0. + actor := MutationReturnValues spawn + self assert: (actor setValue: 0) equals: 0 // Block receives (acc, elem) — accumulator first, element second (BT-820) - self assert: (actor sumViaInject: #(1, 2, 3)) equals: 6. + self assert: (actor sumViaInject: #(1, 2, 3)) equals: 6 // self.value += elem: 0 + 1 + 2 + 3 = 6 - self assert: (actor getValue) equals: 6. + self assert: actor getValue equals: 6 // State should also be updated (side effect of mutations) - self assert: (actor setValue: 0) equals: 0. + self assert: (actor setValue: 0) equals: 0 // safeAdd: succeeds, should return self.value after mutation (10) - self assert: (actor safeAdd: 10) equals: 10. + self assert: (actor safeAdd: 10) equals: 10 // inject:into: as last expression should return accumulator (6), not nil - self assert: (actor getValue) equals: 10. - self assert: (actor setValue: 0) equals: 0. + self assert: actor getValue equals: 10 + self assert: (actor setValue: 0) equals: 0 // failingAdd triggers exception, handler returns -999 - self assert: (actor failingAdd) equals: -999. + self assert: actor failingAdd equals: -999 // Handler's mutation should be applied (0 + 100 = 100) - self assert: (actor getValue) equals: 100. - self assert: (actor setValue: 0) equals: 0. + self assert: actor getValue equals: 100 + self assert: (actor setValue: 0) equals: 0 // addWithCleanup: 5 — body returns self.value (5), cleanup adds 1000 - self assert: (actor addWithCleanup: 5) equals: 5. + self assert: (actor addWithCleanup: 5) equals: 5 // State: body set value to 5, cleanup added 1000 → 1005 - self assert: (actor getValue) equals: 1005 + self assert: actor getValue equals: 1005 diff --git a/stdlib/test/nested_to_do_test.bt b/stdlib/test/nested_to_do_test.bt index 1d28611a0..b1df53308 100644 --- a/stdlib/test/nested_to_do_test.bt +++ b/stdlib/test/nested_to_do_test.bt @@ -2,14 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // BT-478: Tests that nested to:do: loops correctly thread actor field mutations -// through multiple loop iterations (outer × inner increments persist in state). +// through multiple loop iterations (outer × inner increments persist in state) TestCase subclass: NestedToDoTest testNestedLoopWithFieldMutation => - nested := FieldMutationNested spawn. + nested := FieldMutationNested spawn // Test nested to:do: — 3 outer × 2 inner = 6 increments - self assert: (nested nestedIncrement: 3 inner: 2) equals: 6. + self assert: (nested nestedIncrement: 3 inner: 2) equals: 6 // Verify state persists - self assert: (nested getValue) equals: 6 + self assert: nested getValue equals: 6 diff --git a/stdlib/test/nil_protocol_test.bt b/stdlib/test/nil_protocol_test.bt index 72fec66d2..00cf04cbd 100644 --- a/stdlib/test/nil_protocol_test.bt +++ b/stdlib/test/nil_protocol_test.bt @@ -2,54 +2,54 @@ // SPDX-License-Identifier: Apache-2.0 // Tests the nil-testing protocol inherited from ProtoObject — isNil, notNil, -// ifNil:, ifNotNil:, ifNil:ifNotNil:, ifNotNil:ifNil: — on nil and non-nil values. +// ifNil:, ifNotNil:, ifNil:ifNotNil:, ifNotNil:ifNil: — on nil and non-nil values TestCase subclass: NilProtocolTest testNilTestingProtocol => - self deny: (42 isNil). - self assert: (42 notNil). - self deny: ("hello" isNil). - self assert: ("hello" notNil). - self deny: (true isNil). - self assert: (true notNil). - // --------------------------------------------------------------------------- - self assert: (nil isNil). + self deny: 42 isNil + self assert: 42 notNil + self deny: "hello" isNil + self assert: "hello" notNil + self deny: true isNil + self assert: true notNil + // --------------------------------------------------------------------------- + self assert: nil isNil // isNil and notNil on nil - self deny: (nil notNil). + self deny: nil notNil // --------------------------------------------------------------------------- - self assert: (42 ifNil: [99]) equals: 42. + self assert: (42 ifNil: [99]) equals: 42 // ifNil: on non-nil objects - self assert: ("hello" ifNil: ["default"]) equals: "hello". + self assert: ("hello" ifNil: ["default"]) equals: "hello" // --------------------------------------------------------------------------- - self assert: (nil ifNil: [99]) equals: 99. + self assert: (nil ifNil: [99]) equals: 99 // ifNil: on nil - self assert: (nil ifNil: ["default"]) equals: "default". + self assert: (nil ifNil: ["default"]) equals: "default" // --------------------------------------------------------------------------- - self assert: (42 ifNotNil: [:v | v + 1]) equals: 43. + self assert: (42 ifNotNil: [:v | v + 1]) equals: 43 // ifNotNil: on non-nil objects - self assert: ("hello" ifNotNil: [:s | s ++ " world"]) equals: "hello world". + self assert: ("hello" ifNotNil: [:s | s ++ " world"]) equals: "hello world" // Zero-arg block (no receiver passed) - self assert: (42 ifNotNil: [ 99 ]) equals: 99. + self assert: (42 ifNotNil: [ 99 ]) equals: 99 // --------------------------------------------------------------------------- - self assert: ("hello" ifNotNil: [ "yes" ]) equals: "yes". + self assert: ("hello" ifNotNil: [ "yes" ]) equals: "yes" // --------------------------------------------------------------------------- - self assert: (nil ifNotNil: [:v | v + 1]) equals: nil. + self assert: (nil ifNotNil: [:v | v + 1]) equals: nil // ifNotNil: on nil - self assert: (nil ifNotNil: [ 99 ]) equals: nil. + self assert: (nil ifNotNil: [ 99 ]) equals: nil // --------------------------------------------------------------------------- - self assert: (42 ifNil: [0] ifNotNil: [:v | v * 2]) equals: 84. + self assert: (42 ifNil: [0] ifNotNil: [:v | v * 2]) equals: 84 // ifNil:ifNotNil: two-way conditional on non-nil - self assert: ("hello" ifNil: [""] ifNotNil: [:s | s ++ "!"]) equals: "hello!". + self assert: ("hello" ifNil: [""] ifNotNil: [:s | s ++ "!"]) equals: "hello!" // Zero-arg notNil block - self assert: (42 ifNil: [0] ifNotNil: [ 99 ]) equals: 99. + self assert: (42 ifNil: [0] ifNotNil: [ 99 ]) equals: 99 // --------------------------------------------------------------------------- - self assert: (nil ifNil: [0] ifNotNil: [:v | v * 2]) equals: 0. + self assert: (nil ifNil: [0] ifNotNil: [:v | v * 2]) equals: 0 // ifNil:ifNotNil: two-way conditional on nil - self assert: (nil ifNil: ["empty"] ifNotNil: [:s | s ++ "!"]) equals: "empty". + self assert: (nil ifNil: ["empty"] ifNotNil: [:s | s ++ "!"]) equals: "empty" // --------------------------------------------------------------------------- - self assert: (42 ifNotNil: [:v | v * 2] ifNil: [0]) equals: 84. + self assert: (42 ifNotNil: [:v | v * 2] ifNil: [0]) equals: 84 // Zero-arg notNil block - self assert: (42 ifNotNil: [ 99 ] ifNil: [0]) equals: 99. + self assert: (42 ifNotNil: [ 99 ] ifNil: [0]) equals: 99 // --------------------------------------------------------------------------- self assert: (nil ifNotNil: [:v | v * 2] ifNil: [0]) equals: 0 diff --git a/stdlib/test/nlr_state_threading_test.bt b/stdlib/test/nlr_state_threading_test.bt index 48a48e8a8..69d7380e5 100644 --- a/stdlib/test/nlr_state_threading_test.bt +++ b/stdlib/test/nlr_state_threading_test.bt @@ -1,106 +1,106 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-854/BT-857: Tests NLR state threading for value types. +// BT-854/BT-857: Tests NLR state threading for value types // Verifies that 4-tuple NLR throws ({$bt_nlr, Token, Value, State}) // work correctly and that the {Result, State} method return format -// is properly unwrapped by dispatch/3. +// is properly unwrapped by dispatch/3 TestCase subclass: NlrStateThreadingTest testFindFirstReturnsCorrectValue => - // NLR returns the matched element via ^each. - obj := NlrFieldMutation new. - result := obj findFirst: 3 in: #(1, 2, 3, 4, 5). + // NLR returns the matched element via ^each + obj := NlrFieldMutation new + result := obj findFirst: 3 in: #(1, 2, 3, 4, 5) self assert: result equals: 3 testFindFirstNoMatchReturnsNil => - // Normal (non-NLR) path: method returns nil via {nil, Self{N}}. - obj := NlrFieldMutation new. - result := obj findFirst: 100 in: #(1, 2, 3). + // Normal (non-NLR) path: method returns nil via {nil, Self{N}} + obj := NlrFieldMutation new + result := obj findFirst: 100 in: #(1, 2, 3) self assert: result equals: nil testFindAndReturnSelfUpdatesField => - // ^self returns the updated Self with field mutations from before the block. - obj := NlrFieldMutation new. - updated := obj findAndReturnSelf: 3 in: #(1, 2, 3, 4, 5). - self assert: (updated lastQuery) equals: 3 + // ^self returns the updated Self with field mutations from before the block + obj := NlrFieldMutation new + updated := obj findAndReturnSelf: 3 in: #(1, 2, 3, 4, 5) + self assert: updated lastQuery equals: 3 testDetectReturnsMatchingElement => - // detect:in: uses a block predicate and returns the matched element via ^. - obj := NlrFieldMutation new. - result := obj detect: [:x | x > 2] in: #(1, 2, 3, 4, 5). + // detect:in: uses a block predicate and returns the matched element via ^ + obj := NlrFieldMutation new + result := obj detect: [:x | x > 2] in: #(1, 2, 3, 4, 5) self assert: result equals: 3 testDetectNoMatchReturnsNil => - // detect:in: returns nil when no element satisfies the predicate. - obj := NlrFieldMutation new. - result := obj detect: [:x | x > 100] in: #(1, 2, 3). + // detect:in: returns nil when no element satisfies the predicate + obj := NlrFieldMutation new + result := obj detect: [:x | x > 100] in: #(1, 2, 3) self assert: result equals: nil testFindNoneNlrNeverFires => - // Method has NLR infrastructure but ^ never fires. - // Tests the normal {Result, Self{N}} tuple return path. - obj := NlrFieldMutation new. - result := obj findNone: #(1, 2, 3). + // Method has NLR infrastructure but ^ never fires + // Tests the normal {Result, Self{N}} tuple return path + obj := NlrFieldMutation new + result := obj findNone: #(1, 2, 3) self assert: result equals: nil testFindAndReturnSelfNoMatchReturnsSelf => - // Normal (non-NLR) path: findAndReturnSelf:in: returns self at end of method. - obj := NlrFieldMutation new. - updated := obj findAndReturnSelf: 100 in: #(1, 2, 3). - self assert: (updated lastQuery) equals: 100 + // Normal (non-NLR) path: findAndReturnSelf:in: returns self at end of method + obj := NlrFieldMutation new + updated := obj findAndReturnSelf: 100 in: #(1, 2, 3) + self assert: updated lastQuery equals: 100 - // BT-857: anySatisfy: — field mutation before ^ is preserved after early return. + // BT-857: anySatisfy: — field mutation before ^ is preserved after early return testAnySatisfyReturnsTrueOnMatch => - // anySatisfy:in: uses ^ to short-circuit and return true when match found. - obj := NlrFieldMutation new. - result := obj anySatisfy: [:x | x > 3] in: #(1, 2, 3, 4, 5). + // anySatisfy:in: uses ^ to short-circuit and return true when match found + obj := NlrFieldMutation new + result := obj anySatisfy: [:x | x > 3] in: #(1, 2, 3, 4, 5) self assert: result equals: true testAnySatisfyReturnsFalseOnNoMatch => - // Normal (non-NLR) path: all elements fail the predicate; returns false. - obj := NlrFieldMutation new. - result := obj anySatisfy: [:x | x > 100] in: #(1, 2, 3). + // Normal (non-NLR) path: all elements fail the predicate; returns false + obj := NlrFieldMutation new + result := obj anySatisfy: [:x | x > 100] in: #(1, 2, 3) self assert: result equals: false - // BT-857: ^ inside nested HOM — state preserved through multiple frames. + // BT-857: ^ inside nested HOM — state preserved through multiple frames // // findViaSingleHOM:in: and findViaNestedHOM:in: return `^self` (updated self) // when a match is found, or `self` when no match. This allows the caller // to verify visitCount on the returned object, demonstrating that field - // mutations made before ^ are preserved through the NLR 4-tuple. + // mutations made before ^ are preserved through the NLR 4-tuple // // Note on anySatisfy: field mutation tests: for value types, `obj lastQuery` // reflects the original object (not updated in place after a method call that // doesn't return self). The anySatisfy: tests below verify only the return value; - // field mutation preservation is demonstrated by the findViaSingleHOM: tests. + // field mutation preservation is demonstrated by the findViaSingleHOM: tests testFindViaSingleHOMPreservesFieldMutation => // NLR propagates through one HOM frame; visitCount (set to 1 before block) is - // preserved in the returned self. Block uses ^self to return updated self. - obj := NlrNestedHom new. - result := obj findViaSingleHOM: 3 in: #(1, 2, 3, 4, 5). - self assert: (result visitCount) equals: 1 + // preserved in the returned self. Block uses ^self to return updated self + obj := NlrNestedHom new + result := obj findViaSingleHOM: 3 in: #(1, 2, 3, 4, 5) + self assert: result visitCount equals: 1 testFindViaNestedHOMPreservesFieldMutation => // NLR propagates through two HOM frames; visitCount (set to 2 before block) is - // preserved in the returned self. - obj := NlrNestedHom new. - result := obj findViaNestedHOM: 3 in: #(1, 2, 3, 4, 5). - self assert: (result visitCount) equals: 2 + // preserved in the returned self + obj := NlrNestedHom new + result := obj findViaNestedHOM: 3 in: #(1, 2, 3, 4, 5) + self assert: result visitCount equals: 2 testFindViaSingleHOMNoMatchPreservesFieldMutation => - // Non-NLR path through one HOM: ^ never fires, method returns self. - // visitCount is still 1 (set in method body, preserved in returned self). - obj := NlrNestedHom new. - result := obj findViaSingleHOM: 99 in: #(1, 2, 3). - self assert: (result visitCount) equals: 1 + // Non-NLR path through one HOM: ^ never fires, method returns self + // visitCount is still 1 (set in method body, preserved in returned self) + obj := NlrNestedHom new + result := obj findViaSingleHOM: 99 in: #(1, 2, 3) + self assert: result visitCount equals: 1 testFindViaNestedHOMNoMatchPreservesFieldMutation => - // Non-NLR path through two nested HOMs: ^ never fires, method returns self. - // visitCount is still 2 (set in method body, preserved in returned self). - obj := NlrNestedHom new. - result := obj findViaNestedHOM: 99 in: #(1, 2, 3). - self assert: (result visitCount) equals: 2 + // Non-NLR path through two nested HOMs: ^ never fires, method returns self + // visitCount is still 2 (set in method body, preserved in returned self) + obj := NlrNestedHom new + result := obj findViaNestedHOM: 99 in: #(1, 2, 3) + self assert: result visitCount equals: 2 diff --git a/stdlib/test/non_literal_callable_test.bt b/stdlib/test/non_literal_callable_test.bt index b006da145..ac3ba3146 100644 --- a/stdlib/test/non_literal_callable_test.bt +++ b/stdlib/test/non_literal_callable_test.bt @@ -3,21 +3,21 @@ // BT-909: Tests that non-literal callables (block variables) can be passed // to list ops without crashing with badarity. The runtime arity normalization -// wrapper detects Tier-2 blocks at runtime and wraps them to arity 1. +// wrapper detects Tier-2 blocks at runtime and wraps them to arity 1 TestCase subclass: NonLiteralCallableTest // Tier-1 block stored in a variable, passed to collect: testCollectWithBlockVar => - actor := NonLiteralCallableActor spawn. - self assert: (actor collectWithTier1Block) equals: #(10, 20, 30) + actor := NonLiteralCallableActor spawn + self assert: actor collectWithTier1Block equals: #(10, 20, 30) // Tier-1 block stored in a variable, passed to select: testSelectWithBlockVar => - actor := NonLiteralCallableActor spawn. - self assert: (actor selectWithTier1Block) equals: #(3, 4, 5) + actor := NonLiteralCallableActor spawn + self assert: actor selectWithTier1Block equals: #(3, 4, 5) // Tier-2 block stored in a variable, passed to do: — must not crash testDoWithTier2BlockVar => - actor := NonLiteralCallableActor spawn. - self assert: (actor doWithTier2Block) equals: "done" + actor := NonLiteralCallableActor spawn + self assert: actor doWithTier2Block equals: "done" diff --git a/stdlib/test/number_methods_test.bt b/stdlib/test/number_methods_test.bt index 2972f43e3..37f98d059 100644 --- a/stdlib/test/number_methods_test.bt +++ b/stdlib/test/number_methods_test.bt @@ -7,93 +7,93 @@ TestCase subclass: NumberMethodsTest testFloatRounded => // rounded — round to nearest integer - self assert: (3.14 rounded) equals: 3. - self assert: (3.75 rounded) equals: 4 + self assert: 3.14 rounded equals: 3 + self assert: 3.75 rounded equals: 4 testFloatCeiling => // ceiling — smallest integer >= value - self assert: (3.14 ceiling) equals: 4 + self assert: 3.14 ceiling equals: 4 testFloatFloor => // floor — largest integer <= value - self assert: (3.75 floor) equals: 3 + self assert: 3.75 floor equals: 3 testFloatTruncated => // truncated — toward zero - self assert: (3.75 truncated) equals: 3. - self assert: (-3.75 truncated) equals: -3 + self assert: 3.75 truncated equals: 3 + self assert: -3.75 truncated equals: -3 testNegativeRoundingEdgeCases => - self assert: (-3.14 rounded) equals: -3. - self assert: (-3.75 rounded) equals: -4. - self assert: (-3.14 ceiling) equals: -3. - self assert: (-3.75 floor) equals: -4 + self assert: -3.14 rounded equals: -3 + self assert: -3.75 rounded equals: -4 + self assert: -3.14 ceiling equals: -3 + self assert: -3.75 floor equals: -4 testFloatIsZero => - self assert: (0.0 isZero). - self deny: (3.14 isZero) + self assert: 0.0 isZero + self deny: 3.14 isZero testFloatIsPositive => - self assert: (3.14 isPositive). - self deny: (-2.5 isPositive) + self assert: 3.14 isPositive + self deny: -2.5 isPositive testFloatIsNegative => - self assert: (-2.5 isNegative). - self deny: (3.14 isNegative) + self assert: -2.5 isNegative + self deny: 3.14 isNegative testIntegerIsZero => - self assert: (0 isZero). - self deny: (5 isZero) + self assert: 0 isZero + self deny: 5 isZero testIntegerIsPositive => - self assert: (5 isPositive) + self assert: 5 isPositive testIntegerIsNegative => - self assert: (-3 isNegative) + self assert: -3 isNegative testFloatNegated => - self assert: (3.14 negated) equals: -3.14 + self assert: 3.14 negated equals: -3.14 testFloatAbs => - self assert: (-3.14 abs) equals: 3.14 + self assert: -3.14 abs equals: 3.14 testFloatMinMax => - self assert: (3.14 min: 2.71) equals: 2.71. + self assert: (3.14 min: 2.71) equals: 2.71 self assert: (3.14 max: 2.71) equals: 3.14 testFloatAsInteger => // asInteger (truncates) - self assert: (3.75 asInteger) equals: 3 + self assert: 3.75 asInteger equals: 3 testFloatAsString => - self assert: (3.14 asString) equals: "3.14" + self assert: 3.14 asString equals: "3.14" testFloatIsNaN => - self deny: (3.14 isNaN) + self deny: 3.14 isNaN testFloatIsInfinite => - self deny: (3.14 isInfinite) + self deny: 3.14 isInfinite testIntegerSign => - self assert: (5 sign) equals: 1. - self assert: (-3 sign) equals: -1. - self assert: (0 sign) equals: 0 + self assert: 5 sign equals: 1 + self assert: -3 sign equals: -1 + self assert: 0 sign equals: 0 testIntegerBetween => - self assert: (5 between: 1 and: 10). + self assert: (5 between: 1 and: 10) self deny: (15 between: 1 and: 10) testFloatSign => - self assert: (3.14 sign) equals: 1. - self assert: (-2.5 sign) equals: -1 + self assert: 3.14 sign equals: 1 + self assert: -2.5 sign equals: -1 testFloatBetween => self assert: (3.14 between: 1.0 and: 5.0) testRespondsToSign => - self assert: (42 respondsTo: #sign). + self assert: (42 respondsTo: #sign) self assert: (3.14 respondsTo: #sign) testRespondsToBetweenAnd => - self assert: (42 respondsTo: #'between:and:'). + self assert: (42 respondsTo: #'between:and:') self assert: (3.14 respondsTo: #'between:and:') diff --git a/stdlib/test/object_protocol_test.bt b/stdlib/test/object_protocol_test.bt index cb4803a08..c0a992d5e 100644 --- a/stdlib/test/object_protocol_test.bt +++ b/stdlib/test/object_protocol_test.bt @@ -6,73 +6,73 @@ TestCase subclass: ObjectProtocolTest testPrintstringStringRepresentationOfAnyObject => - self assert: (42 printString) equals: "42". - self assert: (0 printString) equals: "0". - self assert: (-7 printString) equals: "-7". + self assert: 42 printString equals: "42" + self assert: 0 printString equals: "0" + self assert: -7 printString equals: "-7" // --- Strings (printString adds surrounding quotes) --- - self assert: ("hello" printString) equals: """hello""". - self assert: ("" printString) equals: """""". + self assert: "hello" printString equals: """hello""" + self assert: "" printString equals: """""" // --- Booleans --- - self assert: (true printString) equals: "true". - self assert: (false printString) equals: "false". + self assert: true printString equals: "true" + self assert: false printString equals: "false" // --- Nil --- - self assert: (nil printString) equals: "nil". + self assert: nil printString equals: "nil" // --- Floats --- - self assert: (3.14 printString) equals: "3.14". - self assert: (-2.5 printString) equals: "-2.5". + self assert: 3.14 printString equals: "3.14" + self assert: -2.5 printString equals: "-2.5" // --- Lists --- - self assert: (#(1, 2, 3) printString) equals: "#(1, 2, 3)". - self assert: (#() printString) equals: "#()". + self assert: #(1, 2, 3) printString equals: "#(1, 2, 3)" + self assert: #() printString equals: "#()" // --- Blocks --- - self assert: ([42] printString) notNil. + self assert: ([42] printString) notNil // --- Dictionaries --- - self assert: (#{} printString size) equals: 3. + self assert: #{} printString size equals: 3 // --- Class objects (BT-477: class_send printString) --- - self assert: (42 class printString) equals: "Integer". - self assert: ("hello" class printString) equals: "String". - self assert: (true class printString) equals: "True". - self assert: (nil class printString) equals: "UndefinedObject" + self assert: 42 class printString equals: "Integer" + self assert: "hello" class printString equals: "String" + self assert: true class printString equals: "True" + self assert: nil class printString equals: "UndefinedObject" testYourselfIdentityMethodReturnsReceiver => - self assert: (42 yourself) equals: 42. - self assert: ("hello" yourself) equals: "hello". - self assert: (true yourself). - self assert: (nil yourself) equals: nil. + self assert: 42 yourself equals: 42 + self assert: "hello" yourself equals: "hello" + self assert: true yourself + self assert: nil yourself equals: nil // yourself should return the same object - self assert: (42 yourself =:= 42). + self assert: (42 yourself =:= 42) self assert: "test" yourself =:= "test" testHashHashValueInteger => // hash returns an integer (non-deterministic, keep wildcard) - self assert: ((42 hash) class) equals: Integer. + self assert: (42 hash) class equals: Integer // Same value should produce same hash - self assert: (42 hash =:= 42 hash). - self assert: ("hello" hash =:= "hello" hash). + self assert: (42 hash =:= 42 hash) + self assert: ("hello" hash =:= "hello" hash) // Hash values are non-deterministic, keep wildcard - self assert: (("hello" hash) class) equals: Integer + self assert: ("hello" hash) class equals: Integer testRespondstoMethodExistenceCheck => // Integers respond to + - self assert: (42 respondsTo: #+). + self assert: (42 respondsTo: #+) // Integers respond to class (inherited from Object) - self assert: (42 respondsTo: #class). + self assert: (42 respondsTo: #class) // Integers do not respond to nonsense - self deny: (42 respondsTo: #totallyFakeMethod). + self deny: (42 respondsTo: #totallyFakeMethod) // Strings respond to size - self assert: ("hello" respondsTo: #size). + self assert: ("hello" respondsTo: #size) // Strings do not respond to nonsense - self deny: ("hello" respondsTo: #totallyFakeMethod). + self deny: ("hello" respondsTo: #totallyFakeMethod) // nil responds to isNil - self assert: (nil respondsTo: #isNil). + self assert: (nil respondsTo: #isNil) // Booleans respond to ifTrue:ifFalse: - self assert: (true respondsTo: #'ifTrue:ifFalse:'). + self assert: (true respondsTo: #'ifTrue:ifFalse:') // Blocks respond to value - self assert: ([1] respondsTo: #value). - self deny: ([1] respondsTo: #invalidMethod). + self assert: ([1] respondsTo: #value) + self deny: ([1] respondsTo: #invalidMethod) // Float responds to arithmetic operations - self assert: (3.14 respondsTo: #+). - self assert: (3.14 respondsTo: #'-'). - self assert: (3.14 respondsTo: #class). - self assert: (3.14 respondsTo: #asString). - self assert: (3.14 respondsTo: #abs). + self assert: (3.14 respondsTo: #+) + self assert: (3.14 respondsTo: #'-') + self assert: (3.14 respondsTo: #class) + self assert: (3.14 respondsTo: #asString) + self assert: (3.14 respondsTo: #abs) self deny: (3.14 respondsTo: #nonExistent) diff --git a/stdlib/test/pattern_matching_test.bt b/stdlib/test/pattern_matching_test.bt index 9d31bce7a..349377e0f 100644 --- a/stdlib/test/pattern_matching_test.bt +++ b/stdlib/test/pattern_matching_test.bt @@ -2,35 +2,35 @@ // SPDX-License-Identifier: Apache-2.0 // BT-406: Tests the match: expression — literal arms (integer, symbol, string), -// wildcard arms, variable capture, guards (when:), and multi-arm dispatch. +// wildcard arms, variable capture, guards (when:), and multi-arm dispatch TestCase subclass: PatternMatchingTest testPatternMatchingWithGuards => - self assert: (42 match: [_ -> "matched"]) equals: "matched". + self assert: (42 match: [_ -> "matched"]) equals: "matched" // Match integer literal — first arm - self assert: (1 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "one". + self assert: (1 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "one" // Match integer literal — second arm - self assert: (2 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "two". + self assert: (2 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "two" // Match integer literal — fallthrough to wildcard - self assert: (3 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "other". + self assert: (3 match: [1 -> "one"; 2 -> "two"; _ -> "other"]) equals: "other" // Match symbol literal - self assert: (#ok match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "success". + self assert: (#ok match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "success" // ═══════════════════════════════════════════════════════════════════════════ - self assert: (#error match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "failure". + self assert: (#error match: [#ok -> "success"; #error -> "failure"; _ -> "unknown"]) equals: "failure" // Match string literal - self assert: ("hello" match: ["hello" -> "greeting"; _ -> "other"]) equals: "greeting". + self assert: ("hello" match: ["hello" -> "greeting"; _ -> "other"]) equals: "greeting" // Variable captures the matched value - self assert: (42 match: [x -> x + 1]) equals: 43. + self assert: (42 match: [x -> x + 1]) equals: 43 // Match with guard — positive - self assert: (10 match: [x when: [x > 0] -> "positive"; _ -> "non-positive"]) equals: "positive". + self assert: (10 match: [x when: [x > 0] -> "positive"; _ -> "non-positive"]) equals: "positive" // Match with guard — non-positive - self assert: (-5 match: [x when: [x > 0] -> "positive"; _ -> "non-positive"]) equals: "non-positive". + self assert: (-5 match: [x when: [x > 0] -> "positive"; _ -> "non-positive"]) equals: "non-positive" // Guard with arithmetic comparison - self assert: (42 match: [x when: [x > 100] -> "big"; x when: [x > 10] -> "medium"; _ -> "small"]) equals: "medium". + self assert: (42 match: [x when: [x > 100] -> "big"; x when: [x > 10] -> "medium"; _ -> "small"]) equals: "medium" // Match on expression result - self assert: ((3 + 4) match: [7 -> "correct"; _ -> "wrong"]) equals: "correct". + self assert: ((3 + 4) match: [7 -> "correct"; _ -> "wrong"]) equals: "correct" // Match negative integer - self assert: (-1 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "minus one". + self assert: (-1 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "minus one" // ═══════════════════════════════════════════════════════════════════════════ self assert: (0 match: [-1 -> "minus one"; 0 -> "zero"; _ -> "other"]) equals: "zero" diff --git a/stdlib/test/protoobject_actors_test.bt b/stdlib/test/protoobject_actors_test.bt index e96954a9b..2958d2249 100644 --- a/stdlib/test/protoobject_actors_test.bt +++ b/stdlib/test/protoobject_actors_test.bt @@ -7,47 +7,47 @@ TestCase subclass: ProtoobjectActorsTest testActorIdentityTests => - a := Counter spawn. - b := a. - c := Counter spawn. + a := Counter spawn + b := a + c := Counter spawn // Same reference - self assert: (a == b). + self assert: (a == b) // Different processes - self deny: (a == c). + self deny: (a == c) self assert: (a /= c) testInheritanceTests => // Actor class has superclass - self assert: (Counter superclass) equals: Actor. + self assert: Counter superclass equals: Actor // Root class has no superclass - self assert: (ProtoObject superclass) equals: nil + self assert: ProtoObject superclass equals: nil testActorBasicMessaging => - counter := Counter spawn. + counter := Counter spawn // Test initial state - self assert: (counter getValue) equals: 0. + self assert: counter getValue equals: 0 // Test increment - self assert: (counter increment) equals: 1. + self assert: counter increment equals: 1 // Verify state persisted - self assert: (counter getValue) equals: 1. + self assert: counter getValue equals: 1 // Test multiple increments - self assert: (counter increment) equals: 2. - self assert: (counter increment) equals: 3. + self assert: counter increment equals: 2 + self assert: counter increment equals: 3 // Test decrement - self assert: (counter decrement) equals: 2. + self assert: counter decrement equals: 2 // Final state verification - self assert: (counter getValue) equals: 2 + self assert: counter getValue equals: 2 testBt427ObjectMethodDelegationForActors => - counter := Counter spawn. + counter := Counter spawn // isNil and notNil — nil-testing protocol from Object (intrinsic, no await) - self deny: (counter isNil). - // Actors inherit Object base methods via the class hierarchy walk. - self assert: (counter notNil). + self deny: counter isNil + // Actors inherit Object base methods via the class hierarchy walk + self assert: counter notNil // respondsTo: — checks both user methods and inherited methods - self assert: (counter respondsTo: #increment). - self assert: (counter respondsTo: #getValue). - self assert: (counter respondsTo: #decrement). - self deny: (counter respondsTo: #nonExistent). + self assert: (counter respondsTo: #increment) + self assert: (counter respondsTo: #getValue) + self assert: (counter respondsTo: #decrement) + self deny: (counter respondsTo: #nonExistent) // class — returns class name from Object - self assert: (counter class) equals: Counter + self assert: counter class equals: Counter diff --git a/stdlib/test/protoobject_manual_test.bt b/stdlib/test/protoobject_manual_test.bt index 0bf2f05d3..4b33feba1 100644 --- a/stdlib/test/protoobject_manual_test.bt +++ b/stdlib/test/protoobject_manual_test.bt @@ -6,14 +6,14 @@ TestCase subclass: ProtoobjectManualTest testIdentityComparison => - self assert: (42 == 42). - self assert: (42 /= 43). - self assert: (nil == nil). - self deny: (nil == false). - self assert: (nil /= false). + self assert: (42 == 42) + self assert: (42 /= 43) + self assert: (nil == nil) + self deny: (nil == false) + self assert: (nil /= false) self deny: (nil /= nil) testPerformWithargumentsDynamicDispatch => - self assert: (42 perform: #+ withArguments: #(3)) equals: 45. - self assert: (42 perform: #asString withArguments: #()) equals: "42". + self assert: (42 perform: #+ withArguments: #(3)) equals: 45 + self assert: (42 perform: #asString withArguments: #()) equals: "42" self assert: ("hello" perform: #++ withArguments: #(" world")) equals: "hello world" diff --git a/stdlib/test/random_test.bt b/stdlib/test/random_test.bt index cd53bd272..179e7c28d 100644 --- a/stdlib/test/random_test.bt +++ b/stdlib/test/random_test.bt @@ -6,94 +6,94 @@ TestCase subclass: RandomTest testClassSideRandomFloat => - self assert: ((Random next) class) equals: Float. + self assert: (Random next) class equals: Float // Random next returns value >= 0.0 - self assert: ((Random next) >= 0.0). + self assert: ((Random next) >= 0.0) // Random next returns value < 1.0 self assert: ((Random next) < 1.0) testClassSideRandomInteger => // Random nextInteger: 1 always returns 1 - self assert: (Random nextInteger: 1) equals: 1. + self assert: (Random nextInteger: 1) equals: 1 // Random nextInteger: returns an Integer - self assert: ((Random nextInteger: 100) class) equals: Integer. + self assert: (Random nextInteger: 100) class equals: Integer // Random nextInteger: returns value >= 1 - self assert: ((Random nextInteger: 100) >= 1). + self assert: ((Random nextInteger: 100) >= 1) // Random nextInteger: returns value <= max - self assert: ((Random nextInteger: 100) <= 100). + self assert: ((Random nextInteger: 100) <= 100) // Random nextInteger: 6 returns between 1 and 6 - result := Random nextInteger: 6. + result := Random nextInteger: 6 self assert: ((result >= 1) and: [result <= 6]) testInstanceSideNew => // Random new returns a Random instance - self assert: ((Random new) class) equals: Random. + self assert: (Random new) class equals: Random // Random new printString - self assert: ((Random new) printString) notNil. + self assert: ((Random new) printString) notNil // Instance next returns a Float - rng := Random new. - self assert: ((rng next) class) equals: Float. + rng := Random new + self assert: (rng next) class equals: Float // Instance next returns value in range - rng2 := Random new. - v := rng2 next. - self assert: ((v >= 0.0) and: [v < 1.0]). + rng2 := Random new + v := rng2 next + self assert: ((v >= 0.0) and: [v < 1.0]) // Instance nextInteger: returns an Integer - rng3 := Random new. - self assert: ((rng3 nextInteger: 100) class) equals: Integer. + rng3 := Random new + self assert: (rng3 nextInteger: 100) class equals: Integer // Instance nextInteger: returns value in range - rng4 := Random new. - n := rng4 nextInteger: 50. + rng4 := Random new + n := rng4 nextInteger: 50 self assert: ((n >= 1) and: [n <= 50]) testInstanceSideSeededDeterministic => // Two identically seeded instances produce the same first value - a := Random seed: 42. - b := Random seed: 42. - self assert: (a next) =:= (b next). + a := Random seed: 42 + b := Random seed: 42 + self assert: (a next) =:= b next // Two identically seeded instances produce the same integer - c := Random seed: 99. - d := Random seed: 99. - self assert: (c nextInteger: 1000) =:= (d nextInteger: 1000). + c := Random seed: 99 + d := Random seed: 99 + self assert: (c nextInteger: 1000) =:= (d nextInteger: 1000) // (statistically extremely unlikely to be equal for float) - e := Random seed: 1. + e := Random seed: 1 // Differently seeded instances generally produce different values - f := Random seed: 999999. - self assert: (e next) /= (f next). + f := Random seed: 999999 + self assert: (e next) /= f next // Same instance returns same value (immutable value type) - g := Random seed: 42. - self assert: (g next) =:= (g next) + g := Random seed: 42 + self assert: (g next) =:= g next testCollectionIntegrationAtrandom => // List atRandom returns an element from the list - self assert: (#(10, 20, 30) atRandom class) equals: Integer. + self assert: #(10, 20, 30) atRandom class equals: Integer // List atRandom returns value that is in the list - elem := #(10, 20, 30) atRandom. - self assert: (#(10, 20, 30) includes: elem). + elem := #(10, 20, 30) atRandom + self assert: (#(10, 20, 30) includes: elem) // Single-element list always returns that element - self assert: (#(42) atRandom) equals: 42. + self assert: #(42) atRandom equals: 42 // Empty list atRandom raises type_error - self should: [#() atRandom] raise: #type_error. + self should: [#() atRandom] raise: #type_error // Tuple atRandom via Erlang interop — deterministic non-empty case - tuple := Erlang erlang list_to_tuple: #(7, 7, 7). - self assert: (tuple atRandom) equals: 7. + tuple := Erlang erlang list_to_tuple: #(7, 7, 7) + self assert: tuple atRandom equals: 7 // Tuple atRandom via Erlang interop — empty tuple raises type_error - emptyTuple := Erlang erlang list_to_tuple: #(). + emptyTuple := Erlang erlang list_to_tuple: #() self should: [emptyTuple atRandom] raise: #type_error testErrorHandling => // nextInteger: with zero raises type_error - self should: [Random nextInteger: 0] raise: #type_error. + self should: [Random nextInteger: 0] raise: #type_error // nextInteger: with negative raises type_error - self should: [Random nextInteger: -5] raise: #type_error. + self should: [Random nextInteger: -5] raise: #type_error // nextInteger: with non-integer raises type_error @expect type - self should: [Random nextInteger: "hello"] raise: #type_error. + self should: [Random nextInteger: "hello"] raise: #type_error // seed: with non-integer raises type_error @expect type - self should: [Random seed: "bad"] raise: #type_error. + self should: [Random seed: "bad"] raise: #type_error // Instance nextInteger: with zero raises type_error - rng5 := Random new. - self should: [rng5 nextInteger: 0] raise: #type_error. + rng5 := Random new + self should: [rng5 nextInteger: 0] raise: #type_error // Instance nextInteger: with negative raises type_error - rng6 := Random new. + rng6 := Random new self should: [rng6 nextInteger: -1] raise: #type_error diff --git a/stdlib/test/recursion_test.bt b/stdlib/test/recursion_test.bt index 8cf91825d..139c2f68d 100644 --- a/stdlib/test/recursion_test.bt +++ b/stdlib/test/recursion_test.bt @@ -7,39 +7,39 @@ TestCase subclass: RecursionTest testRecursiveKeywordMethodFactorial => - m := MathHelper new. + m := MathHelper new // Base cases - self assert: (m factorial: 0) equals: 1. - self assert: (m factorial: 1) equals: 1. + self assert: (m factorial: 0) equals: 1 + self assert: (m factorial: 1) equals: 1 // Recursive cases (5+ depth) - self assert: (m factorial: 5) equals: 120. + self assert: (m factorial: 5) equals: 120 self assert: (m factorial: 10) equals: 3628800 testDoubleRecursiveKeywordMethodFibonacci => - m := MathHelper new. + m := MathHelper new // Base cases - self assert: (m fibonacci: 0) equals: 0. - self assert: (m fibonacci: 1) equals: 1. + self assert: (m fibonacci: 0) equals: 0 + self assert: (m fibonacci: 1) equals: 1 // Recursive cases (5+ depth) - self assert: (m fibonacci: 5) equals: 5. + self assert: (m fibonacci: 5) equals: 5 self assert: (m fibonacci: 10) equals: 55 testRecursiveCountdownDepthVerification => - m := MathHelper new. + m := MathHelper new // Verifies 10+ recursion depth - self assert: (m countdown: 10) equals: 10. + self assert: (m countdown: 10) equals: 10 self assert: (m countdown: 20) equals: 20 testActorRecursiveSelfSends => - // and cross-method self-sends work correctly (no Future/badarith). - a := RecursiveActor spawn. + // and cross-method self-sends work correctly (no Future/badarith) + a := RecursiveActor spawn // Base case (no self-send needed) - self assert: (a factorial: 1) equals: 1. + self assert: (a factorial: 1) equals: 1 // Recursive self-send on Actor - self assert: (a factorial: 5) equals: 120. + self assert: (a factorial: 5) equals: 120 // Actor self-sends use synchronous direct dispatch, so recursive methods - self assert: (a factorial: 10) equals: 3628800. + self assert: (a factorial: 10) equals: 3628800 // Double recursion on Actor - self assert: (a fibonacci: 10) equals: 55. + self assert: (a fibonacci: 10) equals: 55 // Cross-method self-send (self double: n, then * 2) self assert: (a quadruple: 5) equals: 20 diff --git a/stdlib/test/reflection_basic_test.bt b/stdlib/test/reflection_basic_test.bt index 6a632ee3e..c649503f3 100644 --- a/stdlib/test/reflection_basic_test.bt +++ b/stdlib/test/reflection_basic_test.bt @@ -3,45 +3,45 @@ // BT-97, BT-359, BT-765: Tests the basic reflection API on actor objects — // class, respondsTo:, fieldNames, fieldAt:, fieldAt:put:, perform:; and that -// fieldAt:put: raises immutable_value on primitive types (integers, strings). +// fieldAt:put: raises immutable_value on primitive types (integers, strings) // BT-924: fieldAt: on user-defined Value subclass: objects reads slots — see // value_subclass_test.bt. fieldAt: on primitive literals (42, "hello") still -// raises immutable_value since primitives have no map slots. +// raises immutable_value since primitives have no map slots TestCase subclass: ReflectionBasicTest testActorReflectionApi => - c := Counter spawn. + c := Counter spawn // Test class reflection - self assert: (c class) equals: Counter. + self assert: c class equals: Counter // Test respondsTo: with symbol literal - self assert: (c respondsTo: #increment). + self assert: (c respondsTo: #increment) // Test respondsTo: with non-existent method - self deny: (c respondsTo: #nonExistent). + self deny: (c respondsTo: #nonExistent) // Test fieldNames - self assert: (c fieldNames) equals: #(#value). + self assert: c fieldNames equals: #(#value) // Test fieldAt: - read field value - self assert: (c fieldAt: #value) equals: 0. + self assert: (c fieldAt: #value) equals: 0 // Increment to change state - self assert: (c increment) equals: 1. + self assert: c increment equals: 1 // Test fieldAt: after state change - self assert: (c fieldAt: #value) equals: 1. + self assert: (c fieldAt: #value) equals: 1 // Test fieldAt:put: - set field value - self assert: (c fieldAt: #value put: 42) equals: 42. + self assert: (c fieldAt: #value put: 42) equals: 42 // Verify field was set - self assert: (c getValue) equals: 42. + self assert: c getValue equals: 42 // Test perform: - dynamic dispatch (zero-arity method) - self assert: (c perform: #getValue) equals: 42. + self assert: (c perform: #getValue) equals: 42 // Test perform: with another method - self assert: (c perform: #increment) equals: 43. + self assert: (c perform: #increment) equals: 43 // Verify increment worked via getValue - self assert: (c getValue) equals: 43. - // BT-359: fieldAt: on primitive value types (integers) raises immutable_value. - // Note: user-defined Value subclass: objects support fieldAt: for reading (BT-924). - self should: [42 fieldAt: #x] raise: #immutable_value. + self assert: c getValue equals: 43 + // BT-359: fieldAt: on primitive value types (integers) raises immutable_value + // Note: user-defined Value subclass: objects support fieldAt: for reading (BT-924) + self should: [42 fieldAt: #x] raise: #immutable_value // BT-765: fieldAt:put: on immutable literals raises immutable_value error @expect type - self should: [42 fieldAt: #x put: 99] raise: #immutable_value. + self should: [42 fieldAt: #x put: 99] raise: #immutable_value @expect type self should: ["hello" fieldAt: #x put: "world"] raise: #immutable_value diff --git a/stdlib/test/regex_test.bt b/stdlib/test/regex_test.bt index 78373efcf..3854b413e 100644 --- a/stdlib/test/regex_test.bt +++ b/stdlib/test/regex_test.bt @@ -6,80 +6,80 @@ TestCase subclass: RegexTest testRegexConstruction => - self assert: ((Regex from: "[0-9]+") class) equals: Regex. + self assert: (Regex from: "[0-9]+") class equals: Regex // Source returns the original pattern - self assert: ((Regex from: "[0-9]+") source) equals: "[0-9]+". + self assert: (Regex from: "[0-9]+") source equals: "[0-9]+" // Compile with options - self assert: ((Regex from: "[a-z]+" options: #(#caseless)) class) equals: Regex + self assert: (Regex from: "[a-z]+" options: #(#caseless)) class equals: Regex testStringMatchesregexWithStringPatterns => // Simple digit match - self assert: ("hello123" matchesRegex: "[0-9]+"). + self assert: ("hello123" matchesRegex: "[0-9]+") // Full string match fails - self deny: ("hello123" matchesRegex: "^[0-9]+$"). + self deny: ("hello123" matchesRegex: "^[0-9]+$") // Full string match succeeds - self assert: ("12345" matchesRegex: "^[0-9]+$"). + self assert: ("12345" matchesRegex: "^[0-9]+$") // Letters only - self assert: ("hello" matchesRegex: "^[a-z]+$"). + self assert: ("hello" matchesRegex: "^[a-z]+$") // No match self deny: ("hello" matchesRegex: "[0-9]+") testStringMatchesregexWithCompiledRegexObjects => // Match with compiled regex - self assert: ("hello123" matchesRegex: (Regex from: "[0-9]+")). + self assert: ("hello123" matchesRegex: (Regex from: "[0-9]+")) // No match with compiled regex self deny: ("hello" matchesRegex: (Regex from: "[0-9]+")) testStringMatchesregexOptions => // Case-insensitive matching - self assert: ("Hello" matchesRegex: "^[a-z]+$" options: #(#caseless)). + self assert: ("Hello" matchesRegex: "^[a-z]+$" options: #(#caseless)) // Without caseless, fails self deny: ("Hello" matchesRegex: "^[a-z]+$") testStringFirstmatch => // First match returns the matched string - self assert: ("hello123world456" firstMatch: "[0-9]+") equals: "123". + self assert: ("hello123world456" firstMatch: "[0-9]+") equals: "123" // No match returns nil - self assert: ("hello" firstMatch: "[0-9]+") equals: nil. + self assert: ("hello" firstMatch: "[0-9]+") equals: nil // First match with compiled regex self assert: ("abc42def" firstMatch: (Regex from: "[0-9]+")) equals: "42" testStringAllmatches => // All matches returns list of matched strings - self assert: ("a1b2c3" allMatches: "[0-9]+") equals: #("1", "2", "3"). + self assert: ("a1b2c3" allMatches: "[0-9]+") equals: #("1", "2", "3") // No matches returns empty list - self assert: ("hello" allMatches: "[0-9]+") equals: #(). + self assert: ("hello" allMatches: "[0-9]+") equals: #() // All matches with compiled regex - self assert: ("x10y20z30" allMatches: (Regex from: "[0-9]+")) equals: #("10", "20", "30"). + self assert: ("x10y20z30" allMatches: (Regex from: "[0-9]+")) equals: #("10", "20", "30") // Single match returns single-element list self assert: ("abc123def" allMatches: "[0-9]+") equals: #("123") testStringReplaceregexWith => // Replace first match - self assert: ("hello world" replaceRegex: "[aeiou]" with: "*") equals: "h*llo world". + self assert: ("hello world" replaceRegex: "[aeiou]" with: "*") equals: "h*llo world" // No match leaves string unchanged - self assert: ("hello" replaceRegex: "[0-9]+" with: "X") equals: "hello". + self assert: ("hello" replaceRegex: "[0-9]+" with: "X") equals: "hello" // Replace first match with compiled regex self assert: ("abc123def456" replaceRegex: (Regex from: "[0-9]+") with: "NUM") equals: "abcNUMdef456" testStringReplaceallregexWith => // Replace all matches - self assert: ("hello world" replaceAllRegex: "[aeiou]" with: "*") equals: "h*ll* w*rld". + self assert: ("hello world" replaceAllRegex: "[aeiou]" with: "*") equals: "h*ll* w*rld" // No match leaves string unchanged - self assert: ("hello" replaceAllRegex: "[0-9]+" with: "X") equals: "hello". + self assert: ("hello" replaceAllRegex: "[0-9]+" with: "X") equals: "hello" // Replace all with compiled regex self assert: ("a1b2c3" replaceAllRegex: (Regex from: "[0-9]+") with: "N") equals: "aNbNcN" testStringSplitregex => // Split on one or more commas - self assert: ("a,,b,,,c" splitRegex: ",+") equals: #("a", "b", "c"). + self assert: ("a,,b,,,c" splitRegex: ",+") equals: #("a", "b", "c") // Split on whitespace - self assert: ("hello world test" splitRegex: " +") equals: #("hello", "world", "test"). + self assert: ("hello world test" splitRegex: " +") equals: #("hello", "world", "test") // Split with compiled regex self assert: ("a1b2c3" splitRegex: (Regex from: "[0-9]+")) equals: #("a", "b", "c") testErrorHandling => // Invalid regex pattern produces regex_error - self should: [Regex from: "[invalid"] raise: #regex_error. + self should: [Regex from: "[invalid"] raise: #regex_error // Invalid pattern in String method also produces regex_error self should: ["hello" matchesRegex: "[invalid"] raise: #regex_error diff --git a/stdlib/test/remove_from_system_test.bt b/stdlib/test/remove_from_system_test.bt index d052c4c22..10344fa13 100644 --- a/stdlib/test/remove_from_system_test.bt +++ b/stdlib/test/remove_from_system_test.bt @@ -1,10 +1,10 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Tests for Behaviour >> removeFromSystem (BT-785). +// Tests for Behaviour >> removeFromSystem (BT-785) // -// Tests the safety checks: stdlib class rejection and subclass rejection. -// Full integration tests (actual removal and cleanup) are in the e2e suite. +// Tests the safety checks: stdlib class rejection and subclass rejection +// Full integration tests (actual removal and cleanup) are in the e2e suite // // Fixtures: // stdlib/test/fixtures/removal_test_parent.bt — RemovalTestParent @@ -17,21 +17,21 @@ TestCase subclass: RemoveFromSystemTest testStdlibClassRejected => // Attempting to remove a stdlib class raises a runtime_error - self should: [Integer removeFromSystem] raise: #runtime_error. + self should: [Integer removeFromSystem] raise: #runtime_error // => _ testSubclassRejected => - // A class with subclasses cannot be removed (subclasses must go first). - // RemovalTestParent has RemovalTestChild as a subclass (see fixtures). - self should: [RemovalTestParent removeFromSystem] raise: #runtime_error. + // A class with subclasses cannot be removed (subclasses must go first) + // RemovalTestParent has RemovalTestChild as a subclass (see fixtures) + self should: [RemovalTestParent removeFromSystem] raise: #runtime_error // => _ testStringClassRejected => // String is stdlib — cannot be removed - self should: [String removeFromSystem] raise: #runtime_error. + self should: [String removeFromSystem] raise: #runtime_error // => _ testObjectClassRejected => // Object is stdlib — cannot be removed - self should: [Object removeFromSystem] raise: #runtime_error. + self should: [Object removeFromSystem] raise: #runtime_error // => _ diff --git a/stdlib/test/runtime_doc_test.bt b/stdlib/test/runtime_doc_test.bt index 56e7273b7..c00407ee9 100644 --- a/stdlib/test/runtime_doc_test.bt +++ b/stdlib/test/runtime_doc_test.bt @@ -12,40 +12,40 @@ TestCase subclass: RuntimeDocTest self assert: DocTestHelper doc equals: nil testSetClassDoc => - DocTestHelper doc: "A helper for testing". + DocTestHelper doc: "A helper for testing" self assert: DocTestHelper doc equals: "A helper for testing" testSetClassDocOverwrites => - DocTestHelper doc: "First doc". - DocTestHelper doc: "Second doc". + DocTestHelper doc: "First doc" + DocTestHelper doc: "Second doc" self assert: DocTestHelper doc equals: "Second doc" // --- Method doc via >> and doc message --- testMethodDocDefaultsToNil => - m := DocTestHelper >> #greet. + m := DocTestHelper >> #greet self assert: m doc equals: nil testSetMethodDoc => - DocTestHelper setDocForMethod: #greet to: "Say hello". - m := DocTestHelper >> #greet. + DocTestHelper setDocForMethod: #greet to: "Say hello" + m := DocTestHelper >> #greet self assert: m doc equals: "Say hello" testSetMethodDocDifferentMethods => - DocTestHelper setDocForMethod: #answer to: "Return 42". - m := DocTestHelper >> #answer. + DocTestHelper setDocForMethod: #answer to: "Return 42" + m := DocTestHelper >> #answer self assert: m doc equals: "Return 42" // --- CompiledMethod doc accessor --- testCompiledMethodDocField => - DocTestHelper setDocForMethod: #greet to: "Greeting method". - m := DocTestHelper >> #greet. - self assert: m doc equals: "Greeting method". + DocTestHelper setDocForMethod: #greet to: "Greeting method" + m := DocTestHelper >> #greet + self assert: m doc equals: "Greeting method" self assert: m selector equals: #greet // --- doc: returns self (chainable) --- testDocSetterReturnsSelf => - result := DocTestHelper doc: "Chainable". + result := DocTestHelper doc: "Chainable" self assert: result equals: DocTestHelper diff --git a/stdlib/test/sealed_class_test.bt b/stdlib/test/sealed_class_test.bt index 52109f2f9..5c935c332 100644 --- a/stdlib/test/sealed_class_test.bt +++ b/stdlib/test/sealed_class_test.bt @@ -3,26 +3,26 @@ // BT-403: Tests sealed class codegen — sealed actor methods are compiled to // direct __sealed_* calls instead of dynamic dispatch, verified by exercising -// external calls, internal self-sends, and state persistence. +// external calls, internal self-sends, and state persistence TestCase subclass: SealedClassTest testSealedClassOperations => - c := SealedCounter spawn. + c := SealedCounter spawn // Basic read: getValue (uses __sealed_getValue direct call internally) - self assert: (c getValue) equals: 0. + self assert: c getValue equals: 0 // Mutation via external call: increment - self assert: (c increment) equals: 1. + self assert: c increment equals: 1 // Verify state persisted after increment - self assert: (c getValue) equals: 1. + self assert: c getValue equals: 1 // Second increment - self assert: (c increment) equals: 2. + self assert: c increment equals: 2 // Decrement - self assert: (c decrement) equals: 1. + self assert: c decrement equals: 1 // Parentheses needed: unary messages bind tighter than keyword messages - self assert: (c addAmount: 10) equals: 11. + self assert: (c addAmount: 10) equals: 11 // Internal self-send: getValuePlusTen calls self getValue (tests __sealed_* direct call) - self assert: (c getValuePlusTen) equals: 21. + self assert: c getValuePlusTen equals: 21 // Final state verification - self assert: (c getValue) equals: 11 + self assert: c getValue equals: 11 diff --git a/stdlib/test/self_reference_test.bt b/stdlib/test/self_reference_test.bt index 6f4cde51c..eee48ddb0 100644 --- a/stdlib/test/self_reference_test.bt +++ b/stdlib/test/self_reference_test.bt @@ -7,30 +7,30 @@ TestCase subclass: SelfReferenceTest testMethodReturningSelf => - a := SelfRefActor spawn. + a := SelfRefActor spawn // returnSelf returns the actor's self reference - ref := a returnSelf. + ref := a returnSelf // The returned reference responds to class - self assert: (ref class) equals: SelfRefActor. + self assert: ref class equals: SelfRefActor // The returned reference is the same actor (can send messages through it) - self assert: (ref setValue: 99) equals: 99. + self assert: (ref setValue: 99) equals: 99 // Verify the state changed on the original actor (same process) - self assert: (a getValue) equals: 99 + self assert: a getValue equals: 99 testSelfInBlock => - a := SelfRefActor spawn. + a := SelfRefActor spawn // self in block refers to enclosing actor, not the block itself - self assert: (a classInBlock) equals: SelfRefActor + self assert: a classInBlock equals: SelfRefActor testDynamicDispatchViaPerform => - a := SelfRefActor spawn. - a setValue: 99. + a := SelfRefActor spawn + a setValue: 99 // perform: dispatches zero-arg methods dynamically on actors - self assert: (a perform: #getValue) equals: 99. + self assert: (a perform: #getValue) equals: 99 // perform:withArguments: dispatches methods with arguments on actors - self assert: (a perform: #setValue: withArguments: #(42)) equals: 42. - self assert: (a getValue) equals: 42. + self assert: (a perform: #setValue: withArguments: #(42)) equals: 42 + self assert: a getValue equals: 42 // perform: also works on primitives (synchronous dispatch) - self assert: (42 perform: #asString) equals: "42". + self assert: (42 perform: #asString) equals: "42" // perform:withArguments: works on primitives self assert: (10 perform: #+ withArguments: #(32)) equals: 42 diff --git a/stdlib/test/semantic_scope_test.bt b/stdlib/test/semantic_scope_test.bt index 14ddc6047..22f13b2ac 100644 --- a/stdlib/test/semantic_scope_test.bt +++ b/stdlib/test/semantic_scope_test.bt @@ -3,33 +3,33 @@ // Tests variable scoping rules: block parameter isolation, cross-expression // variable persistence, reassignment, closure capture of outer variables, -// and self reference within actor method bodies. +// and self reference within actor method bodies TestCase subclass: SemanticScopeTest testVariableScopeAndClosureCapture => - self assert: ([:x | x + 1] value: 5) equals: 6. + self assert: ([:x | x + 1] value: 5) equals: 6 // Nested block parameters work correctly - self assert: ([:x | [:y | x + y] value: 3] value: 10) equals: 13. + self assert: ([:x | [:y | x + y] value: 3] value: 10) equals: 13 // Variables defined in one expression are accessible in later ones - scopeTestVar := 100. - self assert: scopeTestVar equals: 100. + scopeTestVar := 100 + self assert: scopeTestVar equals: 100 // --- Variable scoping across expressions --- - self assert: (scopeTestVar + 50) equals: 150. + self assert: (scopeTestVar + 50) equals: 150 // Variables can be reassigned - scopeTestVar := 200. - self assert: scopeTestVar equals: 200. - self assert: scopeTestVar equals: 200. + scopeTestVar := 200 + self assert: scopeTestVar equals: 200 + self assert: scopeTestVar equals: 200 // Closures capture outer variables - outerVal := 10. - self assert: outerVal equals: 10. + outerVal := 10 + self assert: outerVal equals: 10 // --- Closure variable capture --- - adder := [:x | x + outerVal]. - self assert: (adder value: 5) equals: 15. + adder := [:x | x + outerVal] + self assert: (adder value: 5) equals: 15 // self is valid in method bodies — actor methods use self.field - c := Counter spawn. + c := Counter spawn // --- Self reference in class methods --- - self assert: (c increment) equals: 1. - self assert: (c increment) equals: 2. - self assert: (c getValue) equals: 2 + self assert: c increment equals: 1 + self assert: c increment equals: 2 + self assert: c getValue equals: 2 diff --git a/stdlib/test/set_test.bt b/stdlib/test/set_test.bt index 25499cf55..b72b8c1cc 100644 --- a/stdlib/test/set_test.bt +++ b/stdlib/test/set_test.bt @@ -6,83 +6,83 @@ TestCase subclass: SetTest testCreationClass => - Set new. - self assert: ((Set new) class) equals: Set + Set new + self assert: (Set new) class equals: Set testIsemptySize => - self assert: ((Set new) isEmpty). - self assert: ((Set new) size) equals: 0 + self assert: (Set new) isEmpty + self assert: (Set new) size equals: 0 testAddIncludes => - s := (Set new) add: 1. - self assert: (s includes: 1). - self deny: (s includes: 2). - self assert: (s size) equals: 1 + s := (Set new) add: 1 + self assert: (s includes: 1) + self deny: (s includes: 2) + self assert: s size equals: 1 testAddDeduplication => - s := (Set new) add: 1. - s2 := (s add: 2) add: 1. - self assert: (s2 size) equals: 2. - self assert: (s2 includes: 1). + s := (Set new) add: 1 + s2 := (s add: 2) add: 1 + self assert: s2 size equals: 2 + self assert: (s2 includes: 1) self assert: (s2 includes: 2) testRemove => - s2 := ((Set new) add: 1) add: 2. - s3 := s2 remove: 1. - self deny: (s3 includes: 1). - self assert: (s3 includes: 2). - self assert: (s3 size) equals: 1 + s2 := ((Set new) add: 1) add: 2 + s3 := s2 remove: 1 + self deny: (s3 includes: 1) + self assert: (s3 includes: 2) + self assert: s3 size equals: 1 testFromList => - colors := Set new fromList: #(#red, #green, #blue). - self assert: (colors size) equals: 3. - self assert: (colors includes: #red). + colors := Set new fromList: #(#red, #green, #blue) + self assert: colors size equals: 3 + self assert: (colors includes: #red) self deny: (colors includes: #yellow) testUnion => - a := Set new fromList: #(1, 2, 3). - b := Set new fromList: #(3, 4, 5). - u := a union: b. - self assert: (u size) equals: 5. - self assert: (u includes: 1). + a := Set new fromList: #(1, 2, 3) + b := Set new fromList: #(3, 4, 5) + u := a union: b + self assert: u size equals: 5 + self assert: (u includes: 1) self assert: (u includes: 5) testIntersection => - a := Set new fromList: #(1, 2, 3). - b := Set new fromList: #(3, 4, 5). - i := a intersection: b. - self assert: (i size) equals: 1. - self assert: (i includes: 3). + a := Set new fromList: #(1, 2, 3) + b := Set new fromList: #(3, 4, 5) + i := a intersection: b + self assert: i size equals: 1 + self assert: (i includes: 3) self deny: (i includes: 1) testDifference => - a := Set new fromList: #(1, 2, 3). - b := Set new fromList: #(3, 4, 5). - d := a difference: b. - self assert: (d size) equals: 2. - self assert: (d includes: 1). + a := Set new fromList: #(1, 2, 3) + b := Set new fromList: #(3, 4, 5) + d := a difference: b + self assert: d size equals: 2 + self assert: (d includes: 1) self deny: (d includes: 3) testIssubsetof => - small := Set new fromList: #(1, 2). - big := Set new fromList: #(1, 2, 3). - self assert: (small isSubsetOf: big). + small := Set new fromList: #(1, 2) + big := Set new fromList: #(1, 2, 3) + self assert: (small isSubsetOf: big) self deny: (big isSubsetOf: small) testAslist => - self assert: (((Set new) fromList: #(3, 1, 2)) asList) equals: #(1, 2, 3) + self assert: ((Set new) fromList: #(3, 1, 2)) asList equals: #(1, 2, 3) testIteration => - self assert: (((Set new) fromList: #(1, 2, 3)) do: [:x | nil]) equals: nil. + self assert: (((Set new) fromList: #(1, 2, 3)) do: [:x | nil]) equals: nil // Block receives each element — inject:into: verifies correct values are passed self assert: (((Set new) fromList: #(1, 2, 3)) inject: 0 into: [:sum :x | sum + x]) equals: 6 testRespondstoMethodReflection => - s4 := (Set new) add: 1. - self assert: (s4 respondsTo: #size). - self assert: (s4 respondsTo: #includes:). + s4 := (Set new) add: 1 + self assert: (s4 respondsTo: #size) + self assert: (s4 respondsTo: #includes:) self deny: (s4 respondsTo: #nonExistent) testPrintstring => - self assert: (((Set new) fromList: #(1, 2, 3)) printString) notNil. + self assert: (((Set new) fromList: #(1, 2, 3)) printString) notNil self assert: ((Set new) printString) notNil diff --git a/stdlib/test/setup_state_test.bt b/stdlib/test/setup_state_test.bt index e9490764a..c86e459c9 100644 --- a/stdlib/test/setup_state_test.bt +++ b/stdlib/test/setup_state_test.bt @@ -1,9 +1,9 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-900: Tests that setUp state flows into test methods. -// Value objects are immutable maps — setUp returns a new Self with fields set. -// The BUnit runner must use that return value as the receiver for test methods. +// BT-900: Tests that setUp state flows into test methods +// Value objects are immutable maps — setUp returns a new Self with fields set +// The BUnit runner must use that return value as the receiver for test methods TestCase subclass: SetupStateTest state: value = 0 diff --git a/stdlib/test/source_file_reload_test.bt b/stdlib/test/source_file_reload_test.bt index d86b5533a..4aeee6503 100644 --- a/stdlib/test/source_file_reload_test.bt +++ b/stdlib/test/source_file_reload_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Tests for Behaviour >> sourceFile and Behaviour >> reload (BT-845, ADR 0040 Phase 2). +// Tests for Behaviour >> sourceFile and Behaviour >> reload (BT-845, ADR 0040 Phase 2) // // Verifies: // - sourceFile returns nil for stdlib classes (never loaded from a user file) @@ -9,19 +9,19 @@ // - sourceFile is a sealed method on all classes (isBehaviour check) // // The positive case (sourceFile returns a path after :load) requires the REPL -// context and is tested in tests/e2e/cases/source_file_reload.bt. +// context and is tested in tests/e2e/cases/source_file_reload.bt TestCase subclass: SourceFileReloadTest testStdlibClassSourceFileIsNil => // Stdlib classes have no user-supplied source file - self assert: Integer sourceFile isNil. + self assert: Integer sourceFile isNil // => _ - self assert: String sourceFile isNil. + self assert: String sourceFile isNil // => _ - self assert: Object sourceFile isNil. + self assert: Object sourceFile isNil // => _ - self assert: Boolean sourceFile isNil. + self assert: Boolean sourceFile isNil // => _ self assert: Actor sourceFile isNil // => _ @@ -33,16 +33,16 @@ TestCase subclass: SourceFileReloadTest testStdlibReloadRaisesNoSourceFile => // Reloading a stdlib class raises no_source_file - self should: [Integer reload] raise: #no_source_file. + self should: [Integer reload] raise: #no_source_file // => _ - self should: [String reload] raise: #no_source_file. + self should: [String reload] raise: #no_source_file // => _ self should: [Object reload] raise: #no_source_file // => _ testSourceFileMethodExists => // sourceFile is a sealed method defined in Behaviour (class protocol) - self assert: (Behaviour includesSelector: #sourceFile). + self assert: (Behaviour includesSelector: #sourceFile) // => _ // Sending sourceFile to any class object returns nil or a path (no DNU) self assert: Integer sourceFile isNil @@ -50,7 +50,7 @@ TestCase subclass: SourceFileReloadTest testReloadMethodExists => // reload is a sealed method defined in Behaviour (class protocol) - self assert: (Behaviour includesSelector: #reload). + self assert: (Behaviour includesSelector: #reload) // => _ // Reloading a stdlib class (Behaviour itself) raises no_source_file self should: [Behaviour reload] raise: #no_source_file diff --git a/stdlib/test/species_test.bt b/stdlib/test/species_test.bt index 75dcbd92a..96272f891 100644 --- a/stdlib/test/species_test.bt +++ b/stdlib/test/species_test.bt @@ -1,10 +1,10 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BUnit tests for the species pattern on Collection (BT-822). +// BUnit tests for the species pattern on Collection (BT-822) // // Verifies that collect:, select:, and reject: return the same -// collection type as the receiver (not always a List). +// collection type as the receiver (not always a List) TestCase subclass: SpeciesTest @@ -13,28 +13,28 @@ TestCase subclass: SpeciesTest // =========================================================================== testListSpecies => - self assert: (#(1, 2, 3) species) equals: List + self assert: #(1, 2, 3) species equals: List testArraySpecies => - self assert: (#[1, 2, 3] species) equals: Array + self assert: #[1, 2, 3] species equals: Array // =========================================================================== // List species — collect:/select:/reject: return List // =========================================================================== testListCollectReturnsListType => - result := #(1, 2, 3) collect: [:x | x * 2]. - self assert: (result class) equals: List. + result := #(1, 2, 3) collect: [:x | x * 2] + self assert: result class equals: List self assert: result equals: #(2, 4, 6) testListSelectReturnsListType => - result := #(1, 2, 3, 4) select: [:x | x > 2]. - self assert: (result class) equals: List. + result := #(1, 2, 3, 4) select: [:x | x > 2] + self assert: result class equals: List self assert: result equals: #(3, 4) testListRejectReturnsListType => - result := #(1, 2, 3, 4) reject: [:x | x > 2]. - self assert: (result class) equals: List. + result := #(1, 2, 3, 4) reject: [:x | x > 2] + self assert: result class equals: List self assert: result equals: #(1, 2) // =========================================================================== @@ -42,18 +42,18 @@ TestCase subclass: SpeciesTest // =========================================================================== testArrayCollectReturnsArrayType => - result := #[1, 2, 3] collect: [:x | x * 2]. - self assert: (result class) equals: Array. + result := #[1, 2, 3] collect: [:x | x * 2] + self assert: result class equals: Array self assert: result equals: #[2, 4, 6] testArraySelectReturnsArrayType => - result := #[1, 2, 3, 4] select: [:x | x > 2]. - self assert: (result class) equals: Array. + result := #[1, 2, 3, 4] select: [:x | x > 2] + self assert: result class equals: Array self assert: result equals: #[3, 4] testArrayRejectReturnsArrayType => - result := #[1, 2, 3, 4] reject: [:x | x > 2]. - self assert: (result class) equals: Array. + result := #[1, 2, 3, 4] reject: [:x | x > 2] + self assert: result class equals: Array self assert: result equals: #[1, 2] // =========================================================================== @@ -61,16 +61,16 @@ TestCase subclass: SpeciesTest // =========================================================================== testSetCollectReturnsSetType => - s := Set new fromList: #(1, 2, 3). - result := s collect: [:x | x * 2]. - self assert: (result class) equals: Set + s := Set new fromList: #(1, 2, 3) + result := s collect: [:x | x * 2] + self assert: result class equals: Set testSetSelectReturnsSetType => - s := Set new fromList: #(1, 2, 3, 4). - result := s select: [:x | x > 2]. - self assert: (result class) equals: Set. - self assert: (result includes: 3). - self assert: (result includes: 4). + s := Set new fromList: #(1, 2, 3, 4) + result := s select: [:x | x > 2] + self assert: result class equals: Set + self assert: (result includes: 3) + self assert: (result includes: 4) self deny: (result includes: 1) // =========================================================================== @@ -78,31 +78,31 @@ TestCase subclass: SpeciesTest // =========================================================================== testListWithAll => - result := List withAll: #(1, 2, 3). - self assert: (result class) equals: List. + result := List withAll: #(1, 2, 3) + self assert: result class equals: List self assert: result equals: #(1, 2, 3) testArrayWithAll => - result := Array withAll: #(1, 2, 3). - self assert: (result class) equals: Array. - self assert: (result at: 1) equals: 1. + result := Array withAll: #(1, 2, 3) + self assert: result class equals: Array + self assert: (result at: 1) equals: 1 self assert: (result at: 3) equals: 3 testSetWithAll => - result := Set withAll: #(1, 2, 2, 3). - self assert: (result class) equals: Set. - self assert: (result size) equals: 3. - self assert: (result includes: 1). + result := Set withAll: #(1, 2, 2, 3) + self assert: result class equals: Set + self assert: result size equals: 3 + self assert: (result includes: 1) self assert: (result includes: 3) testTupleWithAll => - result := Tuple withAll: #(1, 2, 3). - self assert: (result class) equals: Tuple. - self assert: (result size) equals: 3 + result := Tuple withAll: #(1, 2, 3) + self assert: result class equals: Tuple + self assert: result size equals: 3 testStringWithAll => - result := String withAll: #("h", "e", "l", "l", "o"). - self assert: (result class) equals: String. + result := String withAll: #("h", "e", "l", "l", "o") + self assert: result class equals: String self assert: result equals: "hello" // =========================================================================== @@ -110,15 +110,15 @@ TestCase subclass: SpeciesTest // =========================================================================== testDictionaryCollectPreservesKeys => - d := #{#a => 1, #b => 2, #c => 3}. - result := d collect: [:v | v * 10]. - self assert: (result class) equals: Dictionary. - self assert: (result at: #a) equals: 10. - self assert: (result at: #b) equals: 20. + d := #{#a => 1, #b => 2, #c => 3} + result := d collect: [:v | v * 10] + self assert: result class equals: Dictionary + self assert: (result at: #a) equals: 10 + self assert: (result at: #b) equals: 20 self assert: (result at: #c) equals: 30 testDictionaryCollectReturnsDictionary => - d := #{#x => 5}. - result := d collect: [:v | v + 1]. - self assert: (result class) equals: Dictionary. + d := #{#x => 5} + result := d collect: [:v | v + 1] + self assert: result class equals: Dictionary self assert: (result at: #x) equals: 6 diff --git a/stdlib/test/stack_frame_test.bt b/stdlib/test/stack_frame_test.bt index 3c89d8020..89284941a 100644 --- a/stdlib/test/stack_frame_test.bt +++ b/stdlib/test/stack_frame_test.bt @@ -7,59 +7,59 @@ TestCase subclass: StackFrameTest testStackTraceExists => // stackTrace returns a list - result := [1 / 0] on: Exception do: [:e | e stackTrace class]. + result := [1 / 0] on: Exception do: [:e | e stackTrace class] self assert: result equals: List testStackTraceHasEntries => // stackTrace has entries - result := [1 / 0] on: Exception do: [:e | e stackTrace size > 0]. + result := [1 / 0] on: Exception do: [:e | e stackTrace size > 0] self assert: result testStackTraceFromDoesNotUnderstand => // stackTrace from does_not_understand has entries @expect dnu - result := [42 noSuchMethod] on: Exception do: [:e | e stackTrace size > 0]. + result := [42 noSuchMethod] on: Exception do: [:e | e stackTrace size > 0] self assert: result testHandlerWithoutArg => // Handler without arg still works - result := [1 / 0] on: Exception do: [42]. + result := [1 / 0] on: Exception do: [42] self assert: result equals: 42 testRuntimeErrorStackTrace => // RuntimeError also has stackTrace @expect dnu - result := [42 noSuchMethod] on: RuntimeError do: [:e | e stackTrace class]. + result := [42 noSuchMethod] on: RuntimeError do: [:e | e stackTrace class] self assert: result equals: List testStackFrameClass => // stackTrace first is a StackFrame - result := [1 / 0] on: Exception do: [:e | e stackTrace first class]. + result := [1 / 0] on: Exception do: [:e | e stackTrace first class] self assert: result equals: StackFrame testStackFrameMethod => // StackFrame method returns a Symbol - result := [1 / 0] on: Exception do: [:e | (e stackTrace first method) class]. + result := [1 / 0] on: Exception do: [:e | (e stackTrace first method) class] self assert: result equals: Symbol testStackFrameArguments => // StackFrame arguments returns an Integer (arity) - result := [1 / 0] on: Exception do: [:e | (e stackTrace first arguments) class]. + result := [1 / 0] on: Exception do: [:e | (e stackTrace first arguments) class] self assert: result equals: Integer testStackFramePrintString => // StackFrame printString returns a String - result := [1 / 0] on: Exception do: [:e | (e stackTrace first printString) class]. + result := [1 / 0] on: Exception do: [:e | (e stackTrace first printString) class] self assert: result equals: String testStackFrameAccessors => // StackFrame accessors return values without error - frame := [1 / 0] on: Exception do: [:e | e stackTrace first]. - self assert: (frame class) equals: StackFrame. + frame := [1 / 0] on: Exception do: [:e | e stackTrace first] + self assert: frame class equals: StackFrame // line, file, moduleName, receiverClass, sourceLocation may return nil or a value // Verify they respond without crashing - self assert: (frame respondsTo: #line). - self assert: (frame respondsTo: #file). - self assert: (frame respondsTo: #moduleName). - self assert: (frame respondsTo: #receiverClass). + self assert: (frame respondsTo: #line) + self assert: (frame respondsTo: #file) + self assert: (frame respondsTo: #moduleName) + self assert: (frame respondsTo: #receiverClass) self assert: (frame respondsTo: #sourceLocation) diff --git a/stdlib/test/stream_collections_test.bt b/stdlib/test/stream_collections_test.bt index 78bd21bd0..b72e18bcc 100644 --- a/stdlib/test/stream_collections_test.bt +++ b/stdlib/test/stream_collections_test.bt @@ -3,129 +3,129 @@ // Tests Stream on all collection types — List, String, Set, and Dictionary — // verifying that stream, select:, collect:, reject:, drop:, take:, do:, -// inject:into:, detect:, anySatisfy:, allSatisfy:, and Stream on: all work. +// inject:into:, detect:, anySatisfy:, allSatisfy:, and Stream on: all work TestCase subclass: StreamCollectionsTest testStreamOnAllCollectionTypes => - self assert: ((#(1, 2, 3) stream) asList) equals: #(1, 2, 3). + self assert: (#(1, 2, 3) stream) asList equals: #(1, 2, 3) // Empty list stream - self assert: ((#() stream) asList) equals: #(). + self assert: (#() stream) asList equals: #() // Single element - self assert: ((#(42) stream) asList) equals: #(42). + self assert: (#(42) stream) asList equals: #(42) // Lazy pipeline on list stream - self assert: (((#(1, 2, 3, 4, 5) stream) select: [:n | n > 2]) asList) equals: #(3, 4, 5). + self assert: ((#(1, 2, 3, 4, 5) stream) select: [:n | n > 2]) asList equals: #(3, 4, 5) // Collect on list stream - self assert: (((#(1, 2, 3) stream) collect: [:n | n * 10]) asList) equals: #(10, 20, 30). + self assert: ((#(1, 2, 3) stream) collect: [:n | n * 10]) asList equals: #(10, 20, 30) // Stream returns Stream, not List - self assert: ((#(1, 2, 3) stream) class) equals: Stream. + self assert: (#(1, 2, 3) stream) class equals: Stream // Chained lazy pipeline - self assert: ((((#(1, 2, 3, 4, 5, 6) stream) select: [:n | n > 2]) collect: [:n | n * 10]) asList) equals: #(30, 40, 50, 60). + self assert: (((#(1, 2, 3, 4, 5, 6) stream) select: [:n | n > 2]) collect: [:n | n * 10]) asList equals: #(30, 40, 50, 60) // Take on list stream - self assert: ((#(1, 2, 3, 4, 5) stream) take: 3) equals: #(1, 2, 3). + self assert: ((#(1, 2, 3, 4, 5) stream) take: 3) equals: #(1, 2, 3) // Inject into on list stream - self assert: ((#(1, 2, 3) stream) inject: 0 into: [:sum :n | sum + n]) equals: 6. + self assert: ((#(1, 2, 3) stream) inject: 0 into: [:sum :n | sum + n]) equals: 6 // Detect on list stream - self assert: ((#(1, 2, 3, 4) stream) detect: [:n | n > 2]) equals: 3. + self assert: ((#(1, 2, 3, 4) stream) detect: [:n | n > 2]) equals: 3 // anySatisfy on list stream - self assert: ((#(1, 2, 3) stream) anySatisfy: [:n | n > 2]). + self assert: ((#(1, 2, 3) stream) anySatisfy: [:n | n > 2]) // allSatisfy on list stream - self assert: ((#(1, 2, 3) stream) allSatisfy: [:n | n > 0]). + self assert: ((#(1, 2, 3) stream) allSatisfy: [:n | n > 0]) // respondsTo: #stream - self assert: (#(1, 2, 3) respondsTo: #stream). - self assert: ("hello" respondsTo: #stream). - self assert: ((Set new) respondsTo: #stream). - self assert: (#{#a => 1} respondsTo: #stream). + self assert: (#(1, 2, 3) respondsTo: #stream) + self assert: ("hello" respondsTo: #stream) + self assert: ((Set new) respondsTo: #stream) + self assert: (#{#a => 1} respondsTo: #stream) // Basic string stream — characters as graphemes - self assert: (("hello" stream) take: 3) equals: #("h", "e", "l"). + self assert: (("hello" stream) take: 3) equals: #("h", "e", "l") // Full string stream - self assert: (("abc" stream) asList) equals: #("a", "b", "c"). + self assert: ("abc" stream) asList equals: #("a", "b", "c") // Empty string stream - self assert: (("" stream) asList) equals: #(). + self assert: ("" stream) asList equals: #() // Single character - self assert: (("x" stream) asList) equals: #("x"). + self assert: ("x" stream) asList equals: #("x") // Select on string stream - self assert: ((("hello" stream) select: [:ch | ch /= "l"]) asList) equals: #("h", "e", "o"). + self assert: (("hello" stream) select: [:ch | ch /= "l"]) asList equals: #("h", "e", "o") // Collect on string stream - self assert: ((("abc" stream) collect: [:ch | ch uppercase]) asList) equals: #("A", "B", "C"). + self assert: (("abc" stream) collect: [:ch | ch uppercase]) asList equals: #("A", "B", "C") // String stream returns Stream - self assert: (("hello" stream) class) equals: Stream. + self assert: ("hello" stream) class equals: Stream // reject on string stream - self assert: ((("hello" stream) reject: [:ch | ch =:= "l"]) asList) equals: #("h", "e", "o"). + self assert: (("hello" stream) reject: [:ch | ch =:= "l"]) asList equals: #("h", "e", "o") // drop on string stream - self assert: ((("hello" stream) drop: 3) asList) equals: #("l", "o"). + self assert: (("hello" stream) drop: 3) asList equals: #("l", "o") // do: on string stream (side effect, returns nil) - self assert: (("abc" stream) do: [:ch | ch]) equals: nil. + self assert: (("abc" stream) do: [:ch | ch]) equals: nil // inject:into: on string stream - self assert: (("abc" stream) inject: "" into: [:acc :ch | acc ++ ch]) equals: "abc". + self assert: (("abc" stream) inject: "" into: [:acc :ch | acc ++ ch]) equals: "abc" // anySatisfy on string stream - self assert: (("hello" stream) anySatisfy: [:ch | ch =:= "e"]). + self assert: (("hello" stream) anySatisfy: [:ch | ch =:= "e"]) // allSatisfy on string stream - self assert: (("hello" stream) allSatisfy: [:ch | ch /= "z"]). + self assert: (("hello" stream) allSatisfy: [:ch | ch /= "z"]) // Basic set stream - s := ((Set new add: 3) add: 1) add: 2. - self assert: ((s stream) asList) equals: #(1, 2, 3). + s := ((Set new add: 3) add: 1) add: 2 + self assert: (s stream) asList equals: #(1, 2, 3) // Empty set stream - self assert: ((Set new stream) asList) equals: #(). + self assert: (Set new stream) asList equals: #() // Single element set stream - self assert: (((Set new add: 42) stream) asList) equals: #(42). + self assert: ((Set new add: 42) stream) asList equals: #(42) // Select on set stream - self assert: ((((((Set new add: 1) add: 2) add: 3) stream) select: [:n | n > 1]) asList) equals: #(2, 3). + self assert: (((((Set new add: 1) add: 2) add: 3) stream) select: [:n | n > 1]) asList equals: #(2, 3) // Collect on set stream - self assert: ((((((Set new add: 1) add: 2) add: 3) stream) collect: [:n | n * 10]) asList) equals: #(10, 20, 30). + self assert: (((((Set new add: 1) add: 2) add: 3) stream) collect: [:n | n * 10]) asList equals: #(10, 20, 30) // Set stream returns Stream - self assert: (((Set new add: 1) stream) class) equals: Stream. + self assert: ((Set new add: 1) stream) class equals: Stream // reject on set stream - self assert: ((((((Set new add: 1) add: 2) add: 3) stream) reject: [:n | n =:= 2]) asList) equals: #(1, 3). + self assert: (((((Set new add: 1) add: 2) add: 3) stream) reject: [:n | n =:= 2]) asList equals: #(1, 3) // drop on set stream - self assert: ((((((Set new add: 1) add: 2) add: 3) stream) drop: 1) asList) equals: #(2, 3). + self assert: (((((Set new add: 1) add: 2) add: 3) stream) drop: 1) asList equals: #(2, 3) // take on set stream - self assert: (((((Set new add: 1) add: 2) add: 3) stream) take: 2) equals: #(1, 2). + self assert: (((((Set new add: 1) add: 2) add: 3) stream) take: 2) equals: #(1, 2) // do: on set stream (returns nil) - self assert: (((Set new add: 1) stream) do: [:n | n]) equals: nil. + self assert: (((Set new add: 1) stream) do: [:n | n]) equals: nil // inject:into: on set stream - self assert: (((((Set new add: 1) add: 2) add: 3) stream) inject: 0 into: [:sum :n | sum + n]) equals: 6. + self assert: (((((Set new add: 1) add: 2) add: 3) stream) inject: 0 into: [:sum :n | sum + n]) equals: 6 // detect on set stream - self assert: (((((Set new add: 1) add: 2) add: 3) stream) detect: [:n | n > 1]) equals: 2. + self assert: (((((Set new add: 1) add: 2) add: 3) stream) detect: [:n | n > 1]) equals: 2 // anySatisfy on set stream - self assert: ((((Set new add: 1) add: 2) stream) anySatisfy: [:n | n > 1]). + self assert: ((((Set new add: 1) add: 2) stream) anySatisfy: [:n | n > 1]) // allSatisfy on set stream - self assert: ((((Set new add: 1) add: 2) stream) allSatisfy: [:n | n > 0]). + self assert: ((((Set new add: 1) add: 2) stream) allSatisfy: [:n | n > 0]) // Dictionary stream produces Associations - d := #{#a => 1}. - self assert: ((d stream) asList) size equals: 1. + d := #{#a => 1} + self assert: ((d stream) asList) size equals: 1 // Single-entry dictionary stream — verify Association - a := ((#{#x => 42} stream) asList) first. - self assert: (a class) equals: Association. - self assert: (a key) equals: #x. - self assert: (a value) equals: 42. + a := ((#{#x => 42} stream) asList) first + self assert: a class equals: Association + self assert: a key equals: #x + self assert: a value equals: 42 // Empty dictionary stream - self assert: ((#{} stream) asList) equals: #(). + self assert: (#{} stream) asList equals: #() // Dictionary stream returns Stream - self assert: ((#{#a => 1} stream) class) equals: Stream. + self assert: (#{#a => 1} stream) class equals: Stream // Select on dictionary stream - self assert: ((((#{#a => 1, #b => 2, #c => 3} stream) select: [:assoc | assoc value > 1]) asList) size) equals: 2. + self assert: (((#{#a => 1, #b => 2, #c => 3} stream) select: [:assoc | assoc value > 1]) asList) size equals: 2 // Collect on dictionary stream — transform associations - self assert: ((((#{#a => 1, #b => 2} stream) collect: [:assoc | assoc value]) asList) size) equals: 2. + self assert: (((#{#a => 1, #b => 2} stream) collect: [:assoc | assoc value]) asList) size equals: 2 // Detect on dictionary stream - self assert: (((#{#a => 1, #b => 2, #c => 3} stream) detect: [:assoc | assoc value > 2]) value) equals: 3. + self assert: ((#{#a => 1, #b => 2, #c => 3} stream) detect: [:assoc | assoc value > 2]) value equals: 3 // reject on dictionary stream - self assert: ((((#{#a => 1, #b => 2, #c => 3} stream) reject: [:assoc | assoc value =:= 2]) asList) size) equals: 2. + self assert: (((#{#a => 1, #b => 2, #c => 3} stream) reject: [:assoc | assoc value =:= 2]) asList) size equals: 2 // drop on dictionary stream - self assert: ((((#{#a => 1, #b => 2} stream) drop: 1) asList) size) equals: 1. + self assert: (((#{#a => 1, #b => 2} stream) drop: 1) asList) size equals: 1 // take on dictionary stream - self assert: (((#{#a => 1, #b => 2, #c => 3} stream) take: 1) size) equals: 1. + self assert: ((#{#a => 1, #b => 2, #c => 3} stream) take: 1) size equals: 1 // do: on dictionary stream (returns nil) - self assert: ((#{#a => 1} stream) do: [:assoc | assoc]) equals: nil. + self assert: ((#{#a => 1} stream) do: [:assoc | assoc]) equals: nil // inject:into: on dictionary stream — sum values - self assert: ((#{#a => 1, #b => 2, #c => 3} stream) inject: 0 into: [:sum :assoc | sum + (assoc value)]) equals: 6. + self assert: ((#{#a => 1, #b => 2, #c => 3} stream) inject: 0 into: [:sum :assoc | sum + assoc value]) equals: 6 // anySatisfy on dictionary stream - self assert: ((#{#a => 1, #b => 2} stream) anySatisfy: [:assoc | assoc value > 1]). + self assert: ((#{#a => 1, #b => 2} stream) anySatisfy: [:assoc | assoc value > 1]) // allSatisfy on dictionary stream - self assert: ((#{#a => 1, #b => 2} stream) allSatisfy: [:assoc | assoc value > 0]). + self assert: ((#{#a => 1, #b => 2} stream) allSatisfy: [:assoc | assoc value > 0]) // Stream on: with string - self assert: ((Stream on: "abc") asList) equals: #("a", "b", "c"). + self assert: (Stream on: "abc") asList equals: #("a", "b", "c") // Stream on: with set - self assert: ((Stream on: ((Set new add: 1) add: 2)) asList) equals: #(1, 2). + self assert: (Stream on: ((Set new add: 1) add: 2)) asList equals: #(1, 2) // Stream on: with dictionary - self assert: (((Stream on: #{#x => 99}) asList) first value) equals: 99 + self assert: ((Stream on: #{#x => 99}) asList) first value equals: 99 diff --git a/stdlib/test/stream_test.bt b/stdlib/test/stream_test.bt index 362e12174..cc44608ed 100644 --- a/stdlib/test/stream_test.bt +++ b/stdlib/test/stream_test.bt @@ -3,95 +3,95 @@ // Tests the Stream class — from:, from:by:, on: constructors; lazy pipeline // ops (select:, collect:, reject:, drop:); terminals (take:, asList, do:, -// inject:into:, detect:, anySatisfy:, allSatisfy:); and empty-stream behaviour. +// inject:into:, detect:, anySatisfy:, allSatisfy:); and empty-stream behaviour TestCase subclass: StreamTest testStreamConstructorsAndPipelines => - self assert: ((Stream from: 1) take: 5) equals: #(1, 2, 3, 4, 5). - self assert: ((Stream from: 10) take: 3) equals: #(10, 11, 12). - self assert: ((Stream from: 0) take: 1) equals: #(0). - self assert: ((Stream from: -3) take: 4) equals: #(-3, -2, -1, 0). + self assert: ((Stream from: 1) take: 5) equals: #(1, 2, 3, 4, 5) + self assert: ((Stream from: 10) take: 3) equals: #(10, 11, 12) + self assert: ((Stream from: 0) take: 1) equals: #(0) + self assert: ((Stream from: -3) take: 4) equals: #(-3, -2, -1, 0) // Stream from:by: — step function stream - self assert: ((Stream from: 1 by: [:n | n * 2]) take: 5) equals: #(1, 2, 4, 8, 16). - self assert: ((Stream from: 0 by: [:n | n + 10]) take: 4) equals: #(0, 10, 20, 30). - self assert: ((Stream from: 100 by: [:n | n - 1]) take: 3) equals: #(100, 99, 98). + self assert: ((Stream from: 1 by: [:n | n * 2]) take: 5) equals: #(1, 2, 4, 8, 16) + self assert: ((Stream from: 0 by: [:n | n + 10]) take: 4) equals: #(0, 10, 20, 30) + self assert: ((Stream from: 100 by: [:n | n - 1]) take: 3) equals: #(100, 99, 98) // Stream on: — from collection - self assert: ((Stream on: #(1, 2, 3)) asList) equals: #(1, 2, 3). - self assert: ((Stream on: #()) asList) equals: #(). - self assert: ((Stream on: #(42)) asList) equals: #(42). + self assert: (Stream on: #(1, 2, 3)) asList equals: #(1, 2, 3) + self assert: (Stream on: #()) asList equals: #() + self assert: (Stream on: #(42)) asList equals: #(42) // select: — filter - self assert: (((Stream on: #(1, 2, 3, 4, 5)) select: [:n | n > 3]) asList) equals: #(4, 5). - self assert: (((Stream on: #(1, 2, 3, 4, 5, 6)) select: [:n | n isEven]) asList) equals: #(2, 4, 6). + self assert: ((Stream on: #(1, 2, 3, 4, 5)) select: [:n | n > 3]) asList equals: #(4, 5) + self assert: ((Stream on: #(1, 2, 3, 4, 5, 6)) select: [:n | n isEven]) asList equals: #(2, 4, 6) // select: on empty - self assert: (((Stream on: #()) select: [:n | n > 0]) asList) equals: #(). + self assert: ((Stream on: #()) select: [:n | n > 0]) asList equals: #() // collect: — transform - self assert: (((Stream on: #(1, 2, 3)) collect: [:n | n * 10]) asList) equals: #(10, 20, 30). - self assert: (((Stream on: #(1, 2, 3)) collect: [:n | n + 100]) asList) equals: #(101, 102, 103). + self assert: ((Stream on: #(1, 2, 3)) collect: [:n | n * 10]) asList equals: #(10, 20, 30) + self assert: ((Stream on: #(1, 2, 3)) collect: [:n | n + 100]) asList equals: #(101, 102, 103) // reject: — inverse filter - self assert: (((Stream on: #(1, 2, 3, 4, 5)) reject: [:n | n > 3]) asList) equals: #(1, 2, 3). - self assert: (((Stream on: #(1, 2, 3, 4)) reject: [:n | n isEven]) asList) equals: #(1, 3). + self assert: ((Stream on: #(1, 2, 3, 4, 5)) reject: [:n | n > 3]) asList equals: #(1, 2, 3) + self assert: ((Stream on: #(1, 2, 3, 4)) reject: [:n | n isEven]) asList equals: #(1, 3) // drop: — skip first N - self assert: (((Stream on: #(1, 2, 3, 4, 5)) drop: 2) asList) equals: #(3, 4, 5). - self assert: (((Stream on: #(1, 2, 3)) drop: 0) asList) equals: #(1, 2, 3). - self assert: (((Stream on: #(1, 2, 3)) drop: 5) asList) equals: #(). + self assert: ((Stream on: #(1, 2, 3, 4, 5)) drop: 2) asList equals: #(3, 4, 5) + self assert: ((Stream on: #(1, 2, 3)) drop: 0) asList equals: #(1, 2, 3) + self assert: ((Stream on: #(1, 2, 3)) drop: 5) asList equals: #() // take: — first N elements - self assert: ((Stream from: 1) take: 0) equals: #(). - self assert: ((Stream from: 1) take: 3) equals: #(1, 2, 3). + self assert: ((Stream from: 1) take: 0) equals: #() + self assert: ((Stream from: 1) take: 3) equals: #(1, 2, 3) // take: on finite stream (fewer elements than requested) - self assert: ((Stream on: #(1, 2)) take: 10) equals: #(1, 2). + self assert: ((Stream on: #(1, 2)) take: 10) equals: #(1, 2) // do: — iterate with side effects - self assert: ((Stream on: #(1, 2, 3)) do: [:n | n]) equals: nil. + self assert: ((Stream on: #(1, 2, 3)) do: [:n | n]) equals: nil // inject:into: — fold/reduce - self assert: ((Stream on: #(1, 2, 3, 4)) inject: 0 into: [:sum :n | sum + n]) equals: 10. - self assert: ((Stream on: #(1, 2, 3)) inject: 1 into: [:product :n | product * n]) equals: 6. - self assert: ((Stream on: #()) inject: 42 into: [:acc :n | acc + n]) equals: 42. + self assert: ((Stream on: #(1, 2, 3, 4)) inject: 0 into: [:sum :n | sum + n]) equals: 10 + self assert: ((Stream on: #(1, 2, 3)) inject: 1 into: [:product :n | product * n]) equals: 6 + self assert: ((Stream on: #()) inject: 42 into: [:acc :n | acc + n]) equals: 42 // detect: — first matching element - self assert: ((Stream on: #(1, 2, 3, 4, 5)) detect: [:n | n > 3]) equals: 4. - self assert: ((Stream on: #(1, 2, 3)) detect: [:n | n > 10]) equals: nil. + self assert: ((Stream on: #(1, 2, 3, 4, 5)) detect: [:n | n > 3]) equals: 4 + self assert: ((Stream on: #(1, 2, 3)) detect: [:n | n > 10]) equals: nil // asList — materialize - self assert: ((Stream on: #(10, 20, 30)) asList) equals: #(10, 20, 30). + self assert: (Stream on: #(10, 20, 30)) asList equals: #(10, 20, 30) // anySatisfy: — any match? - self assert: ((Stream on: #(1, 2, 3)) anySatisfy: [:n | n > 2]). - self deny: ((Stream on: #(1, 2, 3)) anySatisfy: [:n | n > 10]). - self deny: ((Stream on: #()) anySatisfy: [:n | n > 0]). + self assert: ((Stream on: #(1, 2, 3)) anySatisfy: [:n | n > 2]) + self deny: ((Stream on: #(1, 2, 3)) anySatisfy: [:n | n > 10]) + self deny: ((Stream on: #()) anySatisfy: [:n | n > 0]) // allSatisfy: — all match? - self assert: ((Stream on: #(1, 2, 3)) allSatisfy: [:n | n > 0]). - self deny: ((Stream on: #(1, 2, 3)) allSatisfy: [:n | n > 2]). - self assert: ((Stream on: #()) allSatisfy: [:n | n > 0]). + self assert: ((Stream on: #(1, 2, 3)) allSatisfy: [:n | n > 0]) + self deny: ((Stream on: #(1, 2, 3)) allSatisfy: [:n | n > 2]) + self assert: ((Stream on: #()) allSatisfy: [:n | n > 0]) // Chained lazy ops on infinite stream - self assert: (((Stream from: 1) select: [:n | n isEven]) take: 5) equals: #(2, 4, 6, 8, 10). - self assert: (((Stream from: 1) collect: [:n | n * n]) take: 5) equals: #(1, 4, 9, 16, 25). + self assert: (((Stream from: 1) select: [:n | n isEven]) take: 5) equals: #(2, 4, 6, 8, 10) + self assert: (((Stream from: 1) collect: [:n | n * n]) take: 5) equals: #(1, 4, 9, 16, 25) // Multi-step pipeline - self assert: ((((Stream from: 1) select: [:n | n isEven]) collect: [:n | n * n]) take: 4) equals: #(4, 16, 36, 64). + self assert: ((((Stream from: 1) select: [:n | n isEven]) collect: [:n | n * n]) take: 4) equals: #(4, 16, 36, 64) // Pipeline with drop - self assert: (((Stream from: 1) drop: 5) take: 3) equals: #(6, 7, 8). + self assert: (((Stream from: 1) drop: 5) take: 3) equals: #(6, 7, 8) // inject on finite stream - self assert: ((Stream on: #(1, 2, 3, 4, 5)) inject: 0 into: [:sum :n | sum + n]) equals: 15. - (Stream from: 1) printString. + self assert: ((Stream on: #(1, 2, 3, 4, 5)) inject: 0 into: [:sum :n | sum + n]) equals: 15 + (Stream from: 1) printString // => _ - (Stream on: #(1, 2, 3)) printString. + (Stream on: #(1, 2, 3)) printString // => _ // Pipeline description - ((Stream from: 1) select: [:n | n isEven]) printString. + ((Stream from: 1) select: [:n | n isEven]) printString // => _ - (Stream from: 1) printString. + (Stream from: 1) printString // => _ - self assert: ((Stream from: 1) class) equals: Stream. - self assert: ((Stream on: #()) take: 5) equals: #(). - self assert: ((Stream on: #()) asList) equals: #(). - self assert: ((Stream on: #()) detect: [:x | x > 0]) equals: nil. - self deny: ((Stream on: #()) anySatisfy: [:x | x > 0]). - self assert: ((Stream on: #()) allSatisfy: [:x | x > 0]). - self assert: ((Stream on: #()) inject: 0 into: [:acc :x | acc + x]) equals: 0. - self assert: (((Stream on: #(1, 2, 3)) drop: 10) asList) equals: #() + self assert: (Stream from: 1) class equals: Stream + self assert: ((Stream on: #()) take: 5) equals: #() + self assert: (Stream on: #()) asList equals: #() + self assert: ((Stream on: #()) detect: [:x | x > 0]) equals: nil + self deny: ((Stream on: #()) anySatisfy: [:x | x > 0]) + self assert: ((Stream on: #()) allSatisfy: [:x | x > 0]) + self assert: ((Stream on: #()) inject: 0 into: [:acc :x | acc + x]) equals: 0 + self assert: ((Stream on: #(1, 2, 3)) drop: 10) asList equals: #() testInstanceMethodTypeErrors => // Instance method type errors (constructor errors cannot be tested due to gen_server limitation) @expect type - self should: [(Stream from: 1) select: "not a block"] raise: #type_error. + self should: [(Stream from: 1) select: "not a block"] raise: #type_error @expect type - self should: [(Stream from: 1) collect: 42] raise: #type_error. + self should: [(Stream from: 1) collect: 42] raise: #type_error // BT-765: take: with non-integer argument raises type_error @expect all self should: [(Stream from: 1) take: "five"] raise: #type_error diff --git a/stdlib/test/string_advanced_methods_test.bt b/stdlib/test/string_advanced_methods_test.bt index e5addd966..28517a896 100644 --- a/stdlib/test/string_advanced_methods_test.bt +++ b/stdlib/test/string_advanced_methods_test.bt @@ -6,25 +6,25 @@ TestCase subclass: StringAdvancedMethodsTest testUppercase => - self assert: ("hello" uppercase) equals: "HELLO" + self assert: "hello" uppercase equals: "HELLO" testLowercase => - self assert: ("HELLO" lowercase) equals: "hello" + self assert: "HELLO" lowercase equals: "hello" testTrim => // trim both sides - self assert: (" hello " trim) equals: "hello". + self assert: " hello " trim equals: "hello" // trim with no whitespace (no-op) - self assert: ("hello" trim) equals: "hello" + self assert: "hello" trim equals: "hello" testTrimLeft => - self assert: (" hello" trimLeft) equals: "hello" + self assert: " hello" trimLeft equals: "hello" testTrimRight => - self assert: ("hello " trimRight) equals: "hello" + self assert: "hello " trimRight equals: "hello" testStringEquality => - self assert: ("hello" =:= "hello"). + self assert: ("hello" =:= "hello") self deny: ("hello" =:= "world") testStringInequality => @@ -40,19 +40,19 @@ TestCase subclass: StringAdvancedMethodsTest testStringLessOrEqual => // String less than or equal - self assert: ("abc" <= "abc"). + self assert: ("abc" <= "abc") self assert: ("abc" <= "def") testStringGreaterOrEqual => // String greater than or equal - self assert: ("def" >= "abc"). + self assert: ("def" >= "abc") self assert: ("abc" >= "abc") testSplit => self assert: ("a,b,c" split: ",") equals: #("a", "b", "c") testAsInteger => - self assert: ("42" asInteger) equals: 42 + self assert: "42" asInteger equals: 42 testAsFloat => - self assert: ("3.14" asFloat) equals: 3.14 + self assert: "3.14" asFloat equals: 3.14 diff --git a/stdlib/test/string_interpolation_test.bt b/stdlib/test/string_interpolation_test.bt index b5fb6a381..d96fd442b 100644 --- a/stdlib/test/string_interpolation_test.bt +++ b/stdlib/test/string_interpolation_test.bt @@ -11,13 +11,13 @@ TestCase subclass: StringInterpolationTest testVariableInterpolation => // Simple variable interpolation - name := "World". - self assert: name equals: "World". - self assert: "Hello, {name}!" equals: "Hello, World!". + name := "World" + self assert: name equals: "World" + self assert: "Hello, {name}!" equals: "Hello, World!" // Variable at start - self assert: "{name} says hi" equals: "World says hi". + self assert: "{name} says hi" equals: "World says hi" // Variable at end - self assert: "Hi {name}" equals: "Hi World". + self assert: "Hi {name}" equals: "Hi World" // Only variable (no literal segments) self assert: "{name}" equals: "World" @@ -27,12 +27,12 @@ TestCase subclass: StringInterpolationTest testPrintstringConversion => // Integer printString - self assert: "Age: {30}" equals: "Age: 30". + self assert: "Age: {30}" equals: "Age: 30" // Boolean interpolation - self assert: "Flag: {true}" equals: "Flag: true". - self assert: "Flag: {false}" equals: "Flag: false". + self assert: "Flag: {true}" equals: "Flag: true" + self assert: "Flag: {false}" equals: "Flag: false" // Nil interpolation - self assert: "Value: {nil}" equals: "Value: nil". + self assert: "Value: {nil}" equals: "Value: nil" // Symbol interpolation (displayString: no # prefix) self assert: "Symbol: {#hello}" equals: "Symbol: hello" @@ -42,13 +42,13 @@ TestCase subclass: StringInterpolationTest testMultipleInterpolations => // Two variables - first := "Alice". - self assert: first equals: "Alice". - last := "Bob". - self assert: last equals: "Bob". - self assert: "Name: {first} {last}" equals: "Name: Alice Bob". + first := "Alice" + self assert: first equals: "Alice" + last := "Bob" + self assert: last equals: "Bob" + self assert: "Name: {first} {last}" equals: "Name: Alice Bob" // Mixed literals and expressions - self assert: "a{1}b{2}c" equals: "a1b2c". + self assert: "a{1}b{2}c" equals: "a1b2c" // Adjacent interpolations self assert: "{first}{last}" equals: "AliceBob" @@ -58,21 +58,21 @@ TestCase subclass: StringInterpolationTest testEmptyAndEdgeCases => // Empty string - self assert: "" equals: "". + self assert: "" equals: "" // String with only literals self assert: "no interpolation here" equals: "no interpolation here" testUnicodeContent => // Unicode in literal segments - self assert: "Hello 🎉" equals: "Hello 🎉". + self assert: "Hello 🎉" equals: "Hello 🎉" // Unicode variable - emoji := "🚀". - self assert: emoji equals: "🚀". - self assert: "Launch: {emoji}" equals: "Launch: 🚀". + emoji := "🚀" + self assert: emoji equals: "🚀" + self assert: "Launch: {emoji}" equals: "Launch: 🚀" // CJK characters self assert: "日本語: {42}" equals: "日本語: 42" testActorInterpolationAutoAwait => // Actor printString auto-awaits the future - c := Counter spawn. + c := Counter spawn self assert: "Actor: {c}" equals: "Actor: a Counter" diff --git a/stdlib/test/string_new_methods_test.bt b/stdlib/test/string_new_methods_test.bt index 24f4cf165..44b3b9689 100644 --- a/stdlib/test/string_new_methods_test.bt +++ b/stdlib/test/string_new_methods_test.bt @@ -6,47 +6,47 @@ TestCase subclass: StringNewMethodsTest testReplace => - self assert: ("hello world" replaceAll: "o" with: "0") equals: "hell0 w0rld". - self assert: ("aaa" replaceAll: "a" with: "bb") equals: "bbbbbb". + self assert: ("hello world" replaceAll: "o" with: "0") equals: "hell0 w0rld" + self assert: ("aaa" replaceAll: "a" with: "bb") equals: "bbbbbb" // replaceFirst:with: self assert: ("hello world" replaceFirst: "o" with: "0") equals: "hell0 world" testWords => // words - self assert: ("hello world foo" words) equals: #("hello", "world", "foo"). + self assert: "hello world foo" words equals: #("hello", "world", "foo") // words with extra spaces - self assert: (" hello world " words) equals: #("hello", "world") + self assert: " hello world " words equals: #("hello", "world") testTakeAndDrop => // take: - self assert: ("hello" take: 3) equals: "hel". - self assert: ("hello" take: 10) equals: "hello". - self assert: ("hello" take: 0) equals: "". + self assert: ("hello" take: 3) equals: "hel" + self assert: ("hello" take: 10) equals: "hello" + self assert: ("hello" take: 0) equals: "" // drop: - self assert: ("hello" drop: 2) equals: "llo". - self assert: ("hello" drop: 0) equals: "hello". + self assert: ("hello" drop: 2) equals: "llo" + self assert: ("hello" drop: 0) equals: "hello" self assert: ("hello" drop: 10) equals: "" testPadding => // padLeft: with spaces — verify correct length - self assert: ("hi" padLeft: 5) size equals: 5. + self assert: ("hi" padLeft: 5) size equals: 5 // padRight: with spaces — verify correct length - self assert: ("hi" padRight: 5) size equals: 5. + self assert: ("hi" padRight: 5) size equals: 5 // padLeft:with: - pad with specific character - self assert: ("42" padLeft: 5 with: "0") equals: "00042". + self assert: ("42" padLeft: 5 with: "0") equals: "00042" // padRight:with: - pad with specific character self assert: ("42" padRight: 5 with: "0") equals: "42000" testStringPredicates => // isBlank - self assert: ("" isBlank). - self assert: (" " isBlank). - self deny: ("hello" isBlank). + self assert: "" isBlank + self assert: " " isBlank + self deny: "hello" isBlank // isDigit - self assert: ("123" isDigit). - self deny: ("12a" isDigit). - self deny: ("" isDigit). + self assert: "123" isDigit + self deny: "12a" isDigit + self deny: "" isDigit // isAlpha - self assert: ("hello" isAlpha). - self deny: ("hello1" isAlpha). - self deny: ("" isAlpha) + self assert: "hello" isAlpha + self deny: "hello1" isAlpha + self deny: "" isAlpha diff --git a/stdlib/test/string_operations_test.bt b/stdlib/test/string_operations_test.bt index 7762e6339..78e268c77 100644 --- a/stdlib/test/string_operations_test.bt +++ b/stdlib/test/string_operations_test.bt @@ -7,30 +7,30 @@ TestCase subclass: StringOperationsTest testAt => // 1-based grapheme access - self assert: ("hello" at: 1) equals: "h". + self assert: ("hello" at: 1) equals: "h" self assert: ("hello" at: 5) equals: "o" testCapitalize => - self assert: ("hello" capitalize) equals: "Hello". - self assert: ("HELLO" capitalize) equals: "HELLO" + self assert: "hello" capitalize equals: "Hello" + self assert: "HELLO" capitalize equals: "HELLO" testReverse => - self assert: ("hello" reverse) equals: "olleh" + self assert: "hello" reverse equals: "olleh" testIncludesSubstring => - self assert: ("hello world" includesSubstring: "world"). + self assert: ("hello world" includesSubstring: "world") self deny: ("hello" includesSubstring: "xyz") testStartsWith => - self assert: ("hello" startsWith: "hel"). + self assert: ("hello" startsWith: "hel") self deny: ("hello" startsWith: "xyz") testEndsWith => - self assert: ("hello" endsWith: "llo"). + self assert: ("hello" endsWith: "llo") self deny: ("hello" endsWith: "xyz") testIndexOf => - self assert: ("hello" indexOf: "ell") equals: 2. + self assert: ("hello" indexOf: "ell") equals: 2 self assert: ("hello" indexOf: "xyz") equals: nil testSplitOn => @@ -40,7 +40,7 @@ TestCase subclass: StringOperationsTest self assert: ("ab" repeat: 3) equals: "ababab" testAsList => - self assert: ("hi" asList) equals: #("h", "i") + self assert: "hi" asList equals: #("h", "i") testDo => // do: returns nil @@ -48,16 +48,16 @@ TestCase subclass: StringOperationsTest testCollect => // collect: - map over graphemes (returns list) - self assert: ("hi" collect: [:ch | ch uppercase]) equals: #("H", "I"). - self assert: ("abc" collect: [:ch | ch uppercase]) equals: #("A", "B", "C"). + self assert: ("hi" collect: [:ch | ch uppercase]) equals: #("H", "I") + self assert: ("abc" collect: [:ch | ch uppercase]) equals: #("A", "B", "C") // on string variables (not just literals) - s := "hello". + s := "hello" self assert: (s collect: [:ch | ch uppercase]) equals: #("H", "E", "L", "L", "O") testSelect => // select: - filter graphemes (returns string) - self assert: ("hello" select: [:ch | ch /= "l"]) equals: "heo". - self assert: ("abcd" select: [:ch | ch < "c"]) equals: "ab". + self assert: ("hello" select: [:ch | ch /= "l"]) equals: "heo" + self assert: ("abcd" select: [:ch | ch < "c"]) equals: "ab" // on string variables - s := "hello". + s := "hello" self assert: (s select: [:ch | ch > "h"]) equals: "llo" diff --git a/stdlib/test/string_quote_escape_test.bt b/stdlib/test/string_quote_escape_test.bt index 9789d0c3b..683d1f710 100644 --- a/stdlib/test/string_quote_escape_test.bt +++ b/stdlib/test/string_quote_escape_test.bt @@ -3,17 +3,17 @@ // BT-743: Tests that string literals correctly parse doubled double-quote // characters as a single embedded quote — single, middle, multiple, and -// adjacent embedded quotes. +// adjacent embedded quotes TestCase subclass: StringQuoteEscapeTest testDoubleQuoteEscaping => - self assert: """" equals: """". + self assert: """" equals: """" // Size of a 1-char string containing `"` - self assert: ("""" size) equals: 1. + self assert: """" size equals: 1 // Embedded quotes in the middle of a string - self assert: "say ""hello"" please" equals: "say ""hello"" please". + self assert: "say ""hello"" please" equals: "say ""hello"" please" // Multiple embedded quotes - self assert: "one "" two "" three" equals: "one "" two "" three". + self assert: "one "" two "" three" equals: "one "" two "" three" // String containing two double-quotes self assert: """""" equals: """""" diff --git a/stdlib/test/system_test.bt b/stdlib/test/system_test.bt index ed024a31d..4c92cdcf5 100644 --- a/stdlib/test/system_test.bt +++ b/stdlib/test/system_test.bt @@ -2,48 +2,48 @@ // SPDX-License-Identifier: Apache-2.0 // Tests the System class — getEnv:, getEnv:default:, osPlatform, osFamily, -// architecture, hostname, erlangVersion, pid, and type-error validation. +// architecture, hostname, erlangVersion, pid, and type-error validation TestCase subclass: SystemTest testSystemEnvironmentAndPlatform => - self assert: ((System getEnv: "PATH") class =:= String). + self assert: ((System getEnv: "PATH") class =:= String) // Reading a non-existent env var returns nil - self assert: (System getEnv: "BEAMTALK_TEST_NONEXISTENT_VAR_XYZ") equals: nil. + self assert: (System getEnv: "BEAMTALK_TEST_NONEXISTENT_VAR_XYZ") equals: nil // Non-existent var returns the default - self assert: (System getEnv: "BEAMTALK_TEST_NONEXISTENT_VAR_XYZ" default: "fallback") equals: "fallback". + self assert: (System getEnv: "BEAMTALK_TEST_NONEXISTENT_VAR_XYZ" default: "fallback") equals: "fallback" // Existing var returns the actual value (not the default) - self deny: ((System getEnv: "PATH" default: "nope") =:= "nope"). + self deny: ((System getEnv: "PATH" default: "nope") =:= "nope") // osPlatform returns a string - self assert: (System osPlatform class =:= String). + self assert: (System osPlatform class =:= String) // Platform is one of the known values - self assert: (#("linux", "darwin", "win32") includes: System osPlatform). + self assert: (#("linux", "darwin", "win32") includes: System osPlatform) // osFamily returns a string - self assert: (System osFamily class =:= String). + self assert: (System osFamily class =:= String) // Family is one of the known values - self assert: (#("unix", "win32") includes: System osFamily). + self assert: (#("unix", "win32") includes: System osFamily) // architecture returns a non-empty string - self assert: (System architecture class =:= String). + self assert: (System architecture class =:= String) // --- architecture --- - self assert: (System architecture length > 0). + self assert: (System architecture length > 0) // hostname returns a non-empty string - self assert: (System hostname class =:= String). + self assert: (System hostname class =:= String) // --- hostname --- - self assert: (System hostname length > 0). + self assert: (System hostname length > 0) // erlangVersion returns a non-empty string - self assert: (System erlangVersion class =:= String). + self assert: (System erlangVersion class =:= String) // --- erlangVersion --- - self assert: (System erlangVersion length > 0). + self assert: (System erlangVersion length > 0) // pid returns a positive integer - self assert: (System pid class =:= Integer). + self assert: (System pid class =:= Integer) // --- pid --- - self assert: (System pid > 0). + self assert: (System pid > 0) // getEnv: requires String argument @expect type - self should: [System getEnv: 42] raise: #type_error. + self should: [System getEnv: 42] raise: #type_error // getEnv:default: validates both arguments @expect type - self should: [System getEnv: 42 default: "fallback"] raise: #type_error. + self should: [System getEnv: 42 default: "fallback"] raise: #type_error // --- error cases --- @expect type self should: [System getEnv: "PATH" default: 42] raise: #type_error diff --git a/stdlib/test/test_case_assertion_test.bt b/stdlib/test/test_case_assertion_test.bt index e60cf5ca5..6b57516e7 100644 --- a/stdlib/test/test_case_assertion_test.bt +++ b/stdlib/test/test_case_assertion_test.bt @@ -3,59 +3,59 @@ // ADR 0014 Phase 2: Tests the TestCase framework itself — setUp/tearDown // lifecycle, assert:/deny:/assert:equals: pass cases, and that multiple -// instances can be independently created and used. +// instances can be independently created and used TestCase subclass: TestCaseAssertionTest testLifecycleAndBasicAssertions => - testCase := TestCase new. - self assert: (testCase setUp) equals: nil. - self assert: (testCase tearDown) equals: nil. + testCase := TestCase new + self assert: testCase setUp equals: nil + self assert: testCase tearDown equals: nil // Test assert: with true condition - self assert: (TestCase new assert: true) equals: nil. + self assert: (TestCase new assert: true) equals: nil // Test assert:equals: with matching values - self assert: (TestCase new assert: 3 equals: 3) equals: nil. - self assert: (TestCase new assert: "hello" equals: "hello") equals: nil. - self assert: (TestCase new assert: true equals: true) equals: nil. - self assert: (TestCase new assert: false equals: false) equals: nil. + self assert: (TestCase new assert: 3 equals: 3) equals: nil + self assert: (TestCase new assert: "hello" equals: "hello") equals: nil + self assert: (TestCase new assert: true equals: true) equals: nil + self assert: (TestCase new assert: false equals: false) equals: nil // Test assert:equals: with integers - self assert: (TestCase new assert: 42 equals: 42) equals: nil. - self assert: (TestCase new assert: 0 equals: 0) equals: nil. + self assert: (TestCase new assert: 42 equals: 42) equals: nil + self assert: (TestCase new assert: 0 equals: 0) equals: nil // Test assert:equals: with negative numbers - self assert: (TestCase new assert: -5 equals: -5) equals: nil. + self assert: (TestCase new assert: -5 equals: -5) equals: nil // Test deny: with false condition - self assert: (TestCase new deny: false) equals: nil. + self assert: (TestCase new deny: false) equals: nil // Test that TestCase is a proper Object subclass - self assert: (TestCase superclass) equals: Object. - testInstance := TestCase new. - self assert: (testInstance class) equals: TestCase. + self assert: TestCase superclass equals: Object + testInstance := TestCase new + self assert: testInstance class equals: TestCase // Test that multiple instances can be created - tc2 := TestCase new. - self assert: (tc2 class) equals: TestCase. + tc2 := TestCase new + self assert: tc2 class equals: TestCase // Test lifecycle methods can be called on different instances - tc3 := TestCase new. - self assert: (tc3 setUp) equals: nil. - self assert: (tc3 tearDown) equals: nil + tc3 := TestCase new + self assert: tc3 setUp equals: nil + self assert: tc3 tearDown equals: nil testAssertionFailureTests => // Test assert: with false condition — should raise assertion_failed - self should: [TestCase new assert: false] raise: #assertion_failed. + self should: [TestCase new assert: false] raise: #assertion_failed // Test assert:equals: with unequal values - self should: [TestCase new assert: 3 equals: 4] raise: #assertion_failed. + self should: [TestCase new assert: 3 equals: 4] raise: #assertion_failed // Test assert:equals: with different types - self should: [TestCase new assert: "hello" equals: 42] raise: #assertion_failed. + self should: [TestCase new assert: "hello" equals: 42] raise: #assertion_failed // Test deny: with true condition — should raise assertion_failed - self should: [TestCase new deny: true] raise: #assertion_failed. + self should: [TestCase new deny: true] raise: #assertion_failed // Test fail: unconditional failure self should: [TestCase new fail: "this test should fail"] raise: #assertion_failed testShouldRaiseTests => // Test should:raise: with matching error kind - self assert: (TestCase new should: [1 / 0] raise: #badarith) equals: nil. + self assert: (TestCase new should: [1 / 0] raise: #badarith) equals: nil // Test should:raise: with does_not_understand error @expect dnu - self assert: (TestCase new should: [42 nonExistentMethod] raise: #does_not_understand) equals: nil. + self assert: (TestCase new should: [42 nonExistentMethod] raise: #does_not_understand) equals: nil // Test should:raise: block completes normally (no error raised) - self should: [TestCase new should: [42] raise: #does_not_understand] raise: #assertion_failed. + self should: [TestCase new should: [42] raise: #does_not_understand] raise: #assertion_failed // Test should:raise: with wrong error kind (mismatch) self should: [TestCase new should: [1 / 0] raise: #does_not_understand] raise: #assertion_failed diff --git a/stdlib/test/test_runner_test.bt b/stdlib/test/test_runner_test.bt index e4f595673..37377b7ff 100644 --- a/stdlib/test/test_runner_test.bt +++ b/stdlib/test/test_runner_test.bt @@ -6,33 +6,33 @@ TestCase subclass: TestRunnerTest testResultTotal => - result := TestRunner run: SampleTestCase. - self assert: (result total) equals: 2 + result := TestRunner run: SampleTestCase + self assert: result total equals: 2 testResultPassed => - result := TestRunner run: SampleTestCase. - self assert: (result passed) equals: 2 + result := TestRunner run: SampleTestCase + self assert: result passed equals: 2 testResultFailed => - result := TestRunner run: SampleTestCase. - self assert: (result failed) equals: 0 + result := TestRunner run: SampleTestCase + self assert: result failed equals: 0 testResultHasPassed => - result := TestRunner run: SampleTestCase. - self assert: (result hasPassed) + result := TestRunner run: SampleTestCase + self assert: result hasPassed testResultSummary => - result := TestRunner run: SampleTestCase. + result := TestRunner run: SampleTestCase self deny: (result summary == nil) testResultDuration => - result := TestRunner run: SampleTestCase. + result := TestRunner run: SampleTestCase self assert: (result duration >= 0.0) testResultPrintString => - result := TestRunner run: SampleTestCase. + result := TestRunner run: SampleTestCase self deny: (result printString == nil) testResultFailuresEmpty => - result := TestRunner run: SampleTestCase. + result := TestRunner run: SampleTestCase self assert: (result failures == nil) equals: false diff --git a/stdlib/test/tier2_block_round_trip_test.bt b/stdlib/test/tier2_block_round_trip_test.bt index 560191129..3987f5325 100644 --- a/stdlib/test/tier2_block_round_trip_test.bt +++ b/stdlib/test/tier2_block_round_trip_test.bt @@ -1,37 +1,37 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-851/BT-852/BT-853: Tier 2 block round-trip tests (ADR 0041 Phase 1). +// BT-851/BT-852/BT-853: Tier 2 block round-trip tests (ADR 0041 Phase 1) // Verifies the stateful block calling convention works end-to-end: // a block with captured mutations is passed via self-send to a HOM, // the HOM calls `value:` with the Tier 2 protocol, and the mutation -// propagates back to the caller. +// propagates back to the caller TestCase subclass: Tier2BlockRoundTripTest - // BT-851: Basic round-trip: block mutates count, HOM is last expression. + // BT-851: Basic round-trip: block mutates count, HOM is last expression testStatefulBlockViaHOM => - actor := Tier2BlockTestActor spawn. - self assert: (actor testRoundTrip) equals: 5 + actor := Tier2BlockTestActor spawn + self assert: actor testRoundTrip equals: 5 - // BT-853: Non-last Tier 2 value: call in HOM body. + // BT-853: Non-last Tier 2 value: call in HOM body // The block mutates count (via StateAcc), the HOM continues and returns 99, - // but the state update (count=3) must still propagate back to the caller. + // but the state update (count=3) must still propagate back to the caller testNonLastTier2ValueCallPropagates => - actor := Tier2BlockTestActor spawn. - self assert: (actor testNonLastTier2ValueCall) equals: 3 + actor := Tier2BlockTestActor spawn + self assert: actor testNonLastTier2ValueCall equals: 3 - // BT-853: Tier 2 block result captured in local variable in HOM body. - // Block returns count (=4 after mutation), HOM adds 10, returns 14. + // BT-853: Tier 2 block result captured in local variable in HOM body + // Block returns count (=4 after mutation), HOM adds 10, returns 14 testTier2ResultCaptureInHOM => - actor := Tier2BlockTestActor spawn. - self assert: (actor testTier2ResultCapture) equals: 14 + actor := Tier2BlockTestActor spawn + self assert: actor testTier2ResultCapture equals: 14 - // BT-852/BT-853: Two sequential Tier 2 assignment calls in a HOM. + // BT-852/BT-853: Two sequential Tier 2 assignment calls in a HOM // Verifies new_state is computed AFTER expression_doc to avoid duplicate - // Core Erlang state bindings across multiple Tier 2 assignments. - // Block1: increments count by x, returns count. Block2: multiplies count by x. - // testTwoBlocks: count starts at 0, after block1(2): count=2, r1=2; after block2(r1=2): count=4, r2=4. + // Core Erlang state bindings across multiple Tier 2 assignments + // Block1: increments count by x, returns count. Block2: multiplies count by x + // testTwoBlocks: count starts at 0, after block1(2): count=2, r1=2; after block2(r1=2): count=4, r2=4 testTwoSequentialTier2Assignments => - actor := Tier2BlockTestActor spawn. - self assert: (actor testTwoBlocks) equals: 4 + actor := Tier2BlockTestActor spawn + self assert: actor testTwoBlocks equals: 4 diff --git a/stdlib/test/times_repeat_simple_test.bt b/stdlib/test/times_repeat_simple_test.bt index 3a235b8f5..25e1ac659 100644 --- a/stdlib/test/times_repeat_simple_test.bt +++ b/stdlib/test/times_repeat_simple_test.bt @@ -1,32 +1,32 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// Regression tests for timesRepeat: simple path. +// Regression tests for timesRepeat: simple path // // The simple path (no local mutations, no self-sends, no field writes) // previously generated `let _ = body_code in ...` without ever applying the -// body closure, so the block body silently never executed. +// body closure, so the block body silently never executed // -// The mutation path (local writes / self-sends) was unaffected. +// The mutation path (local writes / self-sends) was unaffected TestCase subclass: TimesRepeatSimpleTest testZeroTimesIsNoOp => - c := Counter spawn. - 0 timesRepeat: [c increment]. - self assert: (c getValue) equals: 0 + c := Counter spawn + 0 timesRepeat: [c increment] + self assert: c getValue equals: 0 testOneTimeRunsBlockOnce => - c := Counter spawn. - 1 timesRepeat: [c increment]. - self assert: (c getValue) equals: 1 + c := Counter spawn + 1 timesRepeat: [c increment] + self assert: c getValue equals: 1 testThreeTimesRunsBlockThreeTimes => - c := Counter spawn. - 3 timesRepeat: [c increment]. - self assert: (c getValue) equals: 3 + c := Counter spawn + 3 timesRepeat: [c increment] + self assert: c getValue equals: 3 testFiveTimesRunsBlockFiveTimes => - c := Counter spawn. - 5 timesRepeat: [c increment]. - self assert: (c getValue) equals: 5 + c := Counter spawn + 5 timesRepeat: [c increment] + self assert: c getValue equals: 5 diff --git a/stdlib/test/tuple_test.bt b/stdlib/test/tuple_test.bt index 4d65da1bd..a70536be7 100644 --- a/stdlib/test/tuple_test.bt +++ b/stdlib/test/tuple_test.bt @@ -2,64 +2,64 @@ // SPDX-License-Identifier: Apache-2.0 // BT-417: Tests the Tuple primitive — creation, display, size, unwrap/unwrapOr:/ -// unwrapOrElse: on ok/error/other tuples, and that unsupported constructors raise. +// unwrapOrElse: on ok/error/other tuples, and that unsupported constructors raise TestCase subclass: TupleTest testCreation => // Tuple new returns an empty tuple - self assert: ((Tuple new) class) equals: Tuple. + self assert: (Tuple new) class equals: Tuple // Tuple new: is not supported (no meaningful init-from-map) self should: [Tuple new: #{#a => 1}] raise: #instantiation_error testDisplay => // Tuple printString shows tuple format - self assert: ((Tuple new) printString size) equals: 2 + self assert: (Tuple new) printString size equals: 2 testSize => // Empty tuple has size 0 - self assert: ((Tuple new) size) equals: 0 + self assert: (Tuple new) size equals: 0 testUnwrapOkTuple => // {ok, 42} unwrap returns 42 - okTuple := Erlang erlang list_to_tuple: #(#ok, 42). - self assert: okTuple unwrap equals: 42. + okTuple := Erlang erlang list_to_tuple: #(#ok, 42) + self assert: okTuple unwrap equals: 42 // {ok, "hello"} unwrap returns the value - okStr := Erlang erlang list_to_tuple: #(#ok, "hello"). + okStr := Erlang erlang list_to_tuple: #(#ok, "hello") self assert: okStr unwrap equals: "hello" testUnwrapErrorTupleRaises => // {error, 'oops'} unwrap raises user_error with reason in message - errTuple := Erlang erlang list_to_tuple: #(#error, #oops). + errTuple := Erlang erlang list_to_tuple: #(#error, #oops) self should: [errTuple unwrap] raise: #user_error testUnwrapOtherTupleRaises => // {other, 'x'} unwrap raises user_error with "unwrap requires..." message - otherTuple := Erlang erlang list_to_tuple: #(#other, #x). + otherTuple := Erlang erlang list_to_tuple: #(#other, #x) self should: [otherTuple unwrap] raise: #user_error testUnwrapOrOkReturnsValue => // {ok, 99} unwrapOr: 0 returns 99 - okTuple := Erlang erlang list_to_tuple: #(#ok, 99). + okTuple := Erlang erlang list_to_tuple: #(#ok, 99) self assert: (okTuple unwrapOr: 0) equals: 99 testUnwrapOrErrorReturnsDefault => // {error, 'fail'} unwrapOr: 0 returns 0 - errTuple := Erlang erlang list_to_tuple: #(#error, #fail). - self assert: (errTuple unwrapOr: 0) equals: 0. + errTuple := Erlang erlang list_to_tuple: #(#error, #fail) + self assert: (errTuple unwrapOr: 0) equals: 0 // {other, 'x'} unwrapOr: 99 returns 99 - otherTuple := Erlang erlang list_to_tuple: #(#other, #x). + otherTuple := Erlang erlang list_to_tuple: #(#other, #x) self assert: (otherTuple unwrapOr: 99) equals: 99 testUnwrapOrElseOkReturnsValue => // {ok, 7} unwrapOrElse: [0] returns 7 - okTuple := Erlang erlang list_to_tuple: #(#ok, 7). + okTuple := Erlang erlang list_to_tuple: #(#ok, 7) self assert: (okTuple unwrapOrElse: [0]) equals: 7 testUnwrapOrElseErrorEvaluatesBlock => // {error, _} unwrapOrElse: [...] evaluates block - errTuple := Erlang erlang list_to_tuple: #(#error, #fail). - self assert: (errTuple unwrapOrElse: [42]) equals: 42. + errTuple := Erlang erlang list_to_tuple: #(#error, #fail) + self assert: (errTuple unwrapOrElse: [42]) equals: 42 // {other, _} unwrapOrElse: [...] evaluates block - otherTuple := Erlang erlang list_to_tuple: #(#other, #x). + otherTuple := Erlang erlang list_to_tuple: #(#other, #x) self assert: (otherTuple unwrapOrElse: [99]) equals: 99 diff --git a/stdlib/test/typed_classes_test.bt b/stdlib/test/typed_classes_test.bt index e161e478f..19e7d4ab7 100644 --- a/stdlib/test/typed_classes_test.bt +++ b/stdlib/test/typed_classes_test.bt @@ -8,40 +8,40 @@ TestCase subclass: TypedClassesTest testAnnotationSyntaxVariations => // Test various type annotation syntax forms - math := TypedMath new. - self assert: (math identity: 4) equals: 4. - self assert: (math identityWithSpace: 5) equals: 5. - self assert: (math sum: 2 with: 3) equals: 5. - self assert: (math maybeName: true) equals: 1. - self assert: (math maybeName: false) equals: "none". + math := TypedMath new + self assert: (math identity: 4) equals: 4 + self assert: (math identityWithSpace: 5) equals: 5 + self assert: (math sum: 2 with: 3) equals: 5 + self assert: (math maybeName: true) equals: 1 + self assert: (math maybeName: false) equals: "none" // asType: cast self assert: ((41 asType: Integer) + 1) equals: 42 testActorBehavior => // Test actor instances with typed methods - counter := TypedCounter spawn. - self assert: (counter increment) equals: 1. - self assert: (counter add: 5) equals: 6. - self assert: (counter current) equals: 6. - account := TypedAccount spawn. - self assert: (account setOwner: "Alice") equals: "Alice". - self assert: (account deposit: 10) equals: 10. - self assert: (account withdraw: 3) equals: 7. - self assert: (account balance) equals: 7. - self assert: (account getOwner) equals: "Alice" + counter := TypedCounter spawn + self assert: counter increment equals: 1 + self assert: (counter add: 5) equals: 6 + self assert: counter current equals: 6 + account := TypedAccount spawn + self assert: (account setOwner: "Alice") equals: "Alice" + self assert: (account deposit: 10) equals: 10 + self assert: (account withdraw: 3) equals: 7 + self assert: account balance equals: 7 + self assert: account getOwner equals: "Alice" testNoFalsePositivesRegression => // Regression tests for permissive typing paths - ledger := TypedLedger spawn. - self assert: (ledger addOne) equals: 1. - self assert: (ledger addOne) equals: 2. - untyped := UntypedContainer spawn. - self assert: (untyped setItem: "hello") equals: "hello". - self assert: (untyped setItem: 99) equals: 99. - typed := TypedAccount spawn. - self assert: (typed deposit: 20) equals: 20. - self assert: (typed deposit: (5 asType: Integer)) equals: 25. - self assert: (typed balance) equals: 25. - math2 := TypedMath new. - self assert: (math2 maybeName: false) equals: "none". + ledger := TypedLedger spawn + self assert: ledger addOne equals: 1 + self assert: ledger addOne equals: 2 + untyped := UntypedContainer spawn + self assert: (untyped setItem: "hello") equals: "hello" + self assert: (untyped setItem: 99) equals: 99 + typed := TypedAccount spawn + self assert: (typed deposit: 20) equals: 20 + self assert: (typed deposit: (5 asType: Integer)) equals: 25 + self assert: typed balance equals: 25 + math2 := TypedMath new + self assert: (math2 maybeName: false) equals: "none" self assert: (math2 maybeName: true) equals: 1 diff --git a/stdlib/test/unary_messages_test.bt b/stdlib/test/unary_messages_test.bt index 25010df32..d31a9ff85 100644 --- a/stdlib/test/unary_messages_test.bt +++ b/stdlib/test/unary_messages_test.bt @@ -2,68 +2,68 @@ // SPDX-License-Identifier: Apache-2.0 // Tests unary message sends on blocks (value), integers (negated, abs, isZero, -// isEven, isOdd), strings (length, isEmpty), and booleans (not). +// isEven, isOdd), strings (length, isEmpty), and booleans (not) TestCase subclass: UnaryMessagesTest testBlockUnaryMessages => - self assert: ([42] value) equals: 42. + self assert: [42] value equals: 42 // Block value with computed body - self assert: ([10 + 5] value) equals: 15. + self assert: [10 + 5] value equals: 15 // Nested block value - self assert: ([[3] value + 2] value) equals: 5 + self assert: [[3] value + 2] value equals: 5 testIntegerUnaryMethods => // negated - returns the negative of the receiver - self assert: (5 negated) equals: -5. + self assert: 5 negated equals: -5 // negated of negative number - self assert: (-3 negated) equals: 3. + self assert: -3 negated equals: 3 // negated of zero - self assert: (0 negated) equals: 0. + self assert: 0 negated equals: 0 // abs - absolute value of positive number - self assert: (5 abs) equals: 5. + self assert: 5 abs equals: 5 // abs - absolute value of negative number - self assert: (-5 abs) equals: 5. + self assert: -5 abs equals: 5 // abs of zero - self assert: (0 abs) equals: 0. + self assert: 0 abs equals: 0 // isZero - true for zero - self assert: (0 isZero). + self assert: 0 isZero // isZero - false for non-zero - self deny: (5 isZero). + self deny: 5 isZero // isZero - false for negative - self deny: (-3 isZero). + self deny: -3 isZero // isEven - true for even numbers - self assert: (4 isEven). + self assert: 4 isEven // isEven - false for odd numbers - self deny: (5 isEven). + self deny: 5 isEven // isEven - true for zero (0 is even) - self assert: (0 isEven). + self assert: 0 isEven // isEven - true for negative even - self assert: (-6 isEven). + self assert: -6 isEven // isOdd - true for odd numbers - self assert: (7 isOdd). + self assert: 7 isOdd // isOdd - false for even numbers - self deny: (8 isOdd). + self deny: 8 isOdd // isOdd - false for zero - self deny: (0 isOdd). + self deny: 0 isOdd // isOdd - true for negative odd - self assert: (-5 isOdd) + self assert: -5 isOdd testStringUnaryMethods => // length - count graphemes in string - self assert: ("hello" length) equals: 5. + self assert: "hello" length equals: 5 // length - empty string - self assert: ("" length) equals: 0. + self assert: "" length equals: 0 // length - single character - self assert: ("a" length) equals: 1. + self assert: "a" length equals: 1 // isEmpty - true for empty string - self assert: ("" isEmpty). + self assert: "" isEmpty // isEmpty - false for non-empty string - self deny: ("hello" isEmpty). + self deny: "hello" isEmpty // isEmpty - false for single character - self deny: ("x" isEmpty) + self deny: "x" isEmpty testBooleanUnaryMethods => // not - covered in booleans.bt but verify here too - self deny: (true not). - self assert: (false not) + self deny: true not + self assert: false not diff --git a/stdlib/test/unicode_test.bt b/stdlib/test/unicode_test.bt index dff3f69fd..2941a6450 100644 --- a/stdlib/test/unicode_test.bt +++ b/stdlib/test/unicode_test.bt @@ -3,27 +3,27 @@ // BT-388: Tests that string operations are Unicode-aware (grapheme clusters) — // equality with CJK and emoji, size in graphemes, at: indexing, reverse, and -// includesSubstring: for multi-byte characters. +// includesSubstring: for multi-byte characters TestCase subclass: UnicodeTest testUnicodeStringOperations => - self assert: "世界" equals: "世界". + self assert: "世界" equals: "世界" // Emoji (4-byte UTF-8) - self assert: "🌍" equals: "🌍". + self assert: "🌍" equals: "🌍" // Mixed ASCII and Unicode - self assert: "Hello 世界 🌍" equals: "Hello 世界 🌍". + self assert: "Hello 世界 🌍" equals: "Hello 世界 🌍" // Japanese - self assert: "こんにちは" equals: "こんにちは". + self assert: "こんにちは" equals: "こんにちは" // Korean - self assert: "안녕하세요" equals: "안녕하세요". - self assert: ("世界" size) equals: 2. - self assert: ("🌍" size) equals: 1. - self assert: ("Hello 世界 🌍" size) equals: 10. - self assert: "世界" =:= "世界". - self deny: "世界" =:= "hello". - self assert: ("Hello 世界" at: 7) equals: "世". - self assert: ("Hello 世界" at: 8) equals: "界". - self assert: ("世界" reverse) equals: "界世". - self assert: ("Hello 世界" includesSubstring: "世"). + self assert: "안녕하세요" equals: "안녕하세요" + self assert: "世界" size equals: 2 + self assert: "🌍" size equals: 1 + self assert: "Hello 世界 🌍" size equals: 10 + self assert: "世界" =:= "世界" + self deny: "世界" =:= "hello" + self assert: ("Hello 世界" at: 7) equals: "世" + self assert: ("Hello 世界" at: 8) equals: "界" + self assert: "世界" reverse equals: "界世" + self assert: ("Hello 世界" includesSubstring: "世") self deny: ("Hello 世界" includesSubstring: "🌍") diff --git a/stdlib/test/value_object_self_send_test.bt b/stdlib/test/value_object_self_send_test.bt index 7ed0a8e64..ea2fde443 100644 --- a/stdlib/test/value_object_self_send_test.bt +++ b/stdlib/test/value_object_self_send_test.bt @@ -2,21 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 // BT-892: Tests that inject:into:, do:, and collect: with self sends -// work correctly in value-object methods (no State variable). +// work correctly in value-object methods (no State variable) TestCase subclass: ValueObjectSelfSendTest testInjectIntoWithSelfSend => - f := StringFormatter new: #{#prefix => "<", #suffix => ">"}. - result := f joinFormatted: #("a", "b", "c"). + f := StringFormatter new: #{#prefix => "<", #suffix => ">"} + result := f joinFormatted: #("a", "b", "c") self assert: result equals: "[a][b][c]" testCollectWithSelfSend => - f := StringFormatter new. - result := f collectFormatted: #("x", "y"). + f := StringFormatter new + result := f collectFormatted: #("x", "y") self assert: result equals: #("[x]", "[y]") testInjectIntoWithSelfSendEmptyList => - f := StringFormatter new. - result := f joinFormatted: #(). + f := StringFormatter new + result := f joinFormatted: #() self assert: result equals: "" diff --git a/stdlib/test/value_object_test.bt b/stdlib/test/value_object_test.bt index c682a07a5..37e95c025 100644 --- a/stdlib/test/value_object_test.bt +++ b/stdlib/test/value_object_test.bt @@ -3,7 +3,7 @@ // BT-926: Comprehensive BUnit tests for Value subclass: construction forms, // with*: functional setters, immutability enforcement, value equality, -// and value objects in collections. +// and value objects in collections // // Fixture: stdlib/test/fixtures/value_point.bt (ValuePoint — x, y slots) // @@ -20,31 +20,31 @@ TestCase subclass: ValueObjectTest // new — default-initialises all slots to their declared defaults testNewDefaultValues => - p := ValuePoint new. - self assert: p x equals: 0. + p := ValuePoint new + self assert: p x equals: 0 self assert: p y equals: 0 // new: — initialises from a map; missing keys keep defaults testNewWithMap => - p := ValuePoint new: #{#x => 5, #y => 10}. - self assert: p x equals: 5. + p := ValuePoint new: #{#x => 5, #y => 10} + self assert: p x equals: 5 self assert: p y equals: 10 testNewWithPartialMap => - p := ValuePoint new: #{#x => 7}. - self assert: p x equals: 7. + p := ValuePoint new: #{#x => 7} + self assert: p x equals: 7 // y keeps its declared default self assert: p y equals: 0 // Keyword constructor — auto-generated from slot names testKeywordConstructor => - p := ValuePoint x: 3 y: 4. - self assert: p x equals: 3. + p := ValuePoint x: 3 y: 4 + self assert: p x equals: 3 self assert: p y equals: 4 testKeywordConstructorZeroValues => - p := ValuePoint x: 0 y: 0. - self assert: p x equals: 0. + p := ValuePoint x: 0 y: 0 + self assert: p x equals: 0 self assert: p y equals: 0 // ========================================================================= @@ -53,42 +53,42 @@ TestCase subclass: ValueObjectTest // with*: returns a new instance with one field changed testWithXReturnsNewInstance => - p := ValuePoint x: 1 y: 2. - p2 := p withX: 99. - self assert: p2 x equals: 99. + p := ValuePoint x: 1 y: 2 + p2 := p withX: 99 + self assert: p2 x equals: 99 // y is preserved from the original self assert: p2 y equals: 2 testWithYReturnsNewInstance => - p := ValuePoint x: 1 y: 2. - p2 := p withY: 99. + p := ValuePoint x: 1 y: 2 + p2 := p withY: 99 // x is preserved from the original - self assert: p2 x equals: 1. + self assert: p2 x equals: 1 self assert: p2 y equals: 99 // Original object is unchanged after with*: testWithSetterDoesNotMutateOriginal => - p := ValuePoint x: 10 y: 20. - p withX: 999. - self assert: p x equals: 10. + p := ValuePoint x: 10 y: 20 + p withX: 999 + self assert: p x equals: 10 self assert: p y equals: 20 // Chaining with*: calls produces cumulative result testChainedWithSetters => - p := ValuePoint new. - p2 := (p withX: 5) withY: 7. - self assert: p2 x equals: 5. + p := ValuePoint new + p2 := (p withX: 5) withY: 7 + self assert: p2 x equals: 5 self assert: p2 y equals: 7 // with*: preserves class identity testWithSetterPreservesClass => - p := ValuePoint x: 1 y: 2. - p2 := p withX: 99. + p := ValuePoint x: 1 y: 2 + p2 := p withX: 99 self assert: p2 class equals: ValuePoint // User-defined methods coexist with auto-generated ones testUserDefinedMethodWithAutoGetters => - p := ValuePoint x: 3 y: 4. + p := ValuePoint x: 3 y: 4 self assert: p distanceSquared equals: 25 // ========================================================================= @@ -97,11 +97,11 @@ TestCase subclass: ValueObjectTest // fieldAt:put: raises immutable_value — direct slot mutation is rejected testFieldAtPutRaisesImmutableValue => - p := ValuePoint x: 1 y: 2. + p := ValuePoint x: 1 y: 2 self should: [p fieldAt: #x put: 99] raise: #immutable_value testFieldAtPutRaisesForAnySlot => - p := ValuePoint x: 0 y: 0. + p := ValuePoint x: 0 y: 0 self should: [p fieldAt: #y put: 42] raise: #immutable_value // self.slot := is rejected at compile time (tested in E2E via @load-error) @@ -112,35 +112,35 @@ TestCase subclass: ValueObjectTest // Two value objects with identical field values are equal (structural equality) testTwoPointsWithSameFieldsAreEqual => - p1 := ValuePoint x: 3 y: 4. - p2 := ValuePoint x: 3 y: 4. + p1 := ValuePoint x: 3 y: 4 + p2 := ValuePoint x: 3 y: 4 self assert: (p1 == p2) // Two value objects with different field values are not equal testTwoPointsWithDifferentFieldsAreNotEqual => - p1 := ValuePoint x: 1 y: 2. - p2 := ValuePoint x: 9 y: 9. + p1 := ValuePoint x: 1 y: 2 + p2 := ValuePoint x: 9 y: 9 self deny: (p1 == p2) // Inequality operator agrees with equality testInequalityOperator => - p1 := ValuePoint x: 1 y: 2. - p2 := ValuePoint x: 1 y: 2. - p3 := ValuePoint x: 5 y: 6. - self deny: (p1 /= p2). + p1 := ValuePoint x: 1 y: 2 + p2 := ValuePoint x: 1 y: 2 + p3 := ValuePoint x: 5 y: 6 + self deny: (p1 /= p2) self assert: (p1 /= p3) // with*: result equals a fresh object with the same values testWithSetterResultEqualsManualConstruct => - p := ValuePoint x: 1 y: 2. - p2 := p withX: 10. - p3 := ValuePoint x: 10 y: 2. + p := ValuePoint x: 1 y: 2 + p2 := p withX: 10 + p3 := ValuePoint x: 10 y: 2 self assert: (p2 == p3) // Default (new) equals keyword constructor with zeros testNewEqualsKeywordConstructorWithDefaults => - p1 := ValuePoint new. - p2 := ValuePoint x: 0 y: 0. + p1 := ValuePoint new + p2 := ValuePoint x: 0 y: 0 self assert: (p1 == p2) // ========================================================================= @@ -149,38 +149,38 @@ TestCase subclass: ValueObjectTest // collect: transforms a collection of value objects testCollectOnValueObjects => - points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 2 y: 2), (ValuePoint x: 3 y: 3)). - xs := points collect: [:p | p x]. + points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 2 y: 2), (ValuePoint x: 3 y: 3)) + xs := points collect: [:p | p x] self assert: xs equals: #(1, 2, 3) // collect: can produce new value objects from old ones testCollectProducesNewValueObjects => - points := #((ValuePoint x: 1 y: 10), (ValuePoint x: 2 y: 20)). - doubled := points collect: [:p | p withX: p x * 2]. - self assert: (doubled at: 1) x equals: 2. + points := #((ValuePoint x: 1 y: 10), (ValuePoint x: 2 y: 20)) + doubled := points collect: [:p | p withX: p x * 2] + self assert: (doubled at: 1) x equals: 2 self assert: (doubled at: 2) x equals: 4 // select: filters a collection of value objects by a predicate testSelectOnValueObjects => - points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 5 y: 5), (ValuePoint x: 2 y: 2)). - big := points select: [:p | p x > 2]. - self assert: big size equals: 1. + points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 5 y: 5), (ValuePoint x: 2 y: 2)) + big := points select: [:p | p x > 2] + self assert: big size equals: 1 self assert: (big at: 1) x equals: 5 // inject:into: folds over a collection of value objects testInjectIntoOnValueObjects => - points := #((ValuePoint x: 1 y: 0), (ValuePoint x: 2 y: 0), (ValuePoint x: 3 y: 0)). - total := points inject: 0 into: [:sum :p | sum + p x]. + points := #((ValuePoint x: 1 y: 0), (ValuePoint x: 2 y: 0), (ValuePoint x: 3 y: 0)) + total := points inject: 0 into: [:sum :p | sum + p x] self assert: total equals: 6 // Size of a collection of value objects testCollectionSizeWithValueObjects => - points := #((ValuePoint x: 0 y: 0), (ValuePoint x: 1 y: 1)). + points := #((ValuePoint x: 0 y: 0), (ValuePoint x: 1 y: 1)) self assert: points size equals: 2 // Value objects can be used as elements in detect: testDetectOnValueObjects => - points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 7 y: 3), (ValuePoint x: 2 y: 2)). - found := points detect: [:p | p x == 7]. - self assert: found x equals: 7. + points := #((ValuePoint x: 1 y: 1), (ValuePoint x: 7 y: 3), (ValuePoint x: 2 y: 2)) + found := points detect: [:p | p x == 7] + self assert: found x equals: 7 self assert: found y equals: 3 diff --git a/stdlib/test/value_subclass_test.bt b/stdlib/test/value_subclass_test.bt index 62082eb45..019eb7324 100644 --- a/stdlib/test/value_subclass_test.bt +++ b/stdlib/test/value_subclass_test.bt @@ -1,76 +1,76 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-923: End-to-end tests for `Value subclass:` auto-generated slot methods. -// Exercises: getters, with*: functional setters, keyword constructor, new, new:. +// BT-923: End-to-end tests for `Value subclass:` auto-generated slot methods +// Exercises: getters, with*: functional setters, keyword constructor, new, new: // BT-924: Reflection tests — fieldAt: reads slots, fieldNames returns slot names, -// fieldAt:put: raises immutable_value. +// fieldAt:put: raises immutable_value TestCase subclass: ValueSubclassTest testAutoGetter => - p := ValuePoint new. + p := ValuePoint new // Auto-generated getter returns the default value - self assert: p x equals: 0. + self assert: p x equals: 0 self assert: p y equals: 0 testAutoGetterAfterNew => - p := ValuePoint new: #{#x => 3, #y => 4}. - self assert: p x equals: 3. + p := ValuePoint new: #{#x => 3, #y => 4} + self assert: p x equals: 3 self assert: p y equals: 4 testAutoSetterReturnsNewInstance => - p := ValuePoint new: #{#x => 1, #y => 2}. - p2 := p withX: 10. + p := ValuePoint new: #{#x => 1, #y => 2} + p2 := p withX: 10 // Original unchanged - self assert: p x equals: 1. + self assert: p x equals: 1 // New instance has updated x, same y - self assert: p2 x equals: 10. + self assert: p2 x equals: 10 self assert: p2 y equals: 2 testChainedWithSetters => - p := ValuePoint new. - p2 := (p withX: 5) withY: 7. - self assert: p2 x equals: 5. + p := ValuePoint new + p2 := (p withX: 5) withY: 7 + self assert: p2 x equals: 5 self assert: p2 y equals: 7 testKeywordConstructor => - p := ValuePoint x: 3 y: 4. - self assert: p x equals: 3. + p := ValuePoint x: 3 y: 4 + self assert: p x equals: 3 self assert: p y equals: 4 testUserDefinedMethodCoexists => - p := ValuePoint x: 3 y: 4. + p := ValuePoint x: 3 y: 4 self assert: p distanceSquared equals: 25 testWithSetterPreservesClass => - p := ValuePoint x: 1 y: 2. - p2 := p withX: 99. + p := ValuePoint x: 1 y: 2 + p2 := p withX: 99 self assert: p2 class equals: ValuePoint testNewDefaultsAllZero => - p := ValuePoint new. - self assert: p x equals: 0. + p := ValuePoint new + self assert: p x equals: 0 self assert: p y equals: 0 // BT-924: fieldAt: reads slot values from value objects testFieldAtReadsSlot => - p := ValuePoint x: 3 y: 4. - self assert: (p fieldAt: #x) equals: 3. - self assert: (p fieldAt: #y) equals: 4. + p := ValuePoint x: 3 y: 4 + self assert: (p fieldAt: #x) equals: 3 + self assert: (p fieldAt: #y) equals: 4 // Non-existent field returns nil (Smalltalk-80 semantics) self assert: (p fieldAt: #z) equals: nil // BT-924: fieldNames returns the slot names of the value object testFieldNamesReturnsSlotCount => - p := ValuePoint x: 1 y: 2. - names := p fieldNames. + p := ValuePoint x: 1 y: 2 + names := p fieldNames // ValuePoint has two slots: x and y self assert: names size equals: 2 - // BT-924: fieldAt:put: raises immutable_value at runtime — use with*: methods instead. - // Compile-time rejection of direct slot mutation (self.slot :=) is a separate feature. + // BT-924: fieldAt:put: raises immutable_value at runtime — use with*: methods instead + // Compile-time rejection of direct slot mutation (self.slot :=) is a separate feature testFieldAtPutRaisesImmutableValue => - p := ValuePoint x: 1 y: 2. + p := ValuePoint x: 1 y: 2 self should: [p fieldAt: #x put: 99] raise: #immutable_value diff --git a/stdlib/test/value_type_local_vars_test.bt b/stdlib/test/value_type_local_vars_test.bt index bfa54ee46..4202e1b75 100644 --- a/stdlib/test/value_type_local_vars_test.bt +++ b/stdlib/test/value_type_local_vars_test.bt @@ -3,19 +3,19 @@ // BT-744: Tests that Object subclass (non-actor) method bodies can use local // variables — single local, multiple locals in sequence, local as message -// receiver, and local from a conditional branch. +// receiver, and local from a conditional branch TestCase subclass: ValueTypeLocalVarsTest testLocalVariablesInValueTypeMethods => - c := Calculator new. + c := Calculator new // Single local variable: assign and read back - self assert: (c double: 7) equals: 14. + self assert: (c double: 7) equals: 14 // Multiple locals in sequence: each must be visible to subsequent expressions - self assert: (c compute: 3) equals: 16. + self assert: (c compute: 3) equals: 16 // Local variable used as receiver of a message send - self assert: (c addAndNegate: 4 to: 6) equals: -10. + self assert: (c addAndNegate: 4 to: 6) equals: -10 // Local variable from a conditional - self assert: (c absVal: -5) equals: 5. + self assert: (c absVal: -5) equals: 5 self assert: (c absVal: 3) equals: 3 diff --git a/stdlib/test/value_type_multi_expr_test.bt b/stdlib/test/value_type_multi_expr_test.bt index f8e3c8732..a319c24fa 100644 --- a/stdlib/test/value_type_multi_expr_test.bt +++ b/stdlib/test/value_type_multi_expr_test.bt @@ -7,15 +7,15 @@ TestCase subclass: ValueTypeMultiExprTest testTwoExpressionMethod => - calc := MultiExprCalc new. - self assert: (calc doubleAfterAdd: 5) equals: 10. - self assert: (calc doubleAfterAdd: 0) equals: 0. + calc := MultiExprCalc new + self assert: (calc doubleAfterAdd: 5) equals: 10 + self assert: (calc doubleAfterAdd: 0) equals: 0 self assert: (calc doubleAfterAdd: -3) equals: -6 testThreeExpressionMethod => - calc := MultiExprCalc new. - // Only the last expression (a * b) is returned. - self assert: (calc compute: 3 with: 4) equals: 12. - // First two expressions execute but results are discarded. - self assert: (calc compute: 5 with: 0) equals: 0. + calc := MultiExprCalc new + // Only the last expression (a * b) is returned + self assert: (calc compute: 3 with: 4) equals: 12 + // First two expressions execute but results are discarded + self assert: (calc compute: 5 with: 0) equals: 0 self assert: (calc compute: -2 with: 3) equals: -6 diff --git a/stdlib/test/value_type_non_local_return_test.bt b/stdlib/test/value_type_non_local_return_test.bt index 0e282248b..bd1761323 100644 --- a/stdlib/test/value_type_non_local_return_test.bt +++ b/stdlib/test/value_type_non_local_return_test.bt @@ -3,23 +3,23 @@ // BT-754: Tests non-local return (^) inside block arguments in Object subclass // (non-actor) methods — empty/non-empty arrays, classify, check, double, and -// on:do: with NLR. +// on:do: with NLR TestCase subclass: ValueTypeNonLocalReturnTest testNonLocalReturnInValueTypeMethods => - self assert: (NlrReturnTest new test: #()) equals: "empty". - self assert: (NlrReturnTest new test: #(1)) equals: "not empty". - self assert: (NlrFoo new classify: 5) equals: "positive". - self assert: (NlrFoo new classify: -1) equals: "non-positive". - self assert: (NlrFoo new classify: 0) equals: "non-positive". - self assert: (NlrBar new check: #()) equals: "empty". - self assert: (NlrBar new check: #(1)) equals: "not empty". - self assert: (NlrBaz new double: 5) equals: 10. - self assert: (NlrSkipper new test: #()) equals: "early". - self assert: (NlrSkipper new test: #(1, 2, 3)) equals: "middle". - self assert: (NlrDoubler new test: 5) equals: 10. - self assert: (NlrDoubler new test: -1) equals: 0. - self assert: (NlrOnDo new test: #()) equals: "early". + self assert: (NlrReturnTest new test: #()) equals: "empty" + self assert: (NlrReturnTest new test: #(1)) equals: "not empty" + self assert: (NlrFoo new classify: 5) equals: "positive" + self assert: (NlrFoo new classify: -1) equals: "non-positive" + self assert: (NlrFoo new classify: 0) equals: "non-positive" + self assert: (NlrBar new check: #()) equals: "empty" + self assert: (NlrBar new check: #(1)) equals: "not empty" + self assert: (NlrBaz new double: 5) equals: 10 + self assert: (NlrSkipper new test: #()) equals: "early" + self assert: (NlrSkipper new test: #(1, 2, 3)) equals: "middle" + self assert: (NlrDoubler new test: 5) equals: 10 + self assert: (NlrDoubler new test: -1) equals: 0 + self assert: (NlrOnDo new test: #()) equals: "early" self assert: (NlrOnDo new test: #(1)) equals: "not early" diff --git a/stdlib/test/value_type_update_test.bt b/stdlib/test/value_type_update_test.bt index 9f3fc3f03..24f30162b 100644 --- a/stdlib/test/value_type_update_test.bt +++ b/stdlib/test/value_type_update_test.bt @@ -1,36 +1,36 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-833: Tests for immutable-update semantics on value types. +// BT-833: Tests for immutable-update semantics on value types // Field assignments use Self-threading (Self -> Self1 -> Self{N}) so that -// `self` in expression position resolves to the latest snapshot. +// `self` in expression position resolves to the latest snapshot TestCase subclass: ValueTypeUpdateTest testSingleFieldUpdate => - b := ValueTypeBuilder new. - b2 := b withX: 42. + b := ValueTypeBuilder new + b2 := b withX: 42 // The returned object has the updated field - self assert: (b2 getX) equals: 42. + self assert: b2 getX equals: 42 // The original object is unchanged (immutable semantics) - self assert: (b getX) equals: 0 + self assert: b getX equals: 0 testChainedSetters => - b := ValueTypeBuilder new. - b2 := (b withX: 10) withY: 20. - self assert: (b2 getX) equals: 10. - self assert: (b2 getY) equals: 20 + b := ValueTypeBuilder new + b2 := (b withX: 10) withY: 20 + self assert: b2 getX equals: 10 + self assert: b2 getY equals: 20 testMultipleFieldAssignmentsInOneMethod => - b := ValueTypeBuilder new. - b2 := b setX: 5 y: 7. - self assert: (b2 getX) equals: 5. - self assert: (b2 getY) equals: 7 + b := ValueTypeBuilder new + b2 := b setX: 5 y: 7 + self assert: b2 getX equals: 5 + self assert: b2 getY equals: 7 testReadThenWrite => - b := ValueTypeBuilder new withX: 10. - b2 := b incrementX: 5. - self assert: (b2 getX) equals: 15. + b := ValueTypeBuilder new withX: 10 + b2 := b incrementX: 5 + self assert: b2 getX equals: 15 // Original unchanged - self assert: (b getX) equals: 10 + self assert: b getX equals: 10 diff --git a/stdlib/test/workspace_interface_test.bt b/stdlib/test/workspace_interface_test.bt index b45526f3b..99e62bf0f 100644 --- a/stdlib/test/workspace_interface_test.bt +++ b/stdlib/test/workspace_interface_test.bt @@ -1,7 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BUnit tests for WorkspaceInterface facade API (BT-849 / ADR 0040 Phase 6). +// BUnit tests for WorkspaceInterface facade API (BT-849 / ADR 0040 Phase 6) // // Tests use class-level introspection (includesSelector:, inheritsFrom:) since // the Workspace singleton is not available in the BUnit test context From da79b88e0c620f2d8e425509f8e476eb31c60931 Mon Sep 17 00:00:00 2001 From: James Casey Date: Sat, 28 Feb 2026 14:36:48 +0000 Subject: [PATCH 2/2] fix: address CodeRabbit review comments BT-964 - error_counter.bt: add missing license header - nlr_baz.bt: remove stale comment that contradicted implementation (the ^ was removed by the lint fix; comment about 'do not simplify to x + x' no longer applies since the body is now x + x per project rules) Co-Authored-By: Claude Sonnet 4.6 --- stdlib/test/fixtures/error_counter.bt | 3 +++ stdlib/test/fixtures/nlr_baz.bt | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/stdlib/test/fixtures/error_counter.bt b/stdlib/test/fixtures/error_counter.bt index 852aad6b9..b0627842b 100644 --- a/stdlib/test/fixtures/error_counter.bt +++ b/stdlib/test/fixtures/error_counter.bt @@ -1,3 +1,6 @@ +// Copyright 2026 James Casey +// SPDX-License-Identifier: Apache-2.0 + // Actor for testing state mutation threading in exception handling blocks // Used by tests/stdlib/exception_mutations.bt (BT-410) diff --git a/stdlib/test/fixtures/nlr_baz.bt b/stdlib/test/fixtures/nlr_baz.bt index 926eeef76..3aa77e240 100644 --- a/stdlib/test/fixtures/nlr_baz.bt +++ b/stdlib/test/fixtures/nlr_baz.bt @@ -1,9 +1,7 @@ // Copyright 2026 James Casey // SPDX-License-Identifier: Apache-2.0 -// BT-754: NlrBaz — top-level ^ regression guard fixture -// Intentional: ^ on last expression tests that top-level ^ still works -// after NLR changes. Do not simplify to `x + x` +// BT-754: NlrBaz — simple value-type fixture used by NLR regression tests Object subclass: NlrBaz double: x => x + x