def test_savedstate_load(self): # The file referenced by 'isolate_file' must exist even if its content is # not read. open(os.path.join(self.cwd, 'fake.isolate'), 'wb').close() values = { 'config_variables': { 'OS': isolate.get_flavor(), }, 'extra_variables': { 'foo': 42, }, 'isolate_file': 'fake.isolate', } expected = { 'algo': 'sha-1', 'child_isolated_files': [], 'command': [], 'config_variables': { 'OS': isolate.get_flavor(), }, 'extra_variables': { 'foo': 42, }, 'files': {}, 'isolate_file': 'fake.isolate', 'path_variables': {}, 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } saved_state = isolate.SavedState.load(values, self.cwd) self.assertEqual(expected, saved_state.flatten())
def test_subdir(self): # The resulting .isolated file will be missing ../../isolate.py. It is # because this file is outside the --subdir parameter. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') options = self._get_option(isolate_file) chromeos_value = int(isolate.get_flavor() == 'linux') options.config_variables['chromeos'] = chromeos_value complete_state = isolate.load_complete_state( options, self.cwd, os.path.join('tests', 'isolate'), False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'algo': 'sha-1', 'command': ['python', 'touch_root.py'], 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': hash_file('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'algo': 'sha-1', 'child_isolated_files': [], 'command': ['python', 'touch_root.py'], 'config_variables': { 'OS': isolate.get_flavor(), 'chromeos': chromeos_value, }, 'extra_variables': { 'foo': 'bar', }, 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': hash_file('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'isolate_file': file_path.safe_relpath( file_path.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'path_variables': {}, 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state)
def test_subdir_variable(self): # The resulting .isolated file will be missing ../../isolate.py. It is # because this file is outside the --subdir parameter. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') options = self._get_option(isolate_file) chromeos_value = int(isolate.get_flavor() == 'linux') options.variables['chromeos'] = chromeos_value options.variables['BAZ'] = os.path.join('tests', 'isolate') complete_state = isolate.load_complete_state( options, self.cwd, '<(BAZ)', False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'command': ['python', 'touch_root.py'], 'files': { os.path.join('tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join('tests', 'isolate'), } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'child_isolated_files': [], 'command': ['python', 'touch_root.py'], 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'isolate_file': isolate.safe_relpath( isolate.trace_inputs.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'variables': { 'foo': 'bar', 'BAZ': os.path.join('tests', 'isolate'), 'OS': isolate.get_flavor(), 'chromeos': chromeos_value, }, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state)
def test_split(self): self._execute( 'hashtable', 'split.isolate', [ '--path-variable', 'DEPTH', '.', '--path-variable', 'PRODUCT_DIR', 'files1', ], False, cwd=os.path.join(ROOT_DIR, 'tests', 'isolate')) # Reimplement _expected_hash_tree(): tree = self._gen_expected_tree(None) isolated_base = self.isolated[:-len('.isolated')] isolated_hashes = [ unicode(isolateserver.hash_file(isolated_base + '.0.isolated', ALGO)), unicode(isolateserver.hash_file(isolated_base + '.1.isolated', ALGO)), ] tree.extend(isolated_hashes) self.assertEqual(sorted(tree), map(unicode, self._result_tree())) # Reimplement _expected_isolated(): files = self._gen_files(None, None, False) expected = { u'algo': u'sha-1', u'command': [u'python', u'split.py'], u'files': {u'split.py': files['split.py']}, u'includes': isolated_hashes, u'os': unicode(isolate.get_flavor()), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), u'version': unicode(isolate.isolateserver.ISOLATED_FILE_VERSION), } self.assertEqual(expected, json.load(open(self.isolated, 'r'))) key = os.path.join(u'test', 'data', 'foo.txt') expected = { u'algo': u'sha-1', u'files': {key: files[key]}, u'os': unicode(isolate.get_flavor()), u'version': unicode(isolate.isolateserver.ISOLATED_FILE_VERSION), } self.assertEqual( expected, json.load(open(isolated_base + '.0.isolated', 'r'))) key = os.path.join(u'files1', 'subdir', '42.txt') expected = { u'algo': u'sha-1', u'files': {key: files[key]}, u'os': unicode(isolate.get_flavor()), u'version': unicode(isolate.isolateserver.ISOLATED_FILE_VERSION), } self.assertEqual( expected, json.load(open(isolated_base + '.1.isolated', 'r')))
def test_variable_arg(self): parser = isolate.optparse.OptionParser() isolate.add_variable_option(parser) expected = [ ('OS', isolate.get_flavor()), ('EXECUTABLE_SUFFIX', '.exe' if isolate.get_flavor() == 'win' else ''), ('Foo', 'bar'), ('Baz', 'sub=string'), ] options, args = parser.parse_args( ['-V', 'Foo', 'bar', '-V', 'Baz=sub=string']) self.assertEqual(expected, options.variables) self.assertEqual([], args)
def test_split(self): self._execute('hashtable', 'split.isolate', ['-V', 'DEPTH', '.', '-V', 'PRODUCT_DIR', 'files1'], False, cwd=os.path.join(ROOT_DIR, 'tests', 'isolate')) # Reimplement _expected_hash_tree(): tree = self._gen_expected_tree(None) isolated_base = self.isolated[:-len('.isolated')] isolated_hashes = [ unicode(calc_sha1(isolated_base + '.0.isolated')), unicode(calc_sha1(isolated_base + '.1.isolated')), ] tree.extend(isolated_hashes) self.assertEqual(sorted(tree), map(unicode, self._result_tree())) # Reimplement _expected_result(): files = self._gen_files(None, None, False) expected = { u'command': [u'python', u'split.py'], u'files': { u'split.py': files['split.py'] }, u'includes': isolated_hashes, u'os': unicode(isolate.get_flavor()), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), } self.assertEqual(expected, json.load(open(self.isolated, 'r'))) key = os.path.join(u'test', 'data', 'foo.txt') expected = { u'files': { key: files[key] }, u'os': unicode(isolate.get_flavor()), } self.assertEqual(expected, json.load(open(isolated_base + '.0.isolated', 'r'))) key = os.path.join(u'files1', 'subdir', '42.txt') expected = { u'files': { key: files[key] }, u'os': unicode(isolate.get_flavor()), } self.assertEqual(expected, json.load(open(isolated_base + '.1.isolated', 'r')))
def test_subdir_variable(self): # The resulting .isolated file will be missing ../../isolate.py. It is # because this file is outside the --subdir parameter. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') options = self._get_option(isolate_file) options.variables['BAZ'] = os.path.join('tests', 'isolate') complete_state = isolate.load_complete_state(options, '<(BAZ)') actual_isolated = complete_state.isolated.flatten() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'command': ['python', 'touch_root.py'], 'files': { os.path.join('tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join('tests', 'isolate'), } self._cleanup_isolated(expected_isolated, actual_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'isolate_file': isolate_file, 'variables': { 'foo': 'bar', 'BAZ': os.path.join('tests', 'isolate'), }, } self.assertEqual(expected_saved_state, actual_saved_state)
def test_split(self): self._execute('archive', 'split.isolate', ['-V', 'DEPTH', '.', '-V', 'PRODUCT_DIR', 'files1'], False, cwd=os.path.join(ROOT_DIR, 'tests', 'isolate')) # Reimplement _expected_hash_tree(): tree = self._gen_expected_tree(None) isolated_base = self.isolated[:-len('.isolated')] isolated_hashes = [ unicode( isolateserver.hash_file(isolated_base + '.0.isolated', ALGO)), unicode( isolateserver.hash_file(isolated_base + '.1.isolated', ALGO)), ] tree.extend(isolated_hashes) self.assertEqual(sorted(tree), map(unicode, self._result_tree())) # Reimplement _expected_isolated(): files = self._gen_files(None, None, False) expected = { u'algo': u'sha-1', u'command': [u'python', u'split.py'], u'files': { u'split.py': files['split.py'] }, u'includes': isolated_hashes, u'os': unicode(isolate.get_flavor()), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), u'version': u'1.0', }
def _expected_saved_state(self, args, read_only, empty_file, extra_vars): flavor = isolate.get_flavor() chromeos_value = int(flavor == 'linux') expected = { u'algo': u'sha-1', u'child_isolated_files': [], u'command': [], u'config_variables': { u'OS': unicode(flavor), u'chromeos': chromeos_value, }, u'extra_variables': { u'EXECUTABLE_SUFFIX': u'.exe' if flavor == 'win' else u'', }, u'files': self._gen_files(read_only, empty_file, True), u'isolate_file': file_path.safe_relpath( file_path.get_native_path_case(unicode(self.filename())), unicode(os.path.dirname(self.isolated))), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), u'path_variables': {}, u'version': unicode(isolate.isolateserver.ISOLATED_FILE_VERSION), } if args: expected[u'command'] = [u'python'] + [unicode(x) for x in args] expected['extra_variables'].update(extra_vars or {}) self.assertEqual(expected, json.load(open(self.saved_state(), 'r')))
def test_load_isolate_for_flavor_empty(self): content = "{}" command, infiles, touched, read_only = isolate.load_isolate_for_flavor( content, isolate.get_flavor()) self.assertEquals([], command) self.assertEquals([], infiles) self.assertEquals([], touched) self.assertEquals(None, read_only)
def _expected_isolated(self, args, read_only, empty_file): """Verifies self.isolated contains the expected data.""" expected = { u'algo': u'sha-1', u'files': self._gen_files(read_only, empty_file, False), u'os': unicode(isolate.get_flavor()), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), u'version': u'1.0', }
def test_result_load_empty(self): values = { } expected = { 'command': [], 'files': {}, 'os': isolate.get_flavor(), } self.assertEquals(expected, isolate.Result.load(values).flatten())
def _get_option(self, isolate_file): OS = isolate.get_flavor() chromeos_value = int(OS == 'linux') class Options(object): isolated = os.path.join(self.directory, 'foo.isolated') outdir = os.path.join(self.directory, 'outdir') isolate = isolate_file variables = {'foo': 'bar', 'OS': OS, 'chromeos': chromeos_value} ignore_broken_items = False return Options()
def _expected_saved_state(self, extra_vars): flavor = isolate.get_flavor() expected = { u'isolate_file': unicode(self.filename()), u'variables': { u'EXECUTABLE_SUFFIX': '.exe' if flavor == 'win' else '', u'OS': unicode(flavor), }, } expected['variables'].update(extra_vars or {}) self.assertEquals(expected, json.load(open(self.saved_state(), 'r')))
def _expected_result(self, args, read_only, empty_file): """Verifies self.isolated contains the expected data.""" expected = { u'files': self._gen_files(read_only, empty_file, False), u'os': unicode(isolate.get_flavor()), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), } if read_only is not None: expected[u'read_only'] = read_only if args: expected[u'command'] = [u'python'] + [unicode(x) for x in args] self.assertEqual(expected, json.load(open(self.isolated, 'r')))
def _wrap_in_condition(cls, variables): """Wraps a variables dict inside the current OS condition. Returns the equivalent string. """ return cls._isolate_dict_to_string( { 'conditions': [ ['OS=="%s"' % isolate.get_flavor(), { 'variables': variables }], ], })
def test_result_load(self): values = { 'command': 'maybe', 'files': {'foo': 42}, 'read_only': 2, } expected = { 'command': 'maybe', 'files': {'foo': 42}, 'os': isolate.get_flavor(), 'read_only': 2, } self.assertEquals(expected, isolate.Result.load(values).flatten())
def test_variable_arg(self): parser = isolate.OptionParserIsolate() parser.require_isolated = False expected_path = { 'Baz': 'sub=string', } expected_config = { 'Foo': 'bar', 'OS': isolate.get_flavor(), } expected_extra = { 'biz': 'b uz=a', 'EXECUTABLE_SUFFIX': '.exe' if isolate.get_flavor() == 'win' else '', } options, args = parser.parse_args( ['--config-variable', 'Foo', 'bar', '--path-variable', 'Baz=sub=string', '--extra-variable', 'biz', 'b uz=a']) self.assertEqual(expected_path, options.path_variables) self.assertEqual(expected_config, options.config_variables) self.assertEqual(expected_extra, options.extra_variables) self.assertEqual([], args)
def test_savedstate_load(self): # The file referenced by 'isolate_file' must exist even if its content is # not read. open(os.path.join(self.cwd, 'fake.isolate'), 'wb').close() values = { 'isolate_file': 'fake.isolate', 'variables': { 'foo': 42, 'OS': isolate.get_flavor(), }, } expected = { 'child_isolated_files': [], 'command': [], 'files': {}, 'isolate_file': 'fake.isolate', 'variables': { 'foo': 42, 'OS': isolate.get_flavor(), }, } saved_state = isolate.SavedState.load(values, self.cwd) self.assertEqual(expected, saved_state.flatten())
def _wrap_in_condition(cls, variables): """Wraps a variables dict inside the current OS condition. Returns the equivalent string. """ flavor = isolate.get_flavor() chromeos_value = int(flavor == 'linux') return cls._isolate_dict_to_string( { 'conditions': [ ['OS=="%s" and chromeos==%d' % (flavor, chromeos_value), { 'variables': variables }], ], })
def _wrap_in_condition(cls, variables): """Wraps a variables dict inside the current OS condition. Returns the equivalent string. """ flavor = isolate.get_flavor() chromeos_value = int(flavor == 'linux') return cls._isolate_dict_to_string({ 'conditions': [ [ 'OS=="%s" and chromeos==%d' % (flavor, chromeos_value), { 'variables': variables } ], ], })
def _gen_files(self, read_only, empty_file, with_time): """Returns a dict of files like calling isolate.process_input() on each file. Arguments: - read_only: Mark all the 'm' modes without the writeable bit. - empty_file: Add a specific empty file (size 0). - with_time: Include 't' timestamps. For saved state .state files. """ root_dir = ROOT_DIR if RELATIVE_CWD[self.case()] == '.': root_dir = os.path.join(root_dir, 'tests', 'isolate') files = dict((unicode(f), {}) for f in DEPENDENCIES[self.case()]) for relfile, v in files.iteritems(): filepath = os.path.join(root_dir, relfile) filestats = os.lstat(filepath) is_link = stat.S_ISLNK(filestats.st_mode) if not is_link: v[u's'] = filestats.st_size if isolate.get_flavor() != 'win': v[u'm'] = self._fix_file_mode(relfile, read_only) else: v[u'm'] = 488 if with_time: # Used to skip recalculating the hash. Use the most recent update # time. v[u't'] = int(round(filestats.st_mtime)) if is_link: v['l'] = os.readlink(filepath) # pylint: disable=E1101 else: # Upgrade the value to unicode so diffing the structure in case of # test failure is easier, since the basestring type must match, # str!=unicode. v[u'h'] = unicode(calc_sha1(filepath)) if empty_file: item = files[empty_file] item['h'] = unicode(SHA_1_NULL) if sys.platform != 'win32': item['m'] = 288 item['s'] = 0 if with_time: item['T'] = True item.pop('t', None) return files
def _execute(self, mode, case, args, need_output, cwd=ROOT_DIR): """Executes isolate.py.""" self.assertEqual( case, self.case() + '.isolate', 'Rename the test case to test_%s()' % case) chromeos_value = int(isolate.get_flavor() == 'linux') cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), mode, '--isolated', self.isolated, '--outdir', self.outdir, '--isolate', self.filename(), '-V', 'chromeos', str(chromeos_value), ] cmd.extend(args) env = os.environ.copy() if 'ISOLATE_DEBUG' in env: del env['ISOLATE_DEBUG'] if need_output or not VERBOSE: stdout = subprocess.PIPE stderr = subprocess.PIPE else: cmd.extend(['-v'] * 3) stdout = None stderr = None logging.debug(cmd) p = subprocess.Popen( cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env, universal_newlines=True) out, err = p.communicate() if p.returncode: raise CalledProcessError(p.returncode, cmd, out, err, cwd) # Do not check on Windows since a lot of spew is generated there. if sys.platform != 'win32': self.assertTrue(err in (None, ''), err) return out
def _gen_files(self, read_only, empty_file): """Returns a dict of files like calling isolate.process_input() on each file. """ root_dir = ROOT_DIR if RELATIVE_CWD[self.case()] == '.': root_dir = os.path.join(root_dir, 'tests', 'isolate') files = dict((unicode(f), {}) for f in DEPENDENCIES[self.case()]) for relfile, v in files.iteritems(): filepath = os.path.join(root_dir, relfile) if self.LEVEL >= isolate.STATS_ONLY: filestats = os.lstat(filepath) is_link = stat.S_ISLNK(filestats.st_mode) if not is_link: v[u'size'] = filestats.st_size if isolate.get_flavor() != 'win': v[u'mode'] = self._fix_file_mode(relfile, read_only) else: v[u'mode'] = 488 # Used the skip recalculating the hash. Use the most recent update # time. v[u'timestamp'] = int(round(filestats.st_mtime)) if is_link: v['link'] = os.readlink(filepath) if self.LEVEL >= isolate.WITH_HASH: if not is_link: # Upgrade the value to unicode so diffing the structure in case of # test failure is easier, since the basestring type must match, # str!=unicode. v[u'sha-1'] = unicode(calc_sha1(filepath)) if empty_file: item = files[empty_file] item['sha-1'] = unicode(SHA_1_NULL) if sys.platform != 'win32': item['mode'] = 288 item['size'] = 0 item['touched_only'] = True item.pop('timestamp', None) return files
def _expected_saved_state(self, args, read_only, empty_file, extra_vars): flavor = isolate.get_flavor() chromeos_value = int(flavor == 'linux') expected = { u'child_isolated_files': [], u'command': [], u'files': self._gen_files(read_only, empty_file, True), u'isolate_file': isolate.safe_relpath( isolate.trace_inputs.get_native_path_case( unicode(self.filename())), unicode(os.path.dirname(self.isolated))), u'relative_cwd': unicode(RELATIVE_CWD[self.case()]), u'variables': { u'EXECUTABLE_SUFFIX': u'.exe' if flavor == 'win' else u'', u'OS': unicode(flavor), u'chromeos': chromeos_value, }, }
def _execute(self, mode, args, need_output): """Executes isolate.py.""" chromeos_value = int(isolate.get_flavor() == 'linux') cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), mode, '--isolated', self.isolated, '-V', 'chromeos', str(chromeos_value), ] cmd.extend(args) env = os.environ.copy() if 'ISOLATE_DEBUG' in env: del env['ISOLATE_DEBUG'] if need_output or not VERBOSE: stdout = subprocess.PIPE stderr = subprocess.STDOUT else: cmd.extend(['-v'] * 3) stdout = None stderr = None logging.debug(cmd) cwd = self.tempdir p = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env, universal_newlines=True) out, err = p.communicate() if p.returncode: raise CalledProcessError(p.returncode, cmd, out, err, cwd) return out
def _execute(self, mode, args, need_output): """Executes isolate.py.""" chromeos_value = int(isolate.get_flavor() == 'linux') cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), mode, '--isolated', self.isolated, '-V', 'chromeos', str(chromeos_value), ] cmd.extend(args) env = os.environ.copy() if 'ISOLATE_DEBUG' in env: del env['ISOLATE_DEBUG'] if need_output or not VERBOSE: stdout = subprocess.PIPE stderr = subprocess.STDOUT else: cmd.extend(['-v'] * 3) stdout = None stderr = None logging.debug(cmd) cwd = self.tempdir p = subprocess.Popen( cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env, universal_newlines=True) out, err = p.communicate() if p.returncode: raise CalledProcessError(p.returncode, cmd, out, err, cwd) return out
def _expect_results(self, args, read_only, extra_vars, empty_file): self._expected_result(args, read_only, empty_file) self._expected_saved_state(args, read_only, empty_file, extra_vars) # Also verifies run_isolated.py will be able to read it. isolate.run_isolated.load_isolated(open(self.isolated, 'r').read()) def _expect_no_result(self): self.assertFalse(os.path.exists(self.isolated)) def _execute(self, mode, case, args, need_output, cwd=ROOT_DIR): """Executes isolate.py.""" self.assertEqual(case, self.case() + '.isolate', 'Rename the test case to test_%s()' % case) chromeos_value = int(isolate.get_flavor() == 'linux') cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), mode, '--isolated', self.isolated, '--outdir', self.outdir, '--isolate', self.filename(), '-V', 'chromeos', str(chromeos_value), ] cmd.extend(args)
def test_load_stale_result(self): directory = tempfile.mkdtemp(prefix='isolate_') try: isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') class Options(object): result = os.path.join(directory, 'result') outdir = os.path.join(directory, '0utdir') isolate = isolate_file variables = {'foo': 'bar'} # Data to be loaded in the .result file. Do not create a .state file. input_data = { 'command': ['python'], 'files': { 'foo': { "mode": 416, "sha-1": "invalid", "size": 538, "timestamp": 1335146921, }, os.path.join('tests', 'isolate', 'touch_root.py'): { "mode": 488, "sha-1": "invalid", "size": 538, "timestamp": 1335146921, }, }, } isolate.trace_inputs.write_json(Options.result, input_data, False) # A CompleteState object contains two parts: # - Result instance stored in complete_state.result, corresponding to the # .result file, is what is read by run_test_from_archive.py. # - SavedState instance stored in compelte_state.saved_state, # corresponding to the .state file, which is simply to aid the developer # when re-running the same command multiple times and contain # discardable information. complete_state = isolate.load_complete_state(Options, isolate.STATS_ONLY) actual_result = complete_state.result.flatten() actual_saved_state = complete_state.saved_state.flatten() expected_result = { 'command': ['python', 'touch_root.py'], 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'mode': 488, 'size': self._size('tests', 'isolate', 'touch_root.py'), }, 'isolate.py': { 'mode': 488, 'size': self._size('isolate.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join('tests', 'isolate'), } if sys.platform == 'win32': # 'mode' are not saved in windows. for values in expected_result['files'].itervalues(): del values['mode'] for item in actual_result['files'].itervalues(): self.assertTrue(item.pop('timestamp')) self.assertEquals(expected_result, actual_result) expected_saved_state = { 'isolate_file': isolate_file, 'variables': {'foo': 'bar'}, } self.assertEquals(expected_saved_state, actual_saved_state) finally: isolate.run_test_from_archive.rmtree(directory)
def test_simple(self): # Create a directory and re-use tests/gtest_fake/gtest_fake_pass.isolate. # Warning: we need to copy the files around, since the original .isolate # file is modified. gtest_fake_base_py = os.path.join('tests', 'gtest_fake', 'gtest_fake_base.py') gtest_fake_pass_py = os.path.join('tests', 'gtest_fake', 'gtest_fake_pass.py') gtest_fake_pass_isolate = os.path.join('tests', 'isolate_test_cases', 'gtest_fake_pass.isolate') self.tempdir = tempfile.mkdtemp(prefix='isolate_test_cases_test') os.mkdir(os.path.join(self.tempdir, 'isolated')) os.mkdir(os.path.join(self.tempdir, 'tests')) os.mkdir(os.path.join(self.tempdir, 'tests', 'gtest_fake')) os.mkdir(os.path.join(self.tempdir, 'tests', 'isolate_test_cases')) self._copy('isolate.py') self._copy(gtest_fake_base_py) self._copy(gtest_fake_pass_isolate) self._copy(gtest_fake_pass_py) basename = os.path.join(self.tempdir, 'isolated', 'gtest_fake_pass') isolated = basename + '.isolated' # Create a proper .isolated file. cmd = [ sys.executable, 'isolate.py', 'check', '--variable', 'FLAG', 'run', '--isolate', os.path.join(self.tempdir, gtest_fake_pass_isolate), '--isolated', isolated, ] if VERBOSE: cmd.extend(['-v'] * 3) subprocess.check_call(cmd, cwd=ROOT_DIR) # Assert the content of the .isolated file. with open(isolated) as f: actual_isolated = json.load(f) root_dir_gtest_fake_pass_py = os.path.join(ROOT_DIR, gtest_fake_pass_py) rel_gtest_fake_pass_py = os.path.join(u'gtest_fake', 'gtest_fake_pass.py') expected_isolated = { u'command': [u'../gtest_fake/gtest_fake_pass.py'], u'files': { rel_gtest_fake_pass_py: { u'm': 488, u'h': unicode( hashlib.sha1( open(root_dir_gtest_fake_pass_py, 'rb').read()).hexdigest()), u's': os.stat(root_dir_gtest_fake_pass_py).st_size, }, }, u'os': unicode(isolate.get_flavor()), u'relative_cwd': u'isolate_test_cases', } if sys.platform == 'win32': expected_isolated['files'][rel_gtest_fake_pass_py].pop('m') self.assertEqual(expected_isolated, actual_isolated) cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate_test_cases.py'), # Forces 4 parallel jobs. '--jobs', '4', '--isolated', isolated, ] if VERBOSE: cmd.extend(['-v'] * 3) logging.debug(' '.join(cmd)) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() or ('', '') # pylint is confused. logging.info(err) self.assertEqual(0, proc.returncode, (out, err)) lines = out.splitlines() expected_out_re = [ r'\[1/3\] \d+\.\d\ds .+', r'\[2/3\] \d+\.\d\ds .+', r'\[3/3\] \d+\.\d\ds .+', ] self.assertEqual(len(expected_out_re), len(lines), (out, err)) for index in range(len(expected_out_re)): self.assertTrue( re.match('^%s$' % expected_out_re[index], lines[index]), '%d\n%r\n%r\n%r' % (index, expected_out_re[index], lines[index], out)) # Junk is printed on win32. if sys.platform != 'win32' and not VERBOSE: self.assertEqual('', err) test_cases = ( 'Foo.Bar1', 'Foo.Bar2', 'Foo.Bar/3', ) expected = { 'conditions': [ [ 'OS=="%s"' % isolate.get_flavor(), { 'variables': { 'isolate_dependency_untracked': [ '../gtest_fake/', ], }, } ], ], } for test_case in test_cases: tracename = trace_test_cases.sanitize_test_case_name(test_case) with open(basename + '.' + tracename + '.isolate', 'r') as f: result = eval(f.read(), {'__builtins__': None}, None) self.assertEqual(expected, result) # Now verify the .isolate file was updated! (That's the magical part where # you say wow!) with open(os.path.join(self.tempdir, gtest_fake_pass_isolate)) as f: actual = eval(f.read(), {'__builtins__': None}, None) all_oses = set(['linux', 'mac', 'win']) host_os = isolate.get_flavor() other_oses = all_oses - set([host_os]) expected = { 'conditions': sorted([ [ 'OS=="%s"' % isolate.get_flavor(), { 'variables': { 'isolate_dependency_untracked': [ '../gtest_fake/', ], }, } ], [ ' or '.join('OS=="%s"' % os for os in sorted(other_oses)), { 'variables': { 'isolate_dependency_tracked': [ '../gtest_fake/gtest_fake_pass.py', ], }, } ], [ ' or '.join('OS=="%s"' % os for os in sorted(all_oses)), { 'variables': { 'command': ['../gtest_fake/gtest_fake_pass.py'], }, } ], ]), } self.assertEqual(expected, actual)
def test_simple(self): # Create a directory and re-use tests/gtest_fake/gtest_fake_pass.isolate. # Warning: we need to copy the files around, since the original .isolate # file is modified. gtest_fake_base_py = os.path.join( 'tests', 'gtest_fake', 'gtest_fake_base.py') gtest_fake_pass_py = os.path.join( 'tests', 'gtest_fake', 'gtest_fake_pass.py') gtest_fake_pass_isolate = os.path.join( 'tests', 'isolate_test_cases', 'gtest_fake_pass.isolate') self.tempdir = tempfile.mkdtemp(prefix='isolate_test_cases_test') os.mkdir(os.path.join(self.tempdir, 'isolated')) os.mkdir(os.path.join(self.tempdir, 'tests')) os.mkdir(os.path.join(self.tempdir, 'tests', 'gtest_fake')) os.mkdir(os.path.join(self.tempdir, 'tests', 'isolate_test_cases')) self._copy('isolate.py') self._copy(gtest_fake_base_py) self._copy(gtest_fake_pass_isolate) self._copy(gtest_fake_pass_py) basename = os.path.join(self.tempdir, 'isolated', 'gtest_fake_pass') isolated = basename + '.isolated' # Create a proper .isolated file. cmd = [ sys.executable, 'isolate.py', 'check', '--variable', 'FLAG', 'run', '--isolate', os.path.join(self.tempdir, gtest_fake_pass_isolate), '--isolated', isolated, ] if VERBOSE: cmd.extend(['-v'] * 3) subprocess.check_call(cmd, cwd=ROOT_DIR) # Assert the content of the .isolated file. with open(isolated) as f: actual_isolated = json.load(f) root_dir_gtest_fake_pass_py = os.path.join(ROOT_DIR, gtest_fake_pass_py) rel_gtest_fake_pass_py = os.path.join(u'gtest_fake', 'gtest_fake_pass.py') expected_isolated = { u'command': [u'../gtest_fake/gtest_fake_pass.py'], u'files': { rel_gtest_fake_pass_py: { u'm': 488, u'h': unicode(hashlib.sha1( open(root_dir_gtest_fake_pass_py, 'rb').read()).hexdigest()), u's': os.stat(root_dir_gtest_fake_pass_py).st_size, }, }, u'os': unicode(isolate.get_flavor()), u'relative_cwd': u'isolate_test_cases', } self.assertTrue( actual_isolated['files'][rel_gtest_fake_pass_py].pop('t')) if sys.platform == 'win32': expected_isolated['files'][rel_gtest_fake_pass_py].pop('m') self.assertEquals(expected_isolated, actual_isolated) cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate_test_cases.py'), # Forces 4 parallel jobs. '--jobs', '4', '--isolated', isolated, ] if VERBOSE: cmd.extend(['-v'] * 3) logging.debug(' '.join(cmd)) proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() or ('', '') # pylint is confused. logging.info(err) self.assertEqual(0, proc.returncode, (out, err)) lines = out.splitlines() expected_out_re = [ r'\[1/3\] \d+\.\d\ds .+', r'\[2/3\] \d+\.\d\ds .+', r'\[3/3\] \d+\.\d\ds .+', ] self.assertEqual(len(expected_out_re), len(lines), (out, err)) for index in range(len(expected_out_re)): self.assertTrue( re.match('^%s$' % expected_out_re[index], lines[index]), '%d\n%r\n%r\n%r' % ( index, expected_out_re[index], lines[index], out)) # Junk is printed on win32. if sys.platform != 'win32' and not VERBOSE: self.assertEqual('', err) test_cases = ( 'Foo.Bar1', 'Foo.Bar2', 'Foo.Bar/3', ) expected = { 'conditions': [ ['OS=="%s"' % isolate.get_flavor(), { 'variables': { 'isolate_dependency_untracked': [ '../gtest_fake/', ], }, }], ], } for test_case in test_cases: tracename = trace_test_cases.sanitize_test_case_name(test_case) with open(basename + '.' + tracename + '.isolate', 'r') as f: result = eval(f.read(), {'__builtins__': None}, None) self.assertEqual(expected, result) # Now verify the .isolate file was updated! (That's the magical part where # you say wow!) with open(os.path.join(self.tempdir, gtest_fake_pass_isolate)) as f: actual = eval(f.read(), {'__builtins__': None}, None) expected = { 'variables': { 'command': ['../gtest_fake/gtest_fake_pass.py'], }, 'conditions': [ ['OS=="%s"' % isolate.get_flavor(), { 'variables': { 'isolate_dependency_untracked': [ '../gtest_fake/', ], }, }, { 'variables': { 'isolate_dependency_tracked': [ '../gtest_fake/gtest_fake_pass.py', ], }, }], ], } self.assertEqual(expected, actual)
def test_root_dir_because_of_variable(self): # Ensures that load_isolate() works even when path variables have deep root # dirs. The end result is similar to touch_root.isolate, except that # no_run.isolate doesn't reference '..' at all. # # A real world example would be PRODUCT_DIR=../../out/Release but nothing in # this directory is mapped. # # Imagine base/base_unittests.isolate would not map anything in # PRODUCT_DIR. In that case, the automatically determined root dir is # src/base, since nothing outside this directory is mapped. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'no_run.isolate') options = self._get_option(isolate_file) chromeos_value = int(isolate.get_flavor() == 'linux') # Any directory outside ROOT_DIR/tests/isolate. options.path_variables['PRODUCT_DIR'] = os.path.join('third_party') complete_state = isolate.load_complete_state(options, ROOT_DIR, None, False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'algo': 'sha-1', 'files': { os.path.join(u'tests', 'isolate', 'files1', 'subdir', '42.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'subdir', '42.txt'), 's': _size('tests', 'isolate', 'files1', 'subdir', '42.txt'), }, os.path.join(u'tests', 'isolate', 'files1', 'test_file1.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'test_file1.txt'), 's': _size('tests', 'isolate', 'files1', 'test_file1.txt'), }, os.path.join(u'tests', 'isolate', 'files1', 'test_file2.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'test_file2.txt'), 's': _size('tests', 'isolate', 'files1', 'test_file2.txt'), }, os.path.join(u'tests', 'isolate', 'no_run.isolate'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'no_run.isolate'), 's': _size('tests', 'isolate', 'no_run.isolate'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'algo': 'sha-1', 'child_isolated_files': [], 'command': [], 'config_variables': { 'OS': isolate.get_flavor(), 'chromeos': chromeos_value, }, 'extra_variables': { 'foo': 'bar', }, 'files': { os.path.join(u'tests', 'isolate', 'files1', 'subdir', '42.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'subdir', '42.txt'), 's': _size('tests', 'isolate', 'files1', 'subdir', '42.txt'), }, os.path.join(u'tests', 'isolate', 'files1', 'test_file1.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'test_file1.txt'), 's': _size('tests', 'isolate', 'files1', 'test_file1.txt'), }, os.path.join(u'tests', 'isolate', 'files1', 'test_file2.txt'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'files1', 'test_file2.txt'), 's': _size('tests', 'isolate', 'files1', 'test_file2.txt'), }, os.path.join(u'tests', 'isolate', 'no_run.isolate'): { 'm': 416, 'h': hash_file('tests', 'isolate', 'no_run.isolate'), 's': _size('tests', 'isolate', 'no_run.isolate'), }, }, 'isolate_file': file_path.safe_relpath( file_path.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'path_variables': { 'PRODUCT_DIR': os.path.join(u'..', '..', 'third_party'), }, 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state) self.assertEqual([], os.listdir(self.directory))
def test_subdir_variable(self): # the resulting .isolated file will be missing ../../isolate.py. it is # because this file is outside the --subdir parameter. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') options = self._get_option(isolate_file) chromeos_value = int(isolate.get_flavor() == 'linux') options.config_variables['chromeos'] = chromeos_value # Path variables are keyed on the directory containing the .isolate file. options.path_variables['TEST_ISOLATE'] = '.' # Note that options.isolated is in self.directory, which is a temporary # directory. complete_state = isolate.load_complete_state( options, os.path.join(ROOT_DIR, 'tests', 'isolate'), '<(TEST_ISOLATE)', False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'algo': 'sha-1', 'command': ['python', 'touch_root.py'], 'files': { os.path.join('tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': hash_file('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) # It is important to note: # - the root directory is ROOT_DIR. # - relative_cwd is tests/isolate. # - TEST_ISOLATE is based of relative_cwd, so it represents tests/isolate. # - anything outside TEST_ISOLATE was not included in the 'files' section. expected_saved_state = { 'algo': 'sha-1', 'child_isolated_files': [], 'command': ['python', 'touch_root.py'], 'config_variables': { 'OS': isolate.get_flavor(), 'chromeos': chromeos_value, }, 'extra_variables': { 'foo': 'bar', }, 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': hash_file('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'isolate_file': file_path.safe_relpath( file_path.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'path_variables': { 'TEST_ISOLATE': '.', }, 'version': isolate.isolateserver.ISOLATED_FILE_VERSION, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state)
self._expected_isolated(args, read_only, empty_file) self._expected_saved_state(args, read_only, empty_file, extra_vars) # Also verifies run_isolated.py will be able to read it. isolate.isolateserver.load_isolated( open(self.isolated, 'r').read(), isolate.run_isolated.get_flavor(), ALGO) def _expect_no_result(self): self.assertFalse(os.path.exists(self.isolated)) def _execute(self, mode, case, args, need_output, cwd=ROOT_DIR): """Executes isolate.py.""" self.assertEqual(case, self.case() + '.isolate', 'Rename the test case to test_%s()' % case) chromeos_value = int(isolate.get_flavor() == 'linux') cmd = [ sys.executable, os.path.join(ROOT_DIR, 'isolate.py'), mode, '--isolated', self.isolated, '--outdir', self.outdir, '--isolate', self.filename(), '-V', 'chromeos', str(chromeos_value), ] cmd.extend(args)
class IsolateModeBase(IsolateBase): def _expect_no_tree(self): self.assertFalse(os.path.exists(self.outdir)) def _result_tree(self): return list_files_tree(self.outdir) def _expected_tree(self): """Verifies the files written in the temporary directory.""" self.assertEqual(sorted(DEPENDENCIES[self.case()]), self._result_tree()) @staticmethod def _fix_file_mode(filename, read_only): """4 modes are supported, 0750 (rwx), 0640 (rw), 0550 (rx), 0440 (r).""" min_mode = 0440 if not read_only: min_mode |= 0200 return (min_mode | 0110) if filename.endswith('.py') else min_mode def _gen_files(self, read_only, empty_file, with_time): """Returns a dict of files like calling isolate.process_input() on each file. Arguments: - read_only: Mark all the 'm' modes without the writeable bit. - empty_file: Add a specific empty file (size 0). - with_time: Include 't' timestamps. For saved state .state files. """ root_dir = ROOT_DIR if RELATIVE_CWD[self.case()] == '.': root_dir = os.path.join(root_dir, 'tests', 'isolate') files = dict((unicode(f), {}) for f in DEPENDENCIES[self.case()]) for relfile, v in files.iteritems(): filepath = os.path.join(root_dir, relfile) filestats = os.lstat(filepath) is_link = stat.S_ISLNK(filestats.st_mode) if not is_link: v[u's'] = filestats.st_size if isolate.get_flavor() != 'win': v[u'm'] = self._fix_file_mode(relfile, read_only) if with_time: # Used to skip recalculating the hash. Use the most recent update # time. v[u't'] = int(round(filestats.st_mtime)) if is_link: v[u'l'] = os.readlink(filepath) # pylint: disable=E1101 else: # Upgrade the value to unicode so diffing the structure in case of # test failure is easier, since the basestring type must match, # str!=unicode. v[u'h'] = unicode(isolateserver.hash_file(filepath, ALGO)) if empty_file: item = files[empty_file] item['h'] = unicode(HASH_NULL) if sys.platform != 'win32': item['m'] = 288 item['s'] = 0 if with_time: item['T'] = True item.pop('t', None) return files
def test_load_stale_isolated(self): isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') # Data to be loaded in the .isolated file. Do not create a .state file. input_data = { 'command': ['python'], 'files': { 'foo': { "m": 416, "h": "invalid", "s": 538, "t": 1335146921, }, os.path.join('tests', 'isolate', 'touch_root.py'): { "m": 488, "h": "invalid", "s": 538, "t": 1335146921, }, }, } options = self._get_option(isolate_file) isolate.trace_inputs.write_json(options.isolated, input_data, False) # A CompleteState object contains two parts: # - Result instance stored in complete_state.isolated, corresponding to the # .isolated file, is what is read by run_test_from_archive.py. # - SavedState instance stored in compelte_state.saved_state, # corresponding to the .state file, which is simply to aid the developer # when re-running the same command multiple times and contain # discardable information. complete_state = isolate.load_complete_state(options, self.cwd, None, False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'command': ['python', 'touch_root.py'], 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, 'isolate.py': { 'm': 488, 'h': _sha1('isolate.py'), 's': _size('isolate.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join('tests', 'isolate'), } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'child_isolated_files': [], 'command': ['python', 'touch_root.py'], 'files': { os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, u'isolate.py': { 'm': 488, 'h': _sha1('isolate.py'), 's': _size('isolate.py'), }, }, 'isolate_file': isolate.safe_relpath( isolate.trace_inputs.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'variables': { 'foo': 'bar', 'OS': isolate.get_flavor(), 'chromeos': options.variables['chromeos'], } } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state)
def test_chromium_split(self): # Create an .isolate file and a tree of random stuff. isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'split.isolate') options = self._get_option(isolate_file) options.variables = { 'OS': isolate.get_flavor(), 'DEPTH': '.', 'PRODUCT_DIR': os.path.join('files1'), } complete_state = isolate.load_complete_state( options, os.path.join(ROOT_DIR, 'tests', 'isolate'), None, False) # By saving the files, it forces splitting the data up. complete_state.save_files() actual_isolated_master = isolate.trace_inputs.read_json( os.path.join(self.directory, 'foo.isolated')) expected_isolated_master = { u'command': [u'python', u'split.py'], u'files': { u'split.py': { u'm': 488, u'h': unicode(_sha1('tests', 'isolate', 'split.py')), u's': _size('tests', 'isolate', 'split.py'), }, }, u'includes': [ unicode(_sha1(os.path.join(self.directory, 'foo.0.isolated'))), unicode(_sha1(os.path.join(self.directory, 'foo.1.isolated'))), ], u'os': unicode(isolate.get_flavor()), u'relative_cwd': u'.', } self._cleanup_isolated(expected_isolated_master) self.assertEqual(expected_isolated_master, actual_isolated_master) actual_isolated_0 = isolate.trace_inputs.read_json( os.path.join(self.directory, 'foo.0.isolated')) expected_isolated_0 = { u'files': { os.path.join(u'test', 'data', 'foo.txt'): { u'm': 416, u'h': unicode(_sha1('tests', 'isolate', 'test', 'data', 'foo.txt')), u's': _size('tests', 'isolate', 'test', 'data', 'foo.txt'), }, }, u'os': unicode(isolate.get_flavor()), } self._cleanup_isolated(expected_isolated_0) self.assertEqual(expected_isolated_0, actual_isolated_0) actual_isolated_1 = isolate.trace_inputs.read_json( os.path.join(self.directory, 'foo.1.isolated')) expected_isolated_1 = { u'files': { os.path.join(u'files1', 'subdir', '42.txt'): { u'm': 416, u'h': unicode( _sha1('tests', 'isolate', 'files1', 'subdir', '42.txt')), u's': _size('tests', 'isolate', 'files1', 'subdir', '42.txt'), }, }, u'os': unicode(isolate.get_flavor()), } self._cleanup_isolated(expected_isolated_1) self.assertEqual(expected_isolated_1, actual_isolated_1) actual_saved_state = isolate.trace_inputs.read_json( isolate.isolatedfile_to_state(options.isolated)) isolated_base = unicode(os.path.basename(options.isolated)) expected_saved_state = { u'child_isolated_files': [ isolated_base[:-len('.isolated')] + '.0.isolated', isolated_base[:-len('.isolated')] + '.1.isolated', ], u'command': [u'python', u'split.py'], u'files': { os.path.join(u'files1', 'subdir', '42.txt'): { u'm': 416, u'h': unicode( _sha1('tests', 'isolate', 'files1', 'subdir', '42.txt')), u's': _size('tests', 'isolate', 'files1', 'subdir', '42.txt'), }, u'split.py': { u'm': 488, u'h': unicode(_sha1('tests', 'isolate', 'split.py')), u's': _size('tests', 'isolate', 'split.py'), }, os.path.join(u'test', 'data', 'foo.txt'): { u'm': 416, u'h': unicode(_sha1('tests', 'isolate', 'test', 'data', 'foo.txt')), u's': _size('tests', 'isolate', 'test', 'data', 'foo.txt'), }, }, u'isolate_file': isolate.safe_relpath( isolate.trace_inputs.get_native_path_case(isolate_file), unicode(os.path.dirname(options.isolated))), u'relative_cwd': u'.', u'variables': { u'OS': unicode(isolate.get_flavor()), u'DEPTH': u'.', u'PRODUCT_DIR': u'files1', }, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state) self.assertEqual( [ 'foo.0.isolated', 'foo.1.isolated', 'foo.isolated', 'foo.isolated.state', ], sorted(os.listdir(self.directory)))
def test_variable(self): isolate_file = os.path.join( ROOT_DIR, 'tests', 'isolate', 'touch_root.isolate') options = self._get_option(isolate_file) chromeos_value = int(isolate.get_flavor() == 'linux') options.variables['chromeos'] = chromeos_value options.variables['PRODUCT_DIR'] = os.path.join('tests', 'isolate') complete_state = isolate.load_complete_state(options, ROOT_DIR, None, False) actual_isolated = complete_state.saved_state.to_isolated() actual_saved_state = complete_state.saved_state.flatten() expected_isolated = { 'command': ['python', 'touch_root.py'], 'files': { 'isolate.py': { 'm': 488, 'h': _sha1('isolate.py'), 's': _size('isolate.py'), }, os.path.join('tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'os': isolate.get_flavor(), 'relative_cwd': os.path.join('tests', 'isolate'), } self._cleanup_isolated(expected_isolated) self.assertEqual(expected_isolated, actual_isolated) expected_saved_state = { 'child_isolated_files': [], 'command': ['python', 'touch_root.py'], 'files': { u'isolate.py': { 'm': 488, 'h': _sha1('isolate.py'), 's': _size('isolate.py'), }, os.path.join(u'tests', 'isolate', 'touch_root.py'): { 'm': 488, 'h': _sha1('tests', 'isolate', 'touch_root.py'), 's': _size('tests', 'isolate', 'touch_root.py'), }, }, 'isolate_file': isolate.safe_relpath( isolate.trace_inputs.get_native_path_case(isolate_file), os.path.dirname(options.isolated)), 'relative_cwd': os.path.join(u'tests', 'isolate'), 'variables': { 'foo': 'bar', 'PRODUCT_DIR': '.', 'OS': isolate.get_flavor(), 'chromeos': chromeos_value, }, } self._cleanup_isolated(expected_saved_state) self._cleanup_saved_state(actual_saved_state) self.assertEqual(expected_saved_state, actual_saved_state) self.assertEqual([], os.listdir(self.directory))