103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#!/usr/bin/env python 203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved. 303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)# found in the LICENSE file. 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)import base64 703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)import json 803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)import unittest 903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 1003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from extensions_paths import SERVER2 1103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from file_system import StatInfo 1203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from future import Future 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from gitiles_file_system import (_CreateStatInfo, 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) _ParseGitilesJson, 1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) GitilesFileSystem) 1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from path_util import IsDirectory 1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from test_file_system import TestFileSystem 1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)from test_util import ReadFile 1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)_BASE_URL = '' 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)_REAL_DATA_DIR = 'chrome/common/extensions/docs/templates/public/extensions/' 2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)_TEST_DATA = (SERVER2, 'test_data', 'gitiles_file_system', 'public_extensions') 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)# GitilesFileSystem expects file content to be encoded in base64. 2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)_TEST_FS = { 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'test1.txt': base64.b64encode('test1'), 2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'dir1': { 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'test2.txt': base64.b64encode('test2'), 2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'dir2': { 3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'test3.txt': base64.b64encode('test3') 3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class _Response(object): 3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def __init__(self, content=''): 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.content = content 3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.status_code = 200 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class DownloadError(Exception): 4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) pass 4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class _FakeGitilesFetcher(object): 4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def __init__(self, fs): 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self._fs = fs 4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci def FetchAsync(self, url, access_token=None): 5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def resolve(): 5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) assert '?' in url 5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if url == _BASE_URL + '?format=JSON': 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return _Response(json.dumps({'commit': 'a_commit'})) 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) path, fmt = url.split('?') 5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Fetch urls are of the form <base_url>/<path>. We only want <path>. 5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) path = path.split('/', 1)[1] 5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if path == _REAL_DATA_DIR: 5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return _Response(ReadFile(*_TEST_DATA)) 6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # ALWAYS skip not found here. 6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content = self._fs.Read((path,), 6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) skip_not_found=True).Get().get(path, None) 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if content is None: 6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # GitilesFS expects a DownloadError if the file wasn't found. 6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) raise DownloadError 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # GitilesFS expects directory content as a JSON string. 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if 'JSON' in fmt: 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) content = json.dumps({ 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'entries': [{ 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # GitilesFS expects directory names to not have a trailing '/'. 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'name': name.rstrip('/'), 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'type': 'tree' if IsDirectory(name) else 'blob' 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } for name in content] 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }) 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return _Response(content) 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return Future(callback=resolve) 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class GitilesFileSystemTest(unittest.TestCase): 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def setUp(self): 8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) fetcher = _FakeGitilesFetcher(TestFileSystem(_TEST_FS)) 8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self._gitiles_fs = GitilesFileSystem(fetcher, _BASE_URL, 'master', None) 8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testParseGitilesJson(self): 8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) test_json = '\n'.join([ 8603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ')]}\'', 8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json.dumps({'commit': 'blah'}) 8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ]) 8903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(_ParseGitilesJson(test_json), {'commit': 'blah'}) 9003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testCreateStatInfo(self): 9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) test_json = '\n'.join([ 9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ')]}\'', 9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) json.dumps({ 9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'id': 'some_long_string', 9603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'entries': [ 9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'mode': 33188, 9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'type': 'blob', 10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'id': 'long_id', 10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'name': '.gitignore' 10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }, 10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'mode': 33188, 10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'type': 'blob', 10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'id': 'another_long_id', 10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'name': 'PRESUBMIT.py' 10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }, 10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) { 11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'mode': 33188, 11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'type': 'blob', 11203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'id': 'yali', 11303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'name': 'README' 11403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 11503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ] 11603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }) 11703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ]) 11803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) expected_stat_info = StatInfo('some_long_string', { 11903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) '.gitignore': 'long_id', 12003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'PRESUBMIT.py': 'another_long_id', 12103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'README': 'yali' 12203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) }) 12303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(_CreateStatInfo(test_json), expected_stat_info) 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testRead(self): 12603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Read a top-level file. 12703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['test1.txt']) 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {'test1.txt': 'test1'}) 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Read a top-level directory. 13003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['dir1/']) 13103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {'dir1/': sorted(['test2.txt', 'dir2/'])}) 13203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Read a nested file. 13303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['dir1/test2.txt']) 13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {'dir1/test2.txt': 'test2'}) 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Read a nested directory. 13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['dir1/dir2/']) 13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {'dir1/dir2/': ['test3.txt']}) 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Read multiple paths. 13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['test1.txt', 'dir1/test2.txt']) 14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {'test1.txt': 'test1', 'dir1/test2.txt': 'test2'}) 14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Test skip not found. 14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) f = self._gitiles_fs.Read(['fakefile'], skip_not_found=True) 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(f.Get(), {}) 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testGetCommitID(self): 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(self._gitiles_fs.GetCommitID().Get(), 'a_commit') 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testStat(self): 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(self._gitiles_fs.Stat(_REAL_DATA_DIR).version, 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'ec21e736a3f00db2c0580e3cf71d91951656caec') 15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) def testGetIdentity(self): 15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) # Test that file systems at different commits still have the same identity. 15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) other_gitiles_fs = GitilesFileSystem.Create(commit='abcdefghijklmnop') 15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertEqual(self._gitiles_fs.GetIdentity(), 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) other_gitiles_fs.GetIdentity()) 15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) yet_another_gitiles_fs = GitilesFileSystem.Create(branch='different') 15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) self.assertNotEqual(self._gitiles_fs.GetIdentity(), 16003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) yet_another_gitiles_fs.GetIdentity()) 16103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 16203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)if __name__ == '__main__': 16303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) unittest.main() 164