diff --git a/tests/record/annotations/Test.java b/tests/record/annotations/Test.java new file mode 100644 index 00000000..4cf9c3c8 --- /dev/null +++ b/tests/record/annotations/Test.java @@ -0,0 +1,170 @@ +import java.lang.annotation.*; +import java.lang.reflect.*; + +// Custom annotations for testing +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.RECORD_COMPONENT, ElementType.PARAMETER}) +@interface MyAnnotation { + String value() default ""; + int priority() default 1; +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.RECORD_COMPONENT) +@interface NotNull { +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.RECORD_COMPONENT) +@interface Range { + int min() default 0; + int max() default 100; +} + +public class Test { + + // Annotated record + @MyAnnotation("PersonRecord") + record Person(@NotNull String name, @Range(min = 0, max = 150) int age) {} + + // Record with multiple annotations + record Product( + @MyAnnotation("ProductName") @NotNull String name, + @MyAnnotation(value = "ProductPrice", priority = 2) double price, + @Range(min = 0, max = 1000) int quantity + ) {} + + // Record with annotation on type + @MyAnnotation("ConfigRecord") + record Config(String host, int port, boolean secure) {} + + public static void main(String[] args) { + System.out.println("=== Annotations Tests ==="); + + testRecordAnnotations(); + testComponentAnnotations(); + testAnnotationReflection(); + testMultipleAnnotations(); + testAnnotationValues(); + } + + public static void testRecordAnnotations() { + System.out.println("--- Test Record Annotations ---"); + Class personClass = Person.class; + + System.out.println("Person class is annotated: " + personClass.isAnnotationPresent(MyAnnotation.class)); + + if (personClass.isAnnotationPresent(MyAnnotation.class)) { + MyAnnotation annotation = personClass.getAnnotation(MyAnnotation.class); + System.out.println("Annotation value: " + annotation.value()); + System.out.println("Annotation priority: " + annotation.priority()); + } + + Class configClass = Config.class; + System.out.println("Config class is annotated: " + configClass.isAnnotationPresent(MyAnnotation.class)); + + if (configClass.isAnnotationPresent(MyAnnotation.class)) { + MyAnnotation annotation = configClass.getAnnotation(MyAnnotation.class); + System.out.println("Config annotation value: " + annotation.value()); + } + } + + public static void testComponentAnnotations() { + System.out.println("--- Test Component Annotations ---"); + Class personClass = Person.class; + RecordComponent[] components = personClass.getRecordComponents(); + + for (RecordComponent component : components) { + System.out.println("Component: " + component.getName()); + + if (component.isAnnotationPresent(NotNull.class)) { + System.out.println(" Has @NotNull annotation"); + } + + if (component.isAnnotationPresent(Range.class)) { + Range range = component.getAnnotation(Range.class); + System.out.println(" Has @Range annotation: min=" + range.min() + ", max=" + range.max()); + } + + Annotation[] annotations = component.getAnnotations(); + System.out.println(" Total annotations: " + annotations.length); + } + } + + public static void testAnnotationReflection() { + System.out.println("--- Test Annotation Reflection ---"); + Class productClass = Product.class; + RecordComponent[] components = productClass.getRecordComponents(); + + for (RecordComponent component : components) { + System.out.println("Component: " + component.getName()); + + Annotation[] annotations = component.getAnnotations(); + for (Annotation annotation : annotations) { + System.out.println(" Annotation type: " + annotation.annotationType().getSimpleName()); + + if (annotation instanceof MyAnnotation) { + MyAnnotation myAnnotation = (MyAnnotation) annotation; + System.out.println(" Value: " + myAnnotation.value()); + System.out.println(" Priority: " + myAnnotation.priority()); + } + + if (annotation instanceof Range) { + Range range = (Range) annotation; + System.out.println(" Min: " + range.min()); + System.out.println(" Max: " + range.max()); + } + } + } + } + + public static void testMultipleAnnotations() { + System.out.println("--- Test Multiple Annotations ---"); + Product product = new Product("Laptop", 999.99, 50); + Class productClass = Product.class; + + try { + RecordComponent nameComponent = null; + RecordComponent priceComponent = null; + + for (RecordComponent component : productClass.getRecordComponents()) { + if ("name".equals(component.getName())) { + nameComponent = component; + } else if ("price".equals(component.getName())) { + priceComponent = component; + } + } + + if (nameComponent != null) { + System.out.println("Name component annotations:"); + System.out.println(" @MyAnnotation present: " + nameComponent.isAnnotationPresent(MyAnnotation.class)); + System.out.println(" @NotNull present: " + nameComponent.isAnnotationPresent(NotNull.class)); + } + + if (priceComponent != null) { + System.out.println("Price component annotations:"); + System.out.println(" @MyAnnotation present: " + priceComponent.isAnnotationPresent(MyAnnotation.class)); + if (priceComponent.isAnnotationPresent(MyAnnotation.class)) { + MyAnnotation annotation = priceComponent.getAnnotation(MyAnnotation.class); + System.out.println(" Value: " + annotation.value()); + System.out.println(" Priority: " + annotation.priority()); + } + } + } catch (Exception e) { + System.out.println("Error accessing annotations: " + e.getMessage()); + } + } + + public static void testAnnotationValues() { + System.out.println("--- Test Annotation Values ---"); + Person person = new Person("Alice", 30); + + System.out.println("Created person: " + person); + System.out.println("Person name: " + person.name()); + System.out.println("Person age: " + person.age()); + + // Annotations don't affect runtime behavior directly + // but can be used for validation, documentation, etc. + System.out.println("Annotations are metadata only - person created successfully"); + } +} diff --git a/tests/record/annotations/ignore.txt b/tests/record/annotations/ignore.txt new file mode 100644 index 00000000..60f1136c --- /dev/null +++ b/tests/record/annotations/ignore.txt @@ -0,0 +1,2 @@ +thread '' has overflowed its stack +fatal runtime error: stack overflow, aborting diff --git a/tests/record/basic/Test.java b/tests/record/basic/Test.java new file mode 100644 index 00000000..3fdc66e4 --- /dev/null +++ b/tests/record/basic/Test.java @@ -0,0 +1,72 @@ +public class Test { + + // Basic record definition + record Person(String name, int age) {} + + record Point(int x, int y) {} + + record Empty() {} + + public static void main(String[] args) { + System.out.println("=== Basic Record Tests ==="); + + testBasicRecordCreation(); + testRecordAccessors(); + testEmptyRecord(); + testRecordWithMultipleComponents(); + testRecordInstantiation(); + } + + public static void testBasicRecordCreation() { + System.out.println("--- Test Basic Record Creation ---"); + Person person = new Person("Alice", 30); + System.out.println("Created person: " + person); + System.out.println("Person class: " + person.getClass().getName()); + System.out.println("Is record: " + person.getClass().isRecord()); + } + + public static void testRecordAccessors() { + System.out.println("--- Test Record Accessors ---"); + Person person = new Person("Bob", 25); + System.out.println("Name: " + person.name()); + System.out.println("Age: " + person.age()); + + Point point = new Point(10, 20); + System.out.println("X: " + point.x()); + System.out.println("Y: " + point.y()); + } + + public static void testEmptyRecord() { + System.out.println("--- Test Empty Record ---"); + Empty empty = new Empty(); + System.out.println("Empty record: " + empty); + System.out.println("Empty record class: " + empty.getClass().getName()); + System.out.println("Is record: " + empty.getClass().isRecord()); + } + + public static void testRecordWithMultipleComponents() { + System.out.println("--- Test Record With Multiple Components ---"); + record Address(String street, String city, String state, int zipCode) {} + + Address address = new Address("123 Main St", "Springfield", "IL", 62701); + System.out.println("Address: " + address); + System.out.println("Street: " + address.street()); + System.out.println("City: " + address.city()); + System.out.println("State: " + address.state()); + System.out.println("Zip: " + address.zipCode()); + } + + public static void testRecordInstantiation() { + System.out.println("--- Test Record Instantiation ---"); + Person[] people = { + new Person("Charlie", 35), + new Person("Diana", 28), + new Person("Eve", 42) + }; + + for (Person p : people) { + System.out.println("Person: " + p.name() + " is " + p.age() + " years old"); + } + } +} + diff --git a/tests/record/basic/ignore.txt b/tests/record/basic/ignore.txt new file mode 100644 index 00000000..8408d102 --- /dev/null +++ b/tests/record/basic/ignore.txt @@ -0,0 +1,14 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[15] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(15) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: === Basic Record Tests === +--- Test Basic Record Creation --- + +stderr: ") \ No newline at end of file diff --git a/tests/record/constructors/Test.java b/tests/record/constructors/Test.java new file mode 100644 index 00000000..37b4b77b --- /dev/null +++ b/tests/record/constructors/Test.java @@ -0,0 +1,100 @@ +public class Test { + + // Record with custom constructor + record Person(String name, int age) { + public Person { + if (name == null || name.isEmpty()) { + throw new IllegalArgumentException("Name cannot be null or empty"); + } + if (age < 0) { + throw new IllegalArgumentException("Age cannot be negative"); + } + } + } + + // Record with custom canonical constructor + record Point(int x, int y) { + public Point(int x, int y) { + this.x = Math.max(0, x); + this.y = Math.max(0, y); + } + } + + // Record with additional constructors + record Rectangle(int width, int height) { + public Rectangle { + if (width <= 0 || height <= 0) { + throw new IllegalArgumentException("Width and height must be positive"); + } + } + + // Additional constructor for square + public Rectangle(int size) { + this(size, size); + } + } + + public static void main(String[] args) { + System.out.println("=== Constructor Tests ==="); + + testCompactConstructor(); + testCanonicalConstructor(); + testAdditionalConstructors(); + testConstructorValidation(); + } + + public static void testCompactConstructor() { + System.out.println("--- Test Compact Constructor ---"); + try { + Person person = new Person("Alice", 30); + System.out.println("Valid person created: " + person); + } catch (Exception e) { + System.out.println("Error: " + e.getMessage()); + } + } + + public static void testCanonicalConstructor() { + System.out.println("--- Test Canonical Constructor ---"); + Point point1 = new Point(-5, 10); + Point point2 = new Point(15, -3); + System.out.println("Point1 (negative x adjusted): " + point1); + System.out.println("Point2 (negative y adjusted): " + point2); + } + + public static void testAdditionalConstructors() { + System.out.println("--- Test Additional Constructors ---"); + Rectangle rect1 = new Rectangle(10, 20); + Rectangle square = new Rectangle(15); + System.out.println("Rectangle: " + rect1); + System.out.println("Square: " + square); + } + + public static void testConstructorValidation() { + System.out.println("--- Test Constructor Validation ---"); + + // Test invalid name + try { + Person invalidPerson = new Person("", 25); + System.out.println("Should not reach here"); + } catch (IllegalArgumentException e) { + System.out.println("Caught expected exception for empty name: " + e.getMessage()); + } + + // Test invalid age + try { + Person invalidPerson = new Person("Bob", -5); + System.out.println("Should not reach here"); + } catch (IllegalArgumentException e) { + System.out.println("Caught expected exception for negative age: " + e.getMessage()); + } + + // Test invalid rectangle + try { + Rectangle invalidRect = new Rectangle(0, 10); + System.out.println("Should not reach here"); + } catch (IllegalArgumentException e) { + System.out.println("Caught expected exception for invalid rectangle: " + e.getMessage()); + } + } +} + diff --git a/tests/record/constructors/ignore.txt b/tests/record/constructors/ignore.txt new file mode 100644 index 00000000..14e43c8f --- /dev/null +++ b/tests/record/constructors/ignore.txt @@ -0,0 +1,14 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/BootstrapMethodError) + backtrace=java/lang/StackTraceElement[8] + detailMessage=String(\"Invalid bootstrap method descriptor: (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;\") + cause=Object(class java/lang/BootstrapMethodError) + stackTrace=java/lang/StackTraceElement[0] + depth=int(8) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + })))): +stdout: === Constructor Tests === +--- Test Compact Constructor --- +Error: array cannot be null +--- Test Canonical Constructor --- + +stderr: ") diff --git a/tests/record/generics/Test.java b/tests/record/generics/Test.java new file mode 100644 index 00000000..3ae4abad --- /dev/null +++ b/tests/record/generics/Test.java @@ -0,0 +1,122 @@ +import java.util.*; + +public class Test { + + // Generic record with single type parameter + record Container(T value) {} + + // Generic record with multiple type parameters + record Pair(K key, V value) {} + + // Generic record with bounded type parameters + record NumberPair(T first, T second) {} + + // Generic record with wildcard usage + record ListContainer(List items) {} + + public static void main(String[] args) { + System.out.println("=== Generics Tests ==="); + + testGenericRecord(); + testMultipleTypeParameters(); + testBoundedTypeParameters(); + testGenericMethods(); + testWildcards(); + testTypeErasure(); + } + + public static void testGenericRecord() { + System.out.println("--- Test Generic Record ---"); + Container stringContainer = new Container<>("Hello World"); + Container intContainer = new Container<>(42); + Container boolContainer = new Container<>(true); + + System.out.println("String container: " + stringContainer); + System.out.println("String value: " + stringContainer.value()); + System.out.println("String value type: " + stringContainer.value().getClass().getSimpleName()); + + System.out.println("Integer container: " + intContainer); + System.out.println("Integer value: " + intContainer.value()); + System.out.println("Integer value type: " + intContainer.value().getClass().getSimpleName()); + + System.out.println("Boolean container: " + boolContainer); + System.out.println("Boolean value: " + boolContainer.value()); + } + + public static void testMultipleTypeParameters() { + System.out.println("--- Test Multiple Type Parameters ---"); + Pair nameAge = new Pair<>("Alice", 30); + Pair idName = new Pair<>(123, "Bob"); + Pair coordinates = new Pair<>("latitude", "longitude"); + + System.out.println("Name-Age pair: " + nameAge); + System.out.println("Key: " + nameAge.key() + ", Value: " + nameAge.value()); + + System.out.println("ID-Name pair: " + idName); + System.out.println("Key: " + idName.key() + ", Value: " + idName.value()); + + System.out.println("Coordinates pair: " + coordinates); + System.out.println("Key: " + coordinates.key() + ", Value: " + coordinates.value()); + } + + public static void testBoundedTypeParameters() { + System.out.println("--- Test Bounded Type Parameters ---"); + NumberPair intPair = new NumberPair<>(10, 20); + NumberPair doublePair = new NumberPair<>(3.14, 2.71); + NumberPair floatPair = new NumberPair<>(1.5f, 2.5f); + + System.out.println("Integer pair: " + intPair); + System.out.println("Double pair: " + doublePair); + System.out.println("Float pair: " + floatPair); + + // This would cause compilation error: + // NumberPair stringPair = new NumberPair<>("a", "b"); + } + + public static void testGenericMethods() { + System.out.println("--- Test Generic Methods ---"); + Container container1 = new Container<>("test"); + Container container2 = new Container<>("test"); + Container container3 = new Container<>("different"); + + System.out.println("container1.equals(container2): " + container1.equals(container2)); + System.out.println("container1.equals(container3): " + container1.equals(container3)); + System.out.println("container1.hashCode(): " + container1.hashCode()); + System.out.println("container2.hashCode(): " + container2.hashCode()); + } + + public static void testWildcards() { + System.out.println("--- Test Wildcards ---"); + List stringList = Arrays.asList("apple", "banana", "cherry"); + List intList = Arrays.asList(1, 2, 3, 4, 5); + + ListContainer stringListContainer = new ListContainer<>(stringList); + ListContainer intListContainer = new ListContainer<>(intList); + + System.out.println("String list container: " + stringListContainer); + System.out.println("String list size: " + stringListContainer.items().size()); + + System.out.println("Integer list container: " + intListContainer); + System.out.println("Integer list size: " + intListContainer.items().size()); + + // Test with nested generics + Container> nestedContainer = new Container<>(stringList); + System.out.println("Nested container: " + nestedContainer); + } + + public static void testTypeErasure() { + System.out.println("--- Test Type Erasure ---"); + Container stringContainer = new Container<>("hello"); + Container intContainer = new Container<>(42); + + System.out.println("String container class: " + stringContainer.getClass().getName()); + System.out.println("Integer container class: " + intContainer.getClass().getName()); + System.out.println("Same class: " + (stringContainer.getClass() == intContainer.getClass())); + + // Test raw types + @SuppressWarnings("rawtypes") + Container rawContainer = new Container("raw value"); + System.out.println("Raw container: " + rawContainer); + System.out.println("Raw container value: " + rawContainer.value()); + } +} diff --git a/tests/record/generics/ignore.txt b/tests/record/generics/ignore.txt new file mode 100644 index 00000000..03a49c23 --- /dev/null +++ b/tests/record/generics/ignore.txt @@ -0,0 +1,14 @@ + InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[15] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(15) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: === Generics Tests === +--- Test Generic Record --- + +stderr: ") \ No newline at end of file diff --git a/tests/record/inheritance/Test.java b/tests/record/inheritance/Test.java new file mode 100644 index 00000000..2ddc89d3 --- /dev/null +++ b/tests/record/inheritance/Test.java @@ -0,0 +1,85 @@ +interface Drawable { + void draw(); +} + +interface Comparable { + int compareTo(T other); +} + +public class Test { + + // Record implementing interfaces + record Circle(double radius) implements Drawable { + public void draw() { + System.out.println("Drawing circle with radius: " + radius); + } + } + + record Person(String name, int age) implements Comparable { + public int compareTo(Person other) { + int nameComparison = this.name.compareTo(other.name); + if (nameComparison != 0) { + return nameComparison; + } + return Integer.compare(this.age, other.age); + } + } + + // Records cannot extend classes (other than Record) + // This would cause compilation error: + // record InvalidRecord(String data) extends Object {} + + public static void main(String[] args) { + System.out.println("=== Inheritance Tests ==="); + + testRecordImplementsInterface(); + testRecordComparable(); + testRecordInheritance(); + testRecordSuperclass(); + } + + public static void testRecordImplementsInterface() { + System.out.println("--- Test Record Implements Interface ---"); + Circle circle = new Circle(5.0); + circle.draw(); + System.out.println("Circle is Drawable: " + (circle instanceof Drawable)); + } + + public static void testRecordComparable() { + System.out.println("--- Test Record Comparable ---"); + Person person1 = new Person("Alice", 30); + Person person2 = new Person("Bob", 25); + Person person3 = new Person("Alice", 35); + + System.out.println("person1.compareTo(person2): " + person1.compareTo(person2)); + System.out.println("person2.compareTo(person1): " + person2.compareTo(person1)); + System.out.println("person1.compareTo(person3): " + person1.compareTo(person3)); + System.out.println("person3.compareTo(person1): " + person3.compareTo(person1)); + } + + public static void testRecordInheritance() { + System.out.println("--- Test Record Inheritance ---"); + Person person = new Person("Charlie", 40); + + // Records implicitly extend java.lang.Record + System.out.println("Person superclass: " + person.getClass().getSuperclass().getName()); + System.out.println("Is Record instance: " + (person instanceof Record)); + + // Records are final - cannot be extended + System.out.println("Person class is final: " + + java.lang.reflect.Modifier.isFinal(person.getClass().getModifiers())); + } + + public static void testRecordSuperclass() { + System.out.println("--- Test Record Superclass Methods ---"); + Circle circle = new Circle(3.0); + + // Test methods inherited from Record + System.out.println("Circle toString: " + circle.toString()); + System.out.println("Circle equals itself: " + circle.equals(circle)); + System.out.println("Circle hashCode: " + circle.hashCode()); + + Circle circle2 = new Circle(3.0); + System.out.println("Two circles with same radius equal: " + circle.equals(circle2)); + } +} diff --git a/tests/record/inheritance/ignore.txt b/tests/record/inheritance/ignore.txt new file mode 100644 index 00000000..29a7f1fe --- /dev/null +++ b/tests/record/inheritance/ignore.txt @@ -0,0 +1,26 @@ + InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[13] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(13) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: === Inheritance Tests === +--- Test Record Implements Interface --- +Drawing circle with radius: 5.0 +Circle is Drawable: true +--- Test Record Comparable --- +person1.compareTo(person2): -1 +person2.compareTo(person1): 1 +person1.compareTo(person3): -1 +person3.compareTo(person1): 1 +--- Test Record Inheritance --- +Person superclass: java.lang.Record +Is Record instance: true +Person class is final: true +--- Test Record Superclass Methods --- + +stderr: ") diff --git a/tests/record/methods/Test.java b/tests/record/methods/Test.java new file mode 100644 index 00000000..e3301a30 --- /dev/null +++ b/tests/record/methods/Test.java @@ -0,0 +1,90 @@ +public class Test { + + record Person(String name, int age) {} + + record Point(int x, int y) {} + + record Book(String title, String author, int pages) {} + + public static void main(String[] args) { + System.out.println("=== Methods Tests ==="); + + testToString(); + testEquals(); + testHashCode(); + testEqualsAndHashCodeConsistency(); + } + + public static void testToString() { + System.out.println("--- Test toString() ---"); + Person person = new Person("Alice", 30); + Point point = new Point(10, 20); + Book book = new Book("1984", "George Orwell", 328); + + System.out.println("Person toString: " + person.toString()); + System.out.println("Point toString: " + point.toString()); + System.out.println("Book toString: " + book.toString()); + } + + public static void testEquals() { + System.out.println("--- Test equals() ---"); + Person person1 = new Person("Bob", 25); + Person person2 = new Person("Bob", 25); + Person person3 = new Person("Charlie", 25); + Person person4 = new Person("Bob", 30); + + System.out.println("person1.equals(person2): " + person1.equals(person2)); + System.out.println("person1.equals(person3): " + person1.equals(person3)); + System.out.println("person1.equals(person4): " + person1.equals(person4)); + System.out.println("person1.equals(null): " + person1.equals(null)); + System.out.println("person1.equals(\"string\"): " + person1.equals("string")); + + Point point1 = new Point(5, 10); + Point point2 = new Point(5, 10); + Point point3 = new Point(10, 5); + + System.out.println("point1.equals(point2): " + point1.equals(point2)); + System.out.println("point1.equals(point3): " + point1.equals(point3)); + } + + public static void testHashCode() { + System.out.println("--- Test hashCode() ---"); + Person person1 = new Person("Diana", 28); + Person person2 = new Person("Diana", 28); + Person person3 = new Person("Eve", 28); + + System.out.println("person1.hashCode(): " + person1.hashCode()); + System.out.println("person2.hashCode(): " + person2.hashCode()); + System.out.println("person3.hashCode(): " + person3.hashCode()); + System.out.println("person1.hashCode() == person2.hashCode(): " + (person1.hashCode() == person2.hashCode())); + + Point point1 = new Point(3, 7); + Point point2 = new Point(3, 7); + Point point3 = new Point(7, 3); + + System.out.println("point1.hashCode(): " + point1.hashCode()); + System.out.println("point2.hashCode(): " + point2.hashCode()); + System.out.println("point3.hashCode(): " + point3.hashCode()); + System.out.println("point1.hashCode() == point2.hashCode(): " + (point1.hashCode() == point2.hashCode())); + } + + public static void testEqualsAndHashCodeConsistency() { + System.out.println("--- Test equals() and hashCode() Consistency ---"); + Book book1 = new Book("To Kill a Mockingbird", "Harper Lee", 281); + Book book2 = new Book("To Kill a Mockingbird", "Harper Lee", 281); + Book book3 = new Book("Pride and Prejudice", "Jane Austen", 432); + + System.out.println("book1.equals(book2): " + book1.equals(book2)); + System.out.println("book1.hashCode() == book2.hashCode(): " + (book1.hashCode() == book2.hashCode())); + System.out.println("book1.equals(book3): " + book1.equals(book3)); + System.out.println("book1.hashCode() == book3.hashCode(): " + (book1.hashCode() == book3.hashCode())); + + // Test reflexivity + System.out.println("book1.equals(book1): " + book1.equals(book1)); + + // Test symmetry + System.out.println("book1.equals(book2) == book2.equals(book1): " + + (book1.equals(book2) == book2.equals(book1))); + } +} + diff --git a/tests/record/methods/ignore.txt b/tests/record/methods/ignore.txt new file mode 100644 index 00000000..bd1c9024 --- /dev/null +++ b/tests/record/methods/ignore.txt @@ -0,0 +1,14 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[13] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(13) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: === Methods Tests === +--- Test toString() --- + +stderr: ") \ No newline at end of file diff --git a/tests/record/nested/Test.java b/tests/record/nested/Test.java new file mode 100644 index 00000000..a3fd837b --- /dev/null +++ b/tests/record/nested/Test.java @@ -0,0 +1,123 @@ +public class Test { + + // Nested record inside class + record Address(String street, String city, String state, int zipCode) {} + + record Person(String name, int age, Address address) {} + + // Static nested record + static record Company(String name, Address headquarters) {} + + public static void main(String[] args) { + System.out.println("=== Nested Records Tests ==="); + + testNestedRecords(); + testLocalRecords(); + testRecordWithNestedRecord(); + testStaticNestedRecord(); + testNestedRecordAccess(); + } + + public static void testNestedRecords() { + System.out.println("--- Test Nested Records ---"); + Address address = new Address("123 Main St", "Springfield", "IL", 62701); + Person person = new Person("Alice", 30, address); + + System.out.println("Person: " + person); + System.out.println("Person name: " + person.name()); + System.out.println("Person address: " + person.address()); + System.out.println("Person street: " + person.address().street()); + System.out.println("Person city: " + person.address().city()); + } + + public static void testLocalRecords() { + System.out.println("--- Test Local Records ---"); + + // Local record inside method + record Point(int x, int y) { + public double distanceFromOrigin() { + return Math.sqrt(x * x + y * y); + } + } + + Point point1 = new Point(3, 4); + Point point2 = new Point(5, 12); + + System.out.println("Point1: " + point1); + System.out.println("Point1 distance from origin: " + point1.distanceFromOrigin()); + System.out.println("Point2: " + point2); + System.out.println("Point2 distance from origin: " + point2.distanceFromOrigin()); + } + + public static void testRecordWithNestedRecord() { + System.out.println("--- Test Record With Nested Record ---"); + + // Record containing another record + record Department(String name, Person manager) {} + + Address managerAddress = new Address("456 Oak Ave", "Chicago", "IL", 60601); + Person manager = new Person("Bob", 45, managerAddress); + Department department = new Department("Engineering", manager); + + System.out.println("Department: " + department); + System.out.println("Department name: " + department.name()); + System.out.println("Manager: " + department.manager()); + System.out.println("Manager name: " + department.manager().name()); + System.out.println("Manager address: " + department.manager().address()); + } + + public static void testStaticNestedRecord() { + System.out.println("--- Test Static Nested Record ---"); + Address headquarters = new Address("789 Business Blvd", "New York", "NY", 10001); + Company company = new Company("Tech Corp", headquarters); + + System.out.println("Company: " + company); + System.out.println("Company name: " + company.name()); + System.out.println("Headquarters: " + company.headquarters()); + System.out.println("Headquarters city: " + company.headquarters().city()); + } + + public static void testNestedRecordAccess() { + System.out.println("--- Test Nested Record Access ---"); + + // Test accessing nested components + Address address = new Address("321 Elm St", "Boston", "MA", 2101); + Person person = new Person("Charlie", 35, address); + + // Direct access + System.out.println("Direct access - name: " + person.name()); + System.out.println("Direct access - age: " + person.age()); + System.out.println("Direct access - full address: " + person.address()); + + // Chained access + System.out.println("Chained access - street: " + person.address().street()); + System.out.println("Chained access - city: " + person.address().city()); + System.out.println("Chained access - state: " + person.address().state()); + System.out.println("Chained access - zip: " + person.address().zipCode()); + + // Test equality with nested records + Address address2 = new Address("321 Elm St", "Boston", "MA", 2101); + Person person2 = new Person("Charlie", 35, address2); + + System.out.println("Addresses equal: " + address.equals(address2)); + System.out.println("Persons equal: " + person.equals(person2)); + } + + // Inner class containing records + static class Container { + record Item(String name, double price) {} + + static void demonstrateInnerRecord() { + System.out.println("--- Test Record in Inner Class ---"); + Item item = new Item("Widget", 19.99); + System.out.println("Item: " + item); + System.out.println("Item name: " + item.name()); + System.out.println("Item price: " + item.price()); + } + } + + static { + Container.demonstrateInnerRecord(); + } +} + diff --git a/tests/record/nested/ignore.txt b/tests/record/nested/ignore.txt new file mode 100644 index 00000000..2bfa51ff --- /dev/null +++ b/tests/record/nested/ignore.txt @@ -0,0 +1,13 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[15] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(15) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: --- Test Record in Inner Class --- + +stderr: ") diff --git a/tests/record/pattern_matching/Test.java b/tests/record/pattern_matching/Test.java new file mode 100644 index 00000000..54bf3735 --- /dev/null +++ b/tests/record/pattern_matching/Test.java @@ -0,0 +1,144 @@ +public class Test { + + // Records for pattern matching tests + record Point(int x, int y) {} + + record Circle(Point center, double radius) {} + + record Rectangle(Point topLeft, Point bottomRight) {} + + // Sealed interface for pattern matching + sealed interface Shape permits CircleShape, RectangleShape {} + + record CircleShape(Point center, double radius) implements Shape {} + + record RectangleShape(Point topLeft, Point bottomRight) implements Shape {} + + public static void main(String[] args) { + System.out.println("=== Pattern Matching Tests ==="); + + testInstanceofPatternMatching(); + testSwitchExpressionPatternMatching(); + testNestedPatternMatching(); + testGuardedPatterns(); + testSealedClassPatternMatching(); + } + + public static void testInstanceofPatternMatching() { + System.out.println("--- Test instanceof Pattern Matching ---"); + Object obj1 = new Point(10, 20); + Object obj2 = new Circle(new Point(5, 5), 3.0); + Object obj3 = "Not a record"; + + // Pattern matching instanceof (Java 14+) + if (obj1 instanceof Point p) { + System.out.println("Pattern matching: Point(" + p.x() + ", " + p.y() + ")"); + } + + if (obj2 instanceof Circle c) { + System.out.println("Circle center: " + c.center() + ", radius: " + c.radius()); + } + + if (obj3 instanceof Point) { + System.out.println("This won't print"); + } else { + System.out.println("obj3 is not a Point: " + obj3); + } + } + + public static void testSwitchExpressionPatternMatching() { + System.out.println("--- Test Switch Expression Pattern Matching ---"); + Object[] objects = { + new Point(1, 2), + new Circle(new Point(0, 0), 5.0), + "Hello", + 42, + new Rectangle(new Point(0, 0), new Point(10, 10)) + }; + + for (Object obj : objects) { + String result = switch (obj) { + case Point p -> "Point at (" + p.x() + ", " + p.y() + ")"; + case Circle c -> "Circle at " + c.center() + " with radius " + c.radius(); + case Rectangle r -> "Rectangle from " + r.topLeft() + " to " + r.bottomRight(); + case String s -> "String: " + s; + case Integer i -> "Integer: " + i; + default -> "Unknown type: " + obj.getClass().getSimpleName(); + }; + System.out.println("Object: " + result); + } + } + + public static void testNestedPatternMatching() { + System.out.println("--- Test Nested Pattern Matching ---"); + Circle circle1 = new Circle(new Point(0, 0), 5.0); + Circle circle2 = new Circle(new Point(3, 4), 2.5); + Rectangle rect = new Rectangle(new Point(1, 1), new Point(5, 5)); + + Object[] shapes = {circle1, circle2, rect}; + + for (Object shape : shapes) { + // Note: Nested pattern matching syntax may vary by Java version + String description = switch (shape) { + case Circle(Point(var x, var y), var radius) -> + "Circle at (" + x + ", " + y + ") with radius " + radius; + case Rectangle(Point(var x1, var y1), Point(var x2, var y2)) -> + "Rectangle from (" + x1 + ", " + y1 + ") to (" + x2 + ", " + y2 + ")"; + default -> "Unknown shape"; + }; + System.out.println("Shape: " + description); + } + } + + public static void testGuardedPatterns() { + System.out.println("--- Test Conditional Pattern Matching ---"); + Point[] points = { + new Point(0, 0), + new Point(5, 0), + new Point(0, 5), + new Point(3, 4), + new Point(-2, 1) + }; + + for (Point point : points) { + String classification = switch (point) { + case Point(int x, int y) -> { + if (x == 0 && y == 0) yield "Origin"; + else if (x > 0 && y == 0) yield "Positive X-axis"; + else if (x == 0 && y > 0) yield "Positive Y-axis"; + else if (x > 0 && y > 0) yield "First quadrant"; + else if (x < 0 && y > 0) yield "Second quadrant"; + else if (x < 0 && y < 0) yield "Third quadrant"; + else if (x > 0 && y < 0) yield "Fourth quadrant"; + else yield "On axis"; + } + }; + System.out.println("Point " + point + " is at: " + classification); + } + } + + public static void testSealedClassPatternMatching() { + System.out.println("--- Test Sealed Class Pattern Matching ---"); + Shape[] shapes = { + new CircleShape(new Point(2, 3), 4.0), + new RectangleShape(new Point(0, 0), new Point(6, 8)) + }; + + for (Shape shape : shapes) { + double area = switch (shape) { + case CircleShape(Point center, double radius) -> Math.PI * radius * radius; + case RectangleShape(Point(int x1, int y1), Point(int x2, int y2)) -> + Math.abs((x2 - x1) * (y2 - y1)); + }; + + String info = switch (shape) { + case CircleShape(Point center, double radius) -> + "Circle at " + center + " with radius " + radius; + case RectangleShape(Point topLeft, Point bottomRight) -> + "Rectangle from " + topLeft + " to " + bottomRight; + }; + + System.out.println(info + " has area: " + area); + } + } +} diff --git a/tests/record/pattern_matching/ignore.txt b/tests/record/pattern_matching/ignore.txt new file mode 100644 index 00000000..2b75183e --- /dev/null +++ b/tests/record/pattern_matching/ignore.txt @@ -0,0 +1,15 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NullPointerException) + backtrace=java/lang/StackTraceElement[15] + detailMessage=String(\"array cannot be null\") + cause=Object(class java/lang/NullPointerException) + stackTrace=java/lang/StackTraceElement[0] + depth=int(15) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + extendedMessageState=int(1) + extendedMessage=Object(null) + })))): +stdout: === Pattern Matching Tests === +--- Test instanceof Pattern Matching --- +Pattern matching: Point(10, 20) + +stderr: ") diff --git a/tests/record/reflection/Test.java b/tests/record/reflection/Test.java new file mode 100644 index 00000000..0da8d2db --- /dev/null +++ b/tests/record/reflection/Test.java @@ -0,0 +1,102 @@ +import java.lang.reflect.*; + +public class Test { + + record Person(String name, int age) {} + + record Point(int x, int y) {} + + record Book(String title, String author, int pages) {} + + public static void main(String[] args) { + System.out.println("=== Reflection Tests ==="); + + testRecordComponents(); + testRecordMethods(); + testRecordFields(); + testRecordClass(); + testRecordConstructors(); + } + + public static void testRecordComponents() { + System.out.println("--- Test Record Components ---"); + Class personClass = Person.class; + + System.out.println("Is record: " + personClass.isRecord()); + RecordComponent[] components = personClass.getRecordComponents(); + System.out.println("Number of components: " + components.length); + + for (RecordComponent component : components) { + System.out.println("Component name: " + component.getName()); + System.out.println("Component type: " + component.getType().getName()); + System.out.println("Component accessor: " + component.getAccessor().getName()); + } + } + + public static void testRecordMethods() { + System.out.println("--- Test Record Methods ---"); + Class pointClass = Point.class; + Method[] methods = pointClass.getDeclaredMethods(); + + System.out.println("Number of methods: " + methods.length); + for (Method method : methods) { + System.out.println("Method: " + method.getName() + + " - Return type: " + method.getReturnType().getSimpleName() + + " - Parameters: " + method.getParameterCount()); + } + } + + public static void testRecordFields() { + System.out.println("--- Test Record Fields ---"); + Class bookClass = Book.class; + Field[] fields = bookClass.getDeclaredFields(); + + System.out.println("Number of fields: " + fields.length); + for (Field field : fields) { + System.out.println("Field: " + field.getName() + + " - Type: " + field.getType().getSimpleName() + + " - Modifiers: " + Modifier.toString(field.getModifiers())); + } + } + + public static void testRecordClass() { + System.out.println("--- Test Record Class Properties ---"); + Class personClass = Person.class; + + System.out.println("Class name: " + personClass.getName()); + System.out.println("Simple name: " + personClass.getSimpleName()); + System.out.println("Is record: " + personClass.isRecord()); + System.out.println("Is final: " + Modifier.isFinal(personClass.getModifiers())); + System.out.println("Superclass: " + personClass.getSuperclass().getName()); + + Class[] interfaces = personClass.getInterfaces(); + System.out.println("Number of interfaces: " + interfaces.length); + for (Class iface : interfaces) { + System.out.println("Interface: " + iface.getName()); + } + } + + public static void testRecordConstructors() { + System.out.println("--- Test Record Constructors ---"); + Class pointClass = Point.class; + Constructor[] constructors = pointClass.getDeclaredConstructors(); + + System.out.println("Number of constructors: " + constructors.length); + for (Constructor constructor : constructors) { + System.out.println("Constructor parameters: " + constructor.getParameterCount()); + Parameter[] parameters = constructor.getParameters(); + for (Parameter param : parameters) { + System.out.println(" Parameter: " + param.getName() + " - Type: " + param.getType().getSimpleName()); + } + } + + // Test creating instance via reflection + try { + Constructor constructor = pointClass.getDeclaredConstructor(int.class, int.class); + Point reflectedPoint = constructor.newInstance(100, 200); + System.out.println("Created via reflection: " + reflectedPoint); + } catch (Exception e) { + System.out.println("Reflection instantiation failed: " + e.getMessage()); + } + } +} diff --git a/tests/record/reflection/ignore.txt b/tests/record/reflection/ignore.txt new file mode 100644 index 00000000..12c4ee40 --- /dev/null +++ b/tests/record/reflection/ignore.txt @@ -0,0 +1 @@ +not yet implemented: java.lang.Class.isRecord0()Z diff --git a/tests/record/serialization/Test.java b/tests/record/serialization/Test.java new file mode 100644 index 00000000..3825380e --- /dev/null +++ b/tests/record/serialization/Test.java @@ -0,0 +1,103 @@ +import java.io.*; + +public class Test { + + record Person(String name, int age) implements Serializable {} + + record Point(int x, int y) implements Serializable {} + + record Book(String title, String author, int pages) implements Serializable { + private static final long serialVersionUID = 1L; + } + + public static void main(String[] args) { + System.out.println("=== Serialization Tests ==="); + + testRecordSerialization(); + testRecordDeserialization(); + testSerializationRoundTrip(); + testSerializableInterface(); + } + + public static void testRecordSerialization() { + System.out.println("--- Test Record Serialization ---"); + Person person = new Person("Alice", 30); + + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(person); + oos.close(); + + byte[] serializedData = baos.toByteArray(); + System.out.println("Person serialized successfully, size: " + serializedData.length + " bytes"); + } catch (IOException e) { + System.out.println("Serialization failed: " + e.getMessage()); + } + } + + public static void testRecordDeserialization() { + System.out.println("--- Test Record Deserialization ---"); + Point originalPoint = new Point(10, 20); + + try { + // Serialize + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(originalPoint); + oos.close(); + + // Deserialize + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + Point deserializedPoint = (Point) ois.readObject(); + ois.close(); + + System.out.println("Original point: " + originalPoint); + System.out.println("Deserialized point: " + deserializedPoint); + System.out.println("Points are equal: " + originalPoint.equals(deserializedPoint)); + System.out.println("Same object reference: " + (originalPoint == deserializedPoint)); + } catch (IOException | ClassNotFoundException e) { + System.out.println("Deserialization failed: " + e.getMessage()); + } + } + + public static void testSerializationRoundTrip() { + System.out.println("--- Test Serialization Round Trip ---"); + Book originalBook = new Book("1984", "George Orwell", 328); + + try { + // Serialize + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(originalBook); + oos.close(); + + // Deserialize + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bais); + Book deserializedBook = (Book) ois.readObject(); + ois.close(); + + System.out.println("Original: " + originalBook); + System.out.println("Round-trip: " + deserializedBook); + System.out.println("Title preserved: " + originalBook.title().equals(deserializedBook.title())); + System.out.println("Author preserved: " + originalBook.author().equals(deserializedBook.author())); + System.out.println("Pages preserved: " + (originalBook.pages() == deserializedBook.pages())); + System.out.println("Hash codes equal: " + (originalBook.hashCode() == deserializedBook.hashCode())); + } catch (IOException | ClassNotFoundException e) { + System.out.println("Round-trip failed: " + e.getMessage()); + } + } + + public static void testSerializableInterface() { + System.out.println("--- Test Serializable Interface ---"); + Person person = new Person("Bob", 25); + Point point = new Point(5, 15); + Book book = new Book("To Kill a Mockingbird", "Harper Lee", 281); + + System.out.println("Person implements Serializable: " + (person instanceof Serializable)); + System.out.println("Point implements Serializable: " + (point instanceof Serializable)); + System.out.println("Book implements Serializable: " + (book instanceof Serializable)); + } +} diff --git a/tests/record/serialization/ignore.txt b/tests/record/serialization/ignore.txt new file mode 100644 index 00000000..d593c024 --- /dev/null +++ b/tests/record/serialization/ignore.txt @@ -0,0 +1,12 @@ +InternalError("Throwable(Object(Some(Object(RwLock { data: Object(java/lang/NoSuchMethodError) + backtrace=java/lang/StackTraceElement[10] + detailMessage=String(\"Method set([BIS)V not found in class java/lang/invoke/VarHandle\") + cause=Object(class java/lang/NoSuchMethodError) + stackTrace=java/lang/StackTraceElement[0] + depth=int(10) + suppressedExceptions=Object(class java/util/Collections$EmptyList) + })))): +stdout: === Serialization Tests === +--- Test Record Serialization --- + +stderr: ") \ No newline at end of file diff --git a/tests/reflection/records/Test.java b/tests/reflection/records/Test.java new file mode 100644 index 00000000..b4743acd --- /dev/null +++ b/tests/reflection/records/Test.java @@ -0,0 +1,280 @@ +import java.lang.reflect.*; +import java.lang.annotation.Annotation; + +public class Test { + + // Test records for reflection + record Person(String name, int age) {} + + record Point(int x, int y) { + public Point { + if (x < 0 || y < 0) { + throw new IllegalArgumentException("Coordinates must be non-negative"); + } + } + } + + record Book(String title, String author, int pages) { + // Additional method + public String getDescription() { + return title + " by " + author + " (" + pages + " pages)"; + } + } + + // Generic record + record Container(T value) {} + + // Record with annotations + record AnnotatedRecord(@Deprecated String data, int count) {} + + public static void main(String[] args) { + System.out.println("=== Record Reflection Tests ==="); + + testIsRecord(); + testRecordComponents(); + testRecordComponentAccessors(); + testRecordConstructors(); + testRecordMethods(); + testRecordFields(); + testRecordSuperclass(); + testGenericRecord(); + testAnnotatedRecord(); + testRecordInstantiation(); + } + + public static void testIsRecord() { + System.out.println("--- Test isRecord() ---"); + Class personClass = Person.class; + Class stringClass = String.class; + Class objectClass = Object.class; + + System.out.println("Person.class.isRecord(): " + personClass.isRecord()); + System.out.println("String.class.isRecord(): " + stringClass.isRecord()); + System.out.println("Object.class.isRecord(): " + objectClass.isRecord()); + + // Test with instances + Person person = new Person("Alice", 30); + System.out.println("person.getClass().isRecord(): " + person.getClass().isRecord()); + } + + public static void testRecordComponents() { + System.out.println("--- Test getRecordComponents() ---"); + Class personClass = Person.class; + + RecordComponent[] components = personClass.getRecordComponents(); + System.out.println("Number of record components: " + components.length); + + for (RecordComponent component : components) { + System.out.println("Component name: " + component.getName()); + System.out.println("Component type: " + component.getType().getName()); + System.out.println("Component generic type: " + component.getGenericType()); + System.out.println("Component declaring record: " + component.getDeclaringRecord().getName()); + } + + // Test empty record + record Empty() {} + Class emptyClass = Empty.class; + RecordComponent[] emptyComponents = emptyClass.getRecordComponents(); + System.out.println("Empty record components: " + emptyComponents.length); + } + + public static void testRecordComponentAccessors() { + System.out.println("--- Test RecordComponent Accessors ---"); + Class pointClass = Point.class; + RecordComponent[] components = pointClass.getRecordComponents(); + + Point point = new Point(10, 20); + + for (RecordComponent component : components) { + try { + Method accessor = component.getAccessor(); + System.out.println("Accessor method: " + accessor.getName()); + System.out.println("Accessor return type: " + accessor.getReturnType().getName()); + + Object value = accessor.invoke(point); + System.out.println("Accessor value for " + component.getName() + ": " + value); + } catch (Exception e) { + System.out.println("Error accessing component " + component.getName() + ": " + e.getMessage()); + } + } + } + + public static void testRecordConstructors() { + System.out.println("--- Test Record Constructors ---"); + Class bookClass = Book.class; + Constructor[] constructors = bookClass.getDeclaredConstructors(); + + System.out.println("Number of constructors: " + constructors.length); + + for (Constructor constructor : constructors) { + System.out.println("Constructor parameter count: " + constructor.getParameterCount()); + Parameter[] parameters = constructor.getParameters(); + + for (int i = 0; i < parameters.length; i++) { + Parameter param = parameters[i]; + System.out.println(" Parameter " + i + ": " + param.getName() + " (" + param.getType().getSimpleName() + ")"); + } + } + + // Test constructor invocation + try { + Constructor bookConstructor = bookClass.getDeclaredConstructor(String.class, String.class, int.class); + Book book = bookConstructor.newInstance("1984", "George Orwell", 328); + System.out.println("Created book via reflection: " + book); + } catch (Exception e) { + System.out.println("Constructor invocation failed: " + e.getMessage()); + } + } + + public static void testRecordMethods() { + System.out.println("--- Test Record Methods ---"); + Class bookClass = Book.class; + Method[] methods = bookClass.getDeclaredMethods(); + + System.out.println("Number of methods: " + methods.length); + + for (Method method : methods) { + System.out.println("Method: " + method.getName()); + System.out.println(" Return type: " + method.getReturnType().getSimpleName()); + System.out.println(" Parameter count: " + method.getParameterCount()); + System.out.println(" Modifiers: " + Modifier.toString(method.getModifiers())); + + // Check if it's an accessor method + boolean isAccessor = false; + RecordComponent[] components = bookClass.getRecordComponents(); + for (RecordComponent component : components) { + if (component.getAccessor().equals(method)) { + isAccessor = true; + break; + } + } + System.out.println(" Is accessor: " + isAccessor); + } + } + + public static void testRecordFields() { + System.out.println("--- Test Record Fields ---"); + Class personClass = Person.class; + Field[] fields = personClass.getDeclaredFields(); + + System.out.println("Number of fields: " + fields.length); + + for (Field field : fields) { + System.out.println("Field: " + field.getName()); + System.out.println(" Type: " + field.getType().getSimpleName()); + System.out.println(" Modifiers: " + Modifier.toString(field.getModifiers())); + System.out.println(" Is final: " + Modifier.isFinal(field.getModifiers())); + System.out.println(" Is private: " + Modifier.isPrivate(field.getModifiers())); + } + + // Test field access + Person person = new Person("Bob", 25); + for (Field field : fields) { + try { + field.setAccessible(true); + Object value = field.get(person); + System.out.println("Field " + field.getName() + " value: " + value); + } catch (Exception e) { + System.out.println("Field access failed for " + field.getName() + ": " + e.getMessage()); + } + } + } + + public static void testRecordSuperclass() { + System.out.println("--- Test Record Superclass ---"); + Class personClass = Person.class; + + System.out.println("Superclass: " + personClass.getSuperclass().getName()); + System.out.println("Is final: " + Modifier.isFinal(personClass.getModifiers())); + System.out.println("Package: " + personClass.getPackage()); + + // Test Record class methods + Person person = new Person("Charlie", 35); + System.out.println("Instance of Record: " + (person instanceof Record)); + + // Test inherited methods from Record + try { + Method toStringMethod = personClass.getMethod("toString"); + Method equalsMethod = personClass.getMethod("equals", Object.class); + Method hashCodeMethod = personClass.getMethod("hashCode"); + + System.out.println("toString() declaring class: " + toStringMethod.getDeclaringClass().getName()); + System.out.println("equals() declaring class: " + equalsMethod.getDeclaringClass().getName()); + System.out.println("hashCode() declaring class: " + hashCodeMethod.getDeclaringClass().getName()); + } catch (Exception e) { + System.out.println("Method lookup failed: " + e.getMessage()); + } + } + + public static void testGenericRecord() { + System.out.println("--- Test Generic Record ---"); + Container stringContainer = new Container<>("Hello"); + Class containerClass = stringContainer.getClass(); + + System.out.println("Generic record class: " + containerClass.getName()); + System.out.println("Is record: " + containerClass.isRecord()); + + RecordComponent[] components = containerClass.getRecordComponents(); + System.out.println("Generic record components: " + components.length); + + for (RecordComponent component : components) { + System.out.println("Component name: " + component.getName()); + System.out.println("Component type: " + component.getType().getName()); + System.out.println("Component generic type: " + component.getGenericType()); + } + + // Test type parameters + TypeVariable[] typeParameters = containerClass.getTypeParameters(); + System.out.println("Type parameters: " + typeParameters.length); + for (TypeVariable typeParam : typeParameters) { + System.out.println("Type parameter: " + typeParam.getName()); + } + } + + public static void testAnnotatedRecord() { + System.out.println("--- Test Annotated Record ---"); + Class annotatedClass = AnnotatedRecord.class; + + System.out.println("Annotated record is record: " + annotatedClass.isRecord()); + + RecordComponent[] components = annotatedClass.getRecordComponents(); + for (RecordComponent component : components) { + System.out.println("Component: " + component.getName()); + + Annotation[] annotations = component.getAnnotations(); + System.out.println(" Annotations: " + annotations.length); + + for (Annotation annotation : annotations) { + System.out.println(" Annotation type: " + annotation.annotationType().getSimpleName()); + } + + // Check for specific annotation + if (component.isAnnotationPresent(Deprecated.class)) { + System.out.println(" Component is deprecated"); + } + } + } + + public static void testRecordInstantiation() { + System.out.println("--- Test Record Instantiation via Reflection ---"); + + try { + Class pointClass = Point.class; + Constructor constructor = pointClass.getDeclaredConstructor(int.class, int.class); + + // Test valid instantiation + Point point1 = constructor.newInstance(5, 10); + System.out.println("Created point via reflection: " + point1); + + // Test invalid instantiation (should trigger validation) + try { + Point point2 = constructor.newInstance(-1, 5); + System.out.println("Invalid point created: " + point2); + } catch (InvocationTargetException e) { + System.out.println("Expected validation error: " + e.getCause().getMessage()); + } + } catch (Exception e) { + System.out.println("Reflection instantiation failed: " + e.getMessage()); + } + } +} diff --git a/tests/reflection/records/ignore.txt b/tests/reflection/records/ignore.txt new file mode 100644 index 00000000..12c4ee40 --- /dev/null +++ b/tests/reflection/records/ignore.txt @@ -0,0 +1 @@ +not yet implemented: java.lang.Class.isRecord0()Z diff --git a/tests/threading/basic/Test.java b/tests/thread/basic/Test.java similarity index 100% rename from tests/threading/basic/Test.java rename to tests/thread/basic/Test.java diff --git a/tests/threading/basic/ignore.txt b/tests/thread/basic/ignore.txt similarity index 100% rename from tests/threading/basic/ignore.txt rename to tests/thread/basic/ignore.txt diff --git a/tests/threading/concurrent_collections/Test.java b/tests/thread/concurrent_collections/Test.java similarity index 100% rename from tests/threading/concurrent_collections/Test.java rename to tests/thread/concurrent_collections/Test.java diff --git a/tests/threading/concurrent_collections/ignore.txt b/tests/thread/concurrent_collections/ignore.txt similarity index 100% rename from tests/threading/concurrent_collections/ignore.txt rename to tests/thread/concurrent_collections/ignore.txt diff --git a/tests/threading/daemon/Test.java b/tests/thread/daemon/Test.java similarity index 100% rename from tests/threading/daemon/Test.java rename to tests/thread/daemon/Test.java diff --git a/tests/threading/daemon/ignore.txt b/tests/thread/daemon/ignore.txt similarity index 100% rename from tests/threading/daemon/ignore.txt rename to tests/thread/daemon/ignore.txt diff --git a/tests/threading/exceptions/Test.java b/tests/thread/exceptions/Test.java similarity index 100% rename from tests/threading/exceptions/Test.java rename to tests/thread/exceptions/Test.java diff --git a/tests/threading/exceptions/ignore.txt b/tests/thread/exceptions/ignore.txt similarity index 100% rename from tests/threading/exceptions/ignore.txt rename to tests/thread/exceptions/ignore.txt diff --git a/tests/threading/interrupt/Test.java b/tests/thread/interrupt/Test.java similarity index 100% rename from tests/threading/interrupt/Test.java rename to tests/thread/interrupt/Test.java diff --git a/tests/threading/interrupt/ignore.txt b/tests/thread/interrupt/ignore.txt similarity index 100% rename from tests/threading/interrupt/ignore.txt rename to tests/thread/interrupt/ignore.txt diff --git a/tests/threading/join/Test.java b/tests/thread/join/Test.java similarity index 100% rename from tests/threading/join/Test.java rename to tests/thread/join/Test.java diff --git a/tests/threading/join/ignore.txt b/tests/thread/join/ignore.txt similarity index 100% rename from tests/threading/join/ignore.txt rename to tests/thread/join/ignore.txt diff --git a/tests/threading/lifecycle/Test.java b/tests/thread/lifecycle/Test.java similarity index 100% rename from tests/threading/lifecycle/Test.java rename to tests/thread/lifecycle/Test.java diff --git a/tests/threading/lifecycle/ignore.txt b/tests/thread/lifecycle/ignore.txt similarity index 100% rename from tests/threading/lifecycle/ignore.txt rename to tests/thread/lifecycle/ignore.txt diff --git a/tests/threading/sleep/Test.java b/tests/thread/sleep/Test.java similarity index 100% rename from tests/threading/sleep/Test.java rename to tests/thread/sleep/Test.java diff --git a/tests/threading/sleep/ignore.txt b/tests/thread/sleep/ignore.txt similarity index 100% rename from tests/threading/sleep/ignore.txt rename to tests/thread/sleep/ignore.txt diff --git a/tests/threading/synchronization/Test.java b/tests/thread/synchronization/Test.java similarity index 100% rename from tests/threading/synchronization/Test.java rename to tests/thread/synchronization/Test.java diff --git a/tests/threading/synchronization/ignore.txt b/tests/thread/synchronization/ignore.txt similarity index 100% rename from tests/threading/synchronization/ignore.txt rename to tests/thread/synchronization/ignore.txt diff --git a/tests/threading/thread_group/Test.java b/tests/thread/thread_group/Test.java similarity index 100% rename from tests/threading/thread_group/Test.java rename to tests/thread/thread_group/Test.java diff --git a/tests/threading/thread_group/ignore.txt b/tests/thread/thread_group/ignore.txt similarity index 100% rename from tests/threading/thread_group/ignore.txt rename to tests/thread/thread_group/ignore.txt diff --git a/tests/threading/thread_local/Test.java b/tests/thread/thread_local/Test.java similarity index 100% rename from tests/threading/thread_local/Test.java rename to tests/thread/thread_local/Test.java diff --git a/tests/threading/thread_local/ignore.txt b/tests/thread/thread_local/ignore.txt similarity index 100% rename from tests/threading/thread_local/ignore.txt rename to tests/thread/thread_local/ignore.txt diff --git a/tests/threading/timing/Test.java b/tests/thread/timing/Test.java similarity index 100% rename from tests/threading/timing/Test.java rename to tests/thread/timing/Test.java diff --git a/tests/threading/timing/ignore.txt b/tests/thread/timing/ignore.txt similarity index 100% rename from tests/threading/timing/ignore.txt rename to tests/thread/timing/ignore.txt diff --git a/tests/threading/virtual/Test.java b/tests/thread/virtual/Test.java similarity index 100% rename from tests/threading/virtual/Test.java rename to tests/thread/virtual/Test.java diff --git a/tests/threading/virtual/ignore.txt b/tests/thread/virtual/ignore.txt similarity index 100% rename from tests/threading/virtual/ignore.txt rename to tests/thread/virtual/ignore.txt diff --git a/tests/threading/volatile/Test.java b/tests/thread/volatile/Test.java similarity index 100% rename from tests/threading/volatile/Test.java rename to tests/thread/volatile/Test.java diff --git a/tests/threading/volatile/ignore.txt b/tests/thread/volatile/ignore.txt similarity index 100% rename from tests/threading/volatile/ignore.txt rename to tests/thread/volatile/ignore.txt diff --git a/tests/threading/wait_notify/Test.java b/tests/thread/wait_notify/Test.java similarity index 100% rename from tests/threading/wait_notify/Test.java rename to tests/thread/wait_notify/Test.java diff --git a/tests/threading/wait_notify/ignore.txt b/tests/thread/wait_notify/ignore.txt similarity index 100% rename from tests/threading/wait_notify/ignore.txt rename to tests/thread/wait_notify/ignore.txt diff --git a/tests/threading/yield/Test.java b/tests/thread/yield/Test.java similarity index 100% rename from tests/threading/yield/Test.java rename to tests/thread/yield/Test.java diff --git a/tests/threading/yield/ignore.txt b/tests/thread/yield/ignore.txt similarity index 100% rename from tests/threading/yield/ignore.txt rename to tests/thread/yield/ignore.txt