diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..df065a7d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,40 @@ +# CLAUDE.md - ModifiableVariable Project Guide + +## Build Commands + +- Build: `mvn clean install` +- Run all tests: `mvn test` +- Run single test: `mvn test -Dtest=ClassName#methodName` (e.g., `mvn test -Dtest=ModifiableVariableTest#testRandomBigIntegerModification`) +- Run with code coverage: `mvn clean install -P coverage` +- Format code: `mvn spotless:apply` + +## Code Style + +- Uses Google Java Style (AOSP variant) for formatting +- Indentation: 4 spaces (no tabs) +- Line endings: GIT_ATTRIBUTES +- License header required on all files + +## Imports + +- Unused imports should be removed +- Import order is managed by spotless + +## Type System + +- Java 21 is required +- Generic types should be properly specified (e.g., `ModifiableVariable`) +- JAXB annotations used for XML serialization + +## Naming Conventions + +- CamelCase for class names +- camelCase for methods and variables +- Classes implementing modifications follow pattern: `[Type][Operation]Modification` +- Factory classes follow pattern: `[Type]ModificationFactory` + +## Error Handling + +- Proper exception handling with appropriate exception types +- FileConfigurationException for configuration-related errors + diff --git a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java index e4e39170..a7582bc2 100644 --- a/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java +++ b/src/main/java/de/rub/nds/modifiablevariable/VariableModification.java @@ -13,12 +13,13 @@ import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlTransient; +import java.io.Serializable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @XmlTransient @XmlAccessorType(XmlAccessType.FIELD) -public abstract class VariableModification { +public abstract class VariableModification implements Serializable { protected static final Logger LOGGER = LogManager.getLogger(VariableModification.class); diff --git a/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java b/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java new file mode 100644 index 00000000..932fd265 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/FileConfigurationExceptionTest.java @@ -0,0 +1,45 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; + +public class FileConfigurationExceptionTest { + + @Test + public void testDefaultConstructor() { + FileConfigurationException exception = new FileConfigurationException(); + + assertNull(exception.getMessage()); + assertNull(exception.getCause()); + } + + @Test + public void testConstructorWithException() { + IllegalArgumentException cause = new IllegalArgumentException("Test cause"); + FileConfigurationException exception = new FileConfigurationException(cause); + + assertNotNull(exception.getMessage()); + assertSame(cause, exception.getCause()); + } + + @Test + public void testConstructorWithMessageAndException() { + String message = "Test error message"; + IllegalArgumentException cause = new IllegalArgumentException("Test cause"); + FileConfigurationException exception = new FileConfigurationException(message, cause); + + assertEquals(message, exception.getMessage()); + assertSame(cause, exception.getCause()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/HoldsModifiableVariableTest.java b/src/test/java/de/rub/nds/modifiablevariable/HoldsModifiableVariableTest.java new file mode 100644 index 00000000..935a460c --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/HoldsModifiableVariableTest.java @@ -0,0 +1,73 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import de.rub.nds.modifiablevariable.integer.ModifiableInteger; +import de.rub.nds.modifiablevariable.util.ReflectionHelper; +import java.lang.reflect.Field; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class HoldsModifiableVariableTest { + + // Test class with HoldsModifiableVariable annotations + private static class TestClass { + @HoldsModifiableVariable private ModifiableVariableHolder holder; + + @HoldsModifiableVariable private List integerList; + + // No annotation + private ModifiableVariableHolder regularHolder; + } + + @Test + public void testAnnotationPresence() throws NoSuchFieldException { + Field holderField = TestClass.class.getDeclaredField("holder"); + HoldsModifiableVariable annotation = + holderField.getAnnotation(HoldsModifiableVariable.class); + + assertNotNull(annotation); + } + + @Test + public void testListFieldAnnotation() throws NoSuchFieldException { + Field listField = TestClass.class.getDeclaredField("integerList"); + HoldsModifiableVariable annotation = listField.getAnnotation(HoldsModifiableVariable.class); + + assertNotNull(annotation); + } + + @Test + public void testNoAnnotation() throws NoSuchFieldException { + Field regularField = TestClass.class.getDeclaredField("regularHolder"); + HoldsModifiableVariable annotation = + regularField.getAnnotation(HoldsModifiableVariable.class); + + assertNull(annotation); + } + + @Test + public void testFindAnnotatedFields() { + // Use ReflectionHelper to find fields with the annotation + List fields = ReflectionHelper.getFieldsUpTo(TestClass.class, Object.class, null); + + int annotatedCount = 0; + for (Field field : fields) { + if (field.isAnnotationPresent(HoldsModifiableVariable.class)) { + annotatedCount++; + } + } + + // We should find 2 annotated fields: holder and integerList + assertEquals(2, annotatedCount); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariableHolderTest.java b/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariableHolderTest.java new file mode 100644 index 00000000..2ade9ecb --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariableHolderTest.java @@ -0,0 +1,182 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import de.rub.nds.modifiablevariable.bytearray.ModifiableByteArray; +import de.rub.nds.modifiablevariable.integer.ModifiableInteger; +import de.rub.nds.modifiablevariable.string.ModifiableString; +import java.lang.reflect.Field; +import java.util.List; +import java.util.Random; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ModifiableVariableHolderTest { + + private TestModifiableVariableHolder holder; + + // Simple implementation of ModifiableVariableHolder for testing + private static class TestModifiableVariableHolder extends ModifiableVariableHolder { + private ModifiableInteger intValue; + private ModifiableString stringValue; + private ModifiableByteArray byteArrayValue; + private byte[] regularByteArray; + private String regularString; + private NestedHolder nestedHolder; + + public TestModifiableVariableHolder() { + intValue = new ModifiableInteger(); + stringValue = new ModifiableString(); + byteArrayValue = new ModifiableByteArray(); + regularByteArray = new byte[] {0x01, 0x02, 0x03}; + regularString = "Regular String"; + nestedHolder = new NestedHolder(); + } + } + + private static class NestedHolder extends ModifiableVariableHolder { + private ModifiableInteger nestedInt; + + public NestedHolder() { + nestedInt = new ModifiableInteger(); + nestedInt.setOriginalValue(42); + } + } + + @BeforeEach + public void setUp() { + holder = new TestModifiableVariableHolder(); + holder.intValue.setOriginalValue(123); + holder.stringValue.setOriginalValue("Test String"); + holder.byteArrayValue.setOriginalValue(new byte[] {0x04, 0x05, 0x06}); + } + + @Test + public void testGetAllModifiableVariableFields() { + List fields = holder.getAllModifiableVariableFields(); + + // Should find 3 fields: intValue, stringValue, byteArrayValue + assertEquals(3, fields.size()); + + // Verify field names + boolean foundIntValue = false; + boolean foundStringValue = false; + boolean foundByteArrayValue = false; + + for (Field field : fields) { + switch (field.getName()) { + case "intValue": + foundIntValue = true; + break; + case "stringValue": + foundStringValue = true; + break; + case "byteArrayValue": + foundByteArrayValue = true; + break; + } + } + + assertTrue(foundIntValue); + assertTrue(foundStringValue); + assertTrue(foundByteArrayValue); + } + + @Test + public void testGetRandomModifiableVariableField() { + // Use a fixed seed for reproducible test + Random random = new Random(123); + + Field field = holder.getRandomModifiableVariableField(random); + assertNotNull(field); + assertTrue(ModifiableVariable.class.isAssignableFrom(field.getType())); + } + + @Test + public void testGetAllModifiableVariableHolders() { + List holders = holder.getAllModifiableVariableHolders(); + + // Should only contain the holder itself by default + assertEquals(1, holders.size()); + assertEquals(holder, holders.get(0)); + } + + @Test + public void testGetRandomModifiableVariableHolder() { + // Use a fixed seed for reproducible test + Random random = new Random(123); + + ModifiableVariableHolder randomHolder = holder.getRandomModifiableVariableHolder(random); + assertNotNull(randomHolder); + assertEquals(holder, randomHolder); // Since only one holder in the list + } + + @Test + public void testReset() { + // Apply a modification to test reset + VariableModification modification = + new VariableModification() { + @Override + protected Integer modifyImplementationHook(Integer input) { + return input + 100; + } + + @Override + public VariableModification createCopy() { + // stub + return null; + } + }; + + holder.intValue.setModifications(modification); + assertEquals(223, holder.intValue.getValue().intValue()); + + // Reset and check that modifications are removed + holder.reset(); + + // Original value should be null but modification should remain + assertNull(holder.intValue.getOriginalValue()); + assertNotNull(holder.intValue.getModifications()); + } + + @Test + public void testGetExtendedString() { + String result = holder.getExtendedString(); + System.out.println("Extended string content: " + result); + + // The structure of the string can vary by platform/environment, so make minimal assertions + assertTrue(result.contains("TestModifiableVariableHolder")); + + // Don't check specific integer value format + assertTrue(result.contains("intValue")); + + // Check other values with less specific formatting requirements + assertTrue(result.contains("stringValue")); + assertTrue(result.contains("Test String")); + + // We only know the bytes will be there somewhere in hex format + assertTrue(result.contains("04")); + assertTrue(result.contains("05")); + assertTrue(result.contains("06")); + assertTrue(result.contains("01")); + assertTrue(result.contains("02")); + assertTrue(result.contains("03")); + + // Check for presence of other fields without exact formatting + assertTrue(result.contains("regularString")); + assertTrue(result.contains("Regular String")); + assertTrue(result.contains("nestedHolder")); + assertTrue(result.contains("NestedHolder")); + assertTrue(result.contains("nestedInt")); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariablePropertyTest.java b/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariablePropertyTest.java new file mode 100644 index 00000000..058d28e4 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/ModifiableVariablePropertyTest.java @@ -0,0 +1,78 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import de.rub.nds.modifiablevariable.ModifiableVariableProperty.Format; +import de.rub.nds.modifiablevariable.ModifiableVariableProperty.Type; +import de.rub.nds.modifiablevariable.integer.ModifiableInteger; +import java.lang.reflect.Field; +import org.junit.jupiter.api.Test; + +public class ModifiableVariablePropertyTest { + + // Test class with annotated fields + private static class TestClass { + @ModifiableVariableProperty(type = Type.LENGTH) + private ModifiableInteger length; + + @ModifiableVariableProperty(type = Type.COUNT) + private ModifiableInteger count; + + @ModifiableVariableProperty(type = Type.SIGNATURE, format = Format.ASN1) + private ModifiableInteger signatureWithFormat; + + @ModifiableVariableProperty private ModifiableInteger defaultProperty; + } + + @Test + public void testLengthProperty() throws NoSuchFieldException { + Field lengthField = TestClass.class.getDeclaredField("length"); + ModifiableVariableProperty annotation = + lengthField.getAnnotation(ModifiableVariableProperty.class); + + assertNotNull(annotation); + assertEquals(Type.LENGTH, annotation.type()); + assertEquals(Format.NONE, annotation.format()); + } + + @Test + public void testCountProperty() throws NoSuchFieldException { + Field countField = TestClass.class.getDeclaredField("count"); + ModifiableVariableProperty annotation = + countField.getAnnotation(ModifiableVariableProperty.class); + + assertNotNull(annotation); + assertEquals(Type.COUNT, annotation.type()); + assertEquals(Format.NONE, annotation.format()); + } + + @Test + public void testSignatureWithFormatProperty() throws NoSuchFieldException { + Field signatureField = TestClass.class.getDeclaredField("signatureWithFormat"); + ModifiableVariableProperty annotation = + signatureField.getAnnotation(ModifiableVariableProperty.class); + + assertNotNull(annotation); + assertEquals(Type.SIGNATURE, annotation.type()); + assertEquals(Format.ASN1, annotation.format()); + } + + @Test + public void testDefaultProperty() throws NoSuchFieldException { + Field defaultField = TestClass.class.getDeclaredField("defaultProperty"); + ModifiableVariableProperty annotation = + defaultField.getAnnotation(ModifiableVariableProperty.class); + + assertNotNull(annotation); + assertEquals(Type.NONE, annotation.type()); + assertEquals(Format.NONE, annotation.format()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java new file mode 100644 index 00000000..86f3a162 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftLeftModificationTest.java @@ -0,0 +1,120 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.biginteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.math.BigInteger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class BigIntegerShiftLeftModificationTest { + + private ModifiableBigInteger modifiableBigInteger; + private BigInteger originalValue; + + @BeforeEach + public void setUp() { + modifiableBigInteger = new ModifiableBigInteger(); + originalValue = new BigInteger("12345678901234567890"); + modifiableBigInteger.setOriginalValue(originalValue); + } + + @Test + public void testShiftLeftModification() { + int shift = 8; + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = originalValue.shiftLeft(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftNegativeNumber() { + BigInteger negativeValue = new BigInteger("-987654321"); + modifiableBigInteger.setOriginalValue(negativeValue); + + int shift = 4; + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = negativeValue.shiftLeft(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithZeroShift() { + int shift = 0; + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = originalValue; // Shifting by 0 should return the same value + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithLargeShift() { + int shift = 128; + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = originalValue.shiftLeft(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithNullInput() { + modifiableBigInteger.setOriginalValue(null); + + int shift = 10; + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = BigInteger.ZERO.shiftLeft(shift); // Should treat null as ZERO + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testEqualsAndHashCode() { + int shift = 15; + BigIntegerShiftLeftModification modification1 = new BigIntegerShiftLeftModification(shift); + BigIntegerShiftLeftModification modification2 = new BigIntegerShiftLeftModification(shift); + BigIntegerShiftLeftModification modification3 = + new BigIntegerShiftLeftModification(shift + 1); + + // Test equals + assertEquals(modification1, modification2); + assertNotEquals(modification1, modification3); + + // Test hashCode + assertEquals(modification1.hashCode(), modification2.hashCode()); + assertNotEquals(modification1.hashCode(), modification3.hashCode()); + } + + @Test + public void testGetterAndSetter() { + BigIntegerShiftLeftModification modification = new BigIntegerShiftLeftModification(); + + int shift = 25; + modification.setShift(shift); + + assertEquals(shift, modification.getShift()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java new file mode 100644 index 00000000..72c384bd --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/biginteger/BigIntegerShiftRightModificationTest.java @@ -0,0 +1,126 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.biginteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.math.BigInteger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class BigIntegerShiftRightModificationTest { + + private ModifiableBigInteger modifiableBigInteger; + private BigInteger originalValue; + + @BeforeEach + public void setUp() { + modifiableBigInteger = new ModifiableBigInteger(); + originalValue = new BigInteger("12345678901234567890"); + modifiableBigInteger.setOriginalValue(originalValue); + } + + @Test + public void testShiftRightModification() { + int shift = 8; + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = originalValue.shiftRight(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightNegativeNumber() { + BigInteger negativeValue = new BigInteger("-987654321"); + modifiableBigInteger.setOriginalValue(negativeValue); + + int shift = 4; + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = negativeValue.shiftRight(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithZeroShift() { + int shift = 0; + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = originalValue; // Shifting by 0 should return the same value + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithLargeShift() { + // First set a large value to have meaningful results after a large right shift + BigInteger largeValue = originalValue.shiftLeft(200); + modifiableBigInteger.setOriginalValue(largeValue); + + int shift = 128; + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = largeValue.shiftRight(shift); + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithNullInput() { + modifiableBigInteger.setOriginalValue(null); + + int shift = 10; + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(shift); + modifiableBigInteger.setModifications(modification); + + BigInteger expected = BigInteger.ZERO.shiftRight(shift); // Should treat null as ZERO + BigInteger result = modifiableBigInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testEqualsAndHashCode() { + int shift = 15; + BigIntegerShiftRightModification modification1 = + new BigIntegerShiftRightModification(shift); + BigIntegerShiftRightModification modification2 = + new BigIntegerShiftRightModification(shift); + BigIntegerShiftRightModification modification3 = + new BigIntegerShiftRightModification(shift + 1); + + // Test equals + assertEquals(modification1, modification2); + assertNotEquals(modification1, modification3); + + // Test hashCode + assertEquals(modification1.hashCode(), modification2.hashCode()); + assertNotEquals(modification1.hashCode(), modification3.hashCode()); + } + + @Test + public void testGetterAndSetter() { + BigIntegerShiftRightModification modification = new BigIntegerShiftRightModification(); + + int shift = 25; + modification.setShift(shift); + + assertEquals(shift, modification.getShift()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java new file mode 100644 index 00000000..88ee0bd2 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/integer/IntegerShiftModificationTest.java @@ -0,0 +1,194 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.integer; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class IntegerShiftModificationTest { + + private ModifiableInteger modifiableInteger; + private int originalValue; + + @BeforeEach + public void setUp() { + modifiableInteger = new ModifiableInteger(); + originalValue = 123456; + modifiableInteger.setOriginalValue(originalValue); + } + + @Test + public void testShiftLeftModification() { + int shift = 4; + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue << shift; + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithZeroShift() { + int shift = 0; + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue; // Shifting by 0 should return the same value + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithMaxShift() { + int shift = 31; // Max shift for int is 31 bits + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue << shift; + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftWithNullInput() { + modifiableInteger.setOriginalValue(null); + + int shift = 4; + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(shift); + modifiableInteger.setModifications(modification); + + int expected = 0 << shift; // Should treat null as 0 + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftLeftEqualsAndHashCode() { + int shift = 10; + IntegerShiftLeftModification modification1 = new IntegerShiftLeftModification(shift); + IntegerShiftLeftModification modification2 = new IntegerShiftLeftModification(shift); + IntegerShiftLeftModification modification3 = new IntegerShiftLeftModification(shift + 1); + + // Test equals + assertEquals(modification1, modification2); + assertNotEquals(modification1, modification3); + + // Test hashCode + assertEquals(modification1.hashCode(), modification2.hashCode()); + assertNotEquals(modification1.hashCode(), modification3.hashCode()); + } + + @Test + public void testShiftLeftGetterAndSetter() { + IntegerShiftLeftModification modification = new IntegerShiftLeftModification(); + + int shift = 15; + modification.setShift(shift); + + assertEquals(shift, modification.getShift()); + } + + @Test + public void testShiftRightModification() { + int shift = 4; + IntegerShiftRightModification modification = new IntegerShiftRightModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue >> shift; + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithNegativeNumber() { + int negativeValue = -98765; + modifiableInteger.setOriginalValue(negativeValue); + + int shift = 4; + IntegerShiftRightModification modification = new IntegerShiftRightModification(shift); + modifiableInteger.setModifications(modification); + + int expected = negativeValue >> shift; + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithZeroShift() { + int shift = 0; + IntegerShiftRightModification modification = new IntegerShiftRightModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue; // Shifting by 0 should return the same value + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithMaxShift() { + int shift = 31; // Max shift for int is 31 bits + IntegerShiftRightModification modification = new IntegerShiftRightModification(shift); + modifiableInteger.setModifications(modification); + + int expected = originalValue >> shift; + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightWithNullInput() { + modifiableInteger.setOriginalValue(null); + + int shift = 4; + IntegerShiftRightModification modification = new IntegerShiftRightModification(shift); + modifiableInteger.setModifications(modification); + + int expected = 0 >> shift; // Should treat null as 0 + int result = modifiableInteger.getValue(); + + assertEquals(expected, result); + } + + @Test + public void testShiftRightEqualsAndHashCode() { + int shift = 10; + IntegerShiftRightModification modification1 = new IntegerShiftRightModification(shift); + IntegerShiftRightModification modification2 = new IntegerShiftRightModification(shift); + IntegerShiftRightModification modification3 = new IntegerShiftRightModification(shift + 1); + + // Test equals + assertEquals(modification1, modification2); + assertNotEquals(modification1, modification3); + + // Test hashCode + assertEquals(modification1.hashCode(), modification2.hashCode()); + assertNotEquals(modification1.hashCode(), modification3.hashCode()); + } + + @Test + public void testShiftRightGetterAndSetter() { + IntegerShiftRightModification modification = new IntegerShiftRightModification(); + + int shift = 15; + modification.setShift(shift); + + assertEquals(shift, modification.getShift()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java b/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java new file mode 100644 index 00000000..8c84d4ba --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/string/ModifiableStringTest.java @@ -0,0 +1,91 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.string; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import de.rub.nds.modifiablevariable.VariableModification; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class ModifiableStringTest { + + private static final Logger LOGGER = LogManager.getLogger(); + private ModifiableString string; + + @BeforeEach + public void setUp() { + string = new ModifiableString(); + string.setOriginalValue("TestString"); + } + + @Test + public void testIsOriginalValueModified() { + assertFalse(string.isOriginalValueModified()); + VariableModification modifier = StringModificationFactory.appendValue("_Modified"); + string.setModifications(modifier); + assertTrue(string.isOriginalValueModified()); + } + + @Test + public void testGetterAndSetterMethods() { + assertEquals("TestString", string.getOriginalValue()); + assertEquals("TestString", string.getValue()); + + string.setOriginalValue("NewTestString"); + assertEquals("NewTestString", string.getOriginalValue()); + assertEquals("NewTestString", string.getValue()); + } + + @Test + public void testAssertions() { + string.setAssertEquals("TestString"); + assertTrue(string.validateAssertions()); + + string.setAssertEquals("WrongValue"); + assertFalse(string.validateAssertions()); + } + + @Test + public void testGetByteArray() { + byte[] expected = "TestString".getBytes(java.nio.charset.StandardCharsets.ISO_8859_1); + byte[] actual = string.getByteArray(expected.length); + + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], actual[i]); + } + } + + @Test + public void testEquals() { + ModifiableString string2 = new ModifiableString(); + string2.setOriginalValue("TestString"); + assertEquals(string, string2); + assertEquals(string2, string); + string2.setModifications(StringModificationFactory.appendValue("_Modified")); + assertNotEquals(string, string2); + assertNotEquals(string2, string); + assertFalse(string.equals(null)); + assertFalse(string.equals("TestString")); + } + + @Test + public void testToString() { + String expectedToString = "ModifiableString{originalValue='TestString'}"; + assertEquals(expectedToString, string.toString()); + + string.setOriginalValue("Test\\String"); + String expectedEscaped = "ModifiableString{originalValue='Test\\\\String'}"; + assertEquals(expectedEscaped, string.toString()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/string/StringModificationTest.java b/src/test/java/de/rub/nds/modifiablevariable/string/StringModificationTest.java new file mode 100644 index 00000000..6da8c997 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/string/StringModificationTest.java @@ -0,0 +1,112 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.string; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import de.rub.nds.modifiablevariable.VariableModification; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class StringModificationTest { + + private ModifiableString modifiableString; + private String originalValue = "TestValue"; + + @BeforeEach + public void setUp() { + modifiableString = new ModifiableString(); + modifiableString.setOriginalValue(originalValue); + } + + @Test + public void testAppendModification() { + String appendValue = "Appended"; + VariableModification modifier = StringModificationFactory.appendValue(appendValue); + modifiableString.setModifications(modifier); + + assertEquals(originalValue + appendValue, modifiableString.getValue()); + } + + @Test + public void testPrependModification() { + String prependValue = "Prepended"; + VariableModification modifier = + StringModificationFactory.prependValue(prependValue); + modifiableString.setModifications(modifier); + + assertEquals(prependValue + originalValue, modifiableString.getValue()); + } + + @Test + public void testExplicitValueModification() { + String explicitValue = "CompletelyDifferent"; + VariableModification modifier = + StringModificationFactory.explicitValue(explicitValue); + modifiableString.setModifications(modifier); + + assertEquals(explicitValue, modifiableString.getValue()); + assertNotEquals(originalValue, modifiableString.getValue()); + } + + @Test + public void testAppendWithEmptyString() { + String appendValue = ""; + VariableModification modifier = StringModificationFactory.appendValue(appendValue); + modifiableString.setModifications(modifier); + + assertEquals(originalValue, modifiableString.getValue()); + } + + @Test + public void testPrependWithEmptyString() { + String prependValue = ""; + VariableModification modifier = + StringModificationFactory.prependValue(prependValue); + modifiableString.setModifications(modifier); + + assertEquals(originalValue, modifiableString.getValue()); + } + + @Test + public void testAppendToEmptyString() { + modifiableString.setOriginalValue(""); + String appendValue = "JustAppended"; + VariableModification modifier = StringModificationFactory.appendValue(appendValue); + modifiableString.setModifications(modifier); + + assertEquals(appendValue, modifiableString.getValue()); + } + + @Test + public void testPrependToEmptyString() { + modifiableString.setOriginalValue(""); + String prependValue = "JustPrepended"; + VariableModification modifier = + StringModificationFactory.prependValue(prependValue); + modifiableString.setModifications(modifier); + + assertEquals(prependValue, modifiableString.getValue()); + } + + @Test + public void testModifierEquality() { + String appendValue = "SomeValue"; + StringAppendValueModification modifier1 = new StringAppendValueModification(appendValue); + StringAppendValueModification modifier2 = new StringAppendValueModification(appendValue); + + assertEquals(modifier1, modifier2); + assertEquals(modifier1.hashCode(), modifier2.hashCode()); + + StringAppendValueModification modifier3 = + new StringAppendValueModification("DifferentValue"); + assertNotEquals(modifier1, modifier3); + assertNotEquals(modifier1.hashCode(), modifier3.hashCode()); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/ComparableByteArrayTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/ComparableByteArrayTest.java new file mode 100644 index 00000000..53550011 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/util/ComparableByteArrayTest.java @@ -0,0 +1,110 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.util; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class ComparableByteArrayTest { + + @Test + public void testConstructorAndGetters() { + byte[] array = new byte[] {1, 2, 3, 4, 5}; + ComparableByteArray comparableArray = new ComparableByteArray(array); + + assertArrayEquals(array, comparableArray.getArray()); + } + + @Test + public void testSetArray() { + byte[] initialArray = new byte[] {1, 2, 3}; + ComparableByteArray comparableArray = new ComparableByteArray(initialArray); + + byte[] newArray = new byte[] {4, 5, 6, 7}; + comparableArray.setArray(newArray); + + assertArrayEquals(newArray, comparableArray.getArray()); + } + + @Test + public void testEqualsWithSameContent() { + byte[] array1 = new byte[] {1, 2, 3, 4, 5}; + byte[] array2 = new byte[] {1, 2, 3, 4, 5}; // Same content but different object + + ComparableByteArray comparable1 = new ComparableByteArray(array1); + ComparableByteArray comparable2 = new ComparableByteArray(array2); + + // Test equality + assertTrue(comparable1.equals(comparable2)); + assertTrue(comparable2.equals(comparable1)); + + // Test hashCode + assertEquals(comparable1.hashCode(), comparable2.hashCode()); + } + + @Test + public void testEqualsWithDifferentContent() { + byte[] array1 = new byte[] {1, 2, 3, 4, 5}; + byte[] array2 = new byte[] {1, 2, 3, 4, 6}; // Different at last position + + ComparableByteArray comparable1 = new ComparableByteArray(array1); + ComparableByteArray comparable2 = new ComparableByteArray(array2); + + // Test inequality + assertFalse(comparable1.equals(comparable2)); + assertFalse(comparable2.equals(comparable1)); + + // Test hashCode should likely be different (not guaranteed but highly probable) + assertNotEquals(comparable1.hashCode(), comparable2.hashCode()); + } + + @Test + public void testEqualsWithDifferentLength() { + byte[] array1 = new byte[] {1, 2, 3}; + byte[] array2 = new byte[] {1, 2, 3, 4}; // Extra element + + ComparableByteArray comparable1 = new ComparableByteArray(array1); + ComparableByteArray comparable2 = new ComparableByteArray(array2); + + // Test inequality + assertFalse(comparable1.equals(comparable2)); + assertFalse(comparable2.equals(comparable1)); + } + + @Test + public void testEqualsWithSameInstance() { + byte[] array = new byte[] {1, 2, 3, 4, 5}; + ComparableByteArray comparable = new ComparableByteArray(array); + + // Test equality with same instance + assertTrue(comparable.equals(comparable)); + } + + @Test + public void testEqualsWithNull() { + byte[] array = new byte[] {1, 2, 3, 4, 5}; + ComparableByteArray comparable = new ComparableByteArray(array); + + // Test equality with null + assertFalse(comparable.equals(null)); + } + + @Test + public void testEqualsWithDifferentClass() { + byte[] array = new byte[] {1, 2, 3, 4, 5}; + ComparableByteArray comparable = new ComparableByteArray(array); + + // Test equality with object of different class + assertFalse(comparable.equals("Not a ComparableByteArray")); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java new file mode 100644 index 00000000..0e58fce1 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/util/RandomHelperTest.java @@ -0,0 +1,137 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Random; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +public class RandomHelperTest { + + @AfterEach + public void tearDown() { + // Reset to default random for other tests + RandomHelper.setRandom(new Random(0)); + } + + @Test + public void testGetRandom() { + Random random = RandomHelper.getRandom(); + assertNotNull(random); + + // Test that the random is initialized with a fixed seed (0) + // by comparing with a known sequence + Random expectedRandom = new Random(0); + for (int i = 0; i < 10; i++) { + assertEquals(expectedRandom.nextInt(), random.nextInt()); + } + } + + @Test + public void testSetRandom() { + Random customRandom = new Random(42); + RandomHelper.setRandom(customRandom); + + Random retrievedRandom = RandomHelper.getRandom(); + assertNotNull(retrievedRandom); + + // Verify it's the same random instance + assertTrue( + retrievedRandom == customRandom, + "Retrieved random should be the same instance as set"); + } + + @Test + public void testGetBadSecureRandom() { + BadRandom badRandom = RandomHelper.getBadSecureRandom(); + assertNotNull(badRandom); + + // Verify the bad random produces expected output based on the fixed seed + Random expectedRandom = new Random(0); + for (int i = 0; i < 10; i++) { + assertEquals(expectedRandom.nextInt(), badRandom.nextInt()); + } + + // Verify it returns the warning message + String algorithm = badRandom.getAlgorithm(); + assertTrue(algorithm.contains("WARNING") && algorithm.contains("insecure")); + } + + @Test + public void testBadRandomImplementation() { + BadRandom badRandom = new BadRandom(); + + // Test default constructor + // Just test that we can get values (don't compare the actual values + // since they might be inconsistent between test runs) + badRandom.nextInt(); + + // Test setSeed + badRandom.setSeed(42); + + // Test other methods without comparing exact values + byte[] bytes = new byte[10]; + badRandom.nextBytes(bytes); + + // Just verify these methods don't throw exceptions + badRandom.nextBoolean(); + badRandom.nextDouble(); + badRandom.nextFloat(); + badRandom.nextGaussian(); + badRandom.nextLong(); + + // Test generateSeed + byte[] generatedSeed = badRandom.generateSeed(5); + assertEquals(5, generatedSeed.length); + + // setSeed with byte array should throw UnsupportedOperationException + assertThrows(UnsupportedOperationException.class, () -> badRandom.setSeed(new byte[1])); + } + + @Test + public void testBadRandomConstructors() { + Random customRandom = new Random(123); + + // Test constructor with Random and seed + BadRandom badRandom1 = new BadRandom(customRandom, null); + assertNotNull(badRandom1.nextInt()); // Just verify it returns a value + + // Test constructor with Random, SPI, and Provider + BadRandom badRandom2 = new BadRandom(customRandom, null, null); + assertNotNull(badRandom2.nextInt()); // Just verify it returns a value + } + + @Test + public void testBadFixedRandom() { + byte fixedValue = 42; // Using a single byte as per the class implementation + BadFixedRandom fixedRandom = new BadFixedRandom(fixedValue); + + byte[] result = new byte[5]; + fixedRandom.nextBytes(result); + + // Verify all bytes in the array are set to the fixed value + for (int i = 0; i < result.length; i++) { + assertEquals(fixedValue, result[i]); + } + + // Test that it ignores the seed parameter + fixedRandom.setSeed(123); + byte[] resultAfterSeed = new byte[5]; + fixedRandom.nextBytes(resultAfterSeed); + + // Verify all bytes are still the fixed value + for (int i = 0; i < resultAfterSeed.length; i++) { + assertEquals(fixedValue, resultAfterSeed[i]); + } + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/ReflectionHelperTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/ReflectionHelperTest.java new file mode 100644 index 00000000..af821541 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/util/ReflectionHelperTest.java @@ -0,0 +1,169 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class ReflectionHelperTest { + + // Helper method to set private fields using reflection + private static void setPrivateField(Object object, String fieldName, Object value) + throws IllegalAccessException { + try { + Field field = findField(object.getClass(), fieldName); + field.setAccessible(true); + field.set(object, value); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + // Helper method to find a field in a class or its superclasses + private static Field findField(Class clazz, String fieldName) throws NoSuchFieldException { + try { + return clazz.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + if (clazz.getSuperclass() != null) { + return findField(clazz.getSuperclass(), fieldName); + } + throw e; + } + } + + private static class BaseClass { + private String baseField; + private int baseIntField; + } + + private static class ChildClass extends BaseClass { + private String childField; + private double childDoubleField; + } + + private static class GenericClass { + private T genericField; + } + + private static class StringGenericImpl extends GenericClass { + private String anotherField; + } + + @Test + public void testGetFieldsUpTo() { + // Get all fields from ChildClass up to but not including Object + List fields = ReflectionHelper.getFieldsUpTo(ChildClass.class, Object.class, null); + + // Should have 4 fields: childField, childDoubleField from ChildClass + // and baseField, baseIntField from BaseClass + assertEquals(4, fields.size()); + + // Verify field names + boolean foundChildField = false; + boolean foundChildDoubleField = false; + boolean foundBaseField = false; + boolean foundBaseIntField = false; + + for (Field field : fields) { + switch (field.getName()) { + case "childField": + foundChildField = true; + assertEquals(String.class, field.getType()); + break; + case "childDoubleField": + foundChildDoubleField = true; + assertEquals(double.class, field.getType()); + break; + case "baseField": + foundBaseField = true; + assertEquals(String.class, field.getType()); + break; + case "baseIntField": + foundBaseIntField = true; + assertEquals(int.class, field.getType()); + break; + } + } + + assertTrue(foundChildField); + assertTrue(foundChildDoubleField); + assertTrue(foundBaseField); + assertTrue(foundBaseIntField); + } + + @Test + public void testGetFieldsUpToWithFilter() { + // Get only String fields + List stringFields = + ReflectionHelper.getFieldsUpTo(ChildClass.class, Object.class, String.class); + + assertEquals(2, stringFields.size()); + + // Verify they are the string fields + boolean foundChildField = false; + boolean foundBaseField = false; + + for (Field field : stringFields) { + switch (field.getName()) { + case "childField": + foundChildField = true; + assertEquals(String.class, field.getType()); + break; + case "baseField": + foundBaseField = true; + assertEquals(String.class, field.getType()); + break; + } + } + + assertTrue(foundChildField); + assertTrue(foundBaseField); + } + + @Test + public void testGetValuesFromFieldList() throws IllegalAccessException { + ChildClass childClass = new ChildClass(); + // Use reflection to set private fields instead of direct access + setPrivateField(childClass, "baseField", "BaseValue"); + setPrivateField(childClass, "baseIntField", 42); + setPrivateField(childClass, "childField", "ChildValue"); + setPrivateField(childClass, "childDoubleField", 3.14); + + List fields = ReflectionHelper.getFieldsUpTo(ChildClass.class, Object.class, null); + List values = ReflectionHelper.getValuesFromFieldList(childClass, fields); + + assertEquals(4, values.size()); + assertTrue(values.contains("BaseValue")); + assertTrue(values.contains(42)); + assertTrue(values.contains("ChildValue")); + assertTrue(values.contains(3.14)); + } + + @Test + public void testGetParameterizedTypes() { + StringGenericImpl impl = new StringGenericImpl(); + Type[] types = ReflectionHelper.getParameterizedTypes(impl); + + assertNotNull(types); + assertEquals(1, types.length); + assertEquals(String.class, types[0]); + + // Test with a non-parameterized class + BaseClass baseClass = new BaseClass(); + types = ReflectionHelper.getParameterizedTypes(baseClass); + + assertNull(types); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapterTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapterTest.java new file mode 100644 index 00000000..0db5f8a4 --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/util/SuppressingBooleanAdapterTest.java @@ -0,0 +1,54 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; + +public class SuppressingBooleanAdapterTest { + + @Test + public void testSuppressingTrueBooleanAdapter() throws Exception { + SuppressingBooleanAdapter adapter = new SuppressingTrueBooleanAdapter(); + + // Test getValueToSuppress + assertEquals(Boolean.TRUE, adapter.getValueToSuppress()); + + // Test unmarshal + assertEquals(Boolean.TRUE, adapter.unmarshal(null)); + assertEquals(Boolean.TRUE, adapter.unmarshal("true")); + assertEquals(Boolean.FALSE, adapter.unmarshal("false")); + assertEquals(Boolean.FALSE, adapter.unmarshal("anything")); + + // Test marshal + assertNull(adapter.marshal(Boolean.TRUE)); + assertNull(adapter.marshal(null)); + assertEquals("false", adapter.marshal(Boolean.FALSE)); + } + + @Test + public void testSuppressingFalseBooleanAdapter() throws Exception { + SuppressingBooleanAdapter adapter = new SuppressingFalseBooleanAdapter(); + + // Test getValueToSuppress + assertEquals(Boolean.FALSE, adapter.getValueToSuppress()); + + // Test unmarshal + assertEquals(Boolean.FALSE, adapter.unmarshal(null)); + assertEquals(Boolean.TRUE, adapter.unmarshal("true")); + assertEquals(Boolean.FALSE, adapter.unmarshal("false")); + assertEquals(Boolean.FALSE, adapter.unmarshal("anything")); + + // Test marshal + assertNull(adapter.marshal(Boolean.FALSE)); + assertNull(adapter.marshal(null)); + assertEquals("true", adapter.marshal(Boolean.TRUE)); + } +} diff --git a/src/test/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapterTest.java b/src/test/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapterTest.java new file mode 100644 index 00000000..3105886a --- /dev/null +++ b/src/test/java/de/rub/nds/modifiablevariable/util/UnformattedByteArrayAdapterTest.java @@ -0,0 +1,80 @@ +/* + * ModifiableVariable - A Variable Concept for Runtime Modifications + * + * Ruhr University Bochum, Paderborn University, Technology Innovation Institute, and Hackmanit GmbH + * + * Licensed under Apache License 2.0 http://www.apache.org/licenses/LICENSE-2.0 + */ +package de.rub.nds.modifiablevariable.util; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class UnformattedByteArrayAdapterTest { + + private UnformattedByteArrayAdapter adapter; + + @BeforeEach + public void setUp() { + adapter = new UnformattedByteArrayAdapter(); + } + + @Test + public void testMarshal() throws Exception { + byte[] input = new byte[] {0x01, 0x02, 0x03, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + String expected = "01 02 03 AB CD EF"; + + assertEquals(expected, adapter.marshal(input)); + } + + @Test + public void testUnmarshalCompactFormat() throws Exception { + String input = "0102ABCDEF"; + byte[] expected = new byte[] {0x01, 0x02, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + + assertArrayEquals(expected, adapter.unmarshal(input)); + } + + @Test + public void testUnmarshalWithSpaces() throws Exception { + String input = "01 02 AB CD EF"; + byte[] expected = new byte[] {0x01, 0x02, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + + assertArrayEquals(expected, adapter.unmarshal(input)); + } + + @Test + public void testUnmarshalWithNewlinesAndSpaces() throws Exception { + String input = "01 02\nAB CD\r\nEF"; + byte[] expected = new byte[] {0x01, 0x02, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF}; + + assertArrayEquals(expected, adapter.unmarshal(input)); + } + + @Test + public void testMarshalEmptyArray() throws Exception { + byte[] input = new byte[0]; + String expected = ""; + + assertEquals(expected, adapter.marshal(input)); + } + + @Test + public void testUnmarshalEmptyString() throws Exception { + String input = ""; + byte[] expected = new byte[0]; + + assertArrayEquals(expected, adapter.unmarshal(input)); + } + + @Test + public void testUnmarshalOnlyWhitespace() throws Exception { + String input = " \n\t\r "; + byte[] expected = new byte[0]; + + assertArrayEquals(expected, adapter.unmarshal(input)); + } +}