Chromium Code Reviews| 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() |