FOP-2425-Marathon/src/graderPrivate/java/h02/TestUtils.java
Oshgnacknak 58e3b905b1 Squashed 'solution/H02/' content from commit 5a755f9
git-subtree-dir: solution/H02
git-subtree-split: 5a755f9abf28a4f7f6670bd3587d1ae2cb3b531d
2025-01-11 16:41:07 +01:00

110 lines
4.1 KiB
Java

package h02;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.tudalgo.algoutils.tutor.general.SpoonUtils;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtParameter;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import static h02.TestConstants.RANDOM_SEED;
public abstract class TestUtils {
/**
* A generator for JSON test data.
*/
public interface JsonGenerator {
/**
* Generates a JSON object node.
*
* @param mapper The object mapper to use.
* @param index The index of the object node.
* @param rnd The random number generator to use.
* @return The generated JSON object node.
*/
ObjectNode generateJson(ObjectMapper mapper, int index, Random rnd);
}
/**
* Generates and saves JSON test data.
*
* @param generator The generator to use.
* @param amount The amount of test data to generate.
* @param fileName The file name to save the test data to.
* @throws IOException If an I/O error occurs.
*/
public static void generateJsonTestData(final JsonGenerator generator, final int amount, final String fileName) throws IOException {
final var seed = RANDOM_SEED;
final var random = new java.util.Random(seed);
final ObjectMapper mapper = new ObjectMapper();
final ArrayNode arrayNode = mapper.createArrayNode();
System.out.println("Generating test data with seed: " + seed);
for (int i = 0; i < amount; i++) {
arrayNode.add(generator.generateJson(mapper, i, random));
}
// convert `ObjectNode` to pretty-print JSON
// System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(arrayNode));
final var path = Paths.get(
"src",
"graderPrivate",
"resources",
"h02",
fileName
).toAbsolutePath();
System.out.printf("Saving to file: %s%n", path);
final var file = path.toFile();
file.createNewFile();
mapper.writerWithDefaultPrettyPrinter().writeValue(file, arrayNode);
}
/**
* Returns the Spoon representation of the given method.
*
* @param clazz the method's owner
* @param methodName the method name
* @param paramTypes the method's formal parameter types, if any
* @return the Spoon representation of the given method
*/
public static CtMethod<?> getCtMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) {
return SpoonUtils.getType(clazz.getName())
.getMethodsByName(methodName)
.stream()
.filter(ctMethod -> {
List<CtParameter<?>> parameters = ctMethod.getParameters();
boolean result = parameters.size() == paramTypes.length;
for (int i = 0; result && i < parameters.size(); i++) {
result = parameters.get(i).getType().getQualifiedName().equals(paramTypes[i].getTypeName());
}
return result;
})
.findAny()
.orElseThrow();
}
/**
* Applies the given consumer to the body and its descendants of the given method.
* See also: {@link #getCtMethod(Class, String, Class[])}.
*
* @param clazz the method's owner
* @param methodName the method name
* @param paramTypes the method's formal parameter types, if any
* @param consumer the consumer to apply
*/
public static void iterateMethodStatements(Class<?> clazz, String methodName, Class<?>[] paramTypes, Consumer<Iterator<CtElement>> consumer) {
Iterator<CtElement> iterator = getCtMethod(clazz, methodName, paramTypes)
.getBody()
.descendantIterator();
consumer.accept(iterator);
}
}