Index: pnacl/driver/tests/translate_options_test.py |
diff --git a/pnacl/driver/tests/translate_options_test.py b/pnacl/driver/tests/translate_options_test.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2d01840e3481ba554c33c37ea63ea22300d25c61 |
--- /dev/null |
+++ b/pnacl/driver/tests/translate_options_test.py |
@@ -0,0 +1,226 @@ |
+#!/usr/bin/python |
+# Copyright (c) 2012 The Native Client Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Tests of the pnacl driver. |
+ |
+This tests that pnacl-translate options pass through to LLC correctly, |
+and are overridden correctly. |
+""" |
+ |
+from driver_env import env |
+import driver_log |
+import driver_test_utils |
+import driver_tools |
+ |
+import cStringIO |
+import os |
+import re |
+import sys |
+import tempfile |
+import unittest |
+ |
+class DriverExitException(Exception): |
+ pass |
+ |
+def FakeExit(i): |
+ raise DriverExitException('Stubbed out DriverExit!') |
+ |
+def MakeFakeStdStream(): |
+ fake_out = cStringIO.StringIO() |
+ fake_err = cStringIO.StringIO() |
+ backup_stdout = sys.stdout |
+ backup_stderr = sys.stderr |
+ sys.stdout = fake_out |
+ sys.stderr = fake_err |
+ return (fake_out, fake_err, backup_stdout, backup_stderr) |
+ |
+def RestoreStdStream(fake_out, fake_err, |
+ backup_stdout, backup_stderr): |
+ sys.stdout = backup_stdout |
+ sys.stderr = backup_stderr |
+ # For some reason, cStringIO.StringIO() returns the same object |
+ # for fake_out, on each iteration. So, if we close() it we could |
+ # end up getting a closed object and write to closed object |
+ # in the next iteration. |
+ fake_out.reset() |
+ fake_out.truncate() |
+ fake_err.reset() |
+ fake_err.truncate() |
+ |
+ |
+class TestLLCOptions(unittest.TestCase): |
+ |
+ def setUp(self): |
+ driver_test_utils.ApplyTestEnvOverrides(env) |
+ self.tempfiles = [] |
+ |
+ def getTemp(self, **kwargs): |
+ # Set delete=False, so that we can close the files and |
+ # re-open them. Windows sometimes does not allow you to |
+ # re-open an already opened temp file. |
+ t = tempfile.NamedTemporaryFile(delete=False, **kwargs) |
+ self.tempfiles.append(t) |
+ return t |
+ |
+ def tearDown(self): |
+ for t in self.tempfiles: |
+ if not t.closed: |
+ t.close() |
+ os.remove(t.name) |
+ # Wipe other temp files that are normally wiped by DriverExit. |
+ # We don't want anything to exit, so we do not call DriverExit manually. |
+ driver_log.TempFiles.wipe() |
+ |
+ def getFakePexe(self): |
+ # Even --dry-run requires a file to exist, so make a fake pexe. |
+ # It even cares that the file is "bitcode" =( |
+ with self.getTemp(suffix='.ll') as t: |
+ with self.getTemp(suffix='.pexe') as p: |
+ t.write(''' |
+define i32 @main() { |
+ ret i32 0 |
+} |
+''') |
+ t.close() |
+ p.close() |
+ driver_tools.RunDriver('as', [t.name, '-o', p.name]) |
+ return p |
+ |
+ |
+ def dryRunTranslateWithFlags(self, pexe, arch, |
Derek Schuff
2013/03/06 21:10:12
make it more clear that this function runs a trans
jvoung (off chromium)
2013/03/06 21:26:58
Done. I think...
|
+ flags, expected_flags): |
+ temp_output = self.getTemp() |
+ temp_output.close() |
+ # Major hack to capture the output. |
+ # RunDriver() prints a bunch of things to stdout, which we need to capture. |
+ # Another major hack is to prevent DriverExit() from aborting the test.' |
+ # The test will surely DriverLog.Fatal() because dry-run currently |
+ # does not handle anything that involves invoking a subprocess and |
+ # grepping the stdout/stderr since it never actually invokes |
+ # the subprocess. Unfortunately, pnacl-translate does grep the output of |
+ # the sandboxed LLC run, so we can only go that far with --dry-run. |
+ (fake_out, fake_err, backup_stdout, backup_stderr) = MakeFakeStdStream() |
+ backup_exit = sys.exit |
+ sys.exit = FakeExit |
+ try: |
+ with self.assertRaises(DriverExitException): |
+ driver_tools.RunDriver('translate', |
+ ['--pnacl-driver-verbose', |
+ '--dry-run', |
+ '-arch', |
+ arch, |
+ pexe.name, |
+ '-o', temp_output.name] + flags) |
+ finally: |
+ out = sys.stdout.getvalue() # release output |
+ err = sys.stderr.getvalue() # release output |
+ RestoreStdStream(fake_out, fake_err, |
+ backup_stdout, backup_stderr) |
+ sys.exit = backup_exit |
+ for f in expected_flags: |
+ self.assertTrue(re.search(f, err), |
+ msg='Searching for regex %s in %s' % (f, err)) |
+ return |
+ |
+ #### Individual tests. |
+ |
+ def test_no_overrides(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that certain defaults are set, when no flags are given. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ [], |
+ ['-mtriple=arm.*', '-mcpu=cortex.*']) |
+ # Test that the default StreamInit is used, when no flags are given. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['--pnacl-sb'], |
+ ['StreamInit h']) |
+ |
+ def test_overrideO0(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that you get O0 when you ask for O0. |
+ # You also get no frame pointer elimination. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-O0'], |
+ ['-O0 ', '-disable-fp-elim ']) |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-O0', '--pnacl-sb'], |
+ ['StreamInitWithOverrides.*-O0.*-disable-fp-elim.*-mcpu=.*']) |
+ |
+ def test_overrideTranslateFast(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that you get O0 when you ask for -translate-fast. |
+ # In this case... you don't get no frame pointer elimination. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-translate-fast'], |
+ ['-O0']) |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-translate-fast', '--pnacl-sb'], |
+ ['StreamInitWithOverrides.*-O0.*-mcpu=.*']) |
+ |
+ def test_overrideTLSUseCall(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that you -mtls-use-call, etc. when you ask for it. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-mtls-use-call', '-fdata-sections', '-ffunction-sections'], |
+ ['-mtls-use-call', '-fdata-sections', '-ffunction-sections']) |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-mtls-use-call', '-fdata-sections', '-ffunction-sections', |
+ '--pnacl-sb'], |
+ ['StreamInitWithOverrides.*-mtls-use-call' + |
+ '.*-fdata-sections.*-ffunction-sections']) |
+ |
+ def test_overrideMCPU(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that you get the -mcpu that you ask for. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-mcpu=cortex-a15'], |
+ ['-mcpu=cortex-a15']) |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'arm', |
+ ['-mcpu=cortex-a15', '--pnacl-sb'], |
+ ['StreamInitWithOverrides.*-mcpu=cortex-a15']) |
+ |
+ def test_overrideMAttr(self): |
+ if driver_test_utils.CanRunHost(): |
+ pexe = self.getFakePexe() |
+ # Test that you get the -mattr=.* that you ask for. |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'x86-64', |
+ ['-mattr=+avx2,+sse4'], |
+ ['-mtriple=x86_64.*', '-mattr=\+avx2,\+sse4']) |
+ self.dryRunTranslateWithFlags( |
+ pexe, |
+ 'x86-64', |
+ ['-mattr=+avx2,+sse4', '--pnacl-sb'], |
+ ['StreamInitWithOverrides.*mattr=\+avx2,\+sse4.*-mcpu=core']) |
+ |
+ |
+if __name__ == '__main__': |
+ unittest.main() |