[Extensions] Fix crash in developerPrivate.inspect API
[chromium-blink-merge.git] / native_client_sdk / src / build_tools / tests / sdktools_test.py
blob71891f68c9196e576a86ce59060ad75ab4a3dbce
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium 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 import os
7 import re
8 import subprocess
9 import sys
10 import tarfile
11 import tempfile
12 import test_server
13 import unittest
14 import zipfile
16 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
17 BUILD_TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
18 TOOLS_DIR = os.path.join(os.path.dirname(BUILD_TOOLS_DIR), 'tools')
20 sys.path.extend([BUILD_TOOLS_DIR, TOOLS_DIR])
21 import getos
22 import manifest_util
23 import oshelpers
26 MANIFEST_BASENAME = 'naclsdk_manifest2.json'
28 # Attribute '' defined outside __init__
29 # pylint: disable=W0201
31 class SdkToolsTestCase(unittest.TestCase):
32 def tearDown(self):
33 if self.server:
34 self.server.Shutdown()
35 oshelpers.Remove(['-rf', self.basedir])
37 def SetupDefault(self):
38 self.SetupWithBaseDirPrefix('sdktools')
40 def SetupWithBaseDirPrefix(self, basedir_prefix, tmpdir=None):
41 self.basedir = tempfile.mkdtemp(prefix=basedir_prefix, dir=tmpdir)
42 self.cache_dir = os.path.join(self.basedir, 'nacl_sdk', 'sdk_cache')
43 # We have to make sure that we build our updaters with a version that is at
44 # least as large as the version in the sdk_tools bundle. If not, update
45 # tests may fail because the "current" version (according to the sdk_cache)
46 # is greater than the version we are attempting to update to.
47 self.current_revision = self._GetSdkToolsBundleRevision()
48 self._BuildUpdater(self.basedir, self.current_revision)
49 self.manifest = self._ReadCacheManifest()
50 self.sdk_tools_bundle = self.manifest.GetBundle('sdk_tools')
51 self.server = test_server.LocalHTTPServer(self.basedir)
53 def _GetSdkToolsBundleRevision(self):
54 """Get the sdk_tools bundle revision.
55 We get this from the checked-in path; this is the same file that
56 build_updater uses to specify the current revision of sdk_tools."""
58 manifest_filename = os.path.join(BUILD_TOOLS_DIR, 'json',
59 'naclsdk_manifest0.json')
60 manifest = manifest_util.SDKManifest()
61 manifest.LoadDataFromString(open(manifest_filename, 'r').read())
62 return manifest.GetBundle('sdk_tools').revision
64 def _WriteConfig(self, config_data):
65 config_filename = os.path.join(self.cache_dir, 'naclsdk_config.json')
66 with open(config_filename, 'w') as stream:
67 stream.write(config_data)
69 def _WriteCacheManifest(self, manifest):
70 """Write the manifest at nacl_sdk/sdk_cache.
72 This is useful for faking having installed a bundle.
73 """
74 manifest_filename = os.path.join(self.cache_dir, MANIFEST_BASENAME)
75 with open(manifest_filename, 'w') as stream:
76 stream.write(manifest.GetDataAsString())
78 def _ReadCacheManifest(self):
79 """Read the manifest at nacl_sdk/sdk_cache."""
80 manifest_filename = os.path.join(self.cache_dir, MANIFEST_BASENAME)
81 manifest = manifest_util.SDKManifest()
82 with open(manifest_filename) as stream:
83 manifest.LoadDataFromString(stream.read())
84 return manifest
86 def _WriteManifest(self):
87 with open(os.path.join(self.basedir, MANIFEST_BASENAME), 'w') as stream:
88 stream.write(self.manifest.GetDataAsString())
90 def _BuildUpdater(self, out_dir, revision=None):
91 build_updater_py = os.path.join(BUILD_TOOLS_DIR, 'build_updater.py')
92 cmd = [sys.executable, build_updater_py, '-o', out_dir]
93 if revision:
94 cmd.extend(['-r', str(revision)])
96 process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
97 _, _ = process.communicate()
98 self.assertEqual(process.returncode, 0)
100 def _BuildUpdaterArchive(self, rel_path, revision):
101 """Build a new sdk_tools bundle.
103 Args:
104 rel_path: The relative path to build the updater.
105 revision: The revision number to give to this bundle.
106 Returns:
107 A manifest_util.Archive() that points to this new bundle on the local
108 server.
110 self._BuildUpdater(os.path.join(self.basedir, rel_path), revision)
112 new_sdk_tools_tgz = os.path.join(self.basedir, rel_path, 'sdk_tools.tgz')
113 with open(new_sdk_tools_tgz, 'rb') as sdk_tools_stream:
114 archive_sha1, archive_size = manifest_util.DownloadAndComputeHash(
115 sdk_tools_stream)
117 archive = manifest_util.Archive('all')
118 archive.url = self.server.GetURL('%s/sdk_tools.tgz' % (rel_path,))
119 archive.checksum = archive_sha1
120 archive.size = archive_size
121 return archive
123 def _Run(self, args, expect_error=False):
124 naclsdk_shell_script = os.path.join(self.basedir, 'nacl_sdk', 'naclsdk')
125 if getos.GetPlatform() == 'win':
126 naclsdk_shell_script += '.bat'
127 cmd = [naclsdk_shell_script]
128 cmd.extend(args)
129 cmd.extend(['-U', self.server.GetURL(MANIFEST_BASENAME)])
130 process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
131 stdout, _ = process.communicate()
133 if ((expect_error and process.returncode == 0) or
134 (not expect_error and process.returncode != 0)):
135 self.fail('Error running nacl_sdk:\n"""\n%s\n"""' % stdout)
137 return stdout
139 def _RunAndExtractRevision(self):
140 stdout = self._Run(['version'])
141 match = re.search('version r(\d+)', stdout)
142 self.assertTrue(match is not None)
143 return int(match.group(1))
146 class TestSdkTools(SdkToolsTestCase):
147 def testPathHasSpaces(self):
148 """Test that running naclsdk from a path with spaces works."""
149 self.SetupWithBaseDirPrefix('sdk tools')
150 self._WriteManifest()
151 self._RunAndExtractRevision()
154 class TestBuildUpdater(SdkToolsTestCase):
155 def setUp(self):
156 self.SetupDefault()
158 def testUpdaterPathsAreSane(self):
159 """Test that the paths to files in nacl_sdk.zip and sdktools.tgz are
160 relative to the output directory."""
161 nacl_sdk_zip_path = os.path.join(self.basedir, 'nacl_sdk.zip')
162 zip_stream = zipfile.ZipFile(nacl_sdk_zip_path, 'r')
163 try:
164 self.assertTrue(all(name.startswith('nacl_sdk')
165 for name in zip_stream.namelist()))
166 finally:
167 zip_stream.close()
169 # sdktools.tgz has no built-in directories to look for. Instead, just look
170 # for some files that must be there.
171 sdktools_tgz_path = os.path.join(self.basedir, 'sdk_tools.tgz')
172 tar_stream = tarfile.open(sdktools_tgz_path, 'r:gz')
173 try:
174 names = [m.name for m in tar_stream.getmembers()]
175 self.assertTrue('LICENSE' in names)
176 self.assertTrue('sdk_update.py' in names)
177 finally:
178 tar_stream.close()
181 class TestAutoUpdateSdkTools(SdkToolsTestCase):
182 def setUp(self):
183 self.SetupDefault()
185 def testNoUpdate(self):
186 """Test that running naclsdk with current revision does nothing."""
187 self._WriteManifest()
188 revision = self._RunAndExtractRevision()
189 self.assertEqual(revision, self.current_revision)
191 def testUpdate(self):
192 """Test that running naclsdk with a new revision will auto-update."""
193 new_revision = self.current_revision + 1
194 archive = self._BuildUpdaterArchive('new', new_revision)
195 self.sdk_tools_bundle.RemoveAllArchivesForHostOS(archive.host_os)
196 self.sdk_tools_bundle.AddArchive(archive)
197 self.sdk_tools_bundle.revision = new_revision
198 self._WriteManifest()
200 revision = self._RunAndExtractRevision()
201 self.assertEqual(revision, new_revision)
203 def testManualUpdateIsIgnored(self):
204 """Test that attempting to manually update sdk_tools is ignored.
206 If the sdk_tools bundle was updated normally (i.e. the old way), it would
207 leave a sdk_tools_update folder that would then be copied over on a
208 subsequent run. This test ensures that there is no folder made.
210 new_revision = self.current_revision + 1
211 archive = self._BuildUpdaterArchive('new', new_revision)
212 self.sdk_tools_bundle.RemoveAllArchivesForHostOS(archive.host_os)
213 self.sdk_tools_bundle.AddArchive(archive)
214 self.sdk_tools_bundle.revision = new_revision
215 self._WriteManifest()
217 sdk_tools_update_dir = os.path.join(self.basedir, 'nacl_sdk',
218 'sdk_tools_update')
219 self.assertFalse(os.path.exists(sdk_tools_update_dir))
220 stdout = self._Run(['update', 'sdk_tools'])
221 self.assertTrue(stdout.find('Ignoring manual update request.') != -1)
222 self.assertFalse(os.path.exists(sdk_tools_update_dir))
224 def testHelpCommand(self):
225 """Running naclsdk with -h should work.
227 This is a regression test for a bug where the auto-updater would remove the
228 sdk_tools directory when running "naclsdk -h".
230 self._WriteManifest()
231 self._Run(['-h'])
234 class TestAutoUpdateSdkToolsDifferentFilesystem(TestAutoUpdateSdkTools):
235 def setUp(self):
236 # On Linux (on my machine at least), /tmp is a different filesystem than
237 # the current directory. os.rename fails when the source and destination
238 # are on different filesystems. Test that case here.
239 self.SetupWithBaseDirPrefix('sdktools', tmpdir='.')
242 if __name__ == '__main__':
243 sys.exit(unittest.main())