Overview
SHA1 Hash: | 78ec862f1af87636c311d60017549f08606871d1 |
---|---|
Date: | 2011-02-23 11:49:26 |
User: | kinaba |
Comment: | Added the source code of "TZTester cafelier+naoya_t custom". |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [9165bd3629]
- sym-trunk inherited from [9165bd3629]
Changes
Added TZTesterSp/ContestApplet.jar version [38843265df3fb2ca]
cannot compute difference between binary files
Added TZTesterSp/Makefile version [362cbea8b2a2ebd3]
1 +TZTester.jar: tangentz/TZTester.class 2 + jar cvf TZTester.jar tangentz/TZTester.class 3 + 4 +install: TZTester.jar 5 + cp TZTester.jar ../workspace/arena_plugin 6 + 7 +clean: 8 + rm -f TZTester.jar tangentz/TZTester.class 9 + 10 +tangentz/TZTester.class: tangentz/TZTester.java 11 + javac -classpath ContestApplet.jar tangentz/TZTester.java
Added TZTesterSp/tangentz/TZTester.java version [60ea23189465161e]
1 +package tangentz; 2 +import java.util.HashMap; 3 +import java.util.Map; 4 +import com.topcoder.client.contestant.ProblemComponentModel; 5 +import com.topcoder.shared.language.Language; 6 +import com.topcoder.shared.problem.*; 7 + 8 + 9 +/** 10 + * @author TangentZ 11 + * 12 + * This tester class is for C++ only. It is based on PopsProcessor which is written for Java. 13 + * It reads in all the given examples for a problem and generates the equivalent C++ code 14 + * to test all the cases. The accumulated running time is 8 seconds, but it is easy to 15 + * selectively run a specific case only. 16 + * 17 + * This tester will define three tags that can be embedded within PopsEdit/FileEdit code template: 18 + * $WRITERCODE$ - place holder for writer code - will be blank if none found 19 + * $PROBLEM$ - place holder for problem description as plain text 20 + * // $RUNTEST$ - place holder for where to put the code that starts the test 21 + * $TESTCODE$ - place holder for where to put the test code 22 + */ 23 +public class TZTester 24 +{ 25 + // Map used to store my tags 26 + private HashMap<String,String> m_Tags = new HashMap<String,String>(); 27 + 28 + // Constants 29 + private static final String k_WRITERCODE = "$WRITERCODE$"; 30 + private static final String k_PROBLEM = "$PROBLEM$"; 31 + private static final String k_RUNTEST = "$RUNTEST$"; 32 + private static final String k_TESTCODE = "$TESTCODE$"; 33 + private static final String k_VERSION = "\n// Powered by TZTester 1.01 [25-Feb-2003] : <cafelier&naoya_t>-custom"; 34 + 35 + // Cut tags 36 + private static final String k_BEGINCUT = "// BEGIN CUT HERE"; 37 + private static final String k_ENDCUT = "// END CUT HERE"; 38 + 39 + // Problem-related variables 40 + private ProblemComponentModel m_Problem = null; 41 + private Language m_Language = null; 42 + 43 + /** 44 + * PreProcess the source code 45 + * 46 + * First determines if it is saved code, writer code, or nothing and stores it in $WRITERCODE$ tag 47 + * Secondly builds a main method with default test cases 48 + */ 49 + public String preProcess(String Source, ProblemComponentModel Problem, Language Lang, Renderer Render) 50 + { 51 + // Set defaults for the tags in case we exit out early 52 + m_Tags.put(k_WRITERCODE, ""); 53 + m_Tags.put(k_PROBLEM, ""); 54 + m_Tags.put(k_RUNTEST, "// *** WARNING *** $RUNTEST$ is not supported by this customized TZTester."); 55 + m_Tags.put(k_TESTCODE, ""); 56 + 57 + // If there is source and the source is NOT equal to the default solution, return it 58 + if( Source.length()>0 && !Source.equals(Problem.getDefaultSolution()) ) 59 + return Source; 60 + 61 + // Check to see if the component has any signature 62 + if( !Problem.hasSignature() ) 63 + { 64 + m_Tags.put(k_TESTCODE, "// *** WARNING *** Problem has no signature defined for it"); 65 + return ""; 66 + } 67 + 68 + // Get the test cases 69 + TestCase[] TestCases = Problem.getTestCases(); 70 + 71 + // Check to see if test cases are defined 72 + if( TestCases==null || TestCases.length==0 ) 73 + { 74 + m_Tags.put(k_TESTCODE, "// *** WARNING *** No test cases defined for this problem"); 75 + return ""; 76 + } 77 + 78 + // Re-initialize the tags 79 + m_Tags.clear(); 80 + m_Tags.put(k_WRITERCODE, Problem.getDefaultSolution()); 81 + try { m_Tags.put(k_PROBLEM, Render.toHTML(m_Language)); } catch (Exception Ex) { } 82 + 83 + m_Problem = Problem; 84 + m_Language = Lang; 85 + 86 + // Generate the test cases 87 + generate_test_code(); 88 + return ""; 89 + } 90 + 91 + /** 92 + * This method will cut the test methods above out 93 + */ 94 + public String postProcess(String Source, Language Lang) 95 + { 96 + // Insert a version string 97 + return Source + k_VERSION; 98 + } 99 + 100 + /** 101 + * This method will return my tags. This method is ALWAYS called after preProcess() 102 + * 103 + * @return a map of my tags 104 + */ 105 + public Map getUserDefinedTags() 106 + { 107 + return m_Tags; 108 + } 109 + 110 + /** 111 + * This method will generate the code for the test cases. 112 + */ 113 + private void generate_test_code() 114 + { 115 + DataType[] ParamTypes = m_Problem.getParamTypes(); 116 + DataType ReturnType = m_Problem.getReturnType(); 117 + TestCase[] Cases = m_Problem.getTestCases(); 118 + StringBuffer Code = new StringBuffer(); 119 + 120 + // <<thanks to naoya_t>> Generate the timer function 121 + Code.append("#include <ctime>\n"); 122 + Code.append("double start_time; string timer()\n"); 123 + Code.append(" { ostringstream os; os << \" (\" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << \" msec)\"; return os.str(); }\n"); 124 + 125 + // Generate the vector output function 126 + Code.append("template<typename T> ostream& operator<<(ostream& os, const vector<T>& v)\n"); 127 + Code.append(" { os << \"{ \";\n"); 128 + Code.append(" for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it)\n"); 129 + Code.append(" os << \'\\\"\' << *it << \'\\\"\' << (it+1==v.end() ? \"\" : \", \"); os << \" }\"; return os; }\n"); 130 + 131 + // Generate the verification function 132 + generate_verification_code(Code, ReturnType); 133 + 134 + // <<modified by cafelier>> : new test code template 135 + Code.append("#define CASE(N) {cerr << \"Test Case #\" << N << \"...\" << flush; start_time=clock();\n"); 136 + Code.append("#define END "); 137 + generate_verifier_call(Code, ParamTypes, ReturnType, Cases[0]); 138 + Code.append("}\n"); 139 + Code.append("int main(){\n\n"); 140 + 141 + // Generate the individual test cases 142 + for(int i=0; i<Cases.length; ++i) 143 + generate_test_case(i, Code, ParamTypes, ReturnType, Cases[i]); 144 + for(int i=0; i<2; ++i) 145 + generate_blank_test_case(Cases.length+i, Code, ParamTypes, ReturnType, Cases[0]); 146 + Code.append("\n}\n"); 147 + 148 + // Insert the cut tags 149 + Code.insert(0, k_BEGINCUT+"\n"); 150 + Code.append(k_ENDCUT); 151 + 152 + // Replace $TESTCODE$ 153 + m_Tags.put(k_TESTCODE, Code.toString()); 154 + } 155 + 156 + /** 157 + * This method will generate the code for verifying test cases. 158 + */ 159 + private void generate_verification_code(StringBuffer Code, DataType ReturnType) 160 + { 161 + String TypeString = ReturnType.getDescriptor(m_Language); 162 + 163 + // <<modified by cafelier>> : new test code template 164 + Code.append("void verify_case(const " + TypeString + "& Expected, const " + TypeString + "& Received) {\n"); 165 + 166 + // Print "PASSED" or "FAILED" based on the result 167 + // <<modified by naoya_t>> : double precision 168 + if (TypeString.equals("double")) { 169 + Code.append(" bool ok = (abs(Expected - Received) < 1e-9);\n"); 170 + } else if (TypeString.equals("vector <double>")) { 171 + // <<modified by cafelier>> : vector<double> !!! 172 + Code.append(" bool ok = true;\n"); 173 + Code.append(" for(int i=0; i<Expected.size(); ++i)\n"); 174 + Code.append(" if( abs(Expected[i]-Received[i]) >= 1e-9 )\n"); 175 + Code.append(" ok = false;\n"); 176 + } else { 177 + Code.append(" bool ok = (Expected == Received);\n"); 178 + } 179 + Code.append(" if(ok) cerr << \"PASSED\" << timer() << endl; "); 180 + Code.append(" else { cerr << \"FAILED\" << timer() << endl;\n "); 181 + 182 + if (ReturnType.getDimension() == 0) 183 + { 184 + Code.append("cerr << \"\\to: \\\"\" << Expected << \'\\\"\' << endl "); 185 + Code.append("<< \"\\tx: \\\"\" << Received << \'\\\"\' << endl; }"); 186 + } 187 + else 188 + { 189 + Code.append("cerr << \"\\to: \" << Expected << endl "); 190 + Code.append("<< \"\\tx: \" << Received << endl; }"); 191 + } 192 + 193 + Code.append(" }\n"); 194 + } 195 + 196 + /** 197 + * This method will generate the code for one test case. 198 + */ 199 + private void generate_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 200 + { 201 + String[] Inputs = Case.getInput(); 202 + String Output = Case.getOutput(); 203 + String Desc = ReturnType.getDescription(); 204 + 205 + /* 206 + * Generate code for setting up individual test cases 207 + * and calling the method with these parameters. 208 + */ 209 + 210 + // <<modified by cafelier>> : new test code template 211 + Code.append("CASE("+Index+")\n"); 212 + 213 + // Generate each input variable separately 214 + for (int I = 0; I < Inputs.length; ++I) { 215 + Code.append("\t"); 216 + generate_parameter(I, Code, ParamTypes[I], Inputs[I]); 217 + Code.append("\n"); 218 + } 219 + 220 + // Generate the output variable as the last variable 221 + Code.append("\t"); 222 + generate_parameter(-1, Code, ReturnType, Output); 223 + Code.append("\n"); 224 + Code.append("END\n"); 225 + } 226 + 227 + private void generate_blank_test_case(int Index, StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 228 + { 229 + String[] Inputs = Case.getInput(); 230 + String Output = Case.getOutput(); 231 + String Desc = ReturnType.getDescription(); 232 + 233 + Code.append("CASE("+Index+")\n"); 234 + for (int I = 0; I < Inputs.length; ++I) { 235 + Code.append("\t"); 236 + generate_parameter(I, Code, ParamTypes[I], ""); 237 + Code.append("\n"); 238 + } 239 + Code.append("\t"); 240 + generate_parameter(-1, Code, ReturnType, ""); 241 + Code.append("\n"); 242 + Code.append("END\n"); 243 + } 244 + 245 + private void generate_verifier_call(StringBuffer Code, DataType[] ParamTypes, DataType ReturnType, TestCase Case) 246 + { 247 + String[] Inputs = Case.getInput(); 248 + String Output = Case.getOutput(); 249 + String Desc = ReturnType.getDescription(); 250 + 251 + Code.append("verify_case(_, " 252 + + m_Problem.getClassName() + "()." + m_Problem.getMethodName() + "("); 253 + for(int i=0; i<Inputs.length; ++i) 254 + { 255 + Code.append( m_Problem.getParamNames()[i] ); 256 + if( i < Inputs.length-1 ) 257 + Code.append(", "); 258 + } 259 + Code.append("));"); 260 + } 261 + 262 + /** 263 + * This method will generate the required parameter as a unique variable. 264 + */ 265 + private void generate_parameter(int Index, StringBuffer Code, DataType ParamType, String Input) 266 + { 267 + // <<modified by cafelier>> : named parameters 268 + String Name = (Index==-1 ? "_" : m_Problem.getParamNames()[Index]); 269 + 270 + String Desc = ParamType.getBaseName(); 271 + 272 + if (ParamType.getDimension() == 0) 273 + { 274 + // Just a scalar value, simply initialize it at declaration (long integers need an 'L' tagged on) 275 + if (Desc.equals("long") || Desc.equals("Long")) 276 + Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "LL; "); 277 + else 278 + Code.append(ParamType.getDescriptor(m_Language) + " " + Name + " = " + Input + "; "); 279 + } 280 + else 281 + { 282 + // <<modified by cafelier>> : empty array 283 + if( Input.matches("^[\\s\\{\\}]+$") ) 284 + { 285 + Code.append(ParamType.getDescriptor(m_Language) + " " + Name + "; "); 286 + } 287 + else 288 + { 289 + // Arrays need to be converted to vector<type> before passing 290 + Code.append(ParamType.getBaseName().toLowerCase() + " " + Name + "_[] = " + Input + ";\n\t"); 291 + Code.append(" "+ParamType.getDescriptor(m_Language) + " " + Name + "(" + Name + "_, " + Name + "_+sizeof("+Name+"_)/sizeof(*"+Name+"_)); "); 292 + } 293 + } 294 + } 295 +}