| #!/usr/bin/env python |
| # |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| # You can obtain one at http://mozilla.org/MPL/2.0/. |
| # |
| |
| import os |
| import sys |
| import tempfile |
| |
| from subprocess import call |
| from shutil import rmtree |
| |
| import logging |
| import unittest |
| |
| |
| def banner(): |
| """ |
| Display interpreter and system info for the test env |
| """ |
| print '*' * 75 |
| cmd = os.path.basename(__file__) |
| print "%s: python version is %s" % (cmd, sys.version) |
| print '*' * 75 |
| |
| |
| def myopts(vals): |
| """ |
| Storage for extra command line args passed. |
| |
| Returns: |
| hash - argparse::Namespace object values |
| """ |
| |
| if not hasattr(myopts, 'vals'): |
| if 'argparse' in sys.modules: |
| tmp = { } # key existance enables unittest module debug |
| else: |
| tmp = { 'debug': False, 'verbose': False } |
| |
| for k in dir(vals): |
| if k[0:1] == '_': |
| continue |
| tmp[k] = getattr(vals, k) |
| myopts.vals = tmp |
| |
| return myopts.vals |
| |
| |
| def path2posix(src): |
| """ |
| Normalize directory path syntax |
| |
| Keyword arguments: |
| src - path to normalize |
| |
| Returns: |
| scalar - a file path with drive separators and windows slashes removed |
| |
| Todo: |
| move to {build,config,tools,toolkit}/python for use in a library |
| """ |
| |
| ## (drive, tail) = os.path.splitdrive(src) |
| ## Support path testing on all platforms |
| drive = '' |
| winpath = src.find(':') |
| if -1 != winpath and 10 > winpath: |
| (drive, tail) = src.split(':', 1) |
| |
| if drive: |
| todo = [ '', drive.rstrip(':').lstrip('/').lstrip('\\') ] |
| todo.extend( tail.lstrip('/').lstrip('\\').split('\\') ) # c:\a => [a] |
| else: # os.name == 'posix' |
| todo = src.split('\\') |
| |
| dst = '/'.join(todo) |
| return dst |
| |
| |
| def checkMkdir(work, debug=False): |
| """ |
| Verify arg permutations for directory mutex creation. |
| |
| Keyword arguments: |
| None |
| |
| Returns: |
| Exception on error |
| |
| Note: |
| Exception() rather than self.assertTrue() is used in this test |
| function to enable scatch cleanup on test exit/failure conditions. |
| Not guaranteed by python closures on early exit. |
| """ |
| |
| logging.debug("Testing: checkMkdir") |
| |
| # On Windows, don't convert paths to POSIX |
| skipposix = sys.platform == "win32" |
| if skipposix: |
| path = os.path.abspath(__file__) |
| dirname_fun = os.path.dirname |
| else: |
| path = path2posix(os.path.abspath(__file__)) |
| import posixpath |
| dirname_fun = posixpath.dirname |
| |
| src = dirname_fun(path) |
| # root is 5 directories up from path |
| root = reduce(lambda x, _: dirname_fun(x), xrange(5), path) |
| |
| rootP = path2posix(root) |
| srcP = path2posix(src) |
| workP = path2posix(work) |
| |
| # C:\foo -vs- /c/foo |
| # [0] command paths use /c/foo |
| # [1] os.path.exists() on mingw() requires C:\ |
| paths = [ |
| "mkdir_bycall", # function generated |
| "mkdir_bydep", # explicit dependency |
| "mkdir_bygen", # by GENERATED_DIRS macro |
| ] |
| |
| ## Use make from the parent "make check" call when available |
| cmd = { 'make': 'make' } |
| shell0 = os.environ.get('MAKE') |
| if shell0: |
| shell = os.path.splitext(shell0)[0] # strip: .exe, .py |
| if -1 != shell.find('make'): |
| print "MAKE COMMAND FOUND: %s" % (shell0) |
| cmd['make'] = shell0 if skipposix else path2posix(shell0) |
| |
| args = [] |
| args.append('%s' % (cmd['make'])) |
| args.append('-C %s' % (work if skipposix else workP)) |
| args.append("-f %s/testor.tmpl" % (src if skipposix else srcP)) |
| args.append('topsrcdir=%s' % (root if skipposix else rootP)) |
| args.append('deps_mkdir_bycall=%s' % paths[0]) |
| args.append('deps_mkdir_bydep=%s' % paths[1]) |
| args.append('deps_mkdir_bygen=%s' % paths[2]) |
| args.append('checkup') # target |
| |
| # Call will fail on mingw with output redirected ?!? |
| if debug: |
| pass |
| if False: # if not debug: |
| args.append('>/dev/null') |
| |
| cmd = '%s' % (' '.join(args)) |
| logging.debug("Running: %s" % (cmd)) |
| rc = call(cmd, shell=True) |
| if rc: |
| raise Exception("make failed ($?=%s): cmd=%s" % (rc, cmd)) |
| |
| for i in paths: |
| path = os.path.join(work, i) |
| logging.debug("Did testing mkdir(%s) succeed?" % (path)) |
| if not os.path.exists(path): |
| raise Exception("Test path %s does not exist" % (path)) |
| |
| |
| def parseargs(): |
| """ |
| Support additional command line arguments for testing |
| |
| Returns: |
| hash - arguments of interested parsed from the command line |
| """ |
| |
| opts = None |
| try: |
| import argparse2 |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--debug', |
| action="store_true", |
| default=False, |
| help='Enable debug mode') |
| # Cannot overload verbose, Verbose: False enables debugging |
| parser.add_argument('--verbose', |
| action="store_true", |
| default=False, |
| help='Enable verbose mode') |
| parser.add_argument('unittest_args', |
| nargs='*' |
| # help='Slurp/pass remaining args to unittest' |
| ) |
| opts = parser.parse_args() |
| |
| except ImportError: |
| pass |
| |
| return opts |
| |
| |
| class TestMakeLogic(unittest.TestCase): |
| """ |
| Test suite used to validate makefile library rules and macros |
| """ |
| |
| def setUp(self): |
| opts = myopts(None) # NameSpace object not hash |
| self.debug = opts['debug'] |
| self.verbose = opts['verbose'] |
| |
| if self.debug: |
| logging.basicConfig(level=logging.DEBUG) |
| |
| if self.verbose: |
| print |
| print "ENVIRONMENT DUMP:" |
| print '=' * 75 |
| for k,v in os.environ.items(): |
| print "env{%s} => %s" % (k, v) |
| print |
| |
| |
| def test_path2posix(self): |
| |
| todo = { |
| '/dev/null' : '/dev/null', |
| 'A:\\a\\b\\c' : '/A/a/b/c', |
| 'B:/x/y' : '/B/x/y', |
| 'C:/x\\y/z' : '/C/x/y/z', |
| '//FOO/bar/tans': '//FOO/bar/tans', |
| '//X\\a/b\\c/d' : '//X/a/b/c/d', |
| '\\c:mozilla\\sandbox': '/c/mozilla/sandbox', |
| } |
| |
| for val,exp in todo.items(): |
| found = path2posix(val) |
| tst = "posix2path(%s): %s != %s)" % (val, exp, found) |
| self.assertEqual(exp, found, "%s: invalid path detected" % (tst)) |
| |
| |
| def test_mkdir(self): |
| """ |
| Verify directory creation rules and macros |
| """ |
| |
| failed = True |
| |
| # Exception handling is used to cleanup scratch space on error |
| try: |
| work = tempfile.mkdtemp() |
| checkMkdir(work, self.debug) |
| failed = False |
| finally: |
| if os.path.exists(work): |
| rmtree(work) |
| |
| self.assertFalse(failed, "Unit test failure detected") |
| |
| |
| if __name__ == '__main__': |
| banner() |
| opts = parseargs() |
| myopts(opts) |
| |
| if opts: |
| if hasattr(opts, 'unittest_args'): |
| sys.argv[1:] = opts.unittest_args |
| else: |
| sys.argv[1:] = [] |
| |
| unittest.main() |