Jack Palevich | 609c994 | 2009-06-25 11:49:43 -0700 | [diff] [blame] | 1 | # |
| 2 | # Test the acc compiler |
| 3 | |
| 4 | import unittest |
| 5 | import subprocess |
| 6 | import os |
| 7 | |
| 8 | def compile(args): |
| 9 | proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) |
| 10 | result = proc.communicate() |
| 11 | return result |
| 12 | |
| 13 | def runCmd(args): |
| 14 | proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| 15 | result = proc.communicate() |
| 16 | return result[0].strip() |
| 17 | |
| 18 | def which(item): |
| 19 | return runCmd(["which", item]) |
| 20 | |
| 21 | def fileType(item): |
| 22 | return runCmd(["file", item]) |
| 23 | |
| 24 | def outputCanRun(): |
| 25 | ft = fileType(which("acc")) |
| 26 | return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0 |
| 27 | |
| 28 | def adb(args): |
| 29 | return runCmd(["adb"] + args) |
| 30 | |
| 31 | gArmInitialized = False |
| 32 | |
| 33 | def setupArm(): |
| 34 | if gArmInitialized: |
| 35 | return |
| 36 | print "Setting up arm" |
| 37 | adb(["remount"]) |
| 38 | adb(["shell", "rm", "/system/bin/acc"]) |
| 39 | adb(["shell", "mkdir", "/system/bin/accdata"]) |
| 40 | adb(["shell", "mkdir", "/system/bin/accdata/data"]) |
| 41 | # Clear out old data TODO: handle recursion |
| 42 | adb(["shell", "rm", "/system/bin/accdata/data/*"]) |
| 43 | # Copy over data |
| 44 | for root, dirs, files in os.walk("data"): |
| 45 | for d in dirs: |
| 46 | adb(["shell", "mkdir", os.path.join(root, d)]) |
| 47 | for f in files: |
| 48 | adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)]) |
| 49 | # Copy over compiler |
| 50 | adb(["sync"]) |
| 51 | gArmInitialied = True |
| 52 | |
| 53 | def compileArm(args): |
| 54 | setupArm() |
| 55 | proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE) |
| 56 | result = proc.communicate() |
| 57 | return result[0].replace("\r","") |
| 58 | |
| 59 | def compare(a, b): |
| 60 | if a != b: |
Jack Palevich | 40600de | 2009-07-01 15:32:35 -0700 | [diff] [blame] | 61 | firstDiff = firstDifference(a, b) |
| 62 | print "Strings differ at character %d '%s' != '%s'" % ( |
| 63 | firstDiff, safeAccess(a, firstDiff), safeAccess(b, firstDiff)) |
| 64 | |
| 65 | def safeAccess(s, i): |
| 66 | if 0 <= i < len(s): |
| 67 | return s[i] |
| 68 | else: |
| 69 | return '?' |
Jack Palevich | 609c994 | 2009-06-25 11:49:43 -0700 | [diff] [blame] | 70 | |
| 71 | def firstDifference(a, b): |
| 72 | commonLen = min(len(a), len(b)) |
| 73 | for i in xrange(0, commonLen): |
| 74 | if a[i] != b[i]: |
| 75 | return i |
| 76 | return commonLen |
| 77 | |
| 78 | class TestACC(unittest.TestCase): |
| 79 | |
| 80 | def compileCheck(self, args, stdErrResult, stdOutResult=""): |
| 81 | out, err = compile(args) |
| 82 | compare(out, stdOutResult) |
| 83 | compare(err, stdErrResult) |
| 84 | self.assertEqual(out, stdOutResult) |
| 85 | self.assertEqual(err, stdErrResult) |
| 86 | |
| 87 | def compileCheckArm(self, args, result): |
| 88 | self.assertEqual(compileArm(args), result) |
| 89 | |
| 90 | def testCompileReturnVal(self): |
| 91 | self.compileCheck(["data/returnval-ansi.c"], "") |
| 92 | |
| 93 | def testCompileReturnVal(self): |
| 94 | self.compileCheck(["data/otcc-ansi.c"], "") |
| 95 | |
| 96 | def testRunReturnVal(self): |
| 97 | self.compileCheck(["-R", "data/returnval-ansi.c"], |
| 98 | "Executing compiled code:\nresult: 42\n") |
Jack Palevich | 40600de | 2009-07-01 15:32:35 -0700 | [diff] [blame] | 99 | |
| 100 | def testStingLiteralConcatenation(self): |
| 101 | self.compileCheck(["-R", "data/testStringConcat.c"], |
| 102 | "Executing compiled code:\nresult: 13\n", "Hello, world\n") |
| 103 | |
Jack Palevich | 609c994 | 2009-06-25 11:49:43 -0700 | [diff] [blame] | 104 | def testRunOTCCANSI(self): |
| 105 | self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"], |
| 106 | "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n") |
| 107 | |
| 108 | def testRunOTCCANSI2(self): |
| 109 | self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"], |
| 110 | "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") |
| 111 | |
| 112 | def testRunConstants(self): |
| 113 | self.compileCheck(["-R", "data/constants.c"], |
| 114 | "Executing compiled code:\nresult: 12\n", |
| 115 | "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" + |
| 116 | "'\\\"' = 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") |
| 117 | |
| 118 | def testArmRunReturnVal(self): |
| 119 | self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"], |
| 120 | "Executing compiled code:\nresult: 42\n") |
| 121 | |
| 122 | if __name__ == '__main__': |
| 123 | if not outputCanRun(): |
| 124 | print "Many tests are expected to fail, because acc is not a 32-bit x86 Linux executable." |
| 125 | unittest.main() |
| 126 | |