blob: 991c7ded6dafc13d0ad0f14aeb3537c9153da27c [file] [log] [blame]
Jack Palevich609c9942009-06-25 11:49:43 -07001#
2# Test the acc compiler
3
4import unittest
5import subprocess
6import os
Jack Palevich59178c02009-07-13 14:15:18 -07007import sets
8
9gArmInitialized = False
Jack Palevich609c9942009-06-25 11:49:43 -070010
11def compile(args):
12 proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
13 result = proc.communicate()
14 return result
15
16def runCmd(args):
17 proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
18 result = proc.communicate()
19 return result[0].strip()
20
21def which(item):
22 return runCmd(["which", item])
23
24def fileType(item):
25 return runCmd(["file", item])
26
27def outputCanRun():
28 ft = fileType(which("acc"))
29 return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0
30
31def adb(args):
32 return runCmd(["adb"] + args)
33
Jack Palevich609c9942009-06-25 11:49:43 -070034def setupArm():
Jack Palevich59178c02009-07-13 14:15:18 -070035 global gArmInitialized
Jack Palevich609c9942009-06-25 11:49:43 -070036 if gArmInitialized:
37 return
38 print "Setting up arm"
39 adb(["remount"])
40 adb(["shell", "rm", "/system/bin/acc"])
41 adb(["shell", "mkdir", "/system/bin/accdata"])
42 adb(["shell", "mkdir", "/system/bin/accdata/data"])
43 # Clear out old data TODO: handle recursion
44 adb(["shell", "rm", "/system/bin/accdata/data/*"])
45 # Copy over data
46 for root, dirs, files in os.walk("data"):
47 for d in dirs:
48 adb(["shell", "mkdir", os.path.join(root, d)])
49 for f in files:
50 adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)])
51 # Copy over compiler
52 adb(["sync"])
Jack Palevich59178c02009-07-13 14:15:18 -070053 gArmInitialized = True
Jack Palevich609c9942009-06-25 11:49:43 -070054
55def compileArm(args):
56 setupArm()
57 proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE)
58 result = proc.communicate()
59 return result[0].replace("\r","")
60
61def compare(a, b):
62 if a != b:
Jack Palevich40600de2009-07-01 15:32:35 -070063 firstDiff = firstDifference(a, b)
Jack Palevichbab80642009-07-09 13:54:54 -070064 print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % (
65 firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff))
Jack Palevich40600de2009-07-01 15:32:35 -070066
67def safeAccess(s, i):
68 if 0 <= i < len(s):
69 return s[i]
70 else:
71 return '?'
Jack Palevich609c9942009-06-25 11:49:43 -070072
73def firstDifference(a, b):
74 commonLen = min(len(a), len(b))
75 for i in xrange(0, commonLen):
76 if a[i] != b[i]:
77 return i
78 return commonLen
79
Jack Palevich59178c02009-07-13 14:15:18 -070080def compareSet(a1,a2,b1,b2):
81 while True:
82 totalLen = len(a1) + len(a2) + len(b1) + len(b2)
83 a1, b1 = matchCommon(a1, b1)
84 a1, b2 = matchCommon(a1, b2)
85 a2, b1 = matchCommon(a2, b1)
86 a2, b2 = matchCommon(a2, b2)
87 newTotalLen = len(a1) + len(a2) + len(b1) + len(b2)
88 if newTotalLen == 0:
89 return True
90 if newTotalLen == totalLen:
91 print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2))
92 print "a1", a1
93 print "a2", a2
94 print "b1", b1
95 print "b2", b2
96 return False
97
98def matchCommon(a, b):
99 while len(a) > 0 and len(b) > 0 and a[0] == b[0]:
100 a = a[1:]
101 b = b[1:]
102 return a, b
103
104def rewritePaths(args):
105 return [rewritePath(x) for x in args]
106
107def rewritePath(p):
108 if p.startswith("data/"):
109 p = "/system/bin/accdata/" + p
110 return p
111
Jack Palevich609c9942009-06-25 11:49:43 -0700112class TestACC(unittest.TestCase):
113
Jack Palevich59178c02009-07-13 14:15:18 -0700114 def compileCheckOld(self, args, stdErrResult, stdOutResult=""):
Jack Palevich609c9942009-06-25 11:49:43 -0700115 out, err = compile(args)
116 compare(out, stdOutResult)
117 compare(err, stdErrResult)
118 self.assertEqual(out, stdOutResult)
119 self.assertEqual(err, stdErrResult)
120
Jack Palevich59178c02009-07-13 14:15:18 -0700121 def checkResult(self, out, err, stdErrResult, stdOutResult=""):
122 a1 = out.splitlines()
123 a2 = err.splitlines()
124 b2 = stdErrResult.splitlines()
125 b1 = stdOutResult.splitlines()
126 self.assertEqual(True, compareSet(a1,a2,b1,b2))
127
128 def compileCheck(self, args, stdErrResult, stdOutResult="",
129 targets=['arm', 'x86']):
130 targetSet = sets.ImmutableSet(targets)
131 if 'x86' in targetSet:
132 out, err = compile(args)
133 self.checkResult(out, err, stdErrResult, stdOutResult)
134 if 'arm' in targetSet:
135 out = compileArm(rewritePaths(args))
136 self.checkResult(out, "", stdErrResult, stdOutResult)
137
Jack Palevich609c9942009-06-25 11:49:43 -0700138 def compileCheckArm(self, args, result):
139 self.assertEqual(compileArm(args), result)
140
141 def testCompileReturnVal(self):
142 self.compileCheck(["data/returnval-ansi.c"], "")
143
Jack Palevich59178c02009-07-13 14:15:18 -0700144 def testCompileOTCCANSII(self):
145 self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86'])
Jack Palevich609c9942009-06-25 11:49:43 -0700146
147 def testRunReturnVal(self):
148 self.compileCheck(["-R", "data/returnval-ansi.c"],
149 "Executing compiled code:\nresult: 42\n")
Jack Palevich40600de2009-07-01 15:32:35 -0700150
Jack Palevichbab80642009-07-09 13:54:54 -0700151 def testStringLiteralConcatenation(self):
Jack Palevich40600de2009-07-01 15:32:35 -0700152 self.compileCheck(["-R", "data/testStringConcat.c"],
153 "Executing compiled code:\nresult: 13\n", "Hello, world\n")
154
Jack Palevich609c9942009-06-25 11:49:43 -0700155 def testRunOTCCANSI(self):
156 self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"],
Jack Palevich59178c02009-07-13 14:15:18 -0700157 "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "",
158 ['x86'])
Jack Palevich609c9942009-06-25 11:49:43 -0700159
160 def testRunOTCCANSI2(self):
161 self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"],
Jack Palevich59178c02009-07-13 14:15:18 -0700162 "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'])
Jack Palevich609c9942009-06-25 11:49:43 -0700163
164 def testRunConstants(self):
165 self.compileCheck(["-R", "data/constants.c"],
166 "Executing compiled code:\nresult: 12\n",
167 "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" +
168 "'\\\"' = 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")
169
Jack Palevichbab80642009-07-09 13:54:54 -0700170 def testRunFloat(self):
171 self.compileCheck(["-R", "data/float.c"],
172 "Executing compiled code:\nresult: 0\n",
Jack Palevichb7718b92009-07-09 22:00:24 -0700173 "int: 1 float: 2.2 double: 3.3\n ftoi(1.4f)=1\n dtoi(2.4)=2\n itof(3)=3\n itod(4)=4\nglobals: 1 2 3 4\nargs: 1 2 3 4\nlocals: 1 2 3 4\ncast rval: 2 4\ncast lval: 1.1 2 3.3 4\n")
Jack Palevichbab80642009-07-09 13:54:54 -0700174
175 def testRunFlops(self):
176 self.compileCheck(["-R", "data/flops.c"],
177 "Executing compiled code:\nresult: 0\n",
178 "-1.1 = -1.1\n" +
179 "!1.2 = 0\n" +
180 "!0 = 1\n" +
181 "double op double:\n" +
182 "1 + 2 = 3\n" +
183 "1 - 2 = -1\n" +
184 "1 * 2 = 2\n" +
185 "1 / 2 = 0.5\n" +
186 "float op float:\n" +
187 "1 + 2 = 3\n" +
188 "1 - 2 = -1\n" +
189 "1 * 2 = 2\n" +
190 "1 / 2 = 0.5\n" +
191 "double op float:\n" +
192 "1 + 2 = 3\n" +
193 "1 - 2 = -1\n" +
194 "1 * 2 = 2\n" +
195 "1 / 2 = 0.5\n" +
196 "double op int:\n" +
197 "1 + 2 = 3\n" +
198 "1 - 2 = -1\n" +
199 "1 * 2 = 2\n" +
200 "1 / 2 = 0.5\n" +
201 "int op double:\n" +
202 "1 + 2 = 3\n" +
203 "1 - 2 = -1\n" +
204 "1 * 2 = 2\n" +
205 "1 / 2 = 0.5\n" +
206 "double op double:\n" +
207 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
208 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
209 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
210 "double op float:\n" +
211 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
212 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
213 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
214 "float op float:\n" +
215 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
216 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
217 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
218 "int op double:\n" +
219 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
220 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
221 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
222 "double op int:\n" +
223 "1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1\n" +
224 "1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0\n" +
225 "2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1\n" +
Jack Palevichb7718b92009-07-09 22:00:24 -0700226 "branching: 1 0 1\n" +
227 "testpassi: 1 2 3 4 5 6 7 8\n" +
228 "testpassf: 1 2 3 4 5 6 7 8\n" +
229 "testpassd: 1 2 3 4 5 6 7 8\n" +
230 "testpassidf: 1 2 3\n"
231 )
Jack Palevichbab80642009-07-09 13:54:54 -0700232
Jack Palevich59178c02009-07-13 14:15:18 -0700233 def oldtestArmRunReturnVal(self):
Jack Palevich609c9942009-06-25 11:49:43 -0700234 self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"],
235 "Executing compiled code:\nresult: 42\n")
236
237if __name__ == '__main__':
238 if not outputCanRun():
239 print "Many tests are expected to fail, because acc is not a 32-bit x86 Linux executable."
240 unittest.main()
241