diff options
author | William Deegan <bill@baddogconsulting.com> | 2019-04-22 16:37:38 (GMT) |
---|---|---|
committer | William Deegan <bill@baddogconsulting.com> | 2019-04-22 16:37:38 (GMT) |
commit | b774c48825febe7261ef4974f64218c243ca347b (patch) | |
tree | 42a8d1003b4acaaf5b0430e015983fc4f3371e06 | |
parent | 5728acaff9b6bc9466bc6f1e5ae8280964443ce1 (diff) | |
download | SCons-b774c48825febe7261ef4974f64218c243ca347b.zip SCons-b774c48825febe7261ef4974f64218c243ca347b.tar.gz SCons-b774c48825febe7261ef4974f64218c243ca347b.tar.bz2 |
changes to unit test to avoid hitting the filesystem
-rw-r--r-- | src/engine/SCons/Tool/JavaCommon.py | 115 | ||||
-rw-r--r-- | src/engine/SCons/Tool/JavaCommonTests.py | 116 |
2 files changed, 136 insertions, 95 deletions
diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index c77ace6..f1c1b4f 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -42,6 +42,33 @@ default_java_version = '1.4' # anonymous inner class parsing. scopeStateVersions = ('1.8') +# Glob patterns for use in finding where the JDK is. +# These are pairs, *dir_glob used in the general case, +# *version_dir_glob if matching only a specific version. +# For now only used for Windows. +java_win32_dir_glob = 'C:/Program Files*/Java/jdk*/bin' +# On windows, since Java 9, there is a dash between 'jdk' and the version +# string that wasn't there before. this glob should catch either way. +java_win32_version_dir_glob = 'C:/Program Files*/Java/jdk*%s*/bin' + +# Glob patterns for use in finding where the JDK headers are. +# These are pairs, *dir_glob used in the general case, +# *version_dir_glob if matching only a specific version. +java_macos_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Headers/' +java_macos_version_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/' + +java_linux_include_dirs_glob = [ + '/usr/lib/jvm/default-java/include', + '/usr/lib/jvm/java-*/include' +] +# Need to match path like below (from Centos 7) +# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include/ +java_linux_version_include_dirs_glob = [ + '/usr/lib/jvm/java-*-sun-%s*/include', + '/usr/lib/jvm/java-%s*-openjdk*/include', + '/usr/java/jdk%s*/include' +] + if java_parsing: # Parse Java files for class names. # @@ -64,14 +91,15 @@ if java_parsing: r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' + r'/\*|\*/|\[\])') + class OuterState(object): """The initial state for parsing a Java file for classes, interfaces, and anonymous inner classes.""" + def __init__(self, version=default_java_version): if not version in ('1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', '1.8', '5', '6', '9.0', '10.0', '11.0', '12.0'): - msg = "Java version %s not supported" % version raise NotImplementedError(msg) @@ -131,15 +159,15 @@ if java_parsing: def closeBracket(self): self.brackets = self.brackets - 1 if len(self.stackBrackets) and \ - self.brackets == self.stackBrackets[-1]: + self.brackets == self.stackBrackets[-1]: self.listOutputs.append('$'.join(self.listClasses)) self.localClasses.pop() self.listClasses.pop() self.anonStacksStack.pop() self.stackBrackets.pop() if len(self.stackAnonClassBrackets) and \ - self.brackets == self.stackAnonClassBrackets[-1] and \ - self.version not in scopeStateVersions: + self.brackets == self.stackAnonClassBrackets[-1] and \ + self.version not in scopeStateVersions: self._getAnonStack().pop() self.stackAnonClassBrackets.pop() @@ -152,13 +180,13 @@ if java_parsing: self.openBracket() elif token == '}': self.closeBracket() - elif token in [ '"', "'" ]: + elif token in ['"', "'"]: return IgnoreState(token, self) elif token == "new": # anonymous inner class if len(self.listClasses) > 0: return self.__getAnonClassState() - return self.__getSkipState() # Skip the class name + return self.__getSkipState() # Skip the class name elif token in ['class', 'interface', 'enum']: if len(self.listClasses) == 0: self.nextAnon = 1 @@ -193,11 +221,13 @@ if java_parsing: def setPackage(self, package): self.package = package + class ScopeState(object): """ A state that parses code within a scope normally, within the confines of a scope. """ + def __init__(self, old_state): self.outer_state = old_state.outer_state self.old_state = old_state @@ -259,13 +289,16 @@ if java_parsing: return self.__getSkipState() return self + class AnonClassState(object): """A state that looks for anonymous inner classes.""" + def __init__(self, old_state): # outer_state is always an instance of OuterState self.outer_state = old_state.outer_state self.old_state = old_state self.brace_level = 0 + def parseToken(self, token): # This is an anonymous class if and only if the next # non-whitespace token is a bracket. Everything between @@ -293,26 +326,32 @@ if java_parsing: if token == '{': self.outer_state.addAnonClass() if self.outer_state.version in scopeStateVersions: - return ScopeState(old_state = self.old_state).parseToken(token) + return ScopeState(old_state=self.old_state).parseToken(token) return self.old_state.parseToken(token) + class SkipState(object): """A state that will skip a specified number of tokens before reverting to the previous state.""" + def __init__(self, tokens_to_skip, old_state): self.tokens_to_skip = tokens_to_skip self.old_state = old_state + def parseToken(self, token): self.tokens_to_skip = self.tokens_to_skip - 1 if self.tokens_to_skip < 1: return self.old_state return self + class ClassState(object): """A state we go into when we hit a class or interface keyword.""" + def __init__(self, outer_state): # outer_state is always an instance of OuterState self.outer_state = outer_state + def parseToken(self, token): # the next non-whitespace token should be the name of the class if token == '\n': @@ -322,12 +361,12 @@ if java_parsing: # 'Foo$1Inner' # https://github.com/SCons/scons/issues/2087 if self.outer_state.localClasses and \ - self.outer_state.stackBrackets[-1] > \ - self.outer_state.stackBrackets[-2]+1: + self.outer_state.stackBrackets[-1] > \ + self.outer_state.stackBrackets[-2] + 1: locals = self.outer_state.localClasses[-1] try: idx = locals[token] - locals[token] = locals[token]+1 + locals[token] = locals[token] + 1 except KeyError: locals[token] = 1 token = str(locals[token]) + token @@ -336,32 +375,40 @@ if java_parsing: self.outer_state.anonStacksStack.append([0]) return self.outer_state + class IgnoreState(object): """A state that will ignore all tokens until it gets to a specified token.""" + def __init__(self, ignore_until, old_state): self.ignore_until = ignore_until self.old_state = old_state + def parseToken(self, token): if self.ignore_until == token: return self.old_state return self + class PackageState(object): """The state we enter when we encounter the package keyword. We assume the next token will be the package name.""" + def __init__(self, outer_state): # outer_state is always an instance of OuterState self.outer_state = outer_state + def parseToken(self, token): self.outer_state.setPackage(token) return self.outer_state + def parse_java_file(fn, version=default_java_version): with open(fn, 'r') as f: data = f.read() return parse_java(data, version) + def parse_java(contents, version=default_java_version, trace=None): """Parse a .java file and return a double of package directory, plus a list of .class files that compiling that .java file will @@ -395,15 +442,6 @@ else: return os.path.split(fn) -# Glob patterns for use in finding where the JDK is. -# These are pairs, *dir_glob used in the general case, -# *version_dir_glob if matching only a specific version. -# For now only used for Windows. -java_win32_dir_glob = 'C:/Program Files*/Java/jdk*/bin' -# On windows, since Java 9, there is a dash between 'jdk' and the version -# string that wasn't there before. this glob should catch either way. -java_win32_version_dir_glob = 'C:/Program Files*/Java/jdk*%s*/bin' - def get_java_install_dirs(platform, version=None): """ Find the java jdk installation directories. @@ -419,7 +457,7 @@ def get_java_install_dirs(platform, version=None): paths = [] if platform == 'win32': if version: - paths = glob.glob(java_win32_version_dir_glob%version) + paths = glob.glob(java_win32_version_dir_glob % version) else: paths = glob.glob(java_win32_dir_glob) else: @@ -429,24 +467,6 @@ def get_java_install_dirs(platform, version=None): return sorted(paths) -# Glob patterns for use in finding where the JDK headers are. -# These are pairs, *dir_glob used in the general case, -# *version_dir_glob if matching only a specific version. -java_macos_include_dir = '/System/Library/Frameworks/JavaVM.framework/Headers/' -java_macos_version_include_dir = '/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/' - -java_linux_include_dirs = [ - '/usr/lib/jvm/default-java/include', - '/usr/lib/jvm/java-*/include' -] -# Need to match path like below (from Centos 7) -# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include/ -java_linux_version_include_dirs = [ - '/usr/lib/jvm/java-*-sun-%s*/include', - '/usr/lib/jvm/java-%s*-openjdk*/include', - '/usr/java/jdk%s*/include' -] - def get_java_include_paths(env, javac, version): """ Find java include paths for JNI building. @@ -467,24 +487,23 @@ def get_java_include_paths(env, javac, version): paths = [java_inc_dir, os.path.join(java_inc_dir, 'win32')] elif env['PLATFORM'] == 'darwin': if not version: - paths = [java_macos_include_dir] + paths = [java_macos_include_dir_glob] else: - paths = sorted(glob.glob(java_macos_version_include_dir%version)) + paths = sorted(glob.glob(java_macos_version_include_dir_glob % version)) else: - base_paths=[] + base_paths = [] if not version: - for p in java_linux_include_dirs: + for p in java_linux_include_dirs_glob: base_paths.extend(glob.glob(p)) else: - for p in java_linux_version_include_dirs: - base_paths.extend(glob.glob(p%version)) + for p in java_linux_version_include_dirs_glob: + base_paths.extend(glob.glob(p % version)) for p in base_paths: - paths.extend([p, os.path.join(p,'linux')]) - - #print("PATHS:%s"%paths) - return paths + paths.extend([p, os.path.join(p, 'linux')]) + # print("PATHS:%s"%paths) + return paths # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/JavaCommonTests.py b/src/engine/SCons/Tool/JavaCommonTests.py index fe04ce9..9242624 100644 --- a/src/engine/SCons/Tool/JavaCommonTests.py +++ b/src/engine/SCons/Tool/JavaCommonTests.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os.path import sys import unittest +import fnmatch import SCons.Scanner.IDL import SCons.Tool.JavaCommon @@ -608,54 +609,75 @@ public class AnonDemo { pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.8') assert expect == classes, (expect, classes) - def test_jdk_globs(self): - test = TestSCons.TestSCons(workdir='') - - if sys.platform == 'win32': - test.subdir(['Program Files'], - ['Program Files', 'Java'], - ['Program Files', 'Java', 'jdk1.8.0_201'], - ['Program Files', 'Java', 'jdk1.8.0_201', 'bin'], - ['Program Files', 'Java', 'jdk-11.0.2'], - ['Program Files', 'Java', 'jdk-11.0.2', 'bin']) - - test.write(['Program Files', 'Java', 'jdk1.8.0_201', 'bin', 'javac.exe'], "echo Java 1.8") - test.write(['Program Files', 'Java', 'jdk-11.0.2', 'bin', 'javac.exe'], "echo Java 11.0") - else: - test.subdir(['jvm'], - ['jvm', 'java'], - ['jvm', 'java', 'bin'], - ['jvm', 'java-11-openjdk-11.0.2'], - ['jvm', 'java-11-openjdk-11.0.2', 'bin'], - ['jvm', 'java-1.8-openjdk-1.8.0'], - ['jvm', 'java-1.8-openjdk-1.8.0', 'bin']) - - test.write(['jvm', 'java', 'bin', 'javac'], "echo Java 1.8") - test.write(['jvm', 'java-11-openjdk-11.0.2', 'bin', 'javac'], "echo Java 11.0") - test.write(['jvm', 'java-1.8-openjdk-1.8.0', 'bin', 'javac'], "echo Java 1.8") - - for version in (None, "1.8", "11.0"): - if version: - if sys.platform == 'win32': - patterns = [ - 'Program Files*/Java/jdk*%s*/bin' % version, - ] - else: - patterns = [ - 'jvm/*-%s*/bin' % version, - ] - else: - if sys.platform == 'win32': - patterns = [ - 'Program Files*/Java/jdk*/bin', - ] - else: - patterns = [ - 'jvm/*/bin', - ] - java_path = test.paths(patterns) - assert java_path, "no java found by pattern %s" % patterns[0] + """ + Verify that the java path globs work with specific examples. + :return: + """ + from SCons.Tool.JavaCommon import java_linux_include_dirs_glob, java_linux_version_include_dirs_glob, java_win32_dir_glob, java_win32_version_dir_glob, java_macos_include_dir_glob, java_macos_version_include_dir_glob + + # Test windows globs + win_java_dirs = [ + ('C:/Program Files/Java/jdk1.8.0_201/bin', '1.8.0'), + ('C:/Program Files/Java/jdk-11.0.2/bin', '11.0.2'), + ('C:/Program Files/Java/jdk1.7.0_80/bin', '1.7.0') + ] + + for (wjd, version) in win_java_dirs: + if not fnmatch.fnmatch(wjd, java_win32_dir_glob): + self.fail("Didn't properly match %s with pattern %s" % (wjd, java_win32_dir_glob)) + if not fnmatch.fnmatch(wjd, java_win32_version_dir_glob % version): + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, java_win32_version_dir_glob % version)) + + non_win_java_include_dirs = [ + ('/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include', '1.8.0'), + ('/usr/lib/jvm/java-1.8.0-openjdk-amd64/include', '1.8.0'), + ('/usr/lib/jvm/java-8-openjdk-amd64/include', '8'), + ] + + # Test non-windows/non-macos globs + for (wjd, version) in non_win_java_include_dirs: + match = False + globs_tried =[] + for jlig in java_linux_include_dirs_glob: + globs_tried.append(jlig) + + if fnmatch.fnmatch(wjd, jlig): + match = True + break + + if not match: + self.fail("Didn't properly match %s with pattern %s" % (wjd, globs_tried)) + + match = False + globs_tried = [] + for jlvig in java_linux_version_include_dirs_glob: + globs_tried.append(jlvig%version) + if fnmatch.fnmatch(wjd, jlvig % version): + match = True + break + + if not match: + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, globs_tried)) + + # Test macos globs + # Test windows globs + macos_java_dirs = [ + # ('/System/Library/Frameworks/JavaVM.framework/Headers/', None), + ('/System/Library/Frameworks/JavaVM.framework/Versions/11.0.2/Headers/', '11.0.2'), + ] + + if not fnmatch.fnmatch('/System/Library/Frameworks/JavaVM.framework/Headers/', java_macos_include_dir_glob): + self.fail("Didn't properly match %s with pattern %s" % ('/System/Library/Frameworks/JavaVM.framework/Headers/', java_macos_include_dir_glob)) + + for (wjd, version) in macos_java_dirs: + if not fnmatch.fnmatch(wjd, java_macos_version_include_dir_glob % version): + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, java_macos_version_include_dir_glob % version)) + + if __name__ == "__main__": |