addon-sdk/source/bin/integration-scripts/integration-check

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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)

mercurial