001package daikon.test; 002 003import static java.nio.charset.StandardCharsets.UTF_8; 004import static java.util.logging.Level.INFO; 005import static org.junit.Assert.fail; 006 007import daikon.FileIO; 008import java.io.BufferedReader; 009import java.io.ByteArrayOutputStream; 010import java.io.IOException; 011import java.io.InputStream; 012import java.io.InputStreamReader; 013import java.io.PrintStream; 014import java.io.UncheckedIOException; 015import java.util.ArrayList; 016import java.util.List; 017import java.util.StringTokenizer; 018import junit.framework.*; 019import org.junit.BeforeClass; 020import org.junit.Test; 021 022/** 023 * This tests various aspects of VarInfoName's and transforming VarInfoName's. This calls 024 * VarInfoNameDriver after parsing all input files of the name "varInfoNameTest.<em>foo</em>". 025 * VarInfoNameDriver does transform tests, and its output is compared to the 026 * "varInfoNameTest.<em>foo</em>.goal" file by this. 027 * 028 * <p>To add a new test case, add a line to the <em>foo</em> file and a line to the goal file with 029 * intended output. Format of the <em>foo</em> file is output method, followed by a variable name. 030 * Output methods are defined in VarInfoNameDriver. To add a new transformation method (which can 031 * then be tested in test cases) add a static Handler implementation to VarInfoNameDriver modeled 032 * after one of the ones already present and add a static {} line after to add the handler to the 033 * list of handlers. 034 */ 035public class VarInfoNameTest { 036 037 private static final String lineSep = daikon.Global.lineSep; 038 039 /** prepare for tests */ 040 @BeforeClass 041 public static void setUpClass() { 042 daikon.LogHelper.setupLogs(INFO); 043 FileIO.new_decl_format = true; 044 } 045 046 @Test 047 public void testParse() { 048 run("testParse"); 049 } 050 051 // Fails mysteriously, only when run from a cron job. The failure is in 052 // obsolescent code (VarInfoNameTest), so comment it out rather than 053 // debugging it. 054 // @Test public void testEscForall() { run("testEscForall"); } 055 @Test 056 public void testSubscript() { 057 run("testSubscript"); 058 } 059 060 @Test 061 public void testJML() { 062 run("testJML"); 063 } 064 065 private void run(String name) { 066 String file = "varInfoNameTest." + name; 067 try (InputStream input_stream = VarInfoNameTest.class.getResourceAsStream(file); 068 InputStream goal_stream = VarInfoNameTest.class.getResourceAsStream(file + ".goal")) { 069 070 if (input_stream == null) { 071 throw new Error("couldn't find " + file); 072 } 073 if (goal_stream == null) { 074 throw new Error("couldn't find " + file + ".goal"); 075 } 076 077 // run the tests 078 ByteArrayOutputStream out = new ByteArrayOutputStream(); 079 VarInfoNameDriver.run(input_stream, new PrintStream(out)); 080 081 // put output into actual 082 List<String> _actual = new ArrayList<>(); 083 @SuppressWarnings("DefaultCharset") // toString(Charset) was introduced in Java 10 084 StringTokenizer tok = new StringTokenizer(out.toString(), lineSep); 085 while (tok.hasMoreTokens()) { 086 _actual.add(tok.nextToken()); 087 } 088 String[] actual = _actual.toArray(new String[0]); 089 090 // put desired into goal 091 List<String> _goal = new ArrayList<>(); 092 try { 093 BufferedReader buf = new BufferedReader(new InputStreamReader(goal_stream, UTF_8)); 094 while (buf.ready()) { 095 String line = buf.readLine(); 096 _goal.add(line); 097 } 098 buf.close(); 099 } catch (IOException e) { 100 throw new RuntimeException(e.toString()); 101 } 102 String[] goal = _goal.toArray(new String[0]); 103 104 // diff desired and output 105 diff(goal, actual); 106 } catch (IOException e) { 107 throw new UncheckedIOException(e); 108 } 109 } 110 111 private void diff(String[] goal, String[] actual) { 112 for (int i = 0; i < goal.length; i++) { 113 String goal_line = goal[i]; 114 if (i >= actual.length) { 115 fail( 116 "Diff error:" 117 + lineSep 118 + "Actual had too few lines, starting with goal line:" 119 + lineSep 120 + "\t" 121 + goal_line); 122 } 123 String actual_line = actual[i]; 124 if (!goal_line.equals(actual_line)) { 125 String goals = ""; 126 String actuals = ""; 127 int low = Math.max(0, i - 3); 128 int high = Math.min(Math.min(i + 3, actual.length - 1), goal.length - 1); 129 for (int j = low; j <= high; j++) { 130 if (!goal[j].equals(actual[j])) { 131 goals += ">"; 132 actuals += ">"; 133 } 134 goals += "\t" + goal[j] + lineSep; 135 actuals += "\t" + actual[j] + lineSep; 136 } 137 fail( 138 "Diff error:" 139 + lineSep 140 + "Different output encountered. Expected:" 141 + lineSep 142 + goals 143 + "Received:" 144 + lineSep 145 + actuals 146 + " on line: " 147 + i); 148 } 149 } 150 if (actual.length > goal.length) { 151 StringBuilder extra = new StringBuilder(); 152 for (int i = goal.length; i < actual.length; i++) { 153 extra.append("\t"); 154 extra.append(actual[i]); 155 extra.append(lineSep); 156 } 157 fail("Diff error:" + lineSep + "Actual had extra lines:" + lineSep + extra.toString()); 158 } 159 } 160 161 // parsing 162 // interning 163 // *name() 164 // object methods 165 166 // Simple 167 // Size 168 // Function 169 // TypeOf 170 // Prestate 171 // Poststate 172 // Add 173 // Elements 174 // Subscript 175 // Slice 176 177 // ElementsFinder 178 // Replacer 179 // InorderFlattener 180 // QuantifierVisitor 181 // QuantHelper.format_esc 182}