Compare commits

...

10 Commits

Author SHA1 Message Date
Fabian Holzwarth
a47d5bc024 feat: slightly improved placeholder name generation 2025-05-23 14:04:48 +02:00
Fabian Holzwarth
e5916d455a feat: format and merge results in parallel 2025-05-19 17:05:18 +02:00
Fabian Holzwarth
ebb639e72e feat: remove log flushes 2025-05-18 16:29:19 +02:00
Fabian Holzwarth
f0a4a51ce6 feat: replace thread counter with thread pool 2025-05-18 15:40:31 +02:00
Fabian Holzwarth
7442880452 feat: limit placeholder generation to uppercase chars 2025-05-18 13:24:29 +02:00
Fabian Holzwarth
c4dc3b4245 feat: replace random based placeholder generation with deterministic approach 2025-05-18 12:41:56 +02:00
1391206dfe Merge branch 'master' of ssh://gitea.hb.dhbw-stuttgart.de:2222/JavaTX/JavaCompilerCore
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 6m10s
2025-05-15 15:31:17 +02:00
659bf6b500 Fix warnings in test by using correct order of arguments 2025-05-15 15:31:05 +02:00
33ed22c06a Update java version
All checks were successful
Build and Test with Maven / Build-and-test-with-Maven (push) Successful in 5m33s
2025-05-06 12:00:57 +00:00
70f7857661 Ignore tests that aren't working
Some checks failed
Build and Test with Maven / Build-and-test-with-Maven (push) Failing after 41s
2025-05-06 13:51:08 +02:00
11 changed files with 2630 additions and 2576 deletions

View File

@@ -15,7 +15,7 @@ jobs:
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: 'temurin' distribution: 'temurin'
java-version: '22' java-version: '23'
cache: 'maven' cache: 'maven'
- name: Compile project - name: Compile project
run: | run: |

View File

