blob: 9679ce80ca9f919fbd94f748d7ddd73b5962ef27 [file] [log] [blame]
Shih-wei Liao77ed6142010-04-07 12:21:42 -07001#
Zonr Chang932648d2010-10-13 22:23:56 +08002# Copyright (C) 2010 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17#
Shih-wei Liao77ed6142010-04-07 12:21:42 -070018# Test the bcc compiler
19
20import unittest
21import subprocess
22import os
23import sys
24
25gArmInitialized = False
26gUseArm = True
27gUseX86 = True
28gRunOTCCOutput = True
29
30
31def parseArgv():
32 global gUseArm
33 global gUseX86
34 global gRunOTCCOutput
35 for arg in sys.argv[1:]:
36 if arg == "--noarm":
37 print "--noarm: not testing ARM"
38 gUseArm = False
39 elif arg == "--nox86":
40 print "--nox86: not testing x86"
41 gUseX86 = False
42 elif arg == "--norunotcc":
43 print "--norunotcc detected, not running OTCC output"
44 gRunOTCCOutput = False
45 else:
46 print "Unknown parameter: ", arg
47 raise "Unknown parameter"
48 sys.argv = sys.argv[0:1]
49
50def compile(args):
51 proc = subprocess.Popen(["../libbcc_driver"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
52 result = proc.communicate()
53 return result
54
55def runCmd(args):
56 proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
57 result = proc.communicate()
58 return result[0].strip()
59
60def uname():
61 return runCmd(["uname"])
62
63def unameM():
64 return runCmd(["uname", "-m"])
65
66def which(item):
67 return runCmd(["which", item])
68
69def fileType(item):
70 return runCmd(["file", item])
71
72def outputCanRun():
73 ft = fileType(which("bcc"))
74 return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0
75
76def checkEnvironment():
77 global gRunOTCCOutput
78 gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun()
79
80def adb(args):
81 return runCmd(["adb"] + args)
82
83def setupArm():
84 global gArmInitialized
85 if gArmInitialized:
86 return
87 print "Setting up arm"
88 adb(["remount"])
89 adb(["shell", "rm", "/system/bin/bcc"])
90 adb(["shell", "mkdir", "/system/bin/bccdata"])
91 adb(["shell", "mkdir", "/system/bin/bccdata/data"])
92 # Clear out old data TODO: handle recursion
93 adb(["shell", "rm", "/system/bin/bccdata/data/*"])
94 # Copy over data
95 for root, dirs, files in os.walk("data"):
96 for d in dirs:
97 adb(["shell", "mkdir", os.path.join(root, d)])
98 for f in files:
99 adb(["push", os.path.join(root, f), os.path.join("/system/bin/bccdata", root, f)])
100 # Copy over compiler
101 adb(["sync"])
102 gArmInitialized = True
103
104def compileArm(args):
105 setupArm()
106 proc = subprocess.Popen(["adb", "shell", "/system/bin/bcc"] + args, stdout=subprocess.PIPE)
107 result = proc.communicate()
108 return result[0].replace("\r","")
109
110def compare(a, b):
111 if a != b:
112 firstDiff = firstDifference(a, b)
113 print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % (
114 firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff))
115
116def safeAccess(s, i):
117 if 0 <= i < len(s):
118 return s[i]
119 else:
120 return '?'
121
122def firstDifference(a, b):
123 commonLen = min(len(a), len(b))
124 for i in xrange(0, commonLen):
125 if a[i] != b[i]:
126 return i
127 return commonLen
128
129# a1 and a2 are the expected stdout and stderr.
130# b1 and b2 are the actual stdout and stderr.
131# Compare the two, sets. Allow any individual line
132# to appear in either stdout or stderr. This is because
133# the way we obtain output on the ARM combines both
134# streams into one sequence.
135
136def compareOuput(a1,a2,b1,b2):
137 while True:
138 totalLen = len(a1) + len(a2) + len(b1) + len(b2)
139 a1, b1 = matchCommon(a1, b1)
140 a1, b2 = matchCommon(a1, b2)
141 a2, b1 = matchCommon(a2, b1)
142 a2, b2 = matchCommon(a2, b2)
143 newTotalLen = len(a1) + len(a2) + len(b1) + len(b2)
144 if newTotalLen == 0:
145 return True
146 if newTotalLen == totalLen:
147 print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2))
148 print "a1", a1
149 print "a2", a2
150 print "b1", b1
151 print "b2", b2
152 return False
153
154def matchCommon(a, b):
155 """Remove common items from the beginning of a and b,
156 return just the tails that are different."""
157 while len(a) > 0 and len(b) > 0 and a[0] == b[0]:
158 a = a[1:]
159 b = b[1:]
160 return a, b
161
162def rewritePaths(args):
163 return [rewritePath(x) for x in args]
164
165def rewritePath(p):
166 """Take a path that's correct on the x86 and convert to a path
167 that's correct on ARM."""
168 if p.startswith("data/"):
169 p = "/system/bin/bccdata/" + p
170 return p
171
172class TestACC(unittest.TestCase):
173
174 def checkResult(self, out, err, stdErrResult, stdOutResult=""):
175 a1 = out.splitlines()
176 a2 = err.splitlines()
177 b2 = stdErrResult.splitlines()
178 b1 = stdOutResult.splitlines()
179 self.assertEqual(True, compareOuput(a1,a2,b1,b2))
180
181 def compileCheck(self, args, stdErrResult, stdOutResult="",
182 targets=['arm', 'x86']):
183 global gUseArm
184 global gUseX86
185 targetSet = frozenset(targets)
186 if gUseX86 and 'x86' in targetSet:
187 print args
188 out, err = compile(args)
189 self.checkResult(out, err, stdErrResult, stdOutResult)
190 if gUseArm and 'arm' in targetSet:
191 out = compileArm(rewritePaths(args))
192 self.checkResult(out, "", stdErrResult, stdOutResult)
193
194 def compileCheckArm(self, args, result):
195 self.assertEqual(compileArm(args), result)
196
197 def testCompileReturnVal(self):
198 self.compileCheck(["data/returnval-ansi.bc"], "")
199
200 def testCompileOTCCANSII(self):
201 self.compileCheck(["data/otcc-ansi.bc"], "", "", ['x86'])
202
203 def testRunReturnVal(self):
204 self.compileCheck(["-R", "data/returnval-ansi.bc"],
205 "Executing compiled code:\nresult: 42\n")
206
207 def testStringLiteralConcatenation(self):
208 self.compileCheck(["-R", "data/testStringConcat.bc"],
209 "Executing compiled code:\nresult: 13\n", "Hello, world\n")
210
211 def testRunOTCCANSI(self):
212 global gRunOTCCOutput
213 if gRunOTCCOutput:
214 self.compileCheck(["-R", "data/otcc-ansi.bc", "data/returnval.c"],
215 "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "",
216 ['x86'])
217
218 def testRunOTCCANSI2(self):
219 global gRunOTCCOutput
220 if gRunOTCCOutput:
221 self.compileCheck(["-R", "data/otcc-ansi.bc", "data/otcc.c", "data/returnval.c"],
222 "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'])
223
224 def testRunConstants(self):
225 self.compileCheck(["-R", "data/constants.bc"],
226 "Executing compiled code:\nresult: 0\n",
227 "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" +
228 "'\\\"' = 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' = 35\n'\\x1f' = 31\n'\\x1F' = 31\n")
229
230 def testRunFloat(self):
231 self.compileCheck(["-R", "data/float.bc"],
232 "Executing compiled code:\nresult: 0\n",
233 """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1
234int: 1 float: 2.2 double: 3.3
235 ftoi(1.4f)=1
236 dtoi(2.4)=2
237 itof(3)=3
238 itod(4)=4
239globals: 1 2 3 4
240args: 1 2 3 4
241locals: 1 2 3 4
242cast rval: 2 4
243cast lval: 1.1 2 3.3 4
244""")
245
246 def testRunFlops(self):
247 self.compileCheck(["-R", "data/flops.bc"],
248 """Executing compiled code:
249result: 0""",
250"""-1.1 = -1.1
251!1.2 = 0
252!0 = 1
253double op double:
2541 + 2 = 3
2551 - 2 = -1
2561 * 2 = 2
2571 / 2 = 0.5
258float op float:
2591 + 2 = 3
2601 - 2 = -1
2611 * 2 = 2
2621 / 2 = 0.5
263double op float:
2641 + 2 = 3
2651 - 2 = -1
2661 * 2 = 2
2671 / 2 = 0.5
268double op int:
2691 + 2 = 3
2701 - 2 = -1
2711 * 2 = 2
2721 / 2 = 0.5
273int op double:
2741 + 2 = 3
2751 - 2 = -1
2761 * 2 = 2
2771 / 2 = 0.5
278double op double:
2791 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
2801 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
2812 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
282double op float:
2831 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
2841 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
2852 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
286float op float:
2871 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
2881 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
2892 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
290int op double:
2911 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
2921 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
2932 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
294double op int:
2951 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1
2961 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0
2972 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1
298branching: 1 0 1
299testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
300testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
301testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
302testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
303testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
304testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
305testpassi: 1 2 3 4 5 6 7 8 9 10 11 12
306testpassf: 1 2 3 4 5 6 7 8 9 10 11 12
307testpassd: 1 2 3 4 5 6 7 8 9 10 11 12
308testpassidf: 1 2 3
309""")
310 def testCasts(self):
311 self.compileCheck(["-R", "data/casts.bc"],
312 """Executing compiled code:
313result: 0""", """Reading from a pointer: 3 3
314Writing to a pointer: 4
315Testing casts: 3 3 4.5 4
316Testing reading (int*): 4
317Testing writing (int*): 8 9
318Testing reading (char*): 0x78 0x56 0x34 0x12
319Testing writing (char*): 0x87654321
320f(10)
321Function pointer result: 70
322Testing read/write (float*): 8.8 9.9
323Testing read/write (double*): 8.8 9.9
324""")
325
326 def testChar(self):
327 self.compileCheck(["-R", "data/char.bc"], """Executing compiled code:
328result: 0""", """a = 99, b = 41
329ga = 100, gb = 44""")
330
331 def testPointerArithmetic(self):
332 self.compileCheck(["-R", "data/pointers.bc"], """Executing compiled code:
333result: 0""", """Pointer difference: 1 4
334Pointer addition: 2
335Pointer comparison to zero: 0 0 1
336Pointer comparison: 1 0 0 0 1
337""")
338 def testRollo3(self):
339 self.compileCheck(["-R", "data/rollo3.bc"], """Executing compiled code:
340result: 10""", """""")
341
342 def testFloatDouble(self):
343 self.compileCheck(["-R", "data/floatdouble.bc"], """Executing compiled code:
344result: 0""", """0.002 0.1 10""")
345
346 def testIncDec(self):
347 self.compileCheck(["-R", "data/inc.bc"], """Executing compiled code:
3480
3491
3502
3511
3521
3532
3541
3550
356result: 0
357""","""""")
358
359 def testIops(self):
360 self.compileCheck(["-R", "data/iops.bc"], """Executing compiled code:
361result: 0""", """Literals: 1 -1
362++
3630
3641
3652
3663
3674
3685
3696
3707
3718
3729
373--
37410
3759
3768
3777
3786
3795
3804
3813
3822
3831
3840
385""")
386
387 def testFilm(self):
388 self.compileCheck(["-R", "data/film.bc"], """Executing compiled code:
389result: 0""", """testing...
390Total bad: 0
391""")
392
393 def testpointers2(self):
394 self.compileCheck(["-R", "data/pointers2.bc"], """Executing compiled code:
395result: 0""", """a = 0, *pa = 0
396a = 2, *pa = 2
397a = 0, *pa = 0 **ppa = 0
398a = 2, *pa = 2 **ppa = 2
399a = 0, *pa = 0 **ppa = 0
400a = 2, *pa = 2 **ppa = 2
401""")
402
403 def testassignmentop(self):
404 self.compileCheck(["-R", "data/assignmentop.bc"], """Executing compiled code:
405result: 0""", """2 *= 5 10
40620 /= 5 4
40717 %= 5 2
40817 += 5 22
40917 -= 5 12
41017<<= 1 34
41117>>= 1 8
41217&= 1 1
41317^= 1 16
41416|= 1 17
415*f() = *f() + 10;
416f()
417f()
418a = 10
419*f() += 10;
420f()
421a = 10
422""")
423
424 def testcomma(self):
425 self.compileCheck(["-R", "data/comma.bc"], """Executing compiled code:
426result: 0""", """statement: 10
427if: a = 0
428while: b = 11
429for: b = 22
430return: 30
431arg: 12
432""")
433
434 def testBrackets(self):
435 self.compileCheck(["-R", "data/brackets.bc"], """Executing compiled code:
436Errors: 0
4372D Errors: 0
438result: 0
439""","""""")
440
441 def testShort(self):
442 self.compileCheck(["-R", "data/short.bc"], """Executing compiled code:
443result: -2
444""","""""")
445
446 def testAssignment(self):
447 self.compileCheck(["-R", "data/assignment.bc"], """Executing compiled code:
448result: 7
449""","""""")
450
451 def testArray(self):
452 self.compileCheck(["-R", "data/array.bc"], """Executing compiled code:
453localInt: 3
454localDouble: 3 3
455globalChar: 3
456globalDouble: 3
457testArgs: 0 2 4
458testDecay: Hi!
459test2D:
460abcdefghijklmnopabcd
461defghijklmnopabcdefg
462ghijklmnopabcdefghij
463jklmnopabcdefghijklm
464mnopabcdefghijklmnop
465pabcdefghijklmnopabc
466cdefghijklmnopabcdef
467fghijklmnopabcdefghi
468ijklmnopabcdefghijkl
469lmnopabcdefghijklmno
470result: 0
471""","""""")
472
473 def testDefines(self):
474 self.compileCheck(["-R", "data/defines.bc"], """Executing compiled code:
475result: 3
476""","""""")
477
478 def testFuncArgs(self):
479 self.compileCheck(["-R", "data/funcargs.bc"], """Executing compiled code:
480result: 4
481""","""""")
482
483 def testB2071670(self):
484 self.compileCheck(["-R", "data/b2071670.bc"], """Executing compiled code:
485result: 1092616192
486""","""""")
487
488 def testStructs(self):
489 self.compileCheck(["-R", "data/structs.bc"], """Executing compiled code:
490testCopying: 37 == 37
491testUnion: 1 == 0x3f800000
492testArgs: (6, 8, 10, 12)
493result: 6
494""","""""")
495
496 def testAddressOf(self):
497 self.compileCheck(["-R", "data/addressOf.bc"], """Executing compiled code:
498testStruct: 10 10 10
499testArray: 1 1 1
500result: 0
501""","""""")
502
503def main():
504 checkEnvironment()
505 parseArgv()
506 unittest.main()
507
508if __name__ == '__main__':
509 main()
510