codeflash/tests/test_java_assertion_removal.py
2026-02-16 08:32:55 +02:00

1431 lines
41 KiB
Python

"""Tests for Java assertion removal transformer.
This test suite covers the transformation of Java test assertions into
regression test code that captures function return values.
All tests assert for full string equality, no substring matching.
"""
from pathlib import Path
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
from codeflash.languages.java.remove_asserts import JavaAssertTransformer, transform_java_assertions
class TestBasicJUnit5Assertions:
"""Tests for basic JUnit 5 assertion transformations."""
def test_assert_equals_basic(self):
source = """\
@Test
void testFibonacci() {
assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_equals_with_message(self):
source = """\
@Test
void testFibonacci() {
assertEquals(55, calculator.fibonacci(10), "Fibonacci of 10 should be 55");
}"""
expected = """\
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_true(self):
source = """\
@Test
void testIsValid() {
assertTrue(validator.isValid("test"));
}"""
expected = """\
@Test
void testIsValid() {
Object _cf_result1 = validator.isValid("test");
}"""
result = transform_java_assertions(source, "isValid")
assert result == expected
def test_assert_false(self):
source = """\
@Test
void testIsInvalid() {
assertFalse(validator.isValid(""));
}"""
expected = """\
@Test
void testIsInvalid() {
Object _cf_result1 = validator.isValid("");
}"""
result = transform_java_assertions(source, "isValid")
assert result == expected
def test_assert_null(self):
source = """\
@Test
void testGetNull() {
assertNull(processor.getValue(null));
}"""
expected = """\
@Test
void testGetNull() {
Object _cf_result1 = processor.getValue(null);
}"""
result = transform_java_assertions(source, "getValue")
assert result == expected
def test_assert_not_null(self):
source = """\
@Test
void testGetValue() {
assertNotNull(processor.getValue("key"));
}"""
expected = """\
@Test
void testGetValue() {
Object _cf_result1 = processor.getValue("key");
}"""
result = transform_java_assertions(source, "getValue")
assert result == expected
def test_assert_not_equals(self):
source = """\
@Test
void testDifferent() {
assertNotEquals(0, calculator.add(1, 2));
}"""
expected = """\
@Test
void testDifferent() {
Object _cf_result1 = calculator.add(1, 2);
}"""
result = transform_java_assertions(source, "add")
assert result == expected
def test_assert_same(self):
source = """\
@Test
void testSame() {
assertSame(expected, factory.getInstance());
}"""
expected = """\
@Test
void testSame() {
Object _cf_result1 = factory.getInstance();
}"""
result = transform_java_assertions(source, "getInstance")
assert result == expected
def test_assert_array_equals(self):
source = """\
@Test
void testSort() {
assertArrayEquals(expected, sorter.sort(input));
}"""
expected = """\
@Test
void testSort() {
Object _cf_result1 = sorter.sort(input);
}"""
result = transform_java_assertions(source, "sort")
assert result == expected
class TestJUnit5PrefixedAssertions:
"""Tests for JUnit 5 assertions with Assertions. prefix."""
def test_assertions_prefix(self):
source = """\
@Test
void testFibonacci() {
Assertions.assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_prefix(self):
source = """\
@Test
void testAdd() {
Assert.assertEquals(5, calculator.add(2, 3));
}"""
expected = """\
@Test
void testAdd() {
Object _cf_result1 = calculator.add(2, 3);
}"""
result = transform_java_assertions(source, "add")
assert result == expected
class TestJUnit5ExceptionAssertions:
"""Tests for JUnit 5 exception assertions."""
def test_assert_throws_lambda(self):
source = """\
@Test
void testDivideByZero() {
assertThrows(IllegalArgumentException.class, () -> calculator.divide(1, 0));
}"""
expected = """\
@Test
void testDivideByZero() {
try { calculator.divide(1, 0); } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "divide")
assert result == expected
def test_assert_throws_block_lambda(self):
source = """\
@Test
void testDivideByZero() {
assertThrows(ArithmeticException.class, () -> {
calculator.divide(1, 0);
});
}"""
expected = """\
@Test
void testDivideByZero() {
try { calculator.divide(1, 0); } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "divide")
assert result == expected
def test_assert_does_not_throw(self):
source = """\
@Test
void testValidDivision() {
assertDoesNotThrow(() -> calculator.divide(10, 2));
}"""
expected = """\
@Test
void testValidDivision() {
try { calculator.divide(10, 2); } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "divide")
assert result == expected
class TestStaticMethodCalls:
"""Tests for static method call handling."""
def test_static_method_call(self):
source = """\
@Test
void testQuickAdd() {
assertEquals(15.0, Calculator.quickAdd(10.0, 5.0));
}"""
expected = """\
@Test
void testQuickAdd() {
Object _cf_result1 = Calculator.quickAdd(10.0, 5.0);
}"""
result = transform_java_assertions(source, "quickAdd")
assert result == expected
def test_static_method_fully_qualified(self):
source = """\
@Test
void testReverse() {
assertEquals("olleh", com.example.StringUtils.reverse("hello"));
}"""
expected = """\
@Test
void testReverse() {
Object _cf_result1 = com.example.StringUtils.reverse("hello");
}"""
result = transform_java_assertions(source, "reverse")
assert result == expected
class TestMultipleAssertions:
"""Tests for multiple assertions in a single test method."""
def test_multiple_assertions_same_function(self):
source = """\
@Test
void testFibonacciSequence() {
assertEquals(0, calculator.fibonacci(0));
assertEquals(1, calculator.fibonacci(1));
assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
@Test
void testFibonacciSequence() {
Object _cf_result1 = calculator.fibonacci(0);
Object _cf_result2 = calculator.fibonacci(1);
Object _cf_result3 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_multiple_assertions_different_functions(self):
source = """\
@Test
void testCalculator() {
assertEquals(5, calculator.add(2, 3));
assertEquals(6, calculator.multiply(2, 3));
}"""
expected = """\
@Test
void testCalculator() {
Object _cf_result1 = calculator.add(2, 3);
assertEquals(6, calculator.multiply(2, 3));
}"""
result = transform_java_assertions(source, "add")
assert result == expected
class TestAssertJFluentAssertions:
"""Tests for AssertJ fluent assertion transformations."""
def test_assertj_basic(self):
source = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testFibonacci() {
assertThat(calculator.fibonacci(10)).isEqualTo(55);
}"""
expected = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assertj_chained(self):
source = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetList() {
assertThat(processor.getList()).hasSize(5).contains("a", "b");
}"""
expected = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetList() {
Object _cf_result1 = processor.getList();
}"""
result = transform_java_assertions(source, "getList")
assert result == expected
def test_assertj_is_null(self):
source = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetNull() {
assertThat(processor.getValue(null)).isNull();
}"""
expected = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetNull() {
Object _cf_result1 = processor.getValue(null);
}"""
result = transform_java_assertions(source, "getValue")
assert result == expected
def test_assertj_is_not_empty(self):
source = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetList() {
assertThat(processor.getList()).isNotEmpty();
}"""
expected = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testGetList() {
Object _cf_result1 = processor.getList();
}"""
result = transform_java_assertions(source, "getList")
assert result == expected
class TestNestedMethodCalls:
"""Tests for nested method calls in assertions."""
def test_nested_call_in_expected(self):
source = """\
@Test
void testCompare() {
assertEquals(helper.getExpected(), calculator.compute(5));
}"""
expected = """\
@Test
void testCompare() {
Object _cf_result1 = calculator.compute(5);
}"""
result = transform_java_assertions(source, "compute")
assert result == expected
def test_nested_call_as_argument(self):
source = """\
@Test
void testProcess() {
assertEquals(expected, processor.process(helper.getData()));
}"""
expected = """\
@Test
void testProcess() {
Object _cf_result1 = processor.process(helper.getData());
}"""
result = transform_java_assertions(source, "process")
assert result == expected
def test_deeply_nested(self):
source = """\
@Test
void testDeep() {
assertEquals(expected, outer.process(inner.compute(calculator.fibonacci(5))));
}"""
expected = """\
@Test
void testDeep() {
Object _cf_result1 = calculator.fibonacci(5);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestWhitespacePreservation:
"""Tests for whitespace and indentation preservation."""
def test_preserves_indentation(self):
source = """\
@Test
void testFibonacci() {
assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_multiline_assertion(self):
source = """\
@Test
void testLongAssertion() {
assertEquals(
expectedValue,
calculator.computeComplexResult(
arg1,
arg2,
arg3
)
);
}"""
expected = """\
@Test
void testLongAssertion() {
Object _cf_result1 = calculator.computeComplexResult(
arg1,
arg2,
arg3
);
}"""
result = transform_java_assertions(source, "computeComplexResult")
assert result == expected
class TestStringsWithSpecialCharacters:
"""Tests for strings containing special characters."""
def test_string_with_parentheses(self):
source = """\
@Test
void testFormat() {
assertEquals("hello (world)", formatter.format("hello", "world"));
}"""
expected = """\
@Test
void testFormat() {
Object _cf_result1 = formatter.format("hello", "world");
}"""
result = transform_java_assertions(source, "format")
assert result == expected
def test_string_with_quotes(self):
source = """\
@Test
void testEscape() {
assertEquals("hello \\"world\\"", formatter.escape("hello \\"world\\""));
}"""
expected = """\
@Test
void testEscape() {
Object _cf_result1 = formatter.escape("hello \\"world\\"");
}"""
result = transform_java_assertions(source, "escape")
assert result == expected
def test_string_with_newlines(self):
source = """\
@Test
void testMultiline() {
assertEquals("line1\\nline2", processor.join("line1", "line2"));
}"""
expected = """\
@Test
void testMultiline() {
Object _cf_result1 = processor.join("line1", "line2");
}"""
result = transform_java_assertions(source, "join")
assert result == expected
class TestNonAssertionCodePreservation:
"""Tests that non-assertion code is preserved unchanged."""
def test_setup_code_preserved(self):
source = """\
@Test
void testWithSetup() {
Calculator calc = new Calculator(2);
int input = 10;
assertEquals(55, calc.fibonacci(input));
}"""
expected = """\
@Test
void testWithSetup() {
Calculator calc = new Calculator(2);
int input = 10;
Object _cf_result1 = calc.fibonacci(input);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_other_method_calls_preserved(self):
source = """\
@Test
void testWithHelper() {
helper.setup();
assertEquals(55, calculator.fibonacci(10));
helper.cleanup();
}"""
expected = """\
@Test
void testWithHelper() {
helper.setup();
Object _cf_result1 = calculator.fibonacci(10);
helper.cleanup();
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_variable_declarations_preserved(self):
source = """\
@Test
void testWithVariables() {
int expected = 55;
int actual = calculator.fibonacci(10);
assertEquals(expected, actual);
}"""
# fibonacci is assigned to 'actual', not in the assertion - no transformation
expected = source
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestParameterizedTests:
"""Tests for parameterized test handling."""
def test_parameterized_test(self):
source = """\
@ParameterizedTest
@CsvSource({
"0, 0",
"1, 1",
"10, 55"
})
void testFibonacciSequence(int n, long expected) {
assertEquals(expected, calculator.fibonacci(n));
}"""
expected = """\
@ParameterizedTest
@CsvSource({
"0, 0",
"1, 1",
"10, 55"
})
void testFibonacciSequence(int n, long expected) {
Object _cf_result1 = calculator.fibonacci(n);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestNestedTestClasses:
"""Tests for nested test class handling."""
def test_nested_class(self):
source = """\
@Nested
@DisplayName("Fibonacci Tests")
class FibonacciTests {
@Test
void testBasic() {
assertEquals(55, calculator.fibonacci(10));
}
}"""
expected = """\
@Nested
@DisplayName("Fibonacci Tests")
class FibonacciTests {
@Test
void testBasic() {
Object _cf_result1 = calculator.fibonacci(10);
}
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestMockitoPreservation:
"""Tests that Mockito code is not modified."""
def test_mockito_when_preserved(self):
source = """\
@Test
void testWithMock() {
when(mockService.getData()).thenReturn("test");
assertEquals("test", processor.process(mockService));
}"""
expected = """\
@Test
void testWithMock() {
when(mockService.getData()).thenReturn("test");
Object _cf_result1 = processor.process(mockService);
}"""
result = transform_java_assertions(source, "process")
assert result == expected
def test_mockito_verify_preserved(self):
source = """\
@Test
void testWithVerify() {
processor.process(mockService);
verify(mockService).getData();
}"""
# No assertions to transform, source unchanged
expected = source
result = transform_java_assertions(source, "process")
assert result == expected
class TestEdgeCases:
"""Tests for edge cases and boundary conditions."""
def test_empty_source(self):
result = transform_java_assertions("", "fibonacci")
assert result == ""
def test_whitespace_only(self):
source = " \n\t "
result = transform_java_assertions(source, "fibonacci")
assert result == source
def test_no_assertions(self):
source = """\
@Test
void testNoAssertions() {
calculator.fibonacci(10);
}"""
expected = source
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assertion_without_target_function(self):
source = """\
@Test
void testOther() {
assertEquals(5, helper.compute(3));
}"""
# No transformation since target function is not in the assertion
expected = source
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_function_name_in_string(self):
source = """\
@Test
void testWithStringContainingFunctionName() {
assertEquals("fibonacci(10) = 55", formatter.format("fibonacci", 10, 55));
}"""
expected = """\
@Test
void testWithStringContainingFunctionName() {
Object _cf_result1 = formatter.format("fibonacci", 10, 55);
}"""
result = transform_java_assertions(source, "format")
assert result == expected
class TestJUnit4Compatibility:
"""Tests for JUnit 4 style assertions."""
def test_junit4_assert_equals(self):
source = """\
import static org.junit.Assert.*;
@Test
public void testFibonacci() {
assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
import static org.junit.Assert.*;
@Test
public void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_junit4_with_message_first(self):
source = """\
@Test
public void testFibonacci() {
assertEquals("Should be 55", 55, calculator.fibonacci(10));
}"""
expected = """\
@Test
public void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestAssertAll:
"""Tests for assertAll grouped assertions."""
def test_assert_all_basic(self):
source = """\
@Test
void testMultiple() {
assertAll(
() -> assertEquals(0, calculator.fibonacci(0)),
() -> assertEquals(1, calculator.fibonacci(1)),
() -> assertEquals(55, calculator.fibonacci(10))
);
}"""
expected = """\
@Test
void testMultiple() {
Object _cf_result1 = calculator.fibonacci(0);
Object _cf_result2 = calculator.fibonacci(1);
Object _cf_result3 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestTransformerClass:
"""Tests for the JavaAssertTransformer class directly."""
def test_invocation_counter_increments(self):
transformer = JavaAssertTransformer("fibonacci")
source = """\
@Test
void test() {
assertEquals(0, calc.fibonacci(0));
assertEquals(1, calc.fibonacci(1));
}"""
expected = """\
@Test
void test() {
Object _cf_result1 = calc.fibonacci(0);
Object _cf_result2 = calc.fibonacci(1);
}"""
result = transformer.transform(source)
assert result == expected
assert transformer.invocation_counter == 2
def test_qualified_name_support(self):
transformer = JavaAssertTransformer(
function_name="fibonacci",
qualified_name="com.example.Calculator.fibonacci",
)
assert transformer.qualified_name == "com.example.Calculator.fibonacci"
def test_custom_analyzer(self):
from codeflash.languages.java.parser import get_java_analyzer
analyzer = get_java_analyzer()
transformer = JavaAssertTransformer("fibonacci", analyzer=analyzer)
assert transformer.analyzer is analyzer
class TestImportDetection:
"""Tests for framework detection from imports."""
def test_detect_junit5(self):
source = """\
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;"""
transformer = JavaAssertTransformer("test")
transformer._detected_framework = transformer._detect_framework(source)
assert transformer._detected_framework == "junit5"
def test_detect_assertj(self):
source = """\
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;"""
transformer = JavaAssertTransformer("test")
transformer._detected_framework = transformer._detect_framework(source)
assert transformer._detected_framework == "assertj"
def test_detect_testng(self):
source = """\
import org.testng.Assert;
import org.testng.annotations.Test;"""
transformer = JavaAssertTransformer("test")
transformer._detected_framework = transformer._detect_framework(source)
assert transformer._detected_framework == "testng"
def test_detect_hamcrest(self):
source = """\
import org.junit.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;"""
transformer = JavaAssertTransformer("test")
transformer._detected_framework = transformer._detect_framework(source)
assert transformer._detected_framework == "hamcrest"
class TestInstrumentGeneratedJavaTest:
"""Tests for the instrument_generated_java_test integration."""
def test_behavior_mode_removes_assertions(self):
from codeflash.languages.java.instrumentation import instrument_generated_java_test
test_code = """\
package com.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class FibonacciTest {
@Test
void testFibonacci() {
Calculator calc = new Calculator();
assertEquals(55, calc.fibonacci(10));
}
}"""
func = FunctionToOptimize(
function_name="fibonacci",
file_path=Path("Calculator.java"),
starting_line=1,
ending_line=5,
parents=[],
is_method=True,
language="java",
)
result = instrument_generated_java_test(
test_code=test_code,
function_name="fibonacci",
qualified_name="com.example.Calculator.fibonacci",
mode="behavior",
function_to_optimize=func,
)
# Behavior mode now adds full instrumentation
assert "FibonacciTest__perfinstrumented" in result
assert "_cf_result" in result
assert "com.codeflash.Serializer.serialize" in result
def test_behavior_mode_with_assertj(self):
from codeflash.languages.java.instrumentation import instrument_generated_java_test
test_code = """\
package com.example;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class StringUtilsTest {
@Test
void testReverse() {
assertThat(StringUtils.reverse("hello")).isEqualTo("olleh");
}
}"""
func = FunctionToOptimize(
function_name="reverse",
file_path=Path("StringUtils.java"),
starting_line=1,
ending_line=5,
parents=[],
is_method=True,
language="java",
)
result = instrument_generated_java_test(
test_code=test_code,
function_name="reverse",
qualified_name="com.example.StringUtils.reverse",
mode="behavior",
function_to_optimize=func,
)
# Behavior mode now adds full instrumentation
assert "StringUtilsTest__perfinstrumented" in result
assert "_cf_result" in result
assert "com.codeflash.Serializer.serialize" in result
class TestComplexRealWorldExamples:
"""Tests based on real-world test patterns."""
def test_calculator_test_pattern(self):
source = """\
@Test
@DisplayName("should calculate compound interest for basic case")
void testBasicCompoundInterest() {
String result = calculator.calculateCompoundInterest(1000.0, 0.05, 1, 12);
assertNotNull(result);
assertTrue(result.contains("."));
}"""
# assertNotNull(result) and assertTrue(result.contains(".")) don't contain the target function
# so they remain unchanged, and the variable assignment is also preserved
expected = source
result = transform_java_assertions(source, "calculateCompoundInterest")
assert result == expected
def test_string_utils_pattern(self):
source = """\
@Test
@DisplayName("should reverse a simple string")
void testReverseSimple() {
assertEquals("olleh", StringUtils.reverse("hello"));
assertEquals("dlrow", StringUtils.reverse("world"));
}"""
expected = """\
@Test
@DisplayName("should reverse a simple string")
void testReverseSimple() {
Object _cf_result1 = StringUtils.reverse("hello");
Object _cf_result2 = StringUtils.reverse("world");
}"""
result = transform_java_assertions(source, "reverse")
assert result == expected
def test_with_before_each_setup(self):
source = """\
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator(2);
}
@Test
void testFibonacci() {
assertEquals(55, calculator.fibonacci(10));
}"""
expected = """\
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator(2);
}
@Test
void testFibonacci() {
Object _cf_result1 = calculator.fibonacci(10);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
class TestConcurrencyPatterns:
"""Tests that assertion removal correctly handles Java concurrency constructs.
Validates that synchronized blocks, volatile field access, atomic operations,
concurrent collections, Thread.sleep, wait/notify, and synchronized method
modifiers are all preserved verbatim after assertion transformation.
"""
def test_synchronized_method_assertion_removal(self):
"""Assertion inside synchronized block is transformed; synchronized wrapper preserved."""
source = """\
@Test
void testSynchronizedAccess() {
synchronized (lock) {
assertEquals(42, counter.incrementAndGet());
}
}"""
expected = """\
@Test
void testSynchronizedAccess() {
synchronized (lock) {
Object _cf_result1 = counter.incrementAndGet();
}
}"""
result = transform_java_assertions(source, "incrementAndGet")
assert result == expected
def test_volatile_field_read_preserved(self):
"""Assertion wrapping a volatile field reader is transformed; method call preserved."""
source = """\
@Test
void testVolatileRead() {
assertTrue(buffer.isReady());
}"""
expected = """\
@Test
void testVolatileRead() {
Object _cf_result1 = buffer.isReady();
}"""
result = transform_java_assertions(source, "isReady")
assert result == expected
def test_synchronized_block_with_multiple_assertions(self):
"""Multiple assertions inside a synchronized block are all transformed."""
source = """\
@Test
void testSynchronizedBlock() {
synchronized (cache) {
assertEquals(1, cache.size());
assertNotNull(cache.get("key"));
assertTrue(cache.containsKey("key"));
}
}"""
expected = """\
@Test
void testSynchronizedBlock() {
synchronized (cache) {
Object _cf_result1 = cache.size();
assertNotNull(cache.get("key"));
assertTrue(cache.containsKey("key"));
}
}"""
result = transform_java_assertions(source, "size")
assert result == expected
def test_synchronized_block_multiple_assertions_same_target(self):
"""Multiple assertions in synchronized block targeting the same function."""
source = """\
@Test
void testSynchronizedBlock() {
synchronized (cache) {
assertNotNull(cache.get("key1"));
assertNotNull(cache.get("key2"));
}
}"""
expected = """\
@Test
void testSynchronizedBlock() {
synchronized (cache) {
Object _cf_result1 = cache.get("key1");
Object _cf_result2 = cache.get("key2");
}
}"""
result = transform_java_assertions(source, "get")
assert result == expected
def test_atomic_operations_preserved(self):
"""Atomic operations (incrementAndGet) are preserved as Object capture calls."""
source = """\
@Test
void testAtomicCounter() {
assertEquals(1, counter.incrementAndGet());
assertEquals(2, counter.incrementAndGet());
}"""
expected = """\
@Test
void testAtomicCounter() {
Object _cf_result1 = counter.incrementAndGet();
Object _cf_result2 = counter.incrementAndGet();
}"""
result = transform_java_assertions(source, "incrementAndGet")
assert result == expected
def test_concurrent_collection_assertion(self):
"""ConcurrentHashMap putIfAbsent call is preserved in assertion transformation."""
source = """\
@Test
void testConcurrentMap() {
assertEquals("value", concurrentMap.putIfAbsent("key", "value"));
}"""
expected = """\
@Test
void testConcurrentMap() {
Object _cf_result1 = concurrentMap.putIfAbsent("key", "value");
}"""
result = transform_java_assertions(source, "putIfAbsent")
assert result == expected
def test_thread_sleep_with_assertion(self):
"""Thread.sleep() before assertion is preserved verbatim."""
source = """\
@Test
void testWithThreadSleep() throws InterruptedException {
Thread.sleep(100);
assertEquals(42, processor.getResult());
}"""
expected = """\
@Test
void testWithThreadSleep() throws InterruptedException {
Thread.sleep(100);
Object _cf_result1 = processor.getResult();
}"""
result = transform_java_assertions(source, "getResult")
assert result == expected
def test_synchronized_method_signature_preserved(self):
"""synchronized modifier on a test method is preserved after transformation."""
source = """\
@Test
synchronized void testSyncMethod() {
assertEquals(10, calculator.compute(5));
}"""
expected = """\
@Test
synchronized void testSyncMethod() {
Object _cf_result1 = calculator.compute(5);
}"""
result = transform_java_assertions(source, "compute")
assert result == expected
def test_wait_notify_pattern_preserved(self):
"""wait/notify pattern around an assertion is preserved."""
source = """\
@Test
void testWaitNotify() {
synchronized (monitor) {
monitor.notify();
}
assertTrue(listener.wasNotified());
}"""
expected = """\
@Test
void testWaitNotify() {
synchronized (monitor) {
monitor.notify();
}
Object _cf_result1 = listener.wasNotified();
}"""
result = transform_java_assertions(source, "wasNotified")
assert result == expected
def test_reentrant_lock_pattern_preserved(self):
"""ReentrantLock acquire/release around assertion is preserved."""
source = """\
@Test
void testReentrantLock() {
lock.lock();
try {
assertEquals(99, sharedResource.getValue());
} finally {
lock.unlock();
}
}"""
expected = """\
@Test
void testReentrantLock() {
lock.lock();
try {
Object _cf_result1 = sharedResource.getValue();
} finally {
lock.unlock();
}
}"""
result = transform_java_assertions(source, "getValue")
assert result == expected
def test_count_down_latch_pattern_preserved(self):
"""CountDownLatch await/countDown around assertion is preserved."""
source = """\
@Test
void testCountDownLatch() throws InterruptedException {
latch.countDown();
latch.await();
assertEquals(42, collector.getTotal());
}"""
expected = """\
@Test
void testCountDownLatch() throws InterruptedException {
latch.countDown();
latch.await();
Object _cf_result1 = collector.getTotal();
}"""
result = transform_java_assertions(source, "getTotal")
assert result == expected
def test_token_bucket_synchronized_method(self):
"""Real pattern: synchronized method call (like TokenBucket.allowRequest) inside assertion."""
source = """\
@Test
void testTokenBucketAllowRequest() {
TokenBucket bucket = new TokenBucket(10, 1);
assertTrue(bucket.allowRequest());
assertTrue(bucket.allowRequest());
}"""
expected = """\
@Test
void testTokenBucketAllowRequest() {
TokenBucket bucket = new TokenBucket(10, 1);
Object _cf_result1 = bucket.allowRequest();
Object _cf_result2 = bucket.allowRequest();
}"""
result = transform_java_assertions(source, "allowRequest")
assert result == expected
def test_circular_buffer_atomic_integer_pattern(self):
"""Real pattern: CircularBuffer with AtomicInteger-backed isEmpty/isFull assertions."""
source = """\
@Test
void testCircularBufferOperations() {
CircularBuffer<Integer> buffer = new CircularBuffer<>(3);
assertTrue(buffer.isEmpty());
buffer.put(1);
assertFalse(buffer.isEmpty());
assertTrue(buffer.put(2));
}"""
expected = """\
@Test
void testCircularBufferOperations() {
CircularBuffer<Integer> buffer = new CircularBuffer<>(3);
Object _cf_result1 = buffer.isEmpty();
buffer.put(1);
Object _cf_result2 = buffer.isEmpty();
Object _cf_result3 = buffer.put(2);
}"""
result = transform_java_assertions(source, "isEmpty")
# isEmpty is target for assertTrue/assertFalse; but put is NOT the target
# so only isEmpty calls inside assertions are transformed
# Actually: assertTrue(buffer.put(2)) also contains a non-target call
# Let's verify what actually happens
# put is not "isEmpty", so assertTrue(buffer.put(2)) has no target call -> untouched
expected_corrected = """\
@Test
void testCircularBufferOperations() {
CircularBuffer<Integer> buffer = new CircularBuffer<>(3);
Object _cf_result1 = buffer.isEmpty();
buffer.put(1);
Object _cf_result2 = buffer.isEmpty();
assertTrue(buffer.put(2));
}"""
result = transform_java_assertions(source, "isEmpty")
assert result == expected_corrected
def test_concurrent_assertion_with_assertj(self):
"""AssertJ assertion on a synchronized method call is correctly transformed."""
source = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testSynchronizedMethodWithAssertJ() {
synchronized (lock) {
assertThat(counter.incrementAndGet()).isEqualTo(1);
}
}"""
expected = """\
import static org.assertj.core.api.Assertions.assertThat;
@Test
void testSynchronizedMethodWithAssertJ() {
synchronized (lock) {
Object _cf_result1 = counter.incrementAndGet();
}
}"""
result = transform_java_assertions(source, "incrementAndGet")
assert result == expected
class TestFullyQualifiedAssertions:
"""Tests for fully qualified assertion calls like org.junit.jupiter.api.Assertions.assertXxx."""
def test_assert_timeout_fully_qualified_with_variable_assignment(self):
source = """\
@Test
void testLargeInput() {
Long result = org.junit.jupiter.api.Assertions.assertTimeout(
Duration.ofSeconds(1),
() -> Fibonacci.fibonacci(100_000)
);
}"""
expected = """\
@Test
void testLargeInput() {
Object _cf_result1 = Fibonacci.fibonacci(100_000);
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_equals_fully_qualified(self):
source = """\
@Test
void testAdd() {
org.junit.jupiter.api.Assertions.assertEquals(5, calc.add(2, 3));
}"""
expected = """\
@Test
void testAdd() {
Object _cf_result1 = calc.add(2, 3);
}"""
result = transform_java_assertions(source, "add")
assert result == expected
class TestAssertThrowsVariableAssignment:
"""Tests for assertThrows with variable assignment (Issue: exception handling instrumentation bug)."""
def test_assert_throws_with_variable_assignment_expression_lambda(self):
"""Test assertThrows assigned to variable with expression lambda."""
source = """\
@Test
void testNegativeInput() {
IllegalArgumentException exception = assertThrows(
IllegalArgumentException.class,
() -> calculator.fibonacci(-1)
);
assertEquals("Negative input not allowed", exception.getMessage());
}"""
expected = """\
@Test
void testNegativeInput() {
IllegalArgumentException exception = null;
try { calculator.fibonacci(-1); } catch (IllegalArgumentException _cf_caught1) { exception = _cf_caught1; } catch (Exception _cf_ignored1) {}
assertEquals("Negative input not allowed", exception.getMessage());
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_throws_with_variable_assignment_block_lambda(self):
"""Test assertThrows assigned to variable with block lambda."""
source = """\
@Test
void testInvalidOperation() {
ArithmeticException ex = assertThrows(ArithmeticException.class, () -> {
calculator.divide(10, 0);
});
assertEquals("Division by zero", ex.getMessage());
}"""
expected = """\
@Test
void testInvalidOperation() {
ArithmeticException ex = null;
try { calculator.divide(10, 0); } catch (ArithmeticException _cf_caught1) { ex = _cf_caught1; } catch (Exception _cf_ignored1) {}
assertEquals("Division by zero", ex.getMessage());
}"""
result = transform_java_assertions(source, "divide")
assert result == expected
def test_assert_throws_with_variable_assignment_generic_exception(self):
"""Test assertThrows with generic Exception type."""
source = """\
@Test
void testGenericException() {
Exception e = assertThrows(Exception.class, () -> processor.process(null));
assertNotNull(e.getMessage());
}"""
expected = """\
@Test
void testGenericException() {
Exception e = null;
try { processor.process(null); } catch (Exception _cf_caught1) { e = _cf_caught1; } catch (Exception _cf_ignored1) {}
assertNotNull(e.getMessage());
}"""
result = transform_java_assertions(source, "process")
assert result == expected
def test_assert_throws_without_variable_assignment(self):
"""Test assertThrows without variable assignment still works (no regression)."""
source = """\
@Test
void testThrowsException() {
assertThrows(IllegalArgumentException.class, () -> calculator.fibonacci(-1));
}"""
expected = """\
@Test
void testThrowsException() {
try { calculator.fibonacci(-1); } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "fibonacci")
assert result == expected
def test_assert_throws_with_variable_and_multi_line_lambda(self):
"""Test assertThrows with variable assignment and multi-line lambda."""
source = """\
@Test
void testComplexException() {
IllegalStateException exception = assertThrows(
IllegalStateException.class,
() -> {
processor.initialize();
processor.execute();
}
);
assertTrue(exception.getMessage().contains("not initialized"));
}"""
expected = """\
@Test
void testComplexException() {
IllegalStateException exception = null;
try { processor.initialize();
processor.execute(); } catch (IllegalStateException _cf_caught1) { exception = _cf_caught1; } catch (Exception _cf_ignored1) {}
assertTrue(exception.getMessage().contains("not initialized"));
}"""
result = transform_java_assertions(source, "execute")
assert result == expected
def test_assert_throws_assigned_with_final_modifier(self):
"""Test assertThrows with final modifier on variable."""
source = """\
@Test
void testDivideByZero() {
final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> calc.divide(1, 0));
}"""
expected = """\
@Test
void testDivideByZero() {
IllegalArgumentException ex = null;
try { calc.divide(1, 0); } catch (IllegalArgumentException _cf_caught1) { ex = _cf_caught1; } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "divide")
assert result == expected
def test_assert_throws_assigned_with_qualified_assertions(self):
"""Test assertThrows with qualified assertion (Assertions.assertThrows)."""
source = """\
@Test
void testDivideByZero() {
IllegalArgumentException ex = Assertions.assertThrows(IllegalArgumentException.class, () -> calc.divide(1, 0));
}"""
expected = """\
@Test
void testDivideByZero() {
IllegalArgumentException ex = null;
try { calc.divide(1, 0); } catch (IllegalArgumentException _cf_caught1) { ex = _cf_caught1; } catch (Exception _cf_ignored1) {}
}"""
result = transform_java_assertions(source, "divide")
assert result == expected