1# 2# Test the acc compiler 3 4import unittest 5import subprocess 6import os 7import sys 8 9gArmInitialized = False 10gUseArm = True 11gUseX86 = True 12gRunOTCCOutput = True 13 14 15def parseArgv(): 16 global gUseArm 17 global gUseX86 18 global gRunOTCCOutput 19 for arg in sys.argv[1:]: 20 if arg == "--noarm": 21 print "--noarm: not testing ARM" 22 gUseArm = False 23 elif arg == "--nox86": 24 print "--nox86: not testing x86" 25 gUseX86 = False 26 elif arg == "--norunotcc": 27 print "--norunotcc detected, not running OTCC output" 28 gRunOTCCOutput = False 29 else: 30 print "Unknown parameter: ", arg 31 raise "Unknown parameter" 32 sys.argv = sys.argv[0:1] 33 34def compile(args): 35 proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 36 result = proc.communicate() 37 return result 38 39def runCmd(args): 40 proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 41 result = proc.communicate() 42 return result[0].strip() 43 44def uname(): 45 return runCmd(["uname"]) 46 47def unameM(): 48 return runCmd(["uname", "-m"]) 49 50def which(item): 51 return runCmd(["which", item]) 52 53def fileType(item): 54 return runCmd(["file", item]) 55 56def outputCanRun(): 57 ft = fileType(which("acc")) 58 return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0 59 60def checkEnvironment(): 61 global gRunOTCCOutput 62 gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun() 63 64def adb(args): 65 return runCmd(["adb"] + args) 66 67def setupArm(): 68 global gArmInitialized 69 if gArmInitialized: 70 return 71 print "Setting up arm" 72 adb(["remount"]) 73 adb(["shell", "rm", "/system/bin/acc"]) 74 adb(["shell", "mkdir", "/system/bin/accdata"]) 75 adb(["shell", "mkdir", "/system/bin/accdata/data"]) 76 # Clear out old data TODO: handle recursion 77 adb(["shell", "rm", "/system/bin/accdata/data/*"]) 78 # Copy over data 79 for root, dirs, files in os.walk("data"): 80 for d in dirs: 81 adb(["shell", "mkdir", os.path.join(root, d)]) 82 for f in files: 83 adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)]) 84 # Copy over compiler 85 adb(["sync"]) 86 gArmInitialized = True 87 88def compileArm(args): 89 setupArm() 90 proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE) 91 result = proc.communicate() 92 return result[0].replace("\r","") 93 94def compare(a, b): 95 if a != b: 96 firstDiff = firstDifference(a, b) 97 print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % ( 98 firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff)) 99 100def safeAccess(s, i): 101 if 0 <= i < len(s): 102 return s[i] 103 else: 104 return '?' 105 106def firstDifference(a, b): 107 commonLen = min(len(a), len(b)) 108 for i in xrange(0, commonLen): 109 if a[i] != b[i]: 110 return i 111 return commonLen 112 113# a1 and a2 are the expected stdout and stderr. 114# b1 and b2 are the actual stdout and stderr. 115# Compare the two, sets. Allow any individual line 116# to appear in either stdout or stderr. This is because 117# the way we obtain output on the ARM combines both 118# streams into one sequence. 119 120def compareOuput(a1,a2,b1,b2): 121 while True: 122 totalLen = len(a1) + len(a2) + len(b1) + len(b2) 123 a1, b1 = matchCommon(a1, b1) 124 a1, b2 = matchCommon(a1, b2) 125 a2, b1 = matchCommon(a2, b1) 126 a2, b2 = matchCommon(a2, b2) 127 newTotalLen = len(a1) + len(a2) + len(b1) + len(b2) 128 if newTotalLen == 0: 129 return True 130 if newTotalLen == totalLen: 131 print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2)) 132 print "a1", a1 133 print "a2", a2 134 print "b1", b1 135 print "b2", b2 136 return False 137 138def matchCommon(a, b): 139 """Remove common items from the beginning of a and b, 140 return just the tails that are different.""" 141 while len(a) > 0 and len(b) > 0 and a[0] == b[0]: 142 a = a[1:] 143 b = b[1:] 144 return a, b 145 146def rewritePaths(args): 147 return [rewritePath(x) for x in args] 148 149def rewritePath(p): 150 """Take a path that's correct on the x86 and convert to a path 151 that's correct on ARM.""" 152 if p.startswith("data/"): 153 p = "/system/bin/accdata/" + p 154 return p 155 156class TestACC(unittest.TestCase): 157 158 def checkResult(self, out, err, stdErrResult, stdOutResult=""): 159 a1 = out.splitlines() 160 a2 = err.splitlines() 161 b2 = stdErrResult.splitlines() 162 b1 = stdOutResult.splitlines() 163 self.assertEqual(True, compareOuput(a1,a2,b1,b2)) 164 165 def compileCheck(self, args, stdErrResult, stdOutResult="", 166 targets=['arm', 'x86']): 167 global gUseArm 168 global gUseX86 169 targetSet = frozenset(targets) 170 if gUseX86 and 'x86' in targetSet: 171 out, err = compile(args) 172 self.checkResult(out, err, stdErrResult, stdOutResult) 173 if gUseArm and 'arm' in targetSet: 174 out = compileArm(rewritePaths(args)) 175 self.checkResult(out, "", stdErrResult, stdOutResult) 176 177 def compileCheckArm(self, args, result): 178 self.assertEqual(compileArm(args), result) 179 180 def testCompileReturnVal(self): 181 self.compileCheck(["data/returnval-ansi.c"], "") 182 183 def testCompileOTCCANSII(self): 184 self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86']) 185 186 def testRunReturnVal(self): 187 self.compileCheck(["-R", "data/returnval-ansi.c"], 188 "Executing compiled code:\nresult: 42\n") 189 190 def testStringLiteralConcatenation(self): 191 self.compileCheck(["-R", "data/testStringConcat.c"], 192 "Executing compiled code:\nresult: 13\n", "Hello, world\n") 193 194 def testRunOTCCANSI(self): 195 global gRunOTCCOutput 196 if gRunOTCCOutput: 197 self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"], 198 "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "", 199 ['x86']) 200 201 def testRunOTCCANSI2(self): 202 global gRunOTCCOutput 203 if gRunOTCCOutput: 204 self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"], 205 "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\notcc.c: about to execute compiled code.\natcc-ansi.c: result: 42\nresult: 42\n", "",['x86']) 206 207 def testRunConstants(self): 208 self.compileCheck(["-R", "data/constants.c"], 209 "Executing compiled code:\nresult: 12\n", 210 "0 = 0\n010 = 8\n0x10 = 16\n'\\a' = 7\n'\\b' = 8\n'\\f' = 12\n'\\n' = 10\n'\\r' = 13\n'\\t' = 9\n'\\v' = 11\n'\\\\' = 92\n'\\'' = 39\n" + 211 "'\\\"' = 34\n'\\?' = 63\n'\\0' = 0\n'\\1' = 1\n'\\12' = 10\n'\\123' = 83\n'\\x0' = 0\n'\\x1' = 1\n'\\x12' = 18\n'\\x123' = 291\n'\\x1f' = 31\n'\\x1F' = 31\n") 212 213 def testRunFloat(self): 214 self.compileCheck(["-R", "data/float.c"], 215 "Executing compiled code:\nresult: 0\n", 216 """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1 217int: 1 float: 2.2 double: 3.3 218 ftoi(1.4f)=1 219 dtoi(2.4)=2 220 itof(3)=3 221 itod(4)=4 222globals: 1 2 3 4 223args: 1 2 3 4 224locals: 1 2 3 4 225cast rval: 2 4 226cast lval: 1.1 2 3.3 4 227""") 228 229 def testRunFlops(self): 230 self.compileCheck(["-R", "data/flops.c"], 231 """Executing compiled code: 232result: 0""", 233"""-1.1 = -1.1 234!1.2 = 0 235!0 = 1 236double op double: 2371 + 2 = 3 2381 - 2 = -1 2391 * 2 = 2 2401 / 2 = 0.5 241float op float: 2421 + 2 = 3 2431 - 2 = -1 2441 * 2 = 2 2451 / 2 = 0.5 246double op float: 2471 + 2 = 3 2481 - 2 = -1 2491 * 2 = 2 2501 / 2 = 0.5 251double op int: 2521 + 2 = 3 2531 - 2 = -1 2541 * 2 = 2 2551 / 2 = 0.5 256int op double: 2571 + 2 = 3 2581 - 2 = -1 2591 * 2 = 2 2601 / 2 = 0.5 261double op double: 2621 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 2631 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 2642 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 265double op float: 2661 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 2671 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 2682 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 269float op float: 2701 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 2711 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 2722 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 273int op double: 2741 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 2751 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 2762 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 277double op int: 2781 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 2791 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 2802 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 281branching: 1 0 1 282testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 283testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 284testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 285testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 286testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 287testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 288testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 289testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 290testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 291testpassidf: 1 2 3 292""") 293 def testCasts(self): 294 self.compileCheck(["-R", "data/casts.c"], 295 """Executing compiled code: 296result: 0""", """Reading from a pointer: 3 3 297Writing to a pointer: 4 298Testing casts: 3 3 4.5 4 299Testing reading (int*): 4 300Testing writing (int*): 8 9 301Testing reading (char*): 0x78 0x56 0x34 0x12 302Testing writing (char*): 0x87654321 303f(10) 304Function pointer result: 70 305Testing read/write (float*): 8.8 9.9 306Testing read/write (double*): 8.8 9.9 307""") 308 309 def testChar(self): 310 self.compileCheck(["-R", "data/char.c"], """Executing compiled code: 311result: 0""", """a = 99, b = 41 312ga = 100, gb = 44""") 313 314 def testPointerArithmetic(self): 315 self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: 316result: 0""", """Pointer difference: 1 4 317Pointer addition: 2 318Pointer comparison to zero: 0 0 1 319Pointer comparison: 1 0 0 0 1 320""") 321 def testRollo3(self): 322 self.compileCheck(["-R", "data/rollo3.c"], """Executing compiled code: 323result: 10""", """""") 324 325 def testFloatDouble(self): 326 self.compileCheck(["-R", "data/floatdouble.c"], """Executing compiled code: 327result: 0""", """0.002 0.1 10""") 328 329 def testIncDec(self): 330 self.compileCheck(["-R", "data/inc.c"], """Executing compiled code: 3310 3321 3332 3341 3351 3362 3371 3380 339result: 0 340""","""""") 341 342 def testIops(self): 343 self.compileCheck(["-R", "data/iops.c"], """Executing compiled code: 344result: 0""", """Literals: 1 -1 345++ 3460 3471 3482 3493 3504 3515 3526 3537 3548 3559 356-- 35710 3589 3598 3607 3616 3625 3634 3643 3652 3661 3670 368""") 369 370 def testFilm(self): 371 self.compileCheck(["-R", "data/film.c"], """Executing compiled code: 372result: 0""", """testing... 373Total bad: 0 374""") 375 376 def testpointers2(self): 377 self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code: 378result: 0""", """a = 0, *pa = 0 379a = 2, *pa = 2 380a = 0, *pa = 0 **ppa = 0 381a = 2, *pa = 2 **ppa = 2 382a = 0, *pa = 0 **ppa = 0 383a = 2, *pa = 2 **ppa = 2 384""") 385 386 def testassignmentop(self): 387 self.compileCheck(["-R", "data/assignmentop.c"], """Executing compiled code: 388result: 0""", """2 *= 5 10 38920 /= 5 4 39017 %= 5 2 39117 += 5 22 39217 -= 5 12 39317<<= 1 34 39417>>= 1 8 39517&= 1 1 39617^= 1 16 39716|= 1 17 398*f() = *f() + 10; 399f() 400f() 401a = 10 402*f() += 10; 403f() 404a = 10 405""") 406 407 def testcomma(self): 408 self.compileCheck(["-R", "data/comma.c"], """Executing compiled code: 409result: 0""", """statement: 10 410if: a = 0 411while: b = 11 412for: b = 22 413return: 30 414arg: 12 415""") 416 417 def testBrackets(self): 418 self.compileCheck(["-R", "data/brackets.c"], """Executing compiled code: 419Errors: 0 4202D Errors: 0 421result: 0 422""","""""") 423 424 def testShort(self): 425 self.compileCheck(["-R", "data/short.c"], """Executing compiled code: 426result: -2 427""","""""") 428 429 def testAssignment(self): 430 self.compileCheck(["-R", "data/assignment.c"], """Executing compiled code: 431result: 7 432""","""""") 433 434 def testArray(self): 435 self.compileCheck(["-R", "data/array.c"], """Executing compiled code: 436localInt: 3 437localDouble: 3 3 438globalChar: 3 439globalDouble: 3 440testArgs: 0 2 4 441testDecay: Hi! 442test2D: 443abcdefghijdefghijklm 444defghijklmghijklmnop 445ghijklmnopjklmnopabc 446jklmnopabcmnopabcdef 447mnopabcdefpabcdefghi 448pabcdefghicdefghijkl 449cdefghijklfghijklmno 450fghijklmnoijklmnopab 451ijklmnopablmnopabcde 452lmnopabcdefghijklmno 453result: 0 454""","""""") 455 456 def testDefines(self): 457 self.compileCheck(["-R", "data/defines.c"], """Executing compiled code: 458result: 3 459""","""""") 460 461 def testFuncArgs(self): 462 self.compileCheck(["-R", "data/funcargs.c"], """Executing compiled code: 463result: 4 464""","""""") 465 466 def testB2071670(self): 467 self.compileCheck(["-R", "data/b2071670.c"], """Executing compiled code: 468result: 1092616192 469""","""""") 470 471 def testStructs(self): 472 self.compileCheck(["-R", "data/structs.c"], """Executing compiled code: 473testCopying: 37 == 37 474testUnion: 1 == 0x3f800000 475testArgs: (6, 8, 10, 12) 476result: 6 477""","""""") 478 479 def testAddressOf(self): 480 self.compileCheck(["-R", "data/addressOf.c"], """Executing compiled code: 481testStruct: 10 10 10 482testArray: 1 1 1 483result: 0 484""","""""") 485 486def main(): 487 checkEnvironment() 488 parseArgv() 489 unittest.main() 490 491if __name__ == '__main__': 492 main() 493 494