package metalexer.jflex;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import junit.framework.TestCase;

public abstract class MetaScannerTestBase extends TestCase {
    private static final String BASE_DIR = "test/backend-jflex";

    private final MetaScannerPropHelper propHelper;

    protected MetaScannerTestBase(String groupName, String layoutName) {
        this.propHelper = new MetaScannerPropHelper(groupName, layoutName);
    }

    protected void checkOutput(String baseName) throws IOException, InterruptedException {
        String inFileName = BASE_DIR + "/" + baseName + ".in";
        String outFileName = BASE_DIR + "/" + baseName + ".out";

        List<Integer> input = new ArrayList<Integer>();
        BufferedReader inReader = new BufferedReader(new FileReader(inFileName));
        while(inReader.ready()) {
            String line = inReader.readLine();
            input.add(propHelper.getMacroValue(line));
        }
        inReader.close();

        List<List<Integer>> expectedOutput = new ArrayList<List<Integer>>();
        BufferedReader outReader = new BufferedReader(new FileReader(outFileName));
        while(outReader.ready()) {
            List<Integer> lineOutput = new ArrayList<Integer>();
            String line = outReader.readLine();
            StringTokenizer tokenizer = new StringTokenizer(line);
            while(tokenizer.hasMoreTokens()) {
                lineOutput.add(propHelper.getEmbeddingValue(tokenizer.nextToken()));
            }
            expectedOutput.add(lineOutput);
        }
        outReader.close();

        if(input.size() != expectedOutput.size()) {
            throw new RuntimeException("Incorrect test specification: " + expectedOutput.size() + " outputs for " + input.size() + " inputs");
        }

        List<List<Integer>> actualOutput = getActualOutput(input);
        for(int i = 0; i < input.size(); i++) {
            assertEquals("Incorrect output on input #" + i, expectedOutput.get(i), actualOutput.get(i));
        }
    }

    protected abstract List<List<Integer>> getActualOutput(List<Integer> input);
}