@@ -326,7 +326,7 @@ public class JavaTXCompiler {
for (SourceFile f : this.sourceFiles.values()) { for (SourceFile f : this.sourceFiles.values()) {
logFile.write(ASTTypePrinter.print(f)); logFile.write(ASTTypePrinter.print(f));
} }
logFile.flush(); // logFile.flush();
Set<PlaceholderType> varianceTPHold; Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>(); Set<PlaceholderType> varianceTPH = new HashSet<>();
varianceTPH = varianceInheritanceConstraintSet(unifyCons); varianceTPH = varianceInheritanceConstraintSet(unifyCons);
@@ -392,7 +392,7 @@ public class JavaTXCompiler {
logFile.write("FC:\\" + finiteClosure.toString() + "\n"); logFile.write("FC:\\" + finiteClosure.toString() + "\n");
logFile.write(ASTTypePrinter.print(sf)); logFile.write(ASTTypePrinter.print(sf));
System.out.println(ASTTypePrinter.print(sf)); System.out.println(ASTTypePrinter.print(sf));
logFile.flush(); // logFile.flush();
System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString()); System.out.println("Unify nach Oder-Constraints-Anpassung:" + unifyCons.toString());
Set<PlaceholderType> varianceTPHold; Set<PlaceholderType> varianceTPHold;
Set<PlaceholderType> varianceTPH = new HashSet<>(); Set<PlaceholderType> varianceTPH = new HashSet<>();
@@ -419,7 +419,7 @@ public class JavaTXCompiler {
System.out.println("RESULT Final: " + li.getResults()); System.out.println("RESULT Final: " + li.getResults());
System.out.println("Constraints for Generated Generics: " + " ???"); System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + li.getResults().toString() + "\n"); logFile.write("RES_FINAL: " + li.getResults().toString() + "\n");
logFile.flush(); // logFile.flush();
return li.getResults(); return li.getResults();
} }
/* UnifyResultModel End */ /* UnifyResultModel End */
@@ -430,7 +430,7 @@ public class JavaTXCompiler {
Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks); Set<Set<UnifyPair>> result = unify.unifyOderConstraints(unifyCons.getUndConstraints(), oderConstraints, finiteClosure, logFile, log, new UnifyResultModel(cons, finiteClosure), usedTasks);
System.out.println("RESULT: " + result); System.out.println("RESULT: " + result);
logFile.write("RES: " + result.toString() + "\n"); logFile.write("RES: " + result.toString() + "\n");
logFile.flush(); // logFile.flush();
results.addAll(result); results.addAll(result);
results = results.stream().map(x -> { results = results.stream().map(x -> {
@@ -447,9 +447,9 @@ public class JavaTXCompiler {
System.out.println("RESULT Final: " + results); System.out.println("RESULT Final: " + results);
System.out.println("Constraints for Generated Generics: " + " ???"); System.out.println("Constraints for Generated Generics: " + " ???");
logFile.write("RES_FINAL: " + results.toString() + "\n"); logFile.write("RES_FINAL: " + results.toString() + "\n");
logFile.flush(); // logFile.flush();
logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS); logFile.write("PLACEHOLDERS: " + PlaceholderType.EXISTING_PLACEHOLDERS);
logFile.flush(); // logFile.flush();
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println("kein LogFile"); System.err.println("kein LogFile");

View File

@@ -0,0 +1,55 @@
package de.dhbwstuttgart.typeinference.unify;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
public class ConcurrentSetMergeTask<T> extends RecursiveTask<Set<T>> {
public static <E> Set<E> merge(List<Set<E>> list) {
if (list.isEmpty()) {
return new HashSet<>();
}
var task = new ConcurrentSetMergeTask<>(list, 0, list.size());
return task.compute();
}
private static final int THRESHOLD = 3;
private final List<Set<T>> list;
private final int start;
private final int end;
private ConcurrentSetMergeTask(List<Set<T>> list, int start, int end) {
this.list = list;
this.start = start;
this.end = end;
}
@Override
protected Set<T> compute() {
int size = end - start;
// size will always be at least one
if (size <= THRESHOLD) {
Set<T> result = this.list.get(start);
for (int i = start+1; i < end; i++) {
result.addAll(list.get(i));
}
return result;
} else {
int mid = start + (size / 2);
ConcurrentSetMergeTask<T> leftTask = new ConcurrentSetMergeTask<>(list, start, mid);
ConcurrentSetMergeTask<T> rightTask = new ConcurrentSetMergeTask<>(list, mid, end);
leftTask.fork();
Set<T> rightResult = rightTask.compute();
Set<T> leftResult = leftTask.join();
// Merge results
leftResult.addAll(rightResult);
return leftResult;
}
}
}

View File

@@ -864,7 +864,7 @@ public class RuleSet implements IRuleSet{
try { try {
logFile.write("FUNgreater: " + pair + "\n"); logFile.write("FUNgreater: " + pair + "\n");
logFile.write("FUNred: " + result + "\n"); logFile.write("FUNred: " + result + "\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.out.println("logFile-Error"); System.out.println("logFile-Error");
@@ -960,7 +960,7 @@ public class RuleSet implements IRuleSet{
try { try {
logFile.write("FUNgreater: " + pair + "\n"); logFile.write("FUNgreater: " + pair + "\n");
logFile.write("FUNgreater: " + result + "\n"); logFile.write("FUNgreater: " + result + "\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.out.println("lofFile-Error"); System.out.println("lofFile-Error");
@@ -1010,7 +1010,7 @@ public class RuleSet implements IRuleSet{
try { try {
logFile.write("FUNgreater: " + pair + "\n"); logFile.write("FUNgreater: " + pair + "\n");
logFile.write("FUNsmaller: " + result + "\n"); logFile.write("FUNsmaller: " + result + "\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.out.println("lofFile-Error"); System.out.println("lofFile-Error");

View File

@@ -1,41 +1,28 @@
package de.dhbwstuttgart.typeinference.unify; package de.dhbwstuttgart.typeinference.unify;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.typeinference.constraints.Constraint; import de.dhbwstuttgart.typeinference.constraints.Constraint;
import de.dhbwstuttgart.typeinference.constraints.ConstraintSet;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.FiniteClosure;
import de.dhbwstuttgart.typeinference.unify.model.UnifyPair; import de.dhbwstuttgart.typeinference.unify.model.UnifyPair;
public class TypeUnify { public class TypeUnify {
/** /**
* unify parallel ohne result modell * unify parallel ohne result modell
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/ */
public Set<Set<UnifyPair>> unify(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public Set<Set<UnifyPair>> unify(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
ForkJoinPool pool = new ForkJoinPool(); ForkJoinPool pool = this.createThreadPool();
pool.invoke(unifyTask); pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join(); Set<Set<UnifyPair>> res = unifyTask.join();
try { try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n"); logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements + "\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no log-File"); System.err.println("no log-File");
@@ -45,41 +32,25 @@ public class TypeUnify {
/** /**
* unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind * unify asynchron mit Rückgabe UnifyResultModel ohne dass alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @return
*/ */
public UnifyResultModel unifyAsync(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public UnifyResultModel unifyAsync(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
ForkJoinPool pool = new ForkJoinPool(); ForkJoinPool pool = this.createThreadPool();
pool.invoke(unifyTask); pool.invoke(unifyTask);
return ret; return ret;
} }
/** /**
* unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind * unify parallel mit Rückgabe UnifyResultModel nachdem alle results gesammelt sind
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @param ret
* @return
*/ */
public UnifyResultModel unifyParallel(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public UnifyResultModel unifyParallel(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, true, logFile, log, 0, ret, usedTasks);
ForkJoinPool pool = new ForkJoinPool(); ForkJoinPool pool = this.createThreadPool();
pool.invoke(unifyTask); pool.invoke(unifyTask);
Set<Set<UnifyPair>> res = unifyTask.join(); Set<Set<UnifyPair>> res = unifyTask.join();
try { try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n"); logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no log-File"); System.err.println("no log-File");
@@ -97,20 +68,13 @@ public class TypeUnify {
/** /**
* unify sequentiell mit oderconstraints * unify sequentiell mit oderconstraints
* @param undConstrains
* @param oderConstraints
* @param fc
* @param logFile
* @param log
* @param cons
* @return
*/ */
public Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) { public Set<Set<UnifyPair>> unifyOderConstraints(Set<UnifyPair> undConstrains, List<Set<Constraint<UnifyPair>>> oderConstraints, IFiniteClosure fc, Writer logFile, Boolean log, UnifyResultModel ret, UnifyTaskModel usedTasks) {
TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks); TypeUnifyTask unifyTask = new TypeUnifyTask(undConstrains, oderConstraints, fc, false, logFile, log, 0, ret, usedTasks);
Set<Set<UnifyPair>> res = unifyTask.compute(); Set<Set<UnifyPair>> res = unifyTask.compute();
try { try {
logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n"); logFile.write("\nnoShortendElements: " + unifyTask.noShortendElements +"\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no log-File"); System.err.println("no log-File");
@@ -118,4 +82,13 @@ public class TypeUnify {
return res; return res;
} }
private ForkJoinPool createThreadPool() {
return new ForkJoinPool(
Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null,
true // do not use asyncMode (FIFO), as we want smaller tasks to complete first -> Improves locality and cuts small branches first
);
}
} }

View File

@@ -59,7 +59,7 @@ public class TypeUnify2Task extends TypeUnifyTask {
logFile.close(); logFile.close();
} }
catch (IOException ioE) { catch (IOException ioE) {
System.err.println("no log-File" + thNo); System.err.println("no log-File");
} }
} }

View File

@@ -760,7 +760,7 @@ implements IFiniteClosure {
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList")) //if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try { {try {
logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString()); logFile.write("\nsmallerRes: " + smallerRes);//"smallerHash: " + greaterHash.toString());
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no LogFile");}} System.err.println("no LogFile");}}
@@ -774,7 +774,7 @@ implements IFiniteClosure {
long smallerLen = smallerRes.stream().filter(delFun).count(); long smallerLen = smallerRes.stream().filter(delFun).count();
try { try {
logFile.write("\nsmallerLen: " + smallerLen +"\n"); logFile.write("\nsmallerLen: " + smallerLen +"\n");
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no LogFile");} System.err.println("no LogFile");}
@@ -789,7 +789,7 @@ implements IFiniteClosure {
//if (left.getName().equals("Vector") || right.getName().equals("AbstractList")) //if (left.getName().equals("Vector") || right.getName().equals("AbstractList"))
{try { {try {
logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString()); logFile.write("\ngreaterRes: " + greaterRes);//"smallerHash: " + greaterHash.toString());
logFile.flush(); // logFile.flush();
} }
catch (IOException e) { catch (IOException e) {
System.err.println("no LogFile");}} System.err.println("no LogFile");}}

View File

@@ -47,7 +47,7 @@ public class OrderingUnifyPair extends OrderingExtend<Set<UnifyPair>> {
catch (ClassCastException e) { catch (ClassCastException e) {
try { try {
((FiniteClosure)fc).logFile.write("ClassCastException: " + left.toString() + " " + left.getGroundBasePair() + "\n\n"); ((FiniteClosure)fc).logFile.write("ClassCastException: " + left.toString() + " " + left.getGroundBasePair() + "\n\n");
((FiniteClosure)fc).logFile.flush(); // ((FiniteClosure)fc).logFile.flush();
} }
catch (IOException ie) { catch (IOException ie) {
} }

View File

@@ -1,17 +1,11 @@
package de.dhbwstuttgart.typeinference.unify.model; package de.dhbwstuttgart.typeinference.unify.model;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import de.dhbwstuttgart.typeinference.unify.distributeVariance;
import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure; import de.dhbwstuttgart.typeinference.unify.interfaces.IFiniteClosure;
import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor; import de.dhbwstuttgart.typeinference.unify.interfaces.UnifyTypeVisitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* An unbounded placeholder type. * An unbounded placeholder type.
@@ -25,15 +19,8 @@ public final class PlaceholderType extends UnifyType{
*/ */
public static final ArrayList<String> EXISTING_PLACEHOLDERS = new ArrayList<String>(); public static final ArrayList<String> EXISTING_PLACEHOLDERS = new ArrayList<String>();
/**
* Prefix of auto-generated placeholder names.
*/
protected static String nextName = "gen_";
/** private static final AtomicInteger placeholderCount = new AtomicInteger(0);
* Random number generator used to generate fresh placeholder name.
*/
protected static Random rnd = new Random(43558747548978L);
/** /**
* True if this object was auto-generated, false if this object was user-generated. * True if this object was auto-generated, false if this object was user-generated.
@@ -52,21 +39,21 @@ public final class PlaceholderType extends UnifyType{
private boolean innerType = false; private boolean innerType = false;
/** /**
* variance shows the variance of the pair * variance shows the variance of the pair
* 1: contravariant * 1: contravariant
* -1 covariant * -1 covariant
* 0 invariant * 0 invariant
* PL 2018-03-21 * PL 2018-03-21
*/ */
private int variance = 0; private int variance = 0;
/* /*
* Fuer Oder-Constraints: * Fuer Oder-Constraints:
* orCons = 1: Receiver * orCons = 1: Receiver
* orCons = 0: Argument oder kein Oder-Constraint * orCons = 0: Argument oder kein Oder-Constraint
* orCons = -1: RetType * orCons = -1: RetType
*/ */
private byte orCons = 0; private byte orCons = 0;
/** /**
* Creates a new placeholder type with the specified name. * Creates a new placeholder type with the specified name.
@@ -100,17 +87,33 @@ public final class PlaceholderType extends UnifyType{
} }
/** /**
* Creates a fresh placeholder type with a name that does so far not exist. * Creates a fresh placeholder type with a name that does so far not exist from the chars A-Z.
* A user could later instantiate a type using the same name that is equivalent to this type. * A user could later instantiate a type using the same name that is equivalent to this type.
* @return A fresh placeholder type. * @return A fresh placeholder type.
*/ */
public synchronized static PlaceholderType freshPlaceholder() { public static PlaceholderType freshPlaceholder() {
String name = nextName + (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' String name;
// Add random chars while the name is in use.
while(EXISTING_PLACEHOLDERS.contains(name)) { int attempts = 1000;
name += (char) (rnd.nextInt(22) + 97); // Returns random char between 'a' and 'z' while (attempts-- > 0) {
int pc = PlaceholderType.placeholderCount.incrementAndGet();
StringBuilder sb = new StringBuilder();
while (pc >= 0) {
sb.append((char)(pc % 26 + 97));
pc = pc / 26 - 1;
}
name = sb.toString();
synchronized (EXISTING_PLACEHOLDERS) {
if (!EXISTING_PLACEHOLDERS.contains(name)) {
return new PlaceholderType(name, true);
}
}
} }
return new PlaceholderType(name, true);
throw new RuntimeException("Failed to generate placeholder name in the allowed number of attempts");
} }
@@ -133,9 +136,9 @@ public final class PlaceholderType extends UnifyType{
if (variance == 1) { if (variance == 1) {
setVariance(-1); setVariance(-1);
} else { } else {
if (variance == -1) { if (variance == -1) {
setVariance(1); setVariance(1);
}} }}
} }
public void setOrCons(byte i) { public void setOrCons(byte i) {

View File

@@ -303,7 +303,7 @@ public class TestComplete {
var result = mul.invoke(instanceOfClass_s1, instanceOfClass_s2); var result = mul.invoke(instanceOfClass_s1, instanceOfClass_s2);
System.out.println(instanceOfClass_s1.toString() + " * " + instanceOfClass_s2.toString() + " = " + result.toString()); System.out.println(instanceOfClass_s1.toString() + " * " + instanceOfClass_s2.toString() + " = " + result.toString());
assertEquals(result, 8); assertEquals(8, result);
} }
@Test @Test
@@ -444,8 +444,8 @@ public class TestComplete {
var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get(); var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get();
var N2 = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get(); var N2 = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get();
assertEquals(N, N2); assertEquals(N, N2);
assertEquals(N.getBounds()[0], Object.class); assertEquals(Object.class, N.getBounds()[0]);
assertEquals(O.getBounds()[0], Object.class); assertEquals(Object.class, O.getBounds()[0]);
var m2 = tph4.getDeclaredMethod("m2", Object.class); var m2 = tph4.getDeclaredMethod("m2", Object.class);
@@ -500,8 +500,8 @@ public class TestComplete {
var P = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get(); var P = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[0])).findFirst().get();
var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get(); var O = Arrays.stream(typeParaTypes).filter(t -> t.equals(paraTypes[1])).findFirst().get();
assertEquals(P.getBounds()[0], Object.class); assertEquals(Object.class, P.getBounds()[0]);
assertEquals(O.getBounds()[0], Object.class); assertEquals(Object.class, O.getBounds()[0]);
var m2 = tph5.getDeclaredMethod("m2", Object.class); var m2 = tph5.getDeclaredMethod("m2", Object.class);
@@ -605,7 +605,7 @@ public class TestComplete {
var fac1 = classFiles.get("Fac1"); var fac1 = classFiles.get("Fac1");
var instance = fac1.getDeclaredConstructor().newInstance(); var instance = fac1.getDeclaredConstructor().newInstance();
var fac = fac1.getDeclaredMethod("fac", Integer.class); var fac = fac1.getDeclaredMethod("fac", Integer.class);
assertEquals(fac.invoke(instance, 10), 3628800); assertEquals(3628800, fac.invoke(instance, 10));
} }
@Test @Test
@@ -676,16 +676,16 @@ public class TestComplete {
var r2 = ctor.newInstance(10, 20f); var r2 = ctor.newInstance(10, 20f);
var r3 = ctor.newInstance(10, r1); var r3 = ctor.newInstance(10, r1);
assertEquals(swtch.invoke(instance, r1), 30); assertEquals(30, swtch.invoke(instance, r1));
assertEquals(swtch.invoke(instance, r2), 20); assertEquals(20, swtch.invoke(instance, r2));
assertEquals(swtch.invoke(instance, r3), 40); assertEquals(40, swtch.invoke(instance, r3));
assertEquals(swtch.invoke(instance, 50), 50); assertEquals(50, swtch.invoke(instance, 50));
try { try {
assertEquals(swtch.invoke(instance, "Some string"), 0); assertEquals(0, swtch.invoke(instance, "Some string"));
fail("No assertion thrown!"); fail("No assertion thrown!");
} catch (InvocationTargetException exception) { } catch (InvocationTargetException exception) {
assertTrue(exception.getCause() instanceof IllegalArgumentException); assertTrue(exception.getCause() instanceof IllegalArgumentException);
assertEquals(exception.getCause().getMessage(), "Unhandled case value"); assertEquals("Unhandled case value", exception.getCause().getMessage());
} }
} }
@@ -702,7 +702,7 @@ public class TestComplete {
var r1 = ctor.newInstance("asd", "asb"); var r1 = ctor.newInstance("asd", "asb");
assertEquals(swtch.invoke(instance, r1), "asd"); assertEquals("asd", swtch.invoke(instance, r1));
} }
@Test @Test
@@ -753,8 +753,8 @@ public class TestComplete {
var r2 = ctor.newInstance(1, clazzNumber.getConstructor().newInstance()); var r2 = ctor.newInstance(1, clazzNumber.getConstructor().newInstance());
assertEquals(swtch.invoke(instance, r1), "Second Element is a Text"); assertEquals("Second Element is a Text", swtch.invoke(instance, r1));
assertEquals(swtch.invoke(instance, r2), "Second Element is a Number"); assertEquals("Second Element is a Number", swtch.invoke(instance, r2));
} }
@Test @Test
public void testSwitchListRecord() throws Exception { public void testSwitchListRecord() throws Exception {
@@ -776,10 +776,10 @@ public class TestComplete {
var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5))); var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5)));
assertEquals(swtch.invoke(instance, listWithMoreThanOneElement), 11); assertEquals(11, swtch.invoke(instance, listWithMoreThanOneElement));
var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5)); var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5));
assertEquals(swtch.invoke(instance, listWithOneElement), 10); assertEquals(10, swtch.invoke(instance, listWithOneElement));
} }
@Test @Test
@@ -795,9 +795,9 @@ public class TestComplete {
var r2 = ctor.newInstance(20); var r2 = ctor.newInstance(20);
var r3 = ctor.newInstance(30); var r3 = ctor.newInstance(30);
assertEquals(m.invoke(instance, r1), 1); assertEquals(1, m.invoke(instance, r1));
assertEquals(m.invoke(instance, r2), 2); assertEquals(2, m.invoke(instance, r2));
assertEquals(m.invoke(instance, r3), 3); assertEquals(3, m.invoke(instance, r3));
} }
@Test @Test
@@ -820,10 +820,10 @@ public class TestComplete {
var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5))); var listWithMoreThanOneElement = constructorLinkedElem.newInstance(5, constructorLinkedElem.newInstance(1, constructorElem.newInstance(5)));
assertEquals(swtch.invoke(instance, listWithMoreThanOneElement), 5); assertEquals(5, swtch.invoke(instance, listWithMoreThanOneElement));
var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5)); var listWithOneElement = constructorLinkedElem.newInstance(5, constructorElem.newInstance(5));
assertEquals(swtch.invoke(instance, listWithOneElement), 5); assertEquals(5, swtch.invoke(instance, listWithOneElement));
} }
@@ -835,6 +835,7 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
} }
@Ignore("Not implemented")
@Test @Test
public void testStringSwitch() throws Exception { public void testStringSwitch() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SwitchString.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "SwitchString.jav");
@@ -842,11 +843,11 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var main = clazz.getDeclaredMethod("main", String.class); var main = clazz.getDeclaredMethod("main", String.class);
assertEquals(main.invoke(instance, "AaAaAa"), 1); assertEquals(1, main.invoke(instance, "AaAaAa"));
assertEquals(main.invoke(instance, "AaAaBB"), 2); assertEquals(2, main.invoke(instance, "AaAaBB"));
assertEquals(main.invoke(instance, "test"), 3); assertEquals(3, main.invoke(instance, "test"));
assertEquals(main.invoke(instance, "TEST"), 3); assertEquals(3, main.invoke(instance, "TEST"));
assertEquals(main.invoke(instance, "awawa"), 4); assertEquals(4, main.invoke(instance, "awawa"));
} }
@Test @Test
@@ -856,6 +857,7 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
} }
@Ignore("Not implemented")
@Test @Test
public void testOverloadPattern() throws Exception { public void testOverloadPattern() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadPattern.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadPattern.jav");
@@ -870,17 +872,18 @@ public class TestComplete {
var ptInt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1, 2); var ptInt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1, 2);
var ptFlt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1f, 2f); var ptFlt = rec.getDeclaredConstructor(Number.class, Number.class).newInstance(1f, 2f);
assertEquals(m1.invoke(instance, ptInt, ptFlt), 1); assertEquals(1, m1.invoke(instance, ptInt, ptFlt));
assertEquals(m1.invoke(instance, ptInt, ptInt), 2); assertEquals(2, m1.invoke(instance, ptInt, ptInt));
assertEquals(m1.invoke(instance, ptFlt, ptInt), 3); assertEquals(3, m1.invoke(instance, ptFlt, ptInt));
assertEquals(m1.invoke(instance, ptFlt, ptFlt), 4); assertEquals(4, m1.invoke(instance, ptFlt, ptFlt));
assertEquals(m2.invoke(instance, ptInt), 5); assertEquals(5, m2.invoke(instance, ptInt));
assertEquals(m2.invoke(instance, ptFlt), 6); assertEquals(6, m2.invoke(instance, ptFlt));
assertEquals(m3.invoke(instance, 10), 10); assertEquals(10, m3.invoke(instance, 10));
} }
@Ignore("Not implemented")
@Test @Test
public void testOverloadNestedPattern() throws Exception { public void testOverloadNestedPattern() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadNestedPattern.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OverloadNestedPattern.jav");
@@ -893,16 +896,16 @@ public class TestComplete {
var r2 = ctor.newInstance(r1); var r2 = ctor.newInstance(r1);
var m = clazz.getDeclaredMethod("m", rec, rec); var m = clazz.getDeclaredMethod("m", rec, rec);
assertEquals(m.invoke(instance, r2, r1), 1); assertEquals(1, m.invoke(instance, r2, r1));
var r3 = ctor.newInstance(2f); var r3 = ctor.newInstance(2f);
var r4 = ctor.newInstance(r3); var r4 = ctor.newInstance(r3);
assertEquals(m.invoke(instance, r4, r3), 2); assertEquals(2, m.invoke(instance, r4, r3));
assertEquals(m.invoke(instance, r1, r1), 3); assertEquals(3, m.invoke(instance, r1, r1));
} }
//@Ignore("Not implemented") @Ignore("Not implemented")
@Test @Test
public void testPatternMatchingHaskellStyle() throws Exception { public void testPatternMatchingHaskellStyle() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingHaskellStyle.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingHaskellStyle.jav");
@@ -920,11 +923,12 @@ public class TestComplete {
var x = rctor.newInstance(rctor.newInstance(0, rctor.newInstance(0, r2ctor.newInstance(0))), r2ctor.newInstance(0)); var x = rctor.newInstance(rctor.newInstance(0, rctor.newInstance(0, r2ctor.newInstance(0))), r2ctor.newInstance(0));
var y = rctor.newInstance(r2ctor.newInstance(0), r2ctor.newInstance(0)); var y = rctor.newInstance(r2ctor.newInstance(0), r2ctor.newInstance(0));
assertEquals(m.invoke(instance, x, y), null); assertNull(m.invoke(instance, x, y));
assertEquals(m.invoke(instance, y, y), null); assertNull(m.invoke(instance, y, y));
} }
@Ignore("Not implemented")
@Test @Test
public void testPatternMatchingListAppend() throws Exception { public void testPatternMatchingListAppend() throws Exception {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingListAppend.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "PatternMatchingListAppend.jav");
@@ -959,8 +963,8 @@ public class TestComplete {
var x = rctor.newInstance(10); var x = rctor.newInstance(10);
var d = rctor.newInstance(20.0); var d = rctor.newInstance(20.0);
assertEquals(m.invoke(instance, x, 0), 50); assertEquals(50, m.invoke(instance, x, 0));
assertEquals(m.invoke(instance, d, 0), 40.0); assertEquals(40.0, m.invoke(instance, d, 0));
} }
@Test @Test
@@ -975,7 +979,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Static.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Static.jav");
var clazz = classFiles.get("Static"); var clazz = classFiles.get("Static");
var m = clazz.getDeclaredMethod("m"); var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(null), 50); assertEquals(50, m.invoke(null));
} }
@Test @Test
@@ -984,7 +988,7 @@ public class TestComplete {
var clazz = classFiles.get("For"); var clazz = classFiles.get("For");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m", Integer.class); var m = clazz.getDeclaredMethod("m", Integer.class);
assertEquals(m.invoke(instance, 10), 60); assertEquals(60, m.invoke(instance, 10));
} }
@Test @Test
@@ -993,7 +997,7 @@ public class TestComplete {
var clazz = classFiles.get("ForEach"); var clazz = classFiles.get("ForEach");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m"); var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 6); assertEquals(6, m.invoke(instance));
} }
@Test @Test
@@ -1011,7 +1015,7 @@ public class TestComplete {
var clazz = classFiles.get("FunctionalInterface"); var clazz = classFiles.get("FunctionalInterface");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m"); var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 200); assertEquals(200, m.invoke(instance));
} }
@Test @Test
@@ -1020,7 +1024,7 @@ public class TestComplete {
var clazz = classFiles.get("Chain"); var clazz = classFiles.get("Chain");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m"); var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 5); assertEquals(5, m.invoke(instance));
} }
@Test @Test
@@ -1073,9 +1077,9 @@ public class TestComplete {
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertNull(clazz.getDeclaredMethod("m").invoke(instance)); assertNull(clazz.getDeclaredMethod("m").invoke(instance));
assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 'C'); assertEquals('C', clazz.getDeclaredMethod("m2").invoke(instance));
assertEquals(clazz.getDeclaredMethod("m3").invoke(instance), 10L); assertEquals(10L, clazz.getDeclaredMethod("m3").invoke(instance));
assertEquals(clazz.getDeclaredMethod("m4").invoke(instance), 10.5F); assertEquals(10.5F, clazz.getDeclaredMethod("m4").invoke(instance));
} }
@Test @Test
@@ -1083,7 +1087,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OLConstructor.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "OLConstructor.jav");
var clazz = classFiles.get("Child"); var clazz = classFiles.get("Child");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getSuperclass().getDeclaredField("x").get(instance), 3); assertEquals(3, clazz.getSuperclass().getDeclaredField("x").get(instance));
} }
@Test @Test
@@ -1091,11 +1095,11 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op1.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Op1.jav");
var clazz = classFiles.get("Op1"); var clazz = classFiles.get("Op1");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("not").invoke(instance), true); assertEquals(true, clazz.getDeclaredMethod("not").invoke(instance));
assertEquals(clazz.getDeclaredMethod("or").invoke(instance), 10 | 20); assertEquals(10 | 20, clazz.getDeclaredMethod("or").invoke(instance));
assertEquals(clazz.getDeclaredMethod("and").invoke(instance), 10 & 20); assertEquals(10 & 20, clazz.getDeclaredMethod("and").invoke(instance));
assertEquals(clazz.getDeclaredMethod("xor").invoke(instance), 10 ^ 20); assertEquals(10 ^ 20, clazz.getDeclaredMethod("xor").invoke(instance));
assertEquals(clazz.getDeclaredMethod("mod").invoke(instance), 10 % 2); assertEquals(10 % 2, clazz.getDeclaredMethod("mod").invoke(instance));
} }
@Ignore("Not implemented") @Ignore("Not implemented")
@@ -1112,18 +1116,18 @@ public class TestComplete {
var clazzPublic = classFiles.get("Access"); var clazzPublic = classFiles.get("Access");
var clazzDefault = classFiles.get("AccessDefault"); var clazzDefault = classFiles.get("AccessDefault");
assertEquals(clazzPublic.getModifiers(), Modifier.PUBLIC); assertEquals(Modifier.PUBLIC, clazzPublic.getModifiers());
assertEquals(clazzDefault.getModifiers(), 0); assertEquals(0, clazzDefault.getModifiers());
assertEquals(clazzPublic.getDeclaredMethod("mPublic").getModifiers(), Modifier.PUBLIC); assertEquals(Modifier.PUBLIC, clazzPublic.getDeclaredMethod("mPublic").getModifiers());
assertEquals(clazzPublic.getDeclaredMethod("mProtected").getModifiers(), Modifier.PROTECTED); assertEquals(Modifier.PROTECTED, clazzPublic.getDeclaredMethod("mProtected").getModifiers());
assertEquals(clazzPublic.getDeclaredMethod("mDefault").getModifiers(), 0); assertEquals(0, clazzPublic.getDeclaredMethod("mDefault").getModifiers());
assertEquals(clazzPublic.getDeclaredMethod("mPrivate").getModifiers(), Modifier.PRIVATE); assertEquals(Modifier.PRIVATE, clazzPublic.getDeclaredMethod("mPrivate").getModifiers());
assertEquals(clazzPublic.getDeclaredField("fPublic").getModifiers(), Modifier.PUBLIC); assertEquals(Modifier.PUBLIC, clazzPublic.getDeclaredField("fPublic").getModifiers());
assertEquals(clazzPublic.getDeclaredField("fProtected").getModifiers(), Modifier.PROTECTED); assertEquals(Modifier.PROTECTED, clazzPublic.getDeclaredField("fProtected").getModifiers());
assertEquals(clazzPublic.getDeclaredField("fDefault").getModifiers(), 0); assertEquals(0, clazzPublic.getDeclaredField("fDefault").getModifiers());
assertEquals(clazzPublic.getDeclaredField("fPrivate").getModifiers(), Modifier.PRIVATE); assertEquals(Modifier.PRIVATE, clazzPublic.getDeclaredField("fPrivate").getModifiers());
} }
@Test @Test
@@ -1161,7 +1165,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Ternary.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Ternary.jav");
var clazz = classFiles.get("Ternary"); var clazz = classFiles.get("Ternary");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5), "small"); assertEquals("small", clazz.getDeclaredMethod("main", Integer.class).invoke(instance, 5));
} }
@Test @Test
@@ -1169,8 +1173,8 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "While.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "While.jav");
var clazz = classFiles.get("While"); var clazz = classFiles.get("While");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5), 5); assertEquals(5, clazz.getDeclaredMethod("m", Integer.class).invoke(instance, 5));
assertEquals(clazz.getDeclaredMethod("m2").invoke(instance), 10); assertEquals(10, clazz.getDeclaredMethod("m2").invoke(instance));
} }
@Test @Test
@@ -1186,7 +1190,7 @@ public class TestComplete {
var clazz = classFiles.get("Assign"); var clazz = classFiles.get("Assign");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
var m = clazz.getDeclaredMethod("m"); var m = clazz.getDeclaredMethod("m");
assertEquals(m.invoke(instance), 20); assertEquals(20, m.invoke(instance));
} }
@Test @Test
@@ -1243,9 +1247,9 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug295.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug295.jav");
var clazz = classFiles.get("Bug295"); var clazz = classFiles.get("Bug295");
var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class, Integer.class).newInstance(1, 2, 3); var instance = clazz.getDeclaredConstructor(Integer.class, Integer.class, Integer.class).newInstance(1, 2, 3);
assertEquals(clazz.getDeclaredField("a").get(instance), 1); assertEquals(1, clazz.getDeclaredField("a").get(instance));
assertEquals(clazz.getDeclaredField("b").get(instance), 2); assertEquals(2, clazz.getDeclaredField("b").get(instance));
assertEquals(clazz.getDeclaredField("c").get(instance), 3); assertEquals(3, clazz.getDeclaredField("c").get(instance));
} }
@Test @Test
@@ -1275,7 +1279,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug300.jav");
var clazz = classFiles.get("Bug300"); var clazz = classFiles.get("Bug300");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("m").invoke(instance), "Base"); assertEquals("Base", clazz.getDeclaredMethod("m").invoke(instance));
} }
@Test @Test
@@ -1320,7 +1324,7 @@ public class TestComplete {
var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug310.jav"); var classFiles = generateClassFiles(new ByteArrayClassLoader(), "Bug310.jav");
var clazz = classFiles.get("Bug310"); var clazz = classFiles.get("Bug310");
var instance = clazz.getDeclaredConstructor().newInstance(); var instance = clazz.getDeclaredConstructor().newInstance();
assertEquals(clazz.getDeclaredMethod("toString").invoke(instance), "3"); assertEquals("3", clazz.getDeclaredMethod("toString").invoke(instance));
} }
@Test @Test