summaryrefslogtreecommitdiffstats
path: root/src/boost/tools/build/test/MockToolset.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/tools/build/test/MockToolset.py')
-rwxr-xr-xsrc/boost/tools/build/test/MockToolset.py267
1 files changed, 267 insertions, 0 deletions
diff --git a/src/boost/tools/build/test/MockToolset.py b/src/boost/tools/build/test/MockToolset.py
new file mode 100755
index 000000000..834a56b0f
--- /dev/null
+++ b/src/boost/tools/build/test/MockToolset.py
@@ -0,0 +1,267 @@
+#!/usr/bin/python
+
+# Copyright (C) 2013 Steven Watanabe
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE.txt or copy at
+# https://www.bfgroup.xyz/b2/LICENSE.txt)
+
+import sys
+
+def create(t):
+ t.write('''mockinfo.py''', '''
+from __future__ import print_function
+import re
+import optparse
+import os
+
+parser = optparse.OptionParser()
+parser.add_option('-o', dest="output_file")
+parser.add_option('-x', dest="language")
+parser.add_option('-c', dest="compile", action="store_true")
+parser.add_option('-I', dest="includes", action="append")
+parser.add_option('-D', dest="defines", action="append")
+parser.add_option('-L', dest="library_path", action="append")
+parser.add_option('--dll', dest="dll", action="store_true")
+parser.add_option('--archive', dest="archive", action="store_true")
+parser.add_option('--static-lib', dest="static_libraries", action="append")
+parser.add_option('--shared-lib', dest="shared_libraries", action="append")
+
+cwd = os.environ["JAM_CWD"]
+
+class MockInfo(object):
+ def __init__(self, verbose=False):
+ self.files = dict()
+ self.commands = list()
+ self.verbose = verbose
+ def source_file(self, name, pattern):
+ self.files[name] = pattern
+ def action(self, command, status=0):
+ if isinstance(command, str):
+ command = command.split()
+ self.commands.append((command, status))
+ def check(self, command):
+ print("Testing command", command)
+ for (raw, status) in self.commands:
+ if self.matches(raw, command):
+ return status
+ def matches(self, raw, command):
+ (expected_options, expected_args) = parser.parse_args(raw)
+ options = command[0]
+ input_files = list(command[1])
+ if self.verbose:
+ print(" - matching against", (expected_options, expected_args))
+ if len(expected_args) != len(input_files):
+ if self.verbose:
+ print(" argument list sizes differ")
+ return False
+ for arg in expected_args:
+ if arg.startswith('$'):
+ fileid = arg[1:]
+ pattern = self.files[fileid] if fileid in self.files else fileid
+ matching_file = None
+ for input_file in input_files:
+ with open(input_file, 'r') as f:
+ contents = f.read()
+ if pattern == contents:
+ matching_file = input_file
+ break
+ if matching_file is not None:
+ input_files.remove(matching_file)
+ else:
+ if self.verbose:
+ print(" Failed to match input file contents: %s" % arg)
+ return False
+ else:
+ if arg in input_files:
+ input_files.remove(arg)
+ else:
+ if self.verbose:
+ print(" Failed to match input file: %s" % arg)
+ return False
+
+ if options.language != expected_options.language:
+ if self.verbose:
+ print(" Failed to match -c")
+ return False
+
+ if options.compile != expected_options.compile:
+ if self.verbose:
+ print(" Failed to match -x")
+ return False
+
+ # Normalize a path for comparison purposes
+ def adjust_path(p):
+ return os.path.normcase(os.path.normpath(os.path.join(cwd, p)))
+
+ # order matters
+ if options.includes is None:
+ options.includes = []
+ if expected_options.includes is None:
+ expected_options.includes = []
+ if list(map(adjust_path, options.includes)) != \
+ list(map(adjust_path, expected_options.includes)):
+ if self.verbose:
+ print(" Failed to match -I ", list(map(adjust_path, options.includes)), \
+ " != ", list(map(adjust_path, expected_options.includes)))
+ return False
+
+ if options.defines is None:
+ options.defines = []
+ if expected_options.defines is None:
+ expected_options.defines = []
+ if options.defines != expected_options.defines:
+ if self.verbose:
+ print(" Failed to match -I ", options.defines, \
+ " != ", expected_options.defines)
+ return False
+
+ if options.library_path is None:
+ options.library_path = []
+ if expected_options.library_path is None:
+ expected_options.library_path = []
+ if list(map(adjust_path, options.library_path)) != \
+ list(map(adjust_path, expected_options.library_path)):
+ if self.verbose:
+ print(" Failed to match -L ", list(map(adjust_path, options.library_path)), \
+ " != ", list(map(adjust_path, expected_options.library_path)))
+ return False
+
+ if options.static_libraries != expected_options.static_libraries:
+ if self.verbose:
+ print(" Failed to match --static-lib")
+ return False
+
+ if options.shared_libraries != expected_options.shared_libraries:
+ if self.verbose:
+ print(" Failed to match --shared-lib")
+ return False
+
+ if options.dll != expected_options.dll:
+ if self.verbose:
+ print(" Failed to match --dll")
+ return False
+
+ if options.archive != expected_options.archive:
+ if self.verbose:
+ print(" Failed to match --archive")
+ return False
+
+ # The output must be handled after everything else
+ # is validated
+ if expected_options.output_file is not None:
+ if options.output_file is not None:
+ if expected_options.output_file.startswith('$'):
+ fileid = expected_options.output_file[1:]
+ if fileid not in self.files:
+ self.files[fileid] = fileid
+ else:
+ assert(self.files[fileid] == fileid)
+ with open(options.output_file, 'w') as output:
+ output.write(fileid)
+ else:
+ if self.verbose:
+ print("Failed to match -o")
+ return False
+ elif options.output_file is not None:
+ if self.verbose:
+ print("Failed to match -o")
+ return False
+
+ # if we've gotten here, then everything matched
+ if self.verbose:
+ print(" Matched")
+ return True
+''')
+
+ t.write('mock.py', '''
+from __future__ import print_function
+import mockinfo
+import markup
+import sys
+
+status = markup.info.check(mockinfo.parser.parse_args())
+if status is not None:
+ exit(status)
+else:
+ print("Unrecognized command: " + ' '.join(sys.argv))
+ exit(1)
+''')
+
+ t.write('mock.jam', '''
+import feature ;
+import toolset ;
+import path ;
+import modules ;
+import common ;
+import type ;
+
+.python-cmd = "\"%s\"" ;
+
+# Behave the same as gcc on Windows, because that's what
+# the test system expects
+type.set-generated-target-prefix SHARED_LIB : <toolset>mock <target-os>windows : lib ;
+type.set-generated-target-suffix STATIC_LIB : <toolset>mock <target-os>windows : a ;
+
+rule init ( )
+{
+ local here = [ path.make [ modules.binding $(__name__) ] ] ;
+ here = [ path.native [ path.root [ path.parent $(here) ] [ path.pwd ] ] ] ;
+ .config-cmd = [ common.variable-setting-command JAM_CWD : $(here) ] $(.python-cmd) -B ;
+}
+
+feature.extend toolset : mock ;
+
+generators.register-c-compiler mock.compile.c++ : CPP : OBJ : <toolset>mock ;
+generators.register-c-compiler mock.compile.c : C : OBJ : <toolset>mock ;
+
+generators.register-linker mock.link : LIB OBJ : EXE : <toolset>mock ;
+generators.register-linker mock.link.dll : LIB OBJ : SHARED_LIB : <toolset>mock ;
+generators.register-archiver mock.archive : OBJ : STATIC_LIB : <toolset>mock ;
+
+toolset.flags mock.compile OPTIONS <link>shared : -fPIC ;
+toolset.flags mock.compile INCLUDES : <include> ;
+toolset.flags mock.compile DEFINES : <define> ;
+
+actions compile.c
+{
+ $(.config-cmd) mock.py -c -x c -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)"
+}
+
+actions compile.c++
+{
+ $(.config-cmd) mock.py -c -x c++ -I"$(INCLUDES)" -D"$(DEFINES)" "$(>)" -o "$(<)"
+}
+
+toolset.flags mock.link USER_OPTIONS <linkflags> ;
+toolset.flags mock.link FINDLIBS-STATIC <find-static-library> ;
+toolset.flags mock.link FINDLIBS-SHARED <find-shared-library> ;
+toolset.flags mock.link LINK_PATH <library-path> ;
+toolset.flags mock.link LIBRARIES <library-file> ;
+
+actions link
+{
+ $(.config-cmd) mock.py "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
+}
+
+actions archive
+{
+ $(.config-cmd) mock.py --archive "$(>)" -o "$(<)" $(USER_OPTIONS)
+}
+
+actions link.dll
+{
+ $(.config-cmd) mock.py --dll "$(>)" -o "$(<)" $(USER_OPTIONS) -L"$(LINK_PATH)" --static-lib=$(FINDLIBS-STATIC) --shared-lib=$(FINDLIBS-SHARED)
+}
+
+''' % sys.executable.replace('\\', '\\\\'))
+
+def set_expected(t, markup):
+ verbose = "True" if t.verbose else "False"
+ t.write('markup.py', '''
+import mockinfo
+info = mockinfo.MockInfo(%s)
+def source_file(name, contents):
+ info.source_file(name, contents)
+def action(command, status=0):
+ info.action(command, status)
+''' % (verbose) + markup)