2 # Copyright 2013 The Swarming Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 that
4 # can be found in the LICENSE file.
17 GOOGLETEST_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18 ROOT_DIR = os.path.dirname(GOOGLETEST_DIR)
20 sys.path.insert(0, ROOT_DIR)
21 sys.path.insert(0, os.path.join(GOOGLETEST_DIR, '..', 'tests'))
24 import trace_test_util
25 from googletest import trace_test_cases
26 from utils import file_path
29 class IsolateTestCases(unittest.TestCase):
33 self.initial_cwd = ROOT_DIR
34 if sys.platform == 'win32':
35 # Windows has no kernel mode concept of current working directory.
36 self.initial_cwd = None
38 # There's 2 kinds of references to python, self.executable,
39 # self.real_executable. It depends how python was started and on which OS.
40 self.executable = unicode(sys.executable)
41 if sys.platform == 'darwin':
42 # /usr/bin/python is a thunk executable that decides which version of
43 # python gets executed.
44 suffix = '.'.join(map(str, sys.version_info[0:2]))
45 if os.access(self.executable + suffix, os.X_OK):
46 # So it'll look like /usr/bin/python2.7
47 self.executable += suffix
49 self.real_executable = file_path.get_native_path_case(
51 # Make sure there's no environment variable that could cause side effects.
52 os.environ.pop('GTEST_SHARD_INDEX', '')
53 os.environ.pop('GTEST_TOTAL_SHARDS', '')
58 # If -v is used, this means the user wants to do further analisys on
60 print('Leaking %s' % self.tempdir)
62 shutil.rmtree(self.tempdir)
64 def _copy(self, root, *relpath):
65 relpath = os.path.join(*relpath)
67 os.path.join(root, relpath),
68 os.path.join(self.tempdir, relpath))
70 @trace_test_util.check_can_trace
71 def test_simple(self):
72 # Create a directory and re-use tests/gtest_fake/gtest_fake_pass.isolate.
73 # Warning: we need to copy the files around, since the original .isolate
75 gtest_fake_base_py = os.path.join(
76 'tests', 'gtest_fake', 'gtest_fake_base.py')
77 gtest_fake_pass_py = os.path.join(
78 'tests', 'gtest_fake', 'gtest_fake_pass.py')
79 gtest_fake_pass_isolate = os.path.join(
80 'tests', 'isolate_test_cases', 'gtest_fake_pass.isolate')
82 self.tempdir = tempfile.mkdtemp(prefix='isolate_test_cases_test')
83 os.mkdir(os.path.join(self.tempdir, 'isolated'))
84 os.mkdir(os.path.join(self.tempdir, 'tests'))
85 os.mkdir(os.path.join(self.tempdir, 'tests', 'gtest_fake'))
86 os.mkdir(os.path.join(self.tempdir, 'tests', 'isolate_test_cases'))
87 self._copy(ROOT_DIR, 'isolate.py')
88 self._copy(GOOGLETEST_DIR, gtest_fake_base_py)
89 self._copy(GOOGLETEST_DIR, gtest_fake_pass_isolate)
90 self._copy(GOOGLETEST_DIR, gtest_fake_pass_py)
92 basename = os.path.join(self.tempdir, 'isolated', 'gtest_fake_pass')
93 isolated = basename + '.isolated'
95 # Create a proper .isolated file.
97 sys.executable, 'isolate.py',
99 '--config-variable', 'OS', 'amiga',
100 '--extra-variable', 'FLAG', 'run',
101 '--isolate', os.path.join(self.tempdir, gtest_fake_pass_isolate),
102 '--isolated', isolated,
105 cmd.extend(['-v'] * 3)
106 subprocess.check_call(cmd, cwd=ROOT_DIR)
108 # Assert the content of the .isolated file.
109 with open(isolated) as f:
110 actual_isolated = json.load(f)
111 root_dir_gtest_fake_pass_py = os.path.join(
112 GOOGLETEST_DIR, gtest_fake_pass_py)
113 rel_gtest_fake_pass_py = os.path.join(u'gtest_fake', 'gtest_fake_pass.py')
114 expected_isolated = {
116 u'command': [u'../gtest_fake/gtest_fake_pass.py'],
118 rel_gtest_fake_pass_py: {
120 u'h': unicode(hashlib.sha1(
121 open(root_dir_gtest_fake_pass_py, 'rb').read()).hexdigest()),
122 u's': os.stat(root_dir_gtest_fake_pass_py).st_size,
125 u'relative_cwd': u'isolate_test_cases',
126 u'version': unicode(isolate.isolateserver.ISOLATED_FILE_VERSION),
128 if sys.platform == 'win32':
129 expected_isolated['files'][rel_gtest_fake_pass_py].pop('m')
130 self.assertEqual(expected_isolated, actual_isolated)
134 os.path.join(GOOGLETEST_DIR, 'isolate_test_cases.py'),
135 # Forces 4 parallel jobs.
137 '--isolated', isolated,
140 cmd.extend(['-v'] * 3)
141 logging.debug(' '.join(cmd))
142 proc = subprocess.Popen(
143 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
144 out, err = proc.communicate() or ('', '') # pylint is confused.
146 self.assertEqual(0, proc.returncode, (out, err))
147 lines = out.splitlines()
149 r'\[0/3\] \d\.\d\ds ',
150 r'\[1/3\] \d+\.\d\ds .+',
151 r'\[2/3\] \d+\.\d\ds .+',
152 r'\[3/3\] \d+\.\d\ds .+',
154 self.assertEqual(len(expected_out_re), len(lines), (out, err))
155 for index in range(len(expected_out_re)):
157 re.match('^%s$' % expected_out_re[index], lines[index]),
159 index, expected_out_re[index], lines[index], out))
160 # Junk is printed on win32.
161 if sys.platform != 'win32' and not VERBOSE:
162 self.assertEqual('', err)
173 'isolate_dependency_untracked': [
180 for test_case in test_cases:
181 tracename = trace_test_cases.sanitize_test_case_name(test_case)
182 with open(basename + '.' + tracename + '.isolate', 'r') as f:
183 result = eval(f.read(), {'__builtins__': None}, None)
184 self.assertEqual(expected, result)
186 # Now verify the .isolate file was updated! (That's the magical part where
188 with open(os.path.join(self.tempdir, gtest_fake_pass_isolate)) as f:
189 actual = eval(f.read(), {'__builtins__': None}, None)
194 'isolate_dependency_untracked': [
201 'command': ['../gtest_fake/gtest_fake_pass.py'],
202 'isolate_dependency_tracked': [
203 '../gtest_fake/gtest_fake_pass.py',
207 self.assertEqual(expected, actual)
210 if __name__ == '__main__':
211 VERBOSE = '-v' in sys.argv
212 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
214 unittest.TestCase.maxDiff = None