2 # Copyright (c) 2014 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Tests of the pnacl driver.
8 This tests that we give useful errors when paths are too long, and don't
9 unnecessarily generate temp file names that are too long ourselves.
14 from driver_env import env
15 import driver_test_utils
23 class TestPathNames(driver_test_utils.DriverTesterCommon):
25 super(TestPathNames, self).setUp()
26 driver_test_utils.ApplyTestEnvOverrides(env)
27 self.backup_exit = sys.exit
28 sys.exit = driver_test_utils.FakeExit
29 cwd_len = len(os.getcwd())
30 # Create a directory whose path will be exactly 240 chars long
31 dir_len = 240 - cwd_len - 1
32 self.cwd_backup = os.getcwd()
33 self.LongTempDir = os.path.join(self.cwd_backup, 'a' * dir_len)
34 os.mkdir(self.LongTempDir)
37 super(TestPathNames, self).tearDown()
38 os.chdir(self.cwd_backup)
39 sys.exit = self.backup_exit
40 shutil.rmtree(self.LongTempDir)
42 def WriteCFile(self, filename):
43 with open(filename, 'w') as f:
44 f.write('int main() { return 0; }')
46 def AssertRaisesAndReturnOutput(self, exc, func, *args):
47 capture_out = cStringIO.StringIO()
48 driver_log.Log.CaptureToStream(capture_out)
49 self.assertRaises(exc, func, *args)
50 driver_log.Log.ResetStreams()
51 return capture_out.getvalue()
53 def test_InputPathTooLong(self):
54 '''Test that clang and ld reject input paths that are too long
56 Test that compiling and linking paths shorter than 255 succeeds and paths
57 longer than 255 fails.
58 Operations in python (e.g. rename) on long paths don't work on Windows,
59 so just run the tests on Linux/Mac (the checks are enabled in unittest
62 if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython():
65 shortname = os.path.join(self.LongTempDir, 'a' * 10)
66 longname = os.path.join(self.LongTempDir, 'a' * 32)
68 assert len(shortname) + 2 < 255
69 assert len(longname) + 2 > 255
70 self.WriteCFile(shortname + '.c')
72 driver_tools.RunDriver('pnacl-clang',
73 [shortname + '.c', '-c', '-o', shortname + '.o'])
75 driver_tools.RunDriver('pnacl-ld',
78 os.rename(shortname + '.c', longname + '.c')
79 os.rename(shortname + '.o', longname + '.o')
82 output = self.AssertRaisesAndReturnOutput(
83 driver_test_utils.DriverExitException,
84 driver_tools.RunDriver,
86 [longname + '.c', '-c', '-o', longname + '.o'])
88 self.assertIn('too long', output)
90 output = self.AssertRaisesAndReturnOutput(
91 driver_test_utils.DriverExitException,
92 driver_tools.RunDriver,
96 self.assertIn('too long', output)
98 def test_ExpandedPathTooLong(self):
99 '''Test that the expanded path is checked with a short relative path'''
100 if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython():
103 os.chdir(self.LongTempDir)
108 # Now we are in a state where the file can be referred to by a relative
109 # path or a normalized absolute path. For 'shortname', both are short
111 assert len(os.path.join(self.LongTempDir, shortname)) + 2 < 255
112 assert len(os.path.join(self.LongTempDir, longname)) + 2 > 255
113 self.WriteCFile(shortname + '.c')
115 # Test that using a relative almost-too-long path works
116 driver_tools.RunDriver('pnacl-clang',
117 [shortname + '.c', '-c', '-o', shortname + '.o'])
119 driver_tools.RunDriver('pnacl-ld',
122 # This name has a short-enough relative path and a short-enough normalized
123 # final path, but the intermediate concatenation of pwd + rel path is too
125 name_with_traversals = os.path.join('..',
126 os.path.basename(self.LongTempDir),
129 output = self.AssertRaisesAndReturnOutput(
130 driver_test_utils.DriverExitException,
131 driver_tools.RunDriver,
133 [name_with_traversals + '.c', '-c', '-o', shortname + '.o'])
134 self.assertIn('expanded', output)
136 # The previous test only gives a long input name. Also test that the output
138 output = self.AssertRaisesAndReturnOutput(
139 driver_test_utils.DriverExitException,
140 driver_tools.RunDriver,
142 [shortname + '.c', '-c', '-o', name_with_traversals + '.o'])
143 self.assertIn('expanded', output)
146 def test_TempFileNotTooLong(self):
147 '''Test that temp files with too-long names are not generated'''
148 if not driver_test_utils.CanRunHost() or driver_tools.IsWindowsPython():
151 # This name is chosen such that the .c file has the maximum length. pnacl-ld
152 # should not generate any temp names longer than that.
153 shortname = os.path.join(self.LongTempDir, 'a' * 12)
155 self.WriteCFile(shortname + '.c')
156 driver_tools.RunDriver('pnacl-clang',
157 [shortname + '.c', '-c', '-o', shortname + '.o'])
159 driver_tools.RunDriver('pnacl-ld',
160 [shortname + '.o', '-o', shortname])
162 # If it's impossible to generate a temp file short enough using our scheme
163 # (i.e. the directory name is so long that 8 chars will be over the limit),
164 # make sure we still fail the right way.
165 longerdir = os.path.join(self.LongTempDir, 'a' * 8)
167 longname = os.path.join(longerdir, 'a' * 3)
168 os.rename(shortname + '.o', longname + '.o')
170 output = self.AssertRaisesAndReturnOutput(
171 driver_test_utils.DriverExitException,
172 driver_tools.RunDriver,
174 [longname + '.o', '-o', longname])
176 self.assertIn('.pexe is too long', output)