• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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