package edu.anu.spice; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; import java.util.HashSet; import javax.script.ScriptException; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; import org.junit.BeforeClass; import org.junit.Test; public abstract class SpiceTest { private static boolean initialize = true; protected static JSONArray expectedOutput; private static String inFile = "test_input.json"; private static String refFile = "test_reference.json"; private static String outFileNoCache = "test_output_no_cache.json"; private static String outFilePreCache = "test_output_pre_cache.json"; private static String outFilePostCache = "test_output_post_cache.json"; private static String testDataPath(String fileName) { File resourcesDirectory = new File("src/test/data"); return resourcesDirectory.getAbsolutePath() + "/" + fileName; } private static JSONArray loadJSONArray(String fileName) throws IOException, ParseException, FileNotFoundException { JSONParser parser = new JSONParser(); return (JSONArray) parser.parse(new FileReader(testDataPath(fileName))); } protected static void compareTuples(JSONArray expectedTuples, JSONArray actualTuples, String type, Object image_id){ assertEquals(String.format("Incorrect number of %s tuples for image_id %s", type, image_id), expectedTuples.size(), actualTuples.size()); HashMap<String, Boolean> expectedTupleMap = new HashMap<String, Boolean>(); for (int j = 0; j < expectedTuples.size(); j++){ JSONObject tuple = (JSONObject) expectedTuples.get(j); String tupleString = tuple.get("tuple").toString(); expectedTupleMap.put(tupleString, (Boolean)tuple.get("truth_value")); } HashSet<String> actualTupleSet = new HashSet<String>(); for (int j = 0; j <actualTuples.size(); j++){ JSONObject tuple = (JSONObject) actualTuples.get(j); String tupleString = tuple.get("tuple").toString(); // Check no duplicates assertFalse(String.format("Duplicated %s tuple found for image id %s: %s", type, image_id, tupleString), actualTupleSet.contains(tupleString)); actualTupleSet.add(tupleString); // Check matches the expected tuple assertTrue(String.format("Found tuple %s, not expected in %s tuples for image id %s", tupleString, type, image_id), expectedTupleMap.containsKey(tupleString)); // Check truth value Boolean truthValue = (Boolean)tuple.get("truth_value"); assertEquals(String.format("Found %s tuple %s with incorrect truth value for image id %s", type, tupleString, image_id), expectedTupleMap.get(tupleString), truthValue); } } private static void runNoCache() throws IOException, ScriptException { SpiceArguments args = new SpiceArguments(); args.inputPath = testDataPath(inFile); args.outputPath = testDataPath(outFileNoCache); args.detailed = true; SpiceScorer scorer = new SpiceScorer(); scorer.scoreBatch(args); } private static void runWithCache() throws IOException, ScriptException { SpiceArguments args = new SpiceArguments(); args.inputPath = testDataPath(inFile); args.outputPath = testDataPath(outFilePreCache); args.detailed = true; args.cache = testDataPath(""); SpiceScorer scorer = new SpiceScorer(); // Iteration to build cache scorer.scoreBatch(args); // Iteration to use cache args.outputPath = testDataPath(outFilePostCache); scorer.scoreBatch(args); } protected static void cleanDir() throws IOException { // Delete any existing cache Files.deleteIfExists(Paths.get(testDataPath("data.mdb"))); Files.deleteIfExists(Paths.get(testDataPath("lock.mdb"))); // Delete existing output Files.deleteIfExists(Paths.get(testDataPath(outFileNoCache))); Files.deleteIfExists(Paths.get(testDataPath(outFilePreCache))); Files.deleteIfExists(Paths.get(testDataPath(outFilePostCache))); } @BeforeClass public static void loadExpectedOutput() throws IOException, ParseException, FileNotFoundException, ScriptException { expectedOutput = loadJSONArray(refFile); // Initialize once only using global variable if (!initialize) { return; } initialize = false; cleanDir(); // Generate fresh test outputs runNoCache(); runWithCache(); } protected abstract void compare(JSONArray expected, JSONArray actual); @Test public void testNoCache() throws IOException, ParseException, FileNotFoundException { compare(expectedOutput, loadJSONArray(outFileNoCache)); } @Test public void testPreCache() throws IOException, ParseException, FileNotFoundException { compare(expectedOutput, loadJSONArray(outFilePreCache)); } @Test public void testPostCache() throws IOException, ParseException, FileNotFoundException { compare(expectedOutput, loadJSONArray(outFilePostCache)); } }