001    package ps4.test;
002    
003    import java.io.BufferedReader;
004    import java.io.File;
005    import java.io.FileNotFoundException;
006    import java.io.FileReader;
007    import java.io.FileWriter;
008    import java.io.IOException;
009    import java.io.Reader;
010    import java.io.Writer;
011    import java.net.URISyntaxException;
012    
013    import junit.framework.Test;
014    import junit.framework.TestCase;
015    import junit.framework.TestSuite;
016    
017    /**
018     * This class, along with a complete PS4TestDriver implementation,
019     * can be used to test the your implementations of Graph and the
020     * path finding algorithm using the script file format described
021     * in the problem set.  It is assumed that the files are
022     * located in the same directory as this class.
023    */
024    public class ScriptFileTests extends TestCase {
025        private final File testDriver;
026    
027        /**
028         * Creates a new ScriptFileTests case, which runs the given test file.
029         * @param testDriver
030         */
031        public ScriptFileTests(File testDriver) {
032            super("testWithScriptFile");
033    
034            this.testDriver = testDriver;
035        }
036    
037        /**
038         * Reads in the contents of a file; changes the line
039         * separator to System.getProperty("line.separator")
040         * @throws FileNotFoundException, IOException
041         * @requires that the specified File exists && File ends with a newline
042         * @returns the contents of that file
043         */
044        private String fileContents(File f) throws IOException {
045            if (f == null) {
046                throw new IllegalArgumentException("No file specified");
047            }
048    
049            BufferedReader br = new BufferedReader(new FileReader(f));
050    
051            StringBuilder result = new StringBuilder();
052            String line = null;
053    
054            // readLine reads up to *any* end-of-line character combination
055            while ((line = br.readLine()) != null) {
056                result.append(line);
057                result.append(System.getProperty("line.separator"));
058            }
059    
060            br.close();
061            return result.toString();
062        }
063    
064        /**
065         * @throws IOException
066         * @requires there exists a test file indicated by testDriver
067         *
068         * @effects runs the test in filename, and output its results to a file in
069         * the same directory with name filename+".actual"; if that file already
070         * exists, it will be overwritten.
071         * @returns the contents of the output file
072         */
073        private String runScriptFile() throws IOException {
074            if (testDriver == null) {
075                throw new RuntimeException("No file specified");
076            }
077    
078            File actual = fileWithSuffix("actual");
079    
080            Reader r = new FileReader(testDriver);
081            Writer w = new FileWriter(actual);
082    
083            PS4TestDriver td = new PS4TestDriver(r, w);
084            td.runTests();
085    
086            return fileContents(actual);
087        }
088    
089        /**
090         * @param newSuffix
091         * @return a File with the same name as testDriver, except that the test
092         *         suffix is replaced by the given suffix
093         */
094        private File fileWithSuffix(String newSuffix) {
095            File parent = testDriver.getParentFile();
096            String driverName = testDriver.getName();
097            String baseName = driverName.substring(0, driverName.length() - "test".length());
098    
099            return new File(parent, baseName + newSuffix);
100        }
101    
102        /**
103         * The only test that is run: run a script file and test its output.
104         * @throws IOException
105         */
106        public void testWithScriptFile() throws IOException {
107            File expected = fileWithSuffix("expected");
108    
109            //TWS: Hack to differentiate tests based on script name
110            setName(testDriver.getName().substring(0, testDriver.getName().lastIndexOf('.')) );
111    
112            assertEquals(testDriver.getName(), fileContents(expected), runScriptFile());
113        }
114    
115        /**
116         * Build a test suite of all of the script files in the directory.
117         * @return the test suite
118         * @throws URISyntaxException
119         */
120        public static Test suite()
121        {
122            TestSuite suite = new TestSuite();
123    
124            // Hack to get at the directory where the files are: they are in the
125            // same directory as the compiled ScriptFileTests class,
126            try {
127                // getResource() cannot be null: this file itself is ScriptFileTests
128                // getParentFile() cannot be null: ScriptFileTests has a package
129                @SuppressWarnings("nullness")
130                File myDirectory = new File(ScriptFileTests.class.getResource("ScriptFileTests.class").toURI()).getParentFile();
131                for (File f : myDirectory.listFiles()) {
132                    if (f.getName().endsWith(".test")) {
133                        suite.addTest(new ScriptFileTests(f));
134                    }
135                }
136                return suite;
137            } catch (URISyntaxException e) {
138                throw new RuntimeException(e);
139            }
140        }
141    }