Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 #!/usr/bin/env python
2 # This Source Code Form is subject to the terms of the Mozilla Public
3 # License, v. 2.0. If a copy of the MPL was not distributed with this
4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 import os
7 import signal
8 import threading
9 import urllib2, urllib
10 import zipfile
11 import tarfile
12 import subprocess
13 import optparse
14 import sys, re
15 #import win32api
18 class SDK:
19 def __init__(self):
20 try:
21 # Take the current working directory
22 self.default_path = os.getcwd()
23 if sys.platform == "win32":
24 self.mswindows = True
25 else:
26 self.mswindows = False
27 # Take the default home path of the user.
28 home = os.path.expanduser('~')
30 # The following are the parameters that can be used to pass a dynamic URL, a specific path or a binry. The binary is not used yet. It will be used in version 2.0
31 # If a dynamic path is to be mentioned, it should start with a '/'. For eg. "/Desktop"
32 parser = optparse.OptionParser()
33 parser.add_option('-u', '--url', dest = 'url', default = 'https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/addon-sdk-latest.zip')
34 parser.add_option('-p', '--path', dest = 'path', default = self.default_path)
35 parser.add_option('-b', '--binary', dest = 'binary')#, default='/Applications/Firefox.app')
36 (options, args) = parser.parse_args()
38 # Get the URL from the parameter
39 self.link = options.url
40 # Set the base path for the user. If the user supplies the path, use the home variable as well. Else, take the default path of this script as the installation directory.
41 if options.path!=self.default_path:
42 if self.mswindows:
43 self.base_path = home + str(options.path).strip() + '\\'
44 else:
45 self.base_path = home + str(options.path).strip() + '/'
46 else:
47 if self.mswindows:
48 self.base_path = str(options.path).strip() + '\\'
49 else:
50 self.base_path = str(options.path).strip() + '/'
51 assert ' ' not in self.base_path, "You cannot have a space in your home path. Please remove the space before you continue."
52 print('Your Base path is =' + self.base_path)
54 # This assignment is not used in this program. It will be used in version 2 of this script.
55 self.bin = options.binary
56 # if app or bin is empty, dont pass anything
58 # Search for the .zip file or tarball file in the URL.
59 i = self.link.rfind('/')
61 self.fname = self.link[i+1:]
62 z = re.search('zip',self.fname,re.I)
63 g = re.search('gz',self.fname,re.I)
64 if z:
65 print 'zip file present in the URL.'
66 self.zip = True
67 self.gz = False
68 elif g:
69 print 'gz file present in the URL'
70 self.gz = True
71 self.zip = False
72 else:
73 print 'zip/gz file not present. Check the URL.'
74 return
75 print("File name is =" + self.fname)
77 # Join the base path and the zip/tar file name to crate a complete Local file path.
78 self.fpath = self.base_path + self.fname
79 print('Your local file path will be=' + self.fpath)
80 except AssertionError, e:
81 print e.args[0]
82 sys.exit(1)
84 # Download function - to download the SDK from the URL to the local machine.
85 def download(self,url,fpath,fname):
86 try:
87 # Start the download
88 print("Downloading...Please be patient!")
89 urllib.urlretrieve(url,filename = fname)
90 print('Download was successful.')
91 except ValueError: # Handles broken URL errors.
92 print 'The URL is ether broken or the file does not exist. Please enter the correct URL.'
93 raise
94 except urllib2.URLError: # Handles URL errors
95 print '\nURL not correct. Check again!'
96 raise
98 # Function to extract the downloaded zipfile.
99 def extract(self, zipfilepath, extfile):
100 try:
101 # Timeout is set to 30 seconds.
102 timeout = 30
103 # Change the directory to the location of the zip file.
104 try:
105 os.chdir(zipfilepath)
106 except OSError:
107 # Will reach here if zip file doesnt exist
108 print 'O/S Error:' + zipfilepath + 'does not exist'
109 raise
111 # Get the folder name of Jetpack to get the exact version number.
112 if self.zip:
113 try:
114 f = zipfile.ZipFile(extfile, "r")
115 except IOError as (errno, strerror): # Handles file errors
116 print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
117 raise
118 list = f.namelist()[0]
119 temp_name = list.split('/')
120 print('Folder Name= ' +temp_name[0])
121 self.folder_name = temp_name[0]
122 elif self.gz:
123 try:
124 f = tarfile.open(extfile,'r')
125 except IOError as (errno, strerror): # Handles file errors
126 print "I/O error - Cannot perform extract operation: {1}".format(errno, strerror)
127 raise
128 list = f.getnames()[0]
129 temp_name = list.split('/')
130 print('Folder Name= ' +temp_name[0])
131 self.folder_name = temp_name[0]
133 print ('Starting to Extract...')
135 # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
136 # timeout, the process is killed.
137 kill_check = threading.Event()
139 if self.zip:
140 # Call the command to unzip the file.
141 if self.mswindows:
142 zipfile.ZipFile.extractall(f)
143 else:
144 p = subprocess.Popen('unzip '+extfile, stdout=subprocess.PIPE, shell=True)
145 pid = p.pid
146 elif self.gz:
147 # Call the command to untar the file.
148 if self.mswindows:
149 tarfile.TarFile.extractall(f)
150 else:
151 p = subprocess.Popen('tar -xf '+extfile, stdout=subprocess.PIPE, shell=True)
152 pid = p.pid
154 #No need to handle for windows because windows automatically replaces old files with new files. It does not ask the user(as it does in Mac/Unix)
155 if self.mswindows==False:
156 watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows ))
157 watch.start()
158 (stdout, stderr) = p.communicate()
159 watch.cancel() # if it's still waiting to run
160 success = not kill_check.isSet()
162 # Abort process if process fails.
163 if not success:
164 raise RuntimeError
165 kill_check.clear()
166 print('Extraction Successful.')
167 except RuntimeError:
168 print "Ending the program"
169 sys.exit(1)
170 except:
171 print "Error during file extraction: ", sys.exc_info()[0]
172 raise
174 # Function to run the cfx testall comands and to make sure the SDK is not broken.
175 def run_testall(self, home_path, folder_name):
176 try:
177 timeout = 500
179 self.new_dir = home_path + folder_name
180 try:
181 os.chdir(self.new_dir)
182 except OSError:
183 # Will reach here if the jetpack 0.X directory doesnt exist
184 print 'O/S Error: Jetpack directory does not exist at ' + self.new_dir
185 raise
186 print '\nStarting tests...'
187 # Timeout code. The subprocess.popen exeutes the command and the thread waits for a timeout. If the process does not finish within the mentioned-
188 # timeout, the process is killed.
189 kill_check = threading.Event()
191 # Set the path for the logs. They will be in the parent directory of the Jetpack SDK.
192 log_path = home_path + 'tests.log'
194 # Subprocess call to set up the jetpack environment and to start the tests. Also sends the output to a log file.
195 if self.bin != None:
196 if self.mswindows:
197 p = subprocess.Popen("bin\\activate && cfx testall -a firefox -b \"" + self.bin + "\"" , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
198 proc_handle = p._handle
199 (stdout,stderr) = p.communicate()
200 else:
201 p = subprocess.Popen('. bin/activate; cfx testall -a firefox -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
202 pid = p.pid
203 (stdout,stderr) = p.communicate()
204 elif self.bin == None:
205 if self.mswindows:
206 p=subprocess.Popen('bin\\activate && cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
207 proc_handle = p._handle
208 (stdout,stderr) = p.communicate()
209 else:
210 p = subprocess.Popen('. bin/activate; cfx testall -a firefox > '+log_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
211 pid = p.pid
212 (stdout,stderr) = p.communicate()
214 #Write the output to log file
215 f=open(log_path,"w")
216 f.write(stdout+stderr)
217 f.close()
219 #Watchdog for timeout process
220 if self.mswindows:
221 watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
222 else:
223 watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
224 watch.start()
225 watch.cancel() # if it's still waiting to run
226 success = not kill_check.isSet()
227 if not success:
228 raise RuntimeError
229 kill_check.clear()
231 if p.returncode!=0:
232 print('\nAll tests were not successful. Check the test-logs in the jetpack directory.')
233 result_sdk(home_path)
234 #sys.exit(1)
235 raise RuntimeError
236 else:
237 ret_code=result_sdk(home_path)
238 if ret_code==0:
239 print('\nAll tests were successful. Yay \o/ . Running a sample package test now...')
240 else:
241 print ('\nThere were errors during the tests.Take a look at logs')
242 raise RuntimeError
243 except RuntimeError:
244 print "Ending the program"
245 sys.exit(1)
246 except:
247 print "Error during the testall command execution:", sys.exc_info()[0]
248 raise
250 def package(self, example_dir):
251 try:
252 timeout = 30
254 print '\nNow Running packaging tests...'
256 kill_check = threading.Event()
258 # Set the path for the example logs. They will be in the parent directory of the Jetpack SDK.
259 exlog_path = example_dir + 'test-example.log'
260 # Subprocess call to test the sample example for packaging.
261 if self.bin!=None:
262 if self.mswindows:
263 p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}" -b \"" + self.bin + "\"' , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
264 proc_handle = p._handle
265 (stdout, stderr) = p.communicate()
266 else:
267 p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' -b ' + self.bin , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
268 pid = p.pid
269 (stdout, stderr) = p.communicate()
270 elif self.bin==None:
271 if self.mswindows:
272 p = subprocess.Popen('bin\\activate && cfx run --pkgdir examples\\reading-data --static-args="{\\"quitWhenDone\\":true}"', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
273 proc_handle = p._handle
274 (stdout, stderr) = p.communicate()
275 else:
276 p = subprocess.Popen('. bin/activate; cfx run --pkgdir examples/reading-data --static-args=\'{\"quitWhenDone\":true}\' ', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
277 pid = p.pid
278 (stdout, stderr) = p.communicate()
280 #Write the output to log file
281 f=open(exlog_path,"w")
282 f.write(stdout+stderr)
283 f.close()
285 #Watch dog for timeout process
286 if self.mswindows:
287 watch = threading.Timer(timeout, kill_process, args=(proc_handle, kill_check, self.mswindows))
288 else:
289 watch = threading.Timer(timeout, kill_process, args=(pid, kill_check, self.mswindows))
290 watch.start()
291 watch.cancel() # if it's still waiting to run
292 success = not kill_check.isSet()
293 if not success:
294 raise RuntimeError
295 kill_check.clear()
297 if p.returncode != 0:
298 print('\nSample tests were not executed correctly. Check the test-example log in jetpack diretory.')
299 result_example(example_dir)
300 raise RuntimeError
301 else:
302 ret_code=result_example(example_dir)
303 if ret_code==0:
304 print('\nAll tests pass. The SDK is working! Yay \o/')
305 else:
306 print ('\nTests passed with warning.Take a look at logs')
307 sys.exit(1)
309 except RuntimeError:
310 print "Ending program"
311 sys.exit(1)
312 except:
313 print "Error during running sample tests:", sys.exc_info()[0]
314 raise
316 def result_sdk(sdk_dir):
317 log_path = sdk_dir + 'tests.log'
318 print 'Results are logged at:' + log_path
319 try:
320 f = open(log_path,'r')
321 # Handles file errors
322 except IOError :
323 print 'I/O error - Cannot open test log at ' + log_path
324 raise
326 for line in reversed(open(log_path).readlines()):
327 if line.strip()=='FAIL':
328 print ('\nOverall result - FAIL. Look at the test log at '+log_path)
329 return 1
330 return 0
333 def result_example(sdk_dir):
334 exlog_path = sdk_dir + 'test-example.log'
335 print 'Sample test results are logged at:' + exlog_path
336 try:
337 f = open(exlog_path,'r')
338 # Handles file errors
339 except IOError :
340 print 'I/O error - Cannot open sample test log at ' + exlog_path
341 raise
343 #Read the file in reverse and check for the keyword 'FAIL'.
344 for line in reversed(open(exlog_path).readlines()):
345 if line.strip()=='FAIL':
346 print ('\nOverall result for Sample tests - FAIL. Look at the test log at '+exlog_path)
347 return 1
348 return 0
350 def kill_process(process, kill_check, mswindows):
351 print '\nProcess Timedout. Killing the process. Please Rerun this script.'
352 if mswindows:
353 win32api.TerminateProcess(process, -1)
354 else:
355 os.kill(process, signal.SIGKILL)
356 kill_check.set()# tell the main routine to kill. Used SIGKILL to hard kill the process.
357 return
359 if __name__ == "__main__":
360 obj = SDK()
361 obj.download(obj.link,obj.fpath,obj.fname)
362 obj.extract(obj.base_path,obj.fname)
363 obj.run_testall(obj.base_path,obj.folder_name)
364 obj.package(obj.base_path)