diff --git a/CMakeLists.txt b/CMakeLists.txt index 5421f75a..14f7e352 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,9 +159,25 @@ elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL PGI) add_definitions(-DPGI) set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS_DEBUG} -O0 -g -traceback -Mallocatable=03 -Mbounds -Mchkfpstk -Mchkstk") +elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL Cray) + + # The Fortran module does not set a variable to the compiler version + # number like the C module does. Since CCE is a suite of compilers we + # can use the C version as a proxy for the Fortran version. + # + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER 8.6.0) + message( FATAL_ERROR "Cray compiler version number ${CMAKE_C_COMPILER_VERSION} < 8.6.0 minimum" ) + endif() + + # Use Cray + add_definitions(-DCray) + add_definitions(-DSTRINGIFY_SIMPLE) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS_DEBUG} -G0 -Rb ${CMAKE_Fortran_FLAGS}") + set(OPENMP_FLAGS " ") + else() - message( FATAL_ERROR "Unrecognized compiler. Please use ifort, gfortran, gfortran-mp-4.8, PGI, or nagfor" ) + message( FATAL_ERROR "Unrecognized compiler. Please use ifort, gfortran, gfortran-mp-4.8, pgfortran, nagfor or cce" ) endif() diff --git a/ChangeLog b/ChangeLog index d759159a..cf163804 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ + +3.2.10 - Cmake fix (#12) -- spaces in COMMAND + - moved to GitHub 3.2.9 October 29, 2017 - bug fix for #62 -- stalled test in some environments diff --git a/Examples/Fixture/GNUmakefile b/Examples/Fixture/GNUmakefile index 74c343d7..212882f3 100644 --- a/Examples/Fixture/GNUmakefile +++ b/Examples/Fixture/GNUmakefile @@ -9,15 +9,11 @@ VPATH = . $(SRC_DIR) $(TEST_DIR) include $(PFUNIT)/include/base.mk -ifeq ($(USEMPI),YES) - FC=mpif90 -endif - EXE = tests$(EXE_EXT) all: $(EXE) ifeq ($(USEMPI),YES) - mpirun -np 1 ./$(EXE) + mpiexec -n 1 ./$(EXE) else ./$(EXE) endif diff --git a/Examples/Fixture/tests/GNUmakefile b/Examples/Fixture/tests/GNUmakefile index d0e9716c..2c94c5f3 100644 --- a/Examples/Fixture/tests/GNUmakefile +++ b/Examples/Fixture/tests/GNUmakefile @@ -17,7 +17,7 @@ ifndef SKIP_INTENTIONALLY_BROKEN endif %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(FC) -c $(FFLAGS) $(FPPFLAGS) $< diff --git a/Examples/MPI_Halo/GNUmakefile b/Examples/MPI_Halo/GNUmakefile index 274ccfae..f938ce2c 100644 --- a/Examples/MPI_Halo/GNUmakefile +++ b/Examples/MPI_Halo/GNUmakefile @@ -9,14 +9,10 @@ VPATH = . $(SRC_DIR) $(TEST_DIR) include $(PFUNIT)/include/base.mk -ifeq ($(USEMPI),YES) - MPIF90=mpif90 -endif - EXE = tests$(EXE_EXT) all: $(EXE) - mpirun -np 4 ./$(EXE) + mpiexec -n 4 ./$(EXE) SUT: make -C $(SRC_DIR) SUT diff --git a/Examples/MPI_Halo/tests/GNUmakefile b/Examples/MPI_Halo/tests/GNUmakefile index effdc50d..d534e525 100644 --- a/Examples/MPI_Halo/tests/GNUmakefile +++ b/Examples/MPI_Halo/tests/GNUmakefile @@ -17,7 +17,7 @@ ifndef SKIP_INTENTIONALLY_BROKEN endif %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(MPIF90) -c $(FFLAGS) $< diff --git a/Examples/MPI_SimpleParameterizedTest/GNUmakefile b/Examples/MPI_SimpleParameterizedTest/GNUmakefile index 1cc9cddf..37d8f472 100644 --- a/Examples/MPI_SimpleParameterizedTest/GNUmakefile +++ b/Examples/MPI_SimpleParameterizedTest/GNUmakefile @@ -8,14 +8,10 @@ VPATH = . $(TEST_DIR) include $(PFUNIT)/include/base.mk -ifeq ($(USEMPI),YES) - MPIF90=mpif90 -endif - EXE = tests$(EXE_EXT) all: $(EXE) - mpirun -np 4 ./$(EXE) + mpiexec -n 4 ./$(EXE) SUT: make -C $(TEST_DIR) tests diff --git a/Examples/MPI_SimpleParameterizedTest/tests/GNUmakefile b/Examples/MPI_SimpleParameterizedTest/tests/GNUmakefile index a8709108..1897246f 100644 --- a/Examples/MPI_SimpleParameterizedTest/tests/GNUmakefile +++ b/Examples/MPI_SimpleParameterizedTest/tests/GNUmakefile @@ -19,7 +19,7 @@ ifndef SKIP_INTENTIONALLY_BROKEN endif %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(MPIF90) -c $(FFLAGS) $< diff --git a/Examples/ParameterizedTest/GNUmakefile b/Examples/ParameterizedTest/GNUmakefile index a4d9b201..3aff8a33 100644 --- a/Examples/ParameterizedTest/GNUmakefile +++ b/Examples/ParameterizedTest/GNUmakefile @@ -9,15 +9,11 @@ VPATH = . $(SRC_DIR) $(TEST_DIR) include $(PFUNIT)/include/base.mk -ifeq ($(USEMPI),YES) - FC=mpif90 -endif - EXE = tests$(EXE_EXT) all: $(EXE) ifeq ($(USEMPI),YES) - mpirun -np 1 ./$(EXE) + mpiexec -n 1 ./$(EXE) else ./$(EXE) endif diff --git a/Examples/ParameterizedTest/tests/GNUmakefile b/Examples/ParameterizedTest/tests/GNUmakefile index 67e9144f..e69499a0 100644 --- a/Examples/ParameterizedTest/tests/GNUmakefile +++ b/Examples/ParameterizedTest/tests/GNUmakefile @@ -13,7 +13,7 @@ testSuites.inc: $(SRCS) FFLAGS += -I$(SRC_DIR) -I$(PFUNIT)/mod %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(FC) -c $(FFLAGS) $< diff --git a/Examples/Robust/GNUmakefile b/Examples/Robust/GNUmakefile index 117ce7b8..5bded9b0 100644 --- a/Examples/Robust/GNUmakefile +++ b/Examples/Robust/GNUmakefile @@ -9,20 +9,18 @@ VPATH = . $(SRC_DIR) $(TEST_DIR) include $(PFUNIT)/include/base.mk -ifeq ($(USEMPI),YES) - FC=mpif90 -endif - EXE = tests$(EXE_EXT) # NOTE: use the -robust flag all: $(EXE) ifeq ($(USEMPI),YES) - echo Warning: Testing -robust flag with MPI, robust will override. - echo driver.F90 will call mpirun on itself with robust set. - echo "Top" level mpirun not needed, may be problemmatic. + @echo + @echo 'Warning: Testing -robust flag with MPI, robust will override.' + @echo ' driver.F90 will call mpirun on itself with robust set.' + @echo ' "Top" level mpirun not needed, may be problemmatic.' + @echo ./$(EXE) -robust - # mpirun -np 1 ./$(EXE) -robust + # mpiexec -n 1 ./$(EXE) -robust else ./$(EXE) -robust -max-timeout-duration 0.16 -max-launch-duration 4.72 endif diff --git a/Examples/Robust/tests/GNUmakefile b/Examples/Robust/tests/GNUmakefile index ff011b8d..a64c8a80 100644 --- a/Examples/Robust/tests/GNUmakefile +++ b/Examples/Robust/tests/GNUmakefile @@ -17,7 +17,7 @@ ifndef SKIP_INTENTIONALLY_BROKEN endif %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(FC) -c $(FFLAGS) $< diff --git a/Examples/Simple/GNUmakefile b/Examples/Simple/GNUmakefile index 397accc8..33d7e63b 100644 --- a/Examples/Simple/GNUmakefile +++ b/Examples/Simple/GNUmakefile @@ -36,12 +36,6 @@ ifeq ($(UNAME),Windows) endif endif -# The following may be redundant since FC should already be -# appropriately set in include/base.mk. -ifeq ($(USEMPI),YES) - FC=mpif90 -endif - EXE = tests$(EXE_EXT) ifneq ($(UNAME),Windows) LIBS = -L$(PFUNIT)/lib -lpfunit @@ -51,14 +45,8 @@ endif all: $(EXE) -# ifeq ($(USEMPI),YES) -# mpirun -np 1 ./$(EXE) -# else -# ./$(EXE) -# endif - ifeq ($(USEMPI),YES) - mpirun -np 1 ./$(EXE) -xml tests.xml + mpiexec -n 1 ./$(EXE) -xml tests.xml else ./$(EXE) -xml tests.xml endif diff --git a/Examples/Simple/tests/GNUmakefile b/Examples/Simple/tests/GNUmakefile index 212dbf0a..5398e92a 100644 --- a/Examples/Simple/tests/GNUmakefile +++ b/Examples/Simple/tests/GNUmakefile @@ -36,7 +36,7 @@ ifneq ($(UNAME),Windows) endif %.F90: %.pf - $(PFUNIT)/bin/pFUnitParser.py $< $@ + $(PFUNIT)/bin/pFUnitParser.py $(FUFLAGS) $< $@ %$(OBJ_EXT): %.F90 $(FC) -c $(FFLAGS) $(FPPFLAGS) $< diff --git a/bin/pFUnitParser.py b/bin/pFUnitParser.py index 0b40e93d..d50488d6 100755 --- a/bin/pFUnitParser.py +++ b/bin/pFUnitParser.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# For python 2.6-2.7 +# For python 2.7 from __future__ import print_function from os.path import * @@ -7,34 +7,59 @@ # from parseBrackets import parseBrackets from parseDirectiveArgs import parseDirectiveArguments + class MyError(Exception): def __init__(self, value): self.value = value + def __str__(self): return repr(self.value) -assertVariants = 'Fail|Equal|True|False|LessThan|LessThanOrEqual|GreaterThan|GreaterThanOrEqual' -assertVariants += '|IsMemberOf|Contains|Any|All|NotAll|None|IsPermutationOf' -assertVariants += '|ExceptionRaised|SameShape|IsNaN|IsFinite' -def cppSetLineAndFile(line, file): - return "#line " + str(line) + ' "' + file + '"\n' +assertVariants = 'Fail|Equal|True|False|LessThan|LessThanOrEqual|GreaterThan' +assertVariants += '|GreaterThanOrEqual|IsMemberOf|Contains|Any|All|NotAll|None' +assertVariants += '|IsPermutationOf|ExceptionRaised|SameShape|IsNaN|IsFinite' + + +def cpp_set_line(line, filename): + return "#line " + str(line) + ' "' + filename + '"\n' + + +def compiler_set_line(line, filename=None): + ''' + Returns a string holding a linemarker as understood by compilers. + + Currently the flags which may appear in such a linemarker are not + supported. These are mostly related to #include debris so are of low + priority at the moment. + ''' + linemarker = '#' + str(line) + if filename: + linemarker += ' "' + filename + '"' + linemarker += '\n' + return linemarker + def getSubroutineName(line): try: - m = re.match('\s*subroutine\s+(\w*)\s*(\\([\w\s,]*\\))?\s*(!.*)*$', line, re.IGNORECASE) + m = re.match('\s*subroutine\s+(\w*)\s*(\\([\w\s,]*\\))?\s*(!.*)*$', + line, re.IGNORECASE) return m.groups()[0] - except: + except Exception: raise MyError('Improper format in declaration of test procedure.') -def parseArgsFirstRest(directiveName,line): - """If the @-directive has more than one argument, parse into first and rest strings. + +def parseArgsFirstRest(directiveName, line): + """ + If the @-directive has more than one argument, parse into first and rest + strings. Added for assertAssociated. """ - argStr = ''; + argStr = '' if directiveName != '': - m = re.match('\s*'+directiveName+'\s*\\((.*\w.*)\\)\s*$',line,re.IGNORECASE) + m = re.match('\s*'+directiveName+'\s*\\((.*\w.*)\\)\s*$', + line, re.IGNORECASE) if m: argStr = m.groups()[0] else: @@ -49,97 +74,110 @@ def parseArgsFirstRest(directiveName,line): elif len(args) == 1: returnArgs = [args[0]] else: - returnArgs = [args[0],','.join(args[1:])] - + returnArgs = [args[0], ','.join(args[1:])] + return returnArgs -def parseArgsFirstSecondRest(directiveName,line): - """If the @-directive must have at least two arguments, parse into first, second, - and rest strings. Added for assertAssociated. +def parseArgsFirstSecondRest(directiveName, line): + """ + If the @-directive must have at least two arguments, parse into first, + second, and rest strings. Added for assertAssociated. """ - args1 = parseArgsFirstRest(directiveName,line) + args1 = parseArgsFirstRest(directiveName, line) returnArgs = None - if args1 != None: + if args1 is not None: if len(args1) == 1: returnArgs = args1 elif len(args1) == 2: - args2 = parseArgsFirstRest('',args1[1]) + args2 = parseArgsFirstRest('', args1[1]) returnArgs = [args1[0]] + args2 elif len(args1) == 3: - print(-999,'parseArgsFirstSecondRest::error!') + print(-999, 'parseArgsFirstSecondRest::error!') returnArgs = None return returnArgs def getSelfObjectName(line): - m = re.match('\s*subroutine\s+\w*\s*\\(\s*(\w+)\s*(,\s*\w+\s*)*\\)\s*$', line, re.IGNORECASE) + m = re.match('\s*subroutine\s+\w*\s*\\(\s*(\w+)\s*(,\s*\w+\s*)*\\)\s*$', + line, re.IGNORECASE) if m: return m.groups()[0] else: return m + def getTypeName(line): m = re.match('\s*type(.*::\s*|\s+)(\w*)\s*$', line, re.IGNORECASE) return m.groups()[1] - + + class Action(): def apply(self, line): m = self.match(line) - if m: self.action(m, line) + if m: + self.action(m, line) return m -#------------------ + +# ------------------ class AtTest(Action): def __init__(self, parser): self.parser = parser self.keyword = '@test' def match(self, line): - m = re.match('\s*'+self.keyword+'(\s*(\\(.*\\))?\s*$)', line, re.IGNORECASE) + m = re.match('\s*'+self.keyword+'(\s*(\\(.*\\))?\s*$)', + line, re.IGNORECASE) return m def action(self, m, line): - options = re.match('\s*'+self.keyword+'\s*\\((.*)\\)\s*$', line, re.IGNORECASE) + options = re.match('\s*'+self.keyword+'\s*\\((.*)\\)\s*$', + line, re.IGNORECASE) method = {} if options: - npesOption = re.search('npes\s*=\s*\\[([0-9,\s]+)\\]', options.groups()[0], re.IGNORECASE) + npesOption = re.search('npes\s*=\s*\\[([0-9,\s]+)\\]', + options.groups()[0], re.IGNORECASE) if npesOption: npesString = npesOption.groups()[0] npes = map(int, npesString.split(',')) method['npRequests'] = npes - #ifdef is optional - matchIfdef = re.match('.*ifdef\s*=\s*(\w+)', options.groups()[0], re.IGNORECASE) - if matchIfdef: + # ifdef is optional + matchIfdef = re.match('.*ifdef\s*=\s*(\w+)', + options.groups()[0], re.IGNORECASE) + if matchIfdef: ifdef = matchIfdef.groups()[0] method['ifdef'] = ifdef - matchIfndef = re.match('.*ifndef\s*=\s*(\w+)', options.groups()[0], re.IGNORECASE) - if matchIfndef: + matchIfndef = re.match('.*ifndef\s*=\s*(\w+)', + options.groups()[0], re.IGNORECASE) + if matchIfndef: ifndef = matchIfndef.groups()[0] method['ifndef'] = ifndef - matchType = re.match('.*type\s*=\s*(\w+)', options.groups()[0], re.IGNORECASE) + matchType = re.match('.*type\s*=\s*(\w+)', + options.groups()[0], re.IGNORECASE) if matchType: print ('Type', matchType.groups()[0]) method['type'] = matchType.groups()[0] - paramOption = re.search('testParameters\s*=\s*[{](.*)[}]', options.groups()[0], re.IGNORECASE) + paramOption = re.search('testParameters\s*=\s*[{](.*)[}]', + options.groups()[0], re.IGNORECASE) if paramOption: paramExpr = paramOption.groups()[0] method['testParameters'] = paramExpr - casesOption = re.search('cases\s*=\s*(\\[[0-9,\s]+\\])', options.groups()[0], re.IGNORECASE) + casesOption = re.search('cases\s*=\s*(\\[[0-9,\s]+\\])', + options.groups()[0], re.IGNORECASE) if casesOption: method['cases'] = casesOption.groups()[0] - nextLine = self.parser.nextLine() method['name'] = getSubroutineName(nextLine) # save "self" name for use with @mpiAssert @@ -155,13 +193,14 @@ def action(self, m, line): self.parser.outputFile.write(nextLine) -#------------------ +# ------------------ # deprecated - should now just use @test class AtMpiTest(AtTest): def __init__(self, parser): self.parser = parser self.keyword = '@mpitest' + class AtTestCase(Action): def __init__(self, parser): self.parser = parser @@ -169,32 +208,37 @@ def __init__(self, parser): def match(self, line): m = re.match('\s*@testcase\s*(|\\(.*\\))\s*$', line, re.IGNORECASE) return m - + def action(self, m, line): - options = re.match('\s*@testcase\s*\\((.*)\\)\s*$', line, re.IGNORECASE) + options = re.match('\s*@testcase\s*\\((.*)\\)\s*$', + line, re.IGNORECASE) if options: - value = re.search('constructor\s*=\s*(\w*)', options.groups()[0], re.IGNORECASE) + value = re.search('constructor\s*=\s*(\w*)', + options.groups()[0], re.IGNORECASE) if value: self.parser.userTestCase['constructor'] = value.groups()[0] - value = re.search('npes\s*=\s*\\[([0-9,\s]+)\\]', options.groups()[0], re.IGNORECASE) + value = re.search('npes\s*=\s*\\[([0-9,\s]+)\\]', + options.groups()[0], re.IGNORECASE) if value: npesString = value.groups()[0] - npes = map(int,npesString.split(',')) + npes = map(int, npesString.split(',')) self.parser.userTestCase['npRequests'] = npes - value = re.search('cases\s*=\s*(\\[[0-9,\s]+\\])', options.groups()[0], re.IGNORECASE) + value = re.search('cases\s*=\s*(\\[[0-9,\s]+\\])', + options.groups()[0], re.IGNORECASE) if value: cases = value.groups()[0] self.parser.userTestCase['cases'] = cases - value = re.search('testParameters\s*=\s*[{](.*)[}]', options.groups()[0], re.IGNORECASE) + value = re.search('testParameters\s*=\s*[{](.*)[}]', + options.groups()[0], re.IGNORECASE) if value: paramExpr = value.groups()[0] self.parser.userTestCase['testParameters'] = paramExpr nextLine = self.parser.nextLine() - self.parser.userTestCase['type']=getTypeName(nextLine) + self.parser.userTestCase['type'] = getTypeName(nextLine) self.parser.commentLine(line) self.parser.outputFile.write(nextLine) @@ -202,13 +246,15 @@ def action(self, m, line): class AtSuite(Action): def __init__(self, parser): self.parser = parser + def match(self, line): nameRe = "'\w+'|" + """\w+""" - m = re.match("\s*@suite\s*\\(\s*name\s*=\s*("+nameRe+")\s*\\)\s*$", line, re.IGNORECASE) + m = re.match("\s*@suite\s*\\(\s*name\s*=\s*("+nameRe+")\s*\\)\s*$", + line, re.IGNORECASE) return m def action(self, m, line): - self.parser.suiteName=m.groups()[0][1:-1] + self.parser.suiteName = m.groups()[0][1:-1] self.parser.wrapModuleName = 'Wrap' + self.parser.suiteName @@ -233,7 +279,8 @@ def __init__(self, parser): self.parser = parser def match(self, line): - m = re.match('\s*@assert('+assertVariants+')\s*\\((.*\w.*)\\)\s*$', line, re.IGNORECASE) + m = re.match('\s*@assert(' + assertVariants + ')\s*\\((.*\w.*)\\)\s*$', + line, re.IGNORECASE) return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -243,31 +290,38 @@ def appendSourceLocation(self, fileHandle, fileName, lineNumber): def action(self, m, line): p = self.parser - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) - p.outputFile.write(" call assert"+m.groups()[0]+"(" + m.groups()[1] + ", &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) + p.outputFile.write(" call assert" + m.groups()[0] + + "(" + m.groups()[1] + ", &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") p.outputFile.write(" if (anyExceptions()) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) + fragment = self.parser.set_line(p.currentLineNumber+1, p.fileName) + p.outputFile.write(fragment) + class AtAssertAssociated(Action): - def __init__(self,parser): + def __init__(self, parser): self.parser = parser def match(self, line): - m = re.match('\s*@assertassociated\s*\\((.*\w.*)\\)\s*$', line, re.IGNORECASE) + m = re.match('\s*@assertassociated\s*\\((.*\w.*)\\)\s*$', + line, re.IGNORECASE) if not m: - m = re.match( \ - '\s*@assertassociated\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assertassociated\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', + line, re.IGNORECASE) # How to get both (a,b) and (a,b,c) to match? if not m: - m = re.match( \ - '\s*@assertassociated\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assertassociated\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', + line, re.IGNORECASE) return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -279,56 +333,65 @@ def action(self, m, line): p = self.parser # args = parseArgsFirstRest('@assertassociated',line) - args = parseArgsFirstSecondRest('@assertassociated',line) + args = parseArgsFirstSecondRest('@assertassociated', line) # print(9000,line) # print(9001,args) - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) if len(args) > 1: - if re.match('.*message=.*',args[1],re.IGNORECASE): - p.outputFile.write(" call assertTrue(associated(" + args[0] + "), " + args[1] + ", &\n") + if re.match('.*message=.*', args[1], re.IGNORECASE): + p.outputFile.write(" call assertTrue(associated(" + + args[0] + "), " + args[1] + ", &\n") elif len(args) > 2: - p.outputFile.write(" call assertTrue(associated(" + args[0] + "," + args[1] + "), " + args[2] + ", &\n") + p.outputFile.write(" call assertTrue(associated(" + + args[0] + "," + args[1] + "), " + + args[2] + ", &\n") else: - p.outputFile.write(" call assertTrue(associated(" + args[0] + "," + args[1] + "), &\n") + p.outputFile.write(" call assertTrue(associated(" + + args[0] + "," + args[1] + "), &\n") else: - p.outputFile.write(" call assertTrue(associated(" + args[0] + "), &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + p.outputFile.write(" call assertTrue(associated(" + + args[0] + "), &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") p.outputFile.write(" if (anyExceptions()) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) + fragment = self.parser.set_line(p.currentLineNumber+1, p.fileName) + p.outputFile.write(fragment) class AtAssertNotAssociated(Action): - def __init__(self,parser): + def __init__(self, parser): self.parser = parser - self.name='@assertnotassociated' + self.name = '@assertnotassociated' def match(self, line): - m = re.match('\s*@assert(not|un)associated\s*\\((.*\w.*)\\)\s*$', line, re.IGNORECASE) + m = re.match('\s*@assert(not|un)associated\s*\\((.*\w.*)\\)\s*$', + line, re.IGNORECASE) if m: - self.name='@assert'+m.groups()[0]+'associated' + self.name = '@assert' + m.groups()[0] + 'associated' else: - self.name='@assertnotassociated' + self.name = '@assertnotassociated' if not m: - m = re.match( \ - '\s*@assert(not|un)associated\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assert(not|un)associated\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', + line, re.IGNORECASE) # How to get both (a,b) and (a,b,c) to match? if not m: - m = re.match( \ - '\s*@assert(not|un)associated\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assert(not|un)associated\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', + line, re.IGNORECASE) if m: - self.name='@assert'+m.groups()[0]+'associated' + self.name = '@assert' + m.groups()[0] + 'associated' else: - self.name='@assertnotassociated' + self.name = '@assertnotassociated' - return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -339,47 +402,56 @@ def appendSourceLocation(self, fileHandle, fileName, lineNumber): def action(self, m, line): p = self.parser - #-- args = parseArgsFirstRest('@assertassociated',line) - #ok args = parseArgsFirstSecondRest('@assertassociated',line) - args = parseArgsFirstSecondRest(self.name,line) + # -- args = parseArgsFirstRest('@assertassociated',line) + # ok args = parseArgsFirstSecondRest('@assertassociated',line) + args = parseArgsFirstSecondRest(self.name, line) # print(9000,line) # print(9001,args) - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) if len(args) > 1: - if re.match('.*message=.*',args[1],re.IGNORECASE): - p.outputFile.write(" call assertFalse(associated(" + args[0] + "), " + args[1] + ", &\n") + if re.match('.*message=.*', args[1], re.IGNORECASE): + p.outputFile.write(" call assertFalse(associated(" + + args[0] + "), " + args[1] + ", &\n") elif len(args) > 2: - p.outputFile.write(" call assertFalse(associated(" + args[0] + "," + args[1] + "), " + args[2] + ", &\n") + p.outputFile.write(" call assertFalse(associated(" + + args[0] + "," + args[1] + "), " + + args[2] + ", &\n") else: - p.outputFile.write(" call assertFalse(associated(" + args[0] + "," + args[1] + "), &\n") + p.outputFile.write(" call assertFalse(associated(" + + args[0] + "," + args[1] + "), &\n") else: - p.outputFile.write(" call assertFalse(associated(" + args[0] + "), &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + p.outputFile.write(" call assertFalse(associated(" + + args[0] + "), &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") p.outputFile.write(" if (anyExceptions()) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) + fragment = self.parser.set_line(p.currentLineNumber + 1, p.fileName) + p.outputFile.write(fragment) class AtAssertEqualUserDefined(Action): """Convenience directive replacing (a,b) with a call to assertTrue(a==b) and an error message, if none is provided when invoked. """ - def __init__(self,parser): + def __init__(self, parser): self.parser = parser def match(self, line): - m = re.match( \ - '\s*@assertequaluserdefined\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assertequaluserdefined\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', + line, re.IGNORECASE) # How to get both (a,b) and (a,b,c) to match? if not m: - m = re.match( \ - '\s*@assertequaluserdefined\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', \ - line, re.IGNORECASE) - + m = re.match('\s*@assertequaluserdefined\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', + line, re.IGNORECASE) + return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -390,41 +462,46 @@ def appendSourceLocation(self, fileHandle, fileName, lineNumber): def action(self, m, line): p = self.parser - args = parseArgsFirstSecondRest('@assertequaluserdefined',line) - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) + args = parseArgsFirstSecondRest('@assertequaluserdefined', line) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) if len(args) > 2: - p.outputFile.write(" call assertTrue(" \ - + args[0] + "==" + args[1] + ", " + args[2] + ", &\n") + p.outputFile.write(" call assertTrue(" + args[0] + + "==" + args[1] + ", " + args[2] + ", &\n") else: - p.outputFile.write(" call assertTrue(" \ - + args[0] + "==" + args[1] + ", &\n") - if not re.match('.*message=.*',line,re.IGNORECASE): - p.outputFile.write(" & message='<" + args[0] + "> not equal to <" + args[1] + ">', &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + p.outputFile.write(" call assertTrue(" + args[0] + + "==" + args[1] + ", &\n") + if not re.match('.*message=.*', line, re.IGNORECASE): + p.outputFile.write(" & message='<" + args[0] + + "> not equal to <" + args[1] + ">', &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") p.outputFile.write(" if (anyExceptions()) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) + fragment = self.parser.set_line(p.currentLineNumber + 1, p.fileName) + p.outputFile.write(fragment) class AtAssertEquivalent(Action): """Convenience directive replacing (a,b) with a call to assertTrue(a.eqv.b) and an error message, if none is provided when invoked. """ - def __init__(self,parser): + def __init__(self, parser): self.parser = parser def match(self, line): - m = re.match( \ - '\s*@assertequivalent\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', \ - line, re.IGNORECASE) + m = re.match('\s*@assertequivalent\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*),(.*\w*.*))\\)\s*$', + line, re.IGNORECASE) # How to get both (a,b) and (a,b,c) to match? if not m: - m = re.match( \ - '\s*@assertequivalent\s*\\((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', \ - line, re.IGNORECASE) - + m = re.match('\s*@assertequivalent\s*\\' + + '((\s*([^,]*\w.*),\s*([^,]*\w.*))\\)\s*$', + line, re.IGNORECASE) + return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -435,29 +512,36 @@ def appendSourceLocation(self, fileHandle, fileName, lineNumber): def action(self, m, line): p = self.parser - args = parseArgsFirstSecondRest('@assertequivalent',line) - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) + args = parseArgsFirstSecondRest('@assertequivalent', line) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) if len(args) > 2: - p.outputFile.write(" call assertTrue(" \ - + args[0] + ".eqv." + args[1] + ", " + args[2] + ", &\n") + p.outputFile.write(" call assertTrue(" + args[0] + + ".eqv." + args[1] + ", " + args[2] + ", &\n") else: - p.outputFile.write(" call assertTrue(" \ - + args[0] + ".eqv." + args[1] + ", &\n") - if not re.match('.*message=.*',line,re.IGNORECASE): - p.outputFile.write(" & message='<" + args[0] + "> not equal to <" + args[1] + ">', &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + p.outputFile.write(" call assertTrue(" + args[0] + + ".eqv." + args[1] + ", &\n") + if not re.match('.*message=.*', line, re.IGNORECASE): + p.outputFile.write(" & message='<" + args[0] + + "> not equal to <" + args[1] + ">', &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") p.outputFile.write(" if (anyExceptions()) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) - + fragment = self.parser.set_line(p.currentLineNumber + 1, p.fileName) + p.outputFile.write(fragment) + class AtMpiAssert(Action): def __init__(self, parser): self.parser = parser def match(self, line): - m = re.match('\s*@mpiassert('+assertVariants+')\s*\\((.*\w.*)\\)\s*$', line, re.IGNORECASE) + m = re.match('\s*@mpiassert(' + + assertVariants + + ')\s*\\((.*\w.*)\\)\s*$', line, re.IGNORECASE) return m def appendSourceLocation(self, fileHandle, fileName, lineNumber): @@ -467,16 +551,24 @@ def appendSourceLocation(self, fileHandle, fileName, lineNumber): def action(self, m, line): p = self.parser - - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber, p.fileName)) - p.outputFile.write(" call assert"+m.groups()[0]+"(" + m.groups()[1] + ", &\n") - self.appendSourceLocation(p.outputFile, p.fileName, p.currentLineNumber) + + p.outputFile.write(self.parser.set_line(p.currentLineNumber, + p.fileName)) + p.outputFile.write(" call assert" + + m.groups()[0] + "(" + m.groups()[1] + ", &\n") + self.appendSourceLocation(p.outputFile, + p.fileName, + p.currentLineNumber) p.outputFile.write(" )\n") # 'this' object may not exist if test is commented out. - if hasattr(p,'currentSelfObjectName'): - p.outputFile.write(" if (anyExceptions("+p.currentSelfObjectName+"%context)) return\n") - p.outputFile.write(cppSetLineAndFile(p.currentLineNumber+1, p.fileName)) + if hasattr(p, 'currentSelfObjectName'): + p.outputFile.write(" if (anyExceptions(" + + p.currentSelfObjectName + + "%context)) return\n") + fragment = self.parser.set_line(p.currentLineNumber + 1, p.fileName) + p.outputFile.write(fragment) + class AtBefore(Action): def __init__(self, parser): @@ -484,7 +576,7 @@ def __init__(self, parser): def match(self, line): m = re.match('\s*@before\s*$', line, re.IGNORECASE) - return m + return m def action(self, m, line): nextLine = self.parser.nextLine() @@ -492,13 +584,14 @@ def action(self, m, line): self.parser.commentLine(line) self.parser.outputFile.write(nextLine) + class AtAfter(Action): def __init__(self, parser): self.parser = parser def match(self, line): m = re.match('\s*@after\s*$', line, re.IGNORECASE) - return m + return m def action(self, m, line): nextLine = self.parser.nextLine() @@ -506,6 +599,7 @@ def action(self, m, line): self.parser.commentLine(line) self.parser.outputFile.write(nextLine) + class AtTestParameter(Action): def __init__(self, parser): self.parser = parser @@ -515,29 +609,39 @@ def match(self, line): return m def action(self, m, line): - options = re.match('\s*@testParameter\s*\\((.*)\\)\s*$', line, re.IGNORECASE) + options = re.match('\s*@testParameter\s*\\((.*)\\)\s*$', + line, re.IGNORECASE) self.parser.commentLine(line) nextLine = self.parser.nextLine() - if not 'testParameterType' in self.parser.userTestCase: - self.parser.userTestCase['testParameterType'] = getTypeName(nextLine) + if 'testParameterType' not in self.parser.userTestCase: + self.parser.userTestCase['testParameterType'] \ + = getTypeName(nextLine) self.parser.outputFile.write(nextLine) if options: - value = re.search('constructor\s*=\s*(\w*)', options.groups()[0], re.IGNORECASE) + value = re.search('constructor\s*=\s*(\w*)', + options.groups()[0], re.IGNORECASE) if value: - self.parser.userTestCase['testParameterConstructor'] = value.groups()[0] + self.parser.userTestCase['testParameterConstructor'] \ + = value.groups()[0] else: - self.parser.userTestCase['testParameterConstructor'] = self.parser.userTestCase['testParameterType'] + self.parser.userTestCase['testParameterConstructor'] \ + = self.parser.userTestCase['testParameterType'] class Parser(): - def __init__(self, inputFileName, outputFileName): + def __init__(self, inputFileName, outputFileName, use_markers): def getBaseName(fileName): from os.path import basename, splitext base = basename(fileName) return splitext(base)[0] + if use_markers: + self.set_line = compiler_set_line + else: + self.set_line = cpp_set_line + self.fileName = inputFileName self.inputFile = open(inputFileName, 'r') self.outputFile = open(outputFileName, 'w') @@ -545,21 +649,22 @@ def getBaseName(fileName): self.suiteName = '' self.currentLineNumber = 0 - self.userModuleName = '' # if any + self.userModuleName = '' # if any self.userTestCase = {} self.userTestCase['setUpMethod'] = '' self.userTestCase['tearDownMethod'] = '' - self.userTestCase['defaultTestParameterNpes'] = [] # is MPI if not empty + # Is MPI if not empty + self.userTestCase['defaultTestParameterNpes'] = [] self.userTestCase['defaultTestParametersExpr'] = '' - self.userTestCase['defaultTestParameterCases'] = [] + self.userTestCase['defaultTestParameterCases'] = [] - self.userTestMethods = [] # each entry is a dictionary + self.userTestMethods = [] # each entry is a dictionary self.wrapModuleName = "Wrap" + getBaseName(inputFileName) self.currentLineNumber = 0 - self.actions=[] + self.actions = [] self.actions.append(AtTest(self)) self.actions.append(AtMpiTest(self)) self.actions.append(AtTestCase(self)) @@ -574,30 +679,34 @@ def getBaseName(fileName): self.actions.append(AtAssertEqualUserDefined(self)) self.actions.append(AtAssertEquivalent(self)) - + self.actions.append(AtMpiAssert(self)) self.actions.append(AtBefore(self)) self.actions.append(AtAfter(self)) self.actions.append(AtTestParameter(self)) - def commentLine(self, line): - self.outputFile.write(re.sub('@','!@',line)) + self.outputFile.write(re.sub('@', '!@', line)) def run(self): def parse(line): for action in self.actions: - if (action.apply(line)): return + if (action.apply(line)): + return self.outputFile.write(line) while True: line = self.nextLine() - if not line: break + if not line: + break parse(line) - if (not self.suiteName): self.suiteName = self.defaultSuiteName - if ('testParameterType' in self.userTestCase and (not 'constructor' in self.userTestCase)): - self.userTestCase['constructor'] = self.userTestCase['testParameterType'] + if (not self.suiteName): + self.suiteName = self.defaultSuiteName + if ('testParameterType' in self.userTestCase + and 'constructor' not in self.userTestCase): + self.userTestCase['constructor'] \ + = self.userTestCase['testParameterType'] self.makeWrapperModule() def isComment(self, line): @@ -607,7 +716,8 @@ def nextLine(self): while True: self.currentLineNumber += 1 line = self.inputFile.readline() - if not line: break + if not line: + break if (self.isComment(line)): self.outputFile.write(line) pass @@ -615,17 +725,15 @@ def nextLine(self): break return line - def printHeader(self): self.outputFile.write('\n') self.outputFile.write('module ' + self.wrapModuleName + '\n') self.outputFile.write(' use pFUnit_mod\n') - if (self.userModuleName): self.outputFile.write(' use ' + self.userModuleName + '\n') + if (self.userModuleName): + self.outputFile.write(' use ' + self.userModuleName + '\n') self.outputFile.write(' implicit none\n') self.outputFile.write(' private\n\n') - - def printTail(self): self.outputFile.write('\n') self.outputFile.write('end module ' + self.wrapModuleName + '\n\n') @@ -633,64 +741,78 @@ def printTail(self): def printWrapUserTestCase(self): self.outputFile.write(' public :: WrapUserTestCase\n') self.outputFile.write(' public :: makeCustomTest\n') - self.outputFile.write(' type, extends(' + self.userTestCase['type'] + ') :: WrapUserTestCase\n') - self.outputFile.write(' procedure(userTestMethod), nopass, pointer :: testMethodPtr\n') + self.outputFile.write(' type, extends(' + + self.userTestCase['type'] + + ') :: WrapUserTestCase\n') + fragment = ' procedure(userTestMethod), ' \ + + 'nopass, pointer :: testMethodPtr\n' + self.outputFile.write(fragment) self.outputFile.write(' contains\n') self.outputFile.write(' procedure :: runMethod\n') self.outputFile.write(' end type WrapUserTestCase\n\n') - + self.outputFile.write(' abstract interface\n') self.outputFile.write(' subroutine userTestMethod(this)\n') if self.userModuleName: self.outputFile.write(' use ' + self.userModuleName + '\n') if 'type' in self.userTestCase: - self.outputFile.write(' class (' + self.userTestCase['type'] + '), intent(inout) :: this\n') + self.outputFile.write(' class (' + + self.userTestCase['type'] + + '), intent(inout) :: this\n') self.outputFile.write(' end subroutine userTestMethod\n') self.outputFile.write(' end interface\n\n') def printRunMethod(self): self.outputFile.write(' subroutine runMethod(this)\n') - self.outputFile.write(' class (WrapUserTestCase), intent(inout) :: this\n\n') + fragment = ' class (WrapUserTestCase), intent(inout) :: this\n\n' + self.outputFile.write(fragment) self.outputFile.write(' call this%testMethodPtr(this)\n') self.outputFile.write(' end subroutine runMethod\n\n') - def printParameterHeader(self, type): - self.outputFile.write(' type (' + type + '), allocatable :: testParameters(:)\n') + self.outputFile.write(' type (' + + type + '), allocatable :: testParameters(:)\n') self.outputFile.write(' type (' + type + ') :: testParameter\n') self.outputFile.write(' integer :: iParam \n') self.outputFile.write(' integer, allocatable :: cases(:) \n') self.outputFile.write(' \n') - def printMakeSuite(self): - self.outputFile.write('function ' + self.suiteName + '() result(suite)\n') + self.outputFile.write('function ' + + self.suiteName + '() result(suite)\n') self.outputFile.write(' use pFUnit_mod\n') - if (self.userModuleName): self.outputFile.write(' use ' + self.userModuleName + '\n') - self.outputFile.write(' use '+ self.wrapModuleName + '\n') + if (self.userModuleName): + self.outputFile.write(' use ' + self.userModuleName + '\n') + self.outputFile.write(' use ' + self.wrapModuleName + '\n') self.outputFile.write(' type (TestSuite) :: suite\n\n') if not self.userModuleName: for testMethod in self.userTestMethods: if ('ifdef' in testMethod): - self.outputFile.write('#ifdef ' + testMethod['ifdef'] + '\n') + self.outputFile.write('#ifdef ' + + testMethod['ifdef'] + '\n') elif ('ifndef' in testMethod): - self.outputFile.write('#ifndef ' + testMethod['ifndef'] + '\n') - self.outputFile.write(' external ' + testMethod['name'] + '\n') + self.outputFile.write('#ifndef ' + + testMethod['ifndef'] + '\n') + self.outputFile.write(' external ' + + testMethod['name'] + '\n') if ('ifdef' in testMethod or 'ifndef' in testMethod): self.outputFile.write('#endif\n') self.outputFile.write('\n') if 'setUp' in self.userTestCase: - self.outputFile.write(' external ' + self.userTestCase['setUp'] + '\n') + self.outputFile.write(' external ' + + self.userTestCase['setUp'] + '\n') if 'tearDown' in self.userTestCase: - self.outputFile.write(' external ' + self.userTestCase['tearDown'] + '\n') + self.outputFile.write(' external ' + + self.userTestCase['tearDown'] + '\n') self.outputFile.write('\n') if 'testParameterType' in self.userTestCase: type = self.userTestCase['testParameterType'] self.printParameterHeader(type) - self.outputFile.write(" suite = newTestSuite('" + self.suiteName + "')\n\n") + self.outputFile.write(" suite = newTestSuite('" + + self.suiteName + "')\n\n") for testMethod in self.userTestMethods: if ('ifdef' in testMethod): @@ -702,7 +824,7 @@ def printMakeSuite(self): else: if 'npRequests' in testMethod: self.addMpiTestMethod(testMethod) - else: # vanilla + else: # vanilla self.addSimpleTestMethod(testMethod) self.outputFile.write('\n') if ('ifdef' in testMethod or 'ifndef' in testMethod): @@ -723,15 +845,17 @@ def addSimpleTestMethod(self, testMethod): args += ', ' + self.userTestCase['tearDown'] if 'type' in testMethod: - type = testMethod['type'] + type = testMethod['type'] else: type = 'newTestMethod' - self.outputFile.write(' call suite%addTest(' + type + '(' + args + '))\n') + self.outputFile.write(' call suite%addTest(' + + type + '(' + args + '))\n') def addMpiTestMethod(self, testMethod): for npes in testMethod['npRequests']: - args = "'" + testMethod['name'] + "', " + testMethod['name'] + ", " + str(npes) + args = "'" + testMethod['name'] \ + + "', " + testMethod['name'] + ", " + str(npes) if 'setUp' in testMethod: args += ', ' + testMethod['setUp'] elif 'setUp' in self.userTestCase: @@ -743,13 +867,13 @@ def addMpiTestMethod(self, testMethod): args += ', ' + self.userTestCase['tearDown'] if 'type' in testMethod: - type = testMethod['type'] + type = testMethod['type'] else: type = 'newMpiTestMethod' - - self.outputFile.write(' call suite%addTest(' + type + '(' + args + '))\n') - + self.outputFile.write(' call suite%addTest(' + + type + '(' + args + '))\n') + def addUserTestMethod(self, testMethod): args = "'" + testMethod['name'] + "', " + testMethod['name'] @@ -766,14 +890,15 @@ def addUserTestMethod(self, testMethod): elif 'cases' in self.userTestCase: cases = self.userTestCase['cases'] - testParameterArg = '' # unless + testParameterArg = '' # unless if 'cases' in locals(): testParameterArg = ', testParameter' self.outputFile.write(' cases = ' + testMethod['cases'] + '\n') - self.outputFile.write(' testParameters = [(' + - self.userTestCase['testParameterConstructor'] + - '(cases(iCase)), iCase = 1, size(cases))]\n\n') + fragment = ' testParameters = [(' \ + + self.userTestCase['testParameterConstructor'] \ + + '(cases(iCase)), iCase = 1, size(cases))]\n\n' + self.outputFile.write(fragment) if 'testParameterType' in self.userTestCase: if 'testParameters' in testMethod: @@ -781,61 +906,70 @@ def addUserTestMethod(self, testMethod): elif 'testParameters' in self.userTestCase: testParameters = self.userTestCase['testParameters'] + found = any('npRequests' in testMethod + for testMethod in self.userTestMethods) isMpiTestCase = 'npRequests' in self.userTestCase - isMpiTestCase = isMpiTestCase or any('npRequests' in testMethod for testMethod in self.userTestMethods) + isMpiTestCase = isMpiTestCase or found if 'testParameters' in locals(): testParameterArg = ', testParameter' - self.outputFile.write(' testParameters = ' + testParameters + '\n\n') + self.outputFile.write(' testParameters = ' + + testParameters + '\n\n') elif isMpiTestCase: testParameterArg = ', testParameter' - for npes in npRequests: if 'testParameters' in locals() or 'cases' in locals(): - self.outputFile.write(' do iParam = 1, size(testParameters)\n') - self.outputFile.write(' testParameter = testParameters(iParam)\n') + fragment = ' do iParam = 1, size(testParameters)\n' + self.outputFile.write(fragment) + fragment = ' testParameter = testParameters(iParam)\n' + self.outputFile.write(fragment) if isMpiTestCase: - self.outputFile.write(' call testParameter%setNumProcessesRequested(' + str(npes) + ')\n') + fragment = ' call testParameter%setNumProcessesRequested(' \ + + str(npes) + ')\n' + self.outputFile.write(fragment) - self.outputFile.write(' call suite%addTest(makeCustomTest(' + + self.outputFile.write(' call suite%addTest(makeCustomTest(' + args + testParameterArg + '))\n') if 'cases' in locals() or 'testParameters' in locals(): self.outputFile.write(' end do\n') - - def printMakeCustomTest(self, isMpiTestCase): args = 'methodName, testMethod' - declareArgs = '#ifdef INTEL_13\n' - declareArgs += ' use pfunit_mod, only: testCase\n' - declareArgs += '#endif\n' - declareArgs += ' type (WrapUserTestCase) :: aTest\n' - declareArgs += '#ifdef INTEL_13\n' - declareArgs += ' target :: aTest\n' - declareArgs += ' class (WrapUserTestCase), pointer :: p\n' - declareArgs += '#endif\n' + declareArgs = '#ifdef INTEL_13\n' + declareArgs += ' use pfunit_mod, only: testCase\n' + declareArgs += '#endif\n' + declareArgs += ' type (WrapUserTestCase) :: aTest\n' + declareArgs += '#ifdef INTEL_13\n' + declareArgs += ' target :: aTest\n' + declareArgs += ' class (WrapUserTestCase), pointer :: p\n' + declareArgs += '#endif\n' declareArgs += ' character(len=*), intent(in) :: methodName\n' declareArgs += ' procedure(userTestMethod) :: testMethod\n' - + if 'testParameterType' in self.userTestCase: args += ', testParameter' - declareArgs += ' type (' + self.userTestCase['testParameterType'] + '), intent(in) :: testParameter\n' + declareArgs += ' type (' \ + + self.userTestCase['testParameterType'] \ + + '), intent(in) :: testParameter\n' - self.outputFile.write(' function makeCustomTest(' + args + ') result(aTest)\n') + self.outputFile.write(' function makeCustomTest(' + + args + ') result(aTest)\n') self.outputFile.write(declareArgs) if 'constructor' in self.userTestCase: if 'testParameterType' in self.userTestCase: - constructor = self.userTestCase['constructor'] + '(testParameter)' + constructor = self.userTestCase['constructor'] \ + + '(testParameter)' else: constructor = self.userTestCase['constructor'] + '()' - self.outputFile.write(' aTest%' + self.userTestCase['type'] + ' = ' + constructor + '\n\n') + self.outputFile.write(' aTest%' + self.userTestCase['type'] + + ' = ' + constructor + '\n\n') self.outputFile.write(' aTest%testMethodPtr => testMethod\n') - + self.outputFile.write('#ifdef INTEL_13\n') self.outputFile.write(' p => aTest\n') self.outputFile.write(' call p%setName(methodName)\n') @@ -844,28 +978,30 @@ def printMakeCustomTest(self, isMpiTestCase): self.outputFile.write('#endif\n') if 'testParameterType' in self.userTestCase: - self.outputFile.write(' call aTest%setTestParameter(testParameter)\n') - + fragment = ' call aTest%setTestParameter(testParameter)\n' + self.outputFile.write(fragment) self.outputFile.write(' end function makeCustomTest\n') def makeWrapperModule(self): - #----------------------------------------------------------- + # ----------------------------------------------------------- # ! Start here self.printHeader() if 'type' in self.userTestCase: self.printWrapUserTestCase() - + self.outputFile.write('contains\n\n') if 'type' in self.userTestCase: self.printRunMethod() if 'type' in self.userTestCase: + found = any('npRequests' in testMethod + for testMethod in self.userTestMethods) isMpiTestCase = 'npRequests' in self.userTestCase - isMpiTestCase = isMpiTestCase or any('npRequests' in testMethod for testMethod in self.userTestMethods) - if isMpiTestCase and not 'testParameterType' in self.userTestCase: + isMpiTestCase = isMpiTestCase or found + if isMpiTestCase and 'testParameterType' not in self.userTestCase: self.userTestCase['testParameterType'] = 'MpiTestParameter' self.printMakeCustomTest(isMpiTestCase) @@ -877,12 +1013,33 @@ def final(self): self.inputFile.close() self.outputFile.close() + +def process_cli(): + ''' + Processes the arguments passed on the command line interface. + + Returns a tuple of source filename (str), target filename (str) and + whether to insert linemarkers rather than #line directives (bool). + ''' + import argparse + + description = 'Converts a pFUnit .pf file into compilable Fortran source.' + cli_parser = argparse.ArgumentParser(description=description, + add_help=False) + cli_parser.add_argument('-help', '-h', '--help', action='help', + help='Display this help and stop') + cli_parser.add_argument('-markers', action='store_true', + help='Use linemarkers instead of #line directives') + cli_parser.add_argument('source', help='Filename of .pf file') + cli_parser.add_argument('target', help='Filename of geenrated .f90 file') + arguments = cli_parser.parse_args() + return arguments.source, arguments.target, arguments.markers + + if __name__ == "__main__": - import sys - print("Processing file", sys.argv[1]) - p = Parser(sys.argv[1], sys.argv[2]) + source_filename, target_filename, use_markers = process_cli() + print("Processing file", source_filename) + p = Parser(source_filename, target_filename, use_markers) p.run() p.final() - print(" ... Done. Results in", sys.argv[2]) - - + print(" ... Done. Results in", target_filename) diff --git a/bin/parseDirectiveArgs.py b/bin/parseDirectiveArgs.py index e631a9d2..0fbf4a61 100755 --- a/bin/parseDirectiveArgs.py +++ b/bin/parseDirectiveArgs.py @@ -4,20 +4,27 @@ import unittest import collections + def flatten(l): - "http://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists-in-python" + """ + http://stackoverflow.com/ + questions/2158395/flatten-an-irregular-list-of-lists-in-python + """ if l: for el in l: - if isinstance(el, collections.Iterable) and not isinstance(el, (str,bytes)): -# The following is incompatible with python 3. -# if isinstance(el, collections.Iterable) and not isinstance(el, basestring): + if isinstance(el, collections.Iterable) \ + and not isinstance(el, (str, bytes)): + # The following is incompatible with python 3. + # if isinstance(el, collections.Iterable) \ + # and not isinstance(el, basestring): for sub in flatten(el): yield sub else: yield el + def parseDirectiveArguments(data): - + """Makes a list whose elements are delimited by commas in an input string. Commas inside a scope started with brackets, parens, single- @@ -27,14 +34,21 @@ def parseDirectiveArguments(data): syntax or ordering rules. It would be nice to throw an exception or emit warnings when we detect suspicious syntax. """ - - pos = 0; npos = len(data); str=''; maskCommas=False - scopeCounts = {'[':0,'(':0,'"':0,"'":0} # Assume well formed scopes. - scopeTerminators = {'[':']','(':')','"':'"',"'":"'"} - scopeNames = {'(':'parens','[':'brackets','"':'double quotes',"'":'single quotes'} + + pos = 0 + npos = len(data) + str = '' + maskCommas = False + scopeCounts = {'[': 0, '(': 0, '"': 0, "'": 0} # Assume well formed scopes + scopeTerminators = {'[': ']', '(': ')', '"': '"', "'": "'"} + scopeNames = {'(': 'parens', + '[': 'brackets', + '"': 'double quotes', + "'": 'single quotes'} while (pos < npos): if data[pos] == ',' and not maskCommas: - return [i for i in flatten([str,parseDirectiveArguments(data[pos+1:])])] + arguments = [str, parseDirectiveArguments(data[pos+1:])] + return [i for i in flatten(arguments)] else: for key in scopeCounts.keys(): if data[pos] == key: @@ -44,32 +58,40 @@ def parseDirectiveArguments(data): scopeCounts[key] = scopeCounts[key] - 1 if scopeCounts[key] < 0: # Maybe try exceptions... - print('parseDirectiveArguments::error: mismatched '+scopeNames[key]+' parenCount < 0 "',str,'" from "',data,'"') + print('parseDirectiveArguments::error: mismatched ' + + scopeNames[key] + ' parenCount < 0 "', str, + '" from "', data, '"') return None else: - maskCommas = sum(map(abs,scopeCounts.values())) > 0 + maskCommas = sum(map(abs, scopeCounts.values())) > 0 str = str + data[pos] pos = pos + 1 return [str] - - + + class TestParseDirectiveArgs(unittest.TestCase): def test_args1(self): - self.assertEqual(['a','b','c'],parseDirectiveArguments('a,b,c')) + self.assertEqual(['a', 'b', 'c'], parseDirectiveArguments('a,b,c')) def test_args2(self): - self.assertEqual(['a','b(1,2)','c((1,3,z(x,y(4))))'],parseDirectiveArguments('a,b(1,2),c((1,3,z(x,y(4))))')) + result = parseDirectiveArguments('a,b(1,2),c((1,3,z(x,y(4))))') + self.assertEqual(['a', 'b(1,2)', 'c((1,3,z(x,y(4))))'], result) def test_args3(self): - self.assertEqual(['a','b','c[d,e,f(x,y)]'],parseDirectiveArguments('a,b,c[d,e,f(x,y)]')) + self.assertEqual(['a', 'b', 'c[d,e,f(x,y)]'], + parseDirectiveArguments('a,b,c[d,e,f(x,y)]')) def test_args4(self): - self.assertEqual(['a','b','c[d,e,f(x,y]'],parseDirectiveArguments('a,b,c[d,e,f(x,y]')) + self.assertEqual(['a', 'b', 'c[d,e,f(x,y]'], + parseDirectiveArguments('a,b,c[d,e,f(x,y]')) def test_args5(self): - self.assertEqual(['a','b="This, is, a, test."'],parseDirectiveArguments('a,b="This, is, a, test."')) - self.assertEqual(["a","b='This, is, a, test.'"],parseDirectiveArguments("a,b='This, is, a, test.'")) + self.assertEqual(['a', 'b="This, is, a, test."'], + parseDirectiveArguments('a,b="This, is, a, test."')) + self.assertEqual(["a", "b='This, is, a, test.'"], + parseDirectiveArguments("a,b='This, is, a, test.'")) + if __name__ == '__main__': print('starting') diff --git a/bin/tests/expectedOutputs/MpiParameterizedTestCaseC.F90 b/bin/tests/expectedOutputs/MpiParameterizedTestCaseC.F90 index a4116ce1..99cb1d97 100644 --- a/bin/tests/expectedOutputs/MpiParameterizedTestCaseC.F90 +++ b/bin/tests/expectedOutputs/MpiParameterizedTestCaseC.F90 @@ -2,7 +2,6 @@ module TestCaseC_mod use pfunit_mod implicit none - !@testCase(constructor=newTestCaseC) type, extends(MpiTestCase) :: TestCaseC integer, allocatable :: table(:) @@ -150,34 +149,38 @@ subroutine runMethod(this) call this%testMethodPtr(this) end subroutine runMethod - function makeCustomTest(methodName, testMethod, testParameter, npesRequested) result(aTest) + function makeCustomTest(methodName, testMethod, testParameter) result(aTest) +#ifdef INTEL_13 + use pfunit_mod, only: testCase +#endif type (WrapUserTestCase) :: aTest +#ifdef INTEL_13 + target :: aTest + class (WrapUserTestCase), pointer :: p +#endif character(len=*), intent(in) :: methodName procedure(userTestMethod) :: testMethod type (C_Parameter), intent(in) :: testParameter - integer, optional, intent(in) :: npesRequested - aTest%TestCaseC = newTestCaseC(testParameter) aTest%testMethodPtr => testMethod +#ifdef INTEL_13 + p => aTest + call p%setName(methodName) +#else call aTest%setName(methodName) +#endif call aTest%setTestParameter(testParameter) - if (present(npesRequested)) then - call aTest%setNumProcessesRequested(npesRequested) - end if - end function makeCustomTest end module WrapTestCaseC_mod function TestCaseC_mod_suite() result(suite) use pFUnit_mod - use WrapTestCaseC_mod use TestCaseC_mod + use WrapTestCaseC_mod type (TestSuite) :: suite - integer, allocatable :: npes(:) - type (C_Parameter), allocatable :: testParameters(:) type (C_Parameter) :: testParameter integer :: iParam @@ -189,17 +192,20 @@ function TestCaseC_mod_suite() result(suite) do iParam = 1, size(testParameters) testParameter = testParameters(iParam) - call suite%addTest(makeCustomTest('testA', testA, testParameter, npesRequested=1)) + call testParameter%setNumProcessesRequested(1) + call suite%addTest(makeCustomTest('testA', testA, testParameter)) end do do iParam = 1, size(testParameters) testParameter = testParameters(iParam) - call suite%addTest(makeCustomTest('testA', testA, testParameter, npesRequested=3)) + call testParameter%setNumProcessesRequested(3) + call suite%addTest(makeCustomTest('testA', testA, testParameter)) end do testParameters = paramGenerator() do iParam = 1, size(testParameters) testParameter = testParameters(iParam) + call testParameter%setNumProcessesRequested(1) call suite%addTest(makeCustomTest('testB', testB, testParameter)) end do @@ -208,6 +214,7 @@ function TestCaseC_mod_suite() result(suite) do iParam = 1, size(testParameters) testParameter = testParameters(iParam) + call testParameter%setNumProcessesRequested(1) call suite%addTest(makeCustomTest('testC', testC, testParameter)) end do diff --git a/bin/tests/expectedOutputs/MpiTestCaseB.F90 b/bin/tests/expectedOutputs/MpiTestCaseB.F90 index 59396820..f0d39dd0 100644 --- a/bin/tests/expectedOutputs/MpiTestCaseB.F90 +++ b/bin/tests/expectedOutputs/MpiTestCaseB.F90 @@ -2,7 +2,6 @@ module MpiTestCaseB_mod use pfunit_mod implicit none - !@testCase(npes = [1,3,5]) type, extends(MpiTestCase) :: MpiTestCaseB integer :: componentI @@ -68,38 +67,54 @@ subroutine runMethod(this) call this%testMethodPtr(this) end subroutine runMethod - function makeCustomTest(methodName, testMethod, npesRequested) result(aTest) + function makeCustomTest(methodName, testMethod, testParameter) result(aTest) +#ifdef INTEL_13 + use pfunit_mod, only: testCase +#endif type (WrapUserTestCase) :: aTest +#ifdef INTEL_13 + target :: aTest + class (WrapUserTestCase), pointer :: p +#endif character(len=*), intent(in) :: methodName procedure(userTestMethod) :: testMethod - integer, optional, intent(in) :: npesRequested - + type (MpiTestParameter), intent(in) :: testParameter aTest%testMethodPtr => testMethod +#ifdef INTEL_13 + p => aTest + call p%setName(methodName) +#else call aTest%setName(methodName) - if (present(npesRequested)) then - call aTest%setNumProcessesRequested(npesRequested) - end if - +#endif + call aTest%setTestParameter(testParameter) end function makeCustomTest end module WrapMpiTestCaseB_mod function MpiTestCaseB_mod_suite() result(suite) use pFUnit_mod - use WrapMpiTestCaseB_mod use MpiTestCaseB_mod + use WrapMpiTestCaseB_mod type (TestSuite) :: suite - integer, allocatable :: npes(:) - + type (MpiTestParameter), allocatable :: testParameters(:) + type (MpiTestParameter) :: testParameter + integer :: iParam + integer, allocatable :: cases(:) + suite = newTestSuite('MpiTestCaseB_mod_suite') - call suite%addTest(makeCustomTest('testA', testA, npesRequested=1)) - call suite%addTest(makeCustomTest('testA', testA, npesRequested=2)) - - call suite%addTest(makeCustomTest('testB', testB, npesRequested=1)) - call suite%addTest(makeCustomTest('testB', testB, npesRequested=3)) - call suite%addTest(makeCustomTest('testB', testB, npesRequested=5)) + call testParameter%setNumProcessesRequested(1) + call suite%addTest(makeCustomTest('testA', testA, testParameter)) + call testParameter%setNumProcessesRequested(2) + call suite%addTest(makeCustomTest('testA', testA, testParameter)) + + call testParameter%setNumProcessesRequested(1) + call suite%addTest(makeCustomTest('testB', testB, testParameter)) + call testParameter%setNumProcessesRequested(3) + call suite%addTest(makeCustomTest('testB', testB, testParameter)) + call testParameter%setNumProcessesRequested(5) + call suite%addTest(makeCustomTest('testB', testB, testParameter)) end function MpiTestCaseB_mod_suite diff --git a/bin/tests/expectedOutputs/ParameterizedTestCaseB.F90 b/bin/tests/expectedOutputs/ParameterizedTestCaseB.F90 index afbd0863..3c373c42 100644 --- a/bin/tests/expectedOutputs/ParameterizedTestCaseB.F90 +++ b/bin/tests/expectedOutputs/ParameterizedTestCaseB.F90 @@ -2,7 +2,6 @@ module TestCaseB_mod use pfunit_mod implicit none - !@testCase(constructor=newTestCaseB) type, extends(ParameterizedTestCase) :: TestCaseB integer, allocatable :: table(:) @@ -98,14 +97,26 @@ subroutine runMethod(this) end subroutine runMethod function makeCustomTest(methodName, testMethod, testParameter) result(aTest) +#ifdef INTEL_13 + use pfunit_mod, only: testCase +#endif type (WrapUserTestCase) :: aTest +#ifdef INTEL_13 + target :: aTest + class (WrapUserTestCase), pointer :: p +#endif character(len=*), intent(in) :: methodName procedure(userTestMethod) :: testMethod type (B_Parameter), intent(in) :: testParameter aTest%TestCaseB = newTestCaseB(testParameter) aTest%testMethodPtr => testMethod +#ifdef INTEL_13 + p => aTest + call p%setName(methodName) +#else call aTest%setName(methodName) +#endif call aTest%setTestParameter(testParameter) end function makeCustomTest @@ -113,12 +124,10 @@ end module WrapTestCaseB_mod function TestCaseB_mod_suite() result(suite) use pFUnit_mod - use WrapTestCaseB_mod use TestCaseB_mod + use WrapTestCaseB_mod type (TestSuite) :: suite - integer, allocatable :: npes(:) - type (B_Parameter), allocatable :: testParameters(:) type (B_Parameter) :: testParameter integer :: iParam diff --git a/bin/tests/expectedOutputs/TestA.F90 b/bin/tests/expectedOutputs/TestA.F90 index 06306659..f8dc5e0a 100644 --- a/bin/tests/expectedOutputs/TestA.F90 +++ b/bin/tests/expectedOutputs/TestA.F90 @@ -13,7 +13,7 @@ end subroutine testMethodA !@test subroutine testMethodB() end subroutine testMethodB - + !@mpitest(npes=[1,3,5]) subroutine testMethodC(this) class (MpiTestMethod), intent(inout) :: this @@ -36,12 +36,10 @@ end module WrapTestA_mod function TestA_mod_suite() result(suite) use pFUnit_mod - use WrapTestA_mod use TestA_mod + use WrapTestA_mod type (TestSuite) :: suite - integer, allocatable :: npes(:) - suite = newTestSuite('TestA_mod_suite') call suite%addTest(newTestMethod('testMethodA', testMethodA)) diff --git a/bin/tests/expectedOutputs/TestCaseA.F90 b/bin/tests/expectedOutputs/TestCaseA.F90 index b0f0effb..2095d1d3 100644 --- a/bin/tests/expectedOutputs/TestCaseA.F90 +++ b/bin/tests/expectedOutputs/TestCaseA.F90 @@ -2,7 +2,6 @@ module TestCaseA_mod use pfunit_mod implicit none - !@testCase type, extends(TestCase) :: TestCaseA integer :: componentI @@ -67,23 +66,33 @@ subroutine runMethod(this) end subroutine runMethod function makeCustomTest(methodName, testMethod) result(aTest) +#ifdef INTEL_13 + use pfunit_mod, only: testCase +#endif type (WrapUserTestCase) :: aTest +#ifdef INTEL_13 + target :: aTest + class (WrapUserTestCase), pointer :: p +#endif character(len=*), intent(in) :: methodName procedure(userTestMethod) :: testMethod aTest%testMethodPtr => testMethod +#ifdef INTEL_13 + p => aTest + call p%setName(methodName) +#else call aTest%setName(methodName) +#endif end function makeCustomTest end module WrapTestCaseA_mod function TestCaseA_mod_suite() result(suite) use pFUnit_mod - use WrapTestCaseA_mod use TestCaseA_mod + use WrapTestCaseA_mod type (TestSuite) :: suite - integer, allocatable :: npes(:) - suite = newTestSuite('TestCaseA_mod_suite') call suite%addTest(makeCustomTest('testA', testA)) diff --git a/bin/tests/expectedOutputs/beforeAfter.F90 b/bin/tests/expectedOutputs/beforeAfter.F90 index d2ac63a6..cf82e629 100644 --- a/bin/tests/expectedOutputs/beforeAfter.F90 +++ b/bin/tests/expectedOutputs/beforeAfter.F90 @@ -40,8 +40,6 @@ function beforeAfter_suite() result(suite) external initA external finalA - integer, allocatable :: npes(:) - suite = newTestSuite('beforeAfter_suite') call suite%addTest(newTestMethod('testMethodA', testMethodA, initA, finalA)) diff --git a/bin/tests/expectedOutputs/simple.F90 b/bin/tests/expectedOutputs/simple.F90 index a040f807..f00eb077 100644 --- a/bin/tests/expectedOutputs/simple.F90 +++ b/bin/tests/expectedOutputs/simple.F90 @@ -37,8 +37,6 @@ function simple_suite() result(suite) external testMethodC - integer, allocatable :: npes(:) - suite = newTestSuite('simple_suite') call suite%addTest(newTestMethod('testMethodA', testMethodA)) diff --git a/bin/tests/inputs/MpiParameterizedTestCaseC.pf b/bin/tests/inputs/MpiParameterizedTestCaseC.pf index a22180b5..e1bf0b5d 100644 --- a/bin/tests/inputs/MpiParameterizedTestCaseC.pf +++ b/bin/tests/inputs/MpiParameterizedTestCaseC.pf @@ -2,7 +2,6 @@ module TestCaseC_mod use pfunit_mod implicit none - @testCase(constructor=newTestCaseC) type, extends(MpiTestCase) :: TestCaseC integer, allocatable :: table(:) diff --git a/bin/tests/inputs/MpiTestCaseB.pf b/bin/tests/inputs/MpiTestCaseB.pf index daf82893..46a74cf3 100644 --- a/bin/tests/inputs/MpiTestCaseB.pf +++ b/bin/tests/inputs/MpiTestCaseB.pf @@ -2,7 +2,6 @@ module MpiTestCaseB_mod use pfunit_mod implicit none - @testCase(npes = [1,3,5]) type, extends(MpiTestCase) :: MpiTestCaseB integer :: componentI diff --git a/bin/tests/inputs/ParameterizedTestCaseB.pf b/bin/tests/inputs/ParameterizedTestCaseB.pf index ddd64585..b3f56020 100644 --- a/bin/tests/inputs/ParameterizedTestCaseB.pf +++ b/bin/tests/inputs/ParameterizedTestCaseB.pf @@ -2,7 +2,6 @@ module TestCaseB_mod use pfunit_mod implicit none - @testCase(constructor=newTestCaseB) type, extends(ParameterizedTestCase) :: TestCaseB integer, allocatable :: table(:) diff --git a/bin/tests/inputs/TestA.pf b/bin/tests/inputs/TestA.pf index ee0ce16d..19dc0015 100644 --- a/bin/tests/inputs/TestA.pf +++ b/bin/tests/inputs/TestA.pf @@ -13,7 +13,7 @@ contains ! Second test subroutine testMethodB() end subroutine testMethodB - + @mpitest(npes=[1,3,5]) subroutine testMethodC(this) class (MpiTestMethod), intent(inout) :: this diff --git a/bin/tests/inputs/TestCaseA.pf b/bin/tests/inputs/TestCaseA.pf index fa9bb5da..e0dfb00f 100644 --- a/bin/tests/inputs/TestCaseA.pf +++ b/bin/tests/inputs/TestCaseA.pf @@ -2,7 +2,6 @@ module TestCaseA_mod use pfunit_mod implicit none - @testCase type, extends(TestCase) :: TestCaseA integer :: componentI diff --git a/bin/tests/runTests.sh b/bin/tests/runTests.sh index 6db1a6de..c3cc1e9b 100755 --- a/bin/tests/runTests.sh +++ b/bin/tests/runTests.sh @@ -1,8 +1,13 @@ -python testParser.py +#!/bin/sh +python -m unittest discover + +TESTS=$(find inputs -name '*.pf' -print) mkdir -p outputs -for file in simple beforeAfter TestA TestCaseA MpiTestCaseB ParameterizedTestCaseB MpiParameterizedTestCaseC +for file in $TESTS do - ../pFUnitParser.py inputs/${file}.pf outputs/${file}.F90 - diff outputs/${file}.F90 expectedOutputs/${file}.F90 + name=$(basename $file | sed 's/\..*$//') + + ../pFUnitParser.py ${file} outputs/${name}.F90 + diff outputs/${name}.F90 expectedOutputs/${name}.F90 done diff --git a/bin/tests/testParser.py b/bin/tests/testParser.py index 93cd113f..c68fe3a5 100644 --- a/bin/tests/testParser.py +++ b/bin/tests/testParser.py @@ -1,8 +1,18 @@ -import unittest +#!/usr/bin/env python + +from __future__ import print_function + +import os.path +import re +import shutil import sys +import tempfile +import unittest + sys.path.append('..') from pFUnitParser import * + class MockWriter(): def __init__(self, parser): self.parser = parser @@ -10,8 +20,10 @@ def __init__(self, parser): def write(self, line): self.parser.outLines.append(line) + class MockParser(Parser): def __init__(self, lines): + self.set_line = cpp_set_line self.saveLines = lines self.lines = self.saveLines[:] self.outputFile = MockWriter(self) @@ -32,11 +44,16 @@ def nextLine(self): def reset(self): self.lines = self.saveLines[:] + class TestParseLine(unittest.TestCase): - def testCppSetLineAndFile(self): - self.assertEqual('#line 7 "foo"\n', cppSetLineAndFile(7, 'foo')) - self.assertEqual('#line 3 "bar"\n', cppSetLineAndFile(3, 'bar')) + def testcpp_set_line(self): + self.assertEqual('#line 7 "foo"\n', cpp_set_line(7, 'foo')) + self.assertEqual('#line 3 "bar"\n', cpp_set_line(3, 'bar')) + + def testcompiler_set_line(self): + self.assertEqual('#7 "foo"\n', compiler_set_line(7, 'foo')) + self.assertEqual('#3 "bar"\n', compiler_set_line(3, 'bar')) def testGetSubroutineName(self): self.assertEqual('a', getSubroutineName('subroutine a()')) @@ -50,12 +67,13 @@ def testGetSelfObjectName(self): self.assertEqual('bc', getSelfObjectName('subroutine a(bc ,d)')) self.assertEqual('bc', getSelfObjectName('subroutine a(bc , d)')) - def testGetTypeName(self): self.assertEqual('foo', getTypeName(' type :: foo')) - self.assertEqual('foo', getTypeName(' type, extends(something) :: foo')) + self.assertEqual('foo', + getTypeName(' type, extends(something) :: foo')) self.assertEqual('foo', getTypeName(' type, abstract :: foo')) - self.assertEqual('foo', getTypeName(' type, extends(something), abstract :: foo')) + result = getTypeName(' type, extends(something), abstract :: foo') + self.assertEqual('foo', result) def testAtTest(self): """Check that a line starting with '@test' is detected as an @@ -63,16 +81,18 @@ def testAtTest(self): nextLine = 'subroutine myTest()\n' parser = MockParser([nextLine]) atTest = AtTest(parser) - + self.assertTrue(atTest.match('@test')) self.assertFalse(atTest.match('! @test')) - self.assertTrue(atTest.match(' @test')) # leading space - self.assertTrue(atTest.match('@TEST')) # case insensitive - self.assertTrue(atTest.match('@Test')) # mixed case - self.assertFalse(atTest.match('@Testb')) # can't have trailing characters without whitespace + self.assertTrue(atTest.match(' @test')) # leading space + self.assertTrue(atTest.match('@TEST')) # case insensitive + self.assertTrue(atTest.match('@Test')) # mixed case + # Can't have trailing characters without whitespace + self.assertFalse(atTest.match('@Testb')) self.assertTrue(atTest.match('@Test (b)')) self.assertTrue(atTest.match('@Test(b)')) - self.assertFalse(atTest.match('@Test b')) # next non-space character needs to be '(') + # Next non-space character needs to be '(') + self.assertFalse(atTest.match('@Test b')) self.assertTrue(atTest.match('@Test(timeout=3.0)')) self.assertFalse(atTest.match('! @Test')) self.assertFalse(atTest.match('@assertTrue')) @@ -80,8 +100,8 @@ def testAtTest(self): atTest.apply('@test\n') self.assertEqual('myTest', parser.userTestMethods[0]['name']) - self.assertEqual('!@test\n',parser.outLines[0]) - self.assertEqual(nextLine,parser.outLines[1]) + self.assertEqual('!@test\n', parser.outLines[0]) + self.assertEqual(nextLine, parser.outLines[1]) def testAtTestNoParens(self): """Check that test procedure with no parens is accepted.""" @@ -90,36 +110,36 @@ def testAtTestNoParens(self): atTest = AtTest(parser) m = atTest.match('@test\n') - atTest.action(m,'@test\n') + atTest.action(m, '@test\n') self.assertEqual('myTest', parser.userTestMethods[0]['name']) - self.assertEqual('!@test\n',parser.outLines[0]) - self.assertEqual(nextLine,parser.outLines[1]) + self.assertEqual('!@test\n', parser.outLines[0]) + self.assertEqual(nextLine, parser.outLines[1]) def testAtTestFail(self): - """Check that useful error is sent if next line is not properly formatted.""" - - nextLine = 'subroutine myTest (] \n' # bad closing paren + """ + Check that useful error is sent if next line is not properly formatted. + """ + nextLine = 'subroutine myTest (] \n' # bad closing paren parser = MockParser([nextLine]) - + with self.assertRaises(MyError): atTest = AtTest(parser) line = '@test' m = atTest.match(line) atTest.action(m, line) - def testAtTestSkipComment(self): """Ignore comment lines between @test and subroutine foo().""" nextLineA = '! ignore this line \n' nextLineB = '\n' nextLineC = 'subroutine myTestC()\n' - parser = MockParser([nextLineA,nextLineB,nextLineC]) + parser = MockParser([nextLineA, nextLineB, nextLineC]) atTest = AtTest(parser) atTest.apply('@test\n') self.assertEqual('myTestC', parser.userTestMethods[0]['name']) - self.assertEqual('!@test\n',parser.outLines[0]) - self.assertEqual(nextLineC,parser.outLines[1]) + self.assertEqual('!@test\n', parser.outLines[0]) + self.assertEqual(nextLineC, parser.outLines[1]) def testAtMpiTest(self): """Check that a line starting with '@mpitest' is detected as an @@ -132,7 +152,7 @@ def testAtMpiTest(self): line = '@mpitest(npes=[1])' m = atMpiTest.match(line) self.assertTrue(m) - atMpiTest.action(m,line) + atMpiTest.action(m, line) self.assertEqual([1], parser.userTestMethods[0]['npRequests']) self.assertFalse('ifdef' in parser.userTestMethods[0]) @@ -141,7 +161,7 @@ def testAtMpiTest(self): parser.reset() m = atMpiTest.match(line) self.assertTrue(m) - atMpiTest.action(m,line) + atMpiTest.action(m, line) self.assertEqual([1], parser.userTestMethods[1]['npRequests']) self.assertFalse('ifdef' in parser.userTestMethods[1]) @@ -149,19 +169,17 @@ def testAtMpiTest(self): parser.reset() m = atMpiTest.match(line) self.assertTrue(m) - atMpiTest.action(m,line) - self.assertEqual([1,2,3], parser.userTestMethods[2]['npRequests']) + atMpiTest.action(m, line) + self.assertEqual([1, 2, 3], parser.userTestMethods[2]['npRequests']) self.assertEqual('USE_MPI', parser.userTestMethods[2]['ifdef']) line = '@mpitest(npes=[3],ifdef=USE_MPI)' parser.reset() m = atMpiTest.match(line) self.assertTrue(m) - atMpiTest.action(m,line) + atMpiTest.action(m, line) self.assertEqual([3], parser.userTestMethods[3]['npRequests']) self.assertEqual('USE_MPI', parser.userTestMethods[3]['ifdef']) - - def testMatchAtTestCase(self): """Check that a line starting with '@testcase' is detected as an @@ -171,10 +189,11 @@ def testMatchAtTestCase(self): atTestCase = AtTestCase(parser) self.assertTrue(atTestCase.match('@testcase')) - self.assertTrue(atTestCase.match(' @testcase')) # leading space - self.assertTrue(atTestCase.match('@TESTCASE')) # case insensitive - self.assertTrue(atTestCase.match('@TestCase')) # mixed case - self.assertFalse(atTestCase.match('@TestCaseb')) # can't have trailing characters without whitespace + self.assertTrue(atTestCase.match(' @testcase')) # leading space + self.assertTrue(atTestCase.match('@TESTCASE')) # case insensitive + self.assertTrue(atTestCase.match('@TestCase')) # mixed case + # Can't have trailing characters without whitespace + self.assertFalse(atTestCase.match('@TestCaseb')) atTestCase.apply('@testCase\n') self.assertEqual('myTestCase', parser.userTestCase['type']) @@ -190,8 +209,9 @@ def testMatchAtAssertEqual(self): self.assertFalse(atAssert.match('@assertEqual')) self.assertFalse(atAssert.match('@assertEqual()')) self.assertTrue(atAssert.match('@assertEqual(a, b)')) - self.assertTrue(atAssert.match('@assertequal(a, b)')) # case insensitive - self.assertTrue(atAssert.match('@ASSERTEQUAL(a, b)')) # case insensitive + # Case insensitive + self.assertTrue(atAssert.match('@assertequal(a, b)')) + self.assertTrue(atAssert.match('@ASSERTEQUAL(a, b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 @@ -207,29 +227,48 @@ def testMatchAtAssertEqual(self): def testParseArgsFirstRest(self): """Test that the first-rest argument parsing is adequate.""" - self.assertEqual(['a1','b1'],parseArgsFirstRest('','a1,b1')) - self.assertEqual(['a4()','b4'],parseArgsFirstRest('','a4(),b4')) - self.assertEqual(['a4%z()','b4'],parseArgsFirstRest('','a4%z(),b4')) - self.assertEqual(['a4','b4%z()'],parseArgsFirstRest('','a4,b4%z()')) - self.assertEqual(['a10','b10,c10'],parseArgsFirstRest('','a10,b10,c10')) - self.assertEqual(['a2'],parseArgsFirstRest("@assertassociated","@assertassociated(a2)")) - self.assertEqual(['a3',"b3,message='This is the message.'"], \ - parseArgsFirstRest("@assertassociated","@assertassociated(a3,b3,message='This is the message.')")) - self.assertEqual(['a','b,c,d'],parseArgsFirstRest("@assertassociated","@assertassociated(a,b,c,d)")) + self.assertEqual(['a1', 'b1'], + parseArgsFirstRest('', 'a1,b1')) + self.assertEqual(['a4()', 'b4'], + parseArgsFirstRest('', 'a4(),b4')) + self.assertEqual(['a4%z()', 'b4'], + parseArgsFirstRest('', 'a4%z(),b4')) + self.assertEqual(['a4', 'b4%z()'], + parseArgsFirstRest('', 'a4,b4%z()')) + self.assertEqual(['a10', 'b10,c10'], + parseArgsFirstRest('', 'a10,b10,c10')) + self.assertEqual(['a2'], + parseArgsFirstRest("@assertassociated", + "@assertassociated(a2)")) + fragment = "@assertassociated(a3,b3,message='This is the message.')" + result = parseArgsFirstRest("@assertassociated", fragment) + self.assertEqual(['a3', "b3,message='This is the message.'"], result) + self.assertEqual(['a', 'b,c,d'], + parseArgsFirstRest("@assertassociated", + "@assertassociated(a,b,c,d)")) def testParseArgsFirstSecondRest(self): """Test that the first-second-rest argument parsing is adequate.""" - self.assertEqual(None,parseArgsFirstSecondRest("@assertassociated","@assertassociated")) - self.assertEqual(None,parseArgsFirstSecondRest("@assertassociated","@assertassociated()")) - self.assertEqual(['a'],parseArgsFirstSecondRest("@assertassociated","@assertassociated(a)")) - self.assertEqual(['a','b'],parseArgsFirstSecondRest("@assertassociated","@assertassociated(a,b)")) - self.assertEqual(['a','b',"message='This is the message.'"], \ - parseArgsFirstSecondRest("@assertassociated", \ - "@assertassociated(a,b,message='This is the message.')")) - self.assertEqual(['a','b%z()','c,d'],parseArgsFirstSecondRest("@assertassociated", \ - "@assertassociated(a,b%z(),c,d)")) - self.assertEqual(['a4','b4','c4'],parseArgsFirstSecondRest('','a4,b4,c4')) - + self.assertEqual(None, + parseArgsFirstSecondRest("@assertassociated", + "@assertassociated")) + self.assertEqual(None, + parseArgsFirstSecondRest("@assertassociated", + "@assertassociated()")) + self.assertEqual(['a'], + parseArgsFirstSecondRest("@assertassociated", + "@assertassociated(a)")) + self.assertEqual(['a', 'b'], + parseArgsFirstSecondRest("@assertassociated", + "@assertassociated(a,b)")) + fragment = "@assertassociated(a,b,message='This is the message.')" + result = parseArgsFirstSecondRest("@assertassociated", fragment) + self.assertEqual(['a', 'b', "message='This is the message.'"], result) + result = parseArgsFirstSecondRest("@assertassociated", + "@assertassociated(a,b%z(),c,d)") + self.assertEqual(['a', 'b%z()', 'c,d'], result) + self.assertEqual(['a4', 'b4', 'c4'], + parseArgsFirstSecondRest('', 'a4,b4,c4')) def testMatchAtAssertAssociated(self): """Check that a line starting with '@assertAssociated' is detected @@ -240,14 +279,16 @@ def testMatchAtAssertAssociated(self): self.assertFalse(atAssertAssociated.match('@assertAssociated')) self.assertFalse(atAssertAssociated.match('@assertAssociated()')) self.assertTrue(atAssertAssociated.match('@assertAssociated(a)')) - self.assertTrue(atAssertAssociated.match('@assertassociated(a)')) # case insensitive - self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertAssociated.match('@assertassociated(a)')) + self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertAssociated.apply(' @assertAssociated(a)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertTrue(associated(a), &\n", parser.outLines[1]) + self.assertEqual(" call assertTrue(associated(a), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -266,15 +307,18 @@ def testMatchAtAssertAssociatedOverloaded1(self): self.assertFalse(atAssertAssociated.match('@assertAssociated')) self.assertFalse(atAssertAssociated.match('@assertAssociated()')) self.assertTrue(atAssertAssociated.match('@assertAssociated(a)')) - self.assertTrue(atAssertAssociated.match('@assertassociated(a,b)')) # case insensitive - self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a,b)')) # case insensitive - self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a_%z(),b)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertAssociated.match('@assertassociated(a,b)')) + self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a,b)')) + self.assertTrue( + atAssertAssociated.match('@ASSERTASSOCIATED(a_%z(),b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertAssociated.apply(' @assertAssociated(a,b)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertTrue(associated(a,b), &\n", parser.outLines[1]) + self.assertEqual(" call assertTrue(associated(a,b), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -293,15 +337,18 @@ def testMatchAtAssertAssociatedOverloaded2(self): self.assertFalse(atAssertAssociated.match('@assertAssociated')) self.assertFalse(atAssertAssociated.match('@assertAssociated()')) self.assertTrue(atAssertAssociated.match('@assertAssociated(a)')) - self.assertTrue(atAssertAssociated.match('@assertassociated(a,b)')) # case insensitive - self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a,b)')) # case insensitive - self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a_%z(),b)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertAssociated.match('@assertassociated(a,b)')) + self.assertTrue(atAssertAssociated.match('@ASSERTASSOCIATED(a,b)')) + self.assertTrue( + atAssertAssociated.match('@ASSERTASSOCIATED(a_%z(),b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertAssociated.apply(' @assertAssociated(a,b,message="c")\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(' call assertTrue(associated(a,b), message="c", &\n', parser.outLines[1]) + self.assertEqual(' call assertTrue(associated(a,b), message="c", &\n', + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -309,7 +356,6 @@ def testMatchAtAssertAssociatedOverloaded2(self): self.assertEqual(" if (anyExceptions()) return\n", parser.outLines[6]) self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[7]) - def testMatchAtAssertUnAssociated(self): """Check that a line starting with '@assertUnAssociated' is detected as an annotation.""" @@ -319,14 +365,16 @@ def testMatchAtAssertUnAssociated(self): self.assertFalse(atAssertUnAssociated.match('@assertUnAssociated')) self.assertFalse(atAssertUnAssociated.match('@assertUnAssociated()')) self.assertTrue(atAssertUnAssociated.match('@assertUnAssociated(a)')) - self.assertTrue(atAssertUnAssociated.match('@assertunassociated(a)')) # case insensitive - self.assertTrue(atAssertUnAssociated.match('@ASSERTUNASSOCIATED(a)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertUnAssociated.match('@assertunassociated(a)')) + self.assertTrue(atAssertUnAssociated.match('@ASSERTUNASSOCIATED(a)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertUnAssociated.apply(' @assertUnAssociated(a)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertFalse(associated(a), &\n", parser.outLines[1]) + self.assertEqual(" call assertFalse(associated(a), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -335,22 +383,26 @@ def testMatchAtAssertUnAssociated(self): self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[7]) def testMatchAtAssertUnAssociatedWith(self): - """Check that a line starting with '@assertUnAssociatedWith' is detected - as an annotation. atAssertUnAssociated(a,b) implies a points to b.""" + """ + Check that a line starting with '@assertUnAssociatedWith' is detected + as an annotation. atAssertUnAssociated(a,b) implies a points to b. + """ parser = MockParser([' \n']) atAssertUnAssociated = AtAssertNotAssociated(parser) self.assertFalse(atAssertUnAssociated.match('@assertUnAssociated')) self.assertFalse(atAssertUnAssociated.match('@assertUnAssociated()')) self.assertTrue(atAssertUnAssociated.match('@assertUnAssociated(a)')) - self.assertTrue(atAssertUnAssociated.match('@assertunassociated(a,b)')) # case insensitive - self.assertTrue(atAssertUnAssociated.match('@ASSERTUNASSOCIATED(a,b)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertUnAssociated.match('@assertunassociated(a,b)')) + self.assertTrue(atAssertUnAssociated.match('@ASSERTUNASSOCIATED(a,b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertUnAssociated.apply(' @assertUnAssociated(a,b)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertFalse(associated(a,b), &\n", parser.outLines[1]) + self.assertEqual(" call assertFalse(associated(a,b), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -367,14 +419,16 @@ def testMatchAtAssertNotassociated(self): self.assertFalse(atAssertNotassociated.match('@assertNotassociated')) self.assertFalse(atAssertNotassociated.match('@assertNotassociated()')) self.assertTrue(atAssertNotassociated.match('@assertNotassociated(a)')) - self.assertTrue(atAssertNotassociated.match('@assertnotassociated(a)')) # case insensitive - self.assertTrue(atAssertNotassociated.match('@ASSERTNOTASSOCIATED(a)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertNotassociated.match('@assertnotassociated(a)')) + self.assertTrue(atAssertNotassociated.match('@ASSERTNOTASSOCIATED(a)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertNotassociated.apply(' @assertNotassociated(a)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertFalse(associated(a), &\n", parser.outLines[1]) + self.assertEqual(" call assertFalse(associated(a), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -383,48 +437,62 @@ def testMatchAtAssertNotassociated(self): self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[7]) def testMatchAtAssertNotassociatedWith(self): - """Check that a line starting with '@assertNotassociatedWith' is detected - as an annotation. atAssertNotassociated(a,b) implies a points to b.""" + """ + Check that a line starting with '@assertNotassociatedWith' is detected + as an annotation. atAssertNotassociated(a,b) implies a points to b. + """ parser = MockParser([' \n']) atAssertNotassociated = AtAssertNotAssociated(parser) self.assertFalse(atAssertNotassociated.match('@assertNotassociated')) self.assertFalse(atAssertNotassociated.match('@assertNotassociated()')) self.assertTrue(atAssertNotassociated.match('@assertNotassociated(a)')) - self.assertTrue(atAssertNotassociated.match('@assertnotassociated(a,b)')) # case insensitive - self.assertTrue(atAssertNotassociated.match('@ASSERTNOTASSOCIATED(a,b)')) # case insensitive + # Case insensitive + self.assertTrue( + atAssertNotassociated.match('@assertnotassociated(a,b)')) + self.assertTrue( + atAssertNotassociated.match('@ASSERTNOTASSOCIATED(a,b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertNotassociated.apply(' @assertNotassociated(a,b)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(" call assertFalse(associated(a,b), &\n", parser.outLines[1]) + self.assertEqual(" call assertFalse(associated(a,b), &\n", + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) self.assertEqual(" )\n", parser.outLines[5]) self.assertEqual(" if (anyExceptions()) return\n", parser.outLines[6]) self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[7]) - def testMatchAtAssertEqualUserDefined(self): - """Check that a line starting with '@assertEqualUserDefined' is detected - as an annotation. atAssertEqualUserDefined(a,b) implies a points to b.""" + """ + Check that a line starting with '@assertEqualUserDefined' is detected + as an annotation. atAssertEqualUserDefined(a,b) implies a points to b. + """ parser = MockParser([' \n']) atAssertEqualUserDefined = AtAssertEqualUserDefined(parser) - self.assertFalse(atAssertEqualUserDefined.match('@assertEqualUserDefined')) - self.assertFalse(atAssertEqualUserDefined.match('@assertEqualUserDefined()')) - self.assertFalse(atAssertEqualUserDefined.match('@assertEqualUserDefined(a)')) - self.assertTrue(atAssertEqualUserDefined.match('@assertequaluserdefined(a,b)')) # case insensitive - self.assertTrue(atAssertEqualUserDefined.match('@ASSERTEQUALUSERDEFINED(a,b)')) # case insensitive + self.assertFalse( + atAssertEqualUserDefined.match('@assertEqualUserDefined')) + self.assertFalse( + atAssertEqualUserDefined.match('@assertEqualUserDefined()')) + self.assertFalse( + atAssertEqualUserDefined.match('@assertEqualUserDefined(a)')) + # Case insensitive + self.assertTrue( + atAssertEqualUserDefined.match('@assertequaluserdefined(a,b)')) + self.assertTrue( + atAssertEqualUserDefined.match('@ASSERTEQUALUSERDEFINED(a,b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertEqualUserDefined.apply(' @assertEqualUserDefined(a,b)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) self.assertEqual(" call assertTrue(a==b, &\n", parser.outLines[1]) - self.assertEqual(" & message=' not equal to ', &\n", parser.outLines[2]) + self.assertEqual(" & message=' not equal to ', &\n", + parser.outLines[2]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[3]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[4]) self.assertEqual(" & 8)", parser.outLines[5]) @@ -433,16 +501,20 @@ def testMatchAtAssertEqualUserDefined(self): self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[8]) def testMatchAtAssertEqualUserDefinedWithMessage(self): - """Check that a line starting with '@assertEqualUserDefined' is detected - as an annotation. atAssertEqualUserDefined(a,b) implies a points to b.""" + """ + Check that a line starting with '@assertEqualUserDefined' is detected + as an annotation. atAssertEqualUserDefined(a,b) implies a points to b. + """ parser = MockParser([' \n']) atAssertEqualUserDefined = AtAssertEqualUserDefined(parser) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 - atAssertEqualUserDefined.apply(' @assertEqualUserDefined(a,b,message="c")\n') + text = ' @assertEqualUserDefined(a,b,message="c")\n' + atAssertEqualUserDefined.apply(text) self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) - self.assertEqual(' call assertTrue(a==b, message="c", &\n', parser.outLines[1]) + self.assertEqual(' call assertTrue(a==b, message="c", &\n', + parser.outLines[1]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[2]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertEqual(" & 8)", parser.outLines[4]) @@ -459,15 +531,17 @@ def testMatchAtAssertEquivalent(self): self.assertFalse(atAssertEquivalent.match('@assertEquivalent')) self.assertFalse(atAssertEquivalent.match('@assertEquivalent()')) self.assertFalse(atAssertEquivalent.match('@assertEquivalent(a)')) - self.assertTrue(atAssertEquivalent.match('@assertequivalent(a,b)')) # case insensitive - self.assertTrue(atAssertEquivalent.match('@ASSERTEQUIVALENT(a,b)')) # case insensitive + # Case insensitive + self.assertTrue(atAssertEquivalent.match('@assertequivalent(a,b)')) + self.assertTrue(atAssertEquivalent.match('@ASSERTEQUIVALENT(a,b)')) parser.fileName = "foo.pfunit" parser.currentLineNumber = 8 atAssertEquivalent.apply(' @assertEquivalent(a,b)\n') self.assertEqual('#line 8 "foo.pfunit"\n', parser.outLines[0]) self.assertEqual(" call assertTrue(a.eqv.b, &\n", parser.outLines[1]) - self.assertEqual(" & message=' not equal to ', &\n", parser.outLines[2]) + self.assertEqual(" & message=' not equal to ', &\n", + parser.outLines[2]) self.assertEqual(" & location=SourceLocation( &\n", parser.outLines[3]) self.assertEqual(" & 'foo.pfunit', &\n", parser.outLines[4]) self.assertEqual(" & 8)", parser.outLines[5]) @@ -475,7 +549,6 @@ def testMatchAtAssertEquivalent(self): self.assertEqual(" if (anyExceptions()) return\n", parser.outLines[7]) self.assertEqual('#line 9 "foo.pfunit"\n', parser.outLines[8]) - def testMatchAtAssertOther(self): """Check that a line starting with '@assert*' is detected as an annotation.""" @@ -485,8 +558,9 @@ def testMatchAtAssertOther(self): self.assertFalse(atAssert.match('@assertTrue')) self.assertFalse(atAssert.match('@assertTrue()')) self.assertTrue(atAssert.match('@assertTrue(a)')) - self.assertTrue(atAssert.match('@asserttrue(a)')) # case insensitive - self.assertTrue(atAssert.match('@ASSERTTRUE(a)')) # case insensitive + # Case insensitive + self.assertTrue(atAssert.match('@asserttrue(a)')) + self.assertTrue(atAssert.match('@ASSERTTRUE(a)')) parser.fileName = 'foo.pfunit' parser.currentLineNumber = 8 @@ -510,8 +584,9 @@ def testMatchAtMpiAssert(self): self.assertFalse(atMpiAssert.match('@mpiAssertTrue()')) self.assertTrue(atMpiAssert.match('@mpiAssertTrue(a)')) self.assertTrue(atMpiAssert.match('@mpiAssertTrue(a,b)')) - self.assertTrue(atMpiAssert.match('@mpiasserttrue(a)')) # case insensitive - self.assertTrue(atMpiAssert.match('@MPIASSERTTRUE(a)')) # case insensitive + # Case insensitive + self.assertTrue(atMpiAssert.match('@mpiasserttrue(a)')) + self.assertTrue(atMpiAssert.match('@MPIASSERTTRUE(a)')) parser.fileName = 'foo.pfunit' parser.currentLineNumber = 8 @@ -522,13 +597,14 @@ def testMatchAtMpiAssert(self): self.assertTrue(" & 'foo.pfunit', &\n", parser.outLines[3]) self.assertTrue(" & 8)", parser.outLines[4]) self.assertTrue(" )\n", parser.outLines[5]) - self.assertTrue(" if (anyExceptions(this%getMpiCommunicator())) return\n", parser.outLines[6]) + expected = " if (anyExceptions(this%getMpiCommunicator())) return\n" + self.assertTrue(expected, parser.outLines[6]) self.assertTrue("#line 9 'foo.pfunit'\n", parser.outLines[7]) def testMatchAtBefore(self): - """Check that a line starting with '@before*' ...""" + """Check that a line starting with '@before*' ...""" procedure = 'mySetUp' - nextLine = 'subroutine ' + procedure +'()\n' + nextLine = 'subroutine ' + procedure + '()\n' parser = MockParser([nextLine]) atBefore = AtBefore(parser) self.assertTrue(atBefore.match(' @before')) @@ -539,11 +615,10 @@ def testMatchAtBefore(self): self.assertEqual('!@before\n', parser.outLines[0]) self.assertEqual(nextLine, parser.outLines[1]) - def testMatchAtAfter(self): - """Check that a line starting with '@after*' ...""" + """Check that a line starting with '@after*' ...""" procedure = 'myTearDown' - nextLine = 'subroutine ' + procedure +'()\n' + nextLine = 'subroutine ' + procedure + '()\n' parser = MockParser([nextLine]) atAfter = AtAfter(parser) self.assertTrue(atAfter.match(' @after')) @@ -555,7 +630,9 @@ def testMatchAtAfter(self): self.assertEqual(nextLine, parser.outLines[1]) def testMatchAtSuite(self): - """Check that a line starting with '@suite changes the suite name ...""" + """ + Check that a line starting with '@suite changes the suite name ... + """ parser = MockParser(['\n']) atSuite = AtSuite(parser) self.assertTrue(atSuite.match(" @suite (name='a')")) @@ -569,5 +646,295 @@ def testMatchAtSuite(self): self.assertEqual('mySuite', parser.suiteName) +class TestParser(unittest.TestCase): + _FUNIT_SOURCE = '''module test_mod + implicit none + private + @TestCase + type, public, extends(TestCase) :: test_type + contains + procedure setUp + procedure tearDown + procedure testTest + end type test_type +contains + subroutine setUp(this) + implicit none + class(test_type), intent(inout) :: this + end subroutine setUp + subroutine tearDown(this) + implicit none + class(test_type), intent(inout) :: this + end subroutine tearDown + @test + subroutine testTest(this) + implicit none + class(test_type), intent(inout) :: this + @assertEqual(2, 4) + end subroutine testTest +end module test_mod +''' + + def setUp(self): + self._re_type = type(re.compile('hello, world')) + self._directory = tempfile.mkdtemp() + self._source_filename = os.path.join(self._directory, 'test.pf') + self._target_filename = os.path.join(self._directory, 'test.F90') + + with open(self._source_filename, 'w') as source: + print(TestParser._FUNIT_SOURCE, file=source) + + def tearDown(self): + shutil.rmtree(self._directory) + + def testLinemarkers(self): + expected = ['module test_mod', + ' implicit none', + ' private', + ' !@TestCase', + ' type, public, extends(TestCase) :: test_type', + ' contains', + ' procedure setUp', + ' procedure tearDown', + ' procedure testTest', + ' end type test_type', + 'contains', + ' subroutine setUp(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + ' end subroutine setUp', + ' subroutine tearDown(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + ' end subroutine tearDown', + ' !@test', + ' subroutine testTest(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + re.compile(r'#24 "/(\S+)/test.pf"'), + ' call assertEqual(2, 4, &', + ' & location=SourceLocation( &', + ' & \'test.pf\', &', + ' & 24) )', + ' if (anyExceptions()) return', + re.compile(r'#25 "/(\S+)/test.pf"'), + ' end subroutine testTest', + 'end module test_mod', + '', + '', + 'module Wraptest_mod', + ' use pFUnit_mod', + ' use test_mod', + ' implicit none', + ' private', + '', + ' public :: WrapUserTestCase', + ' public :: makeCustomTest', + ' type, extends(test_type) :: WrapUserTestCase', + ' procedure(userTestMethod), nopass, pointer :: ' + + 'testMethodPtr', + ' contains', + ' procedure :: runMethod', + ' end type WrapUserTestCase', + '', + ' abstract interface', + ' subroutine userTestMethod(this)', + ' use test_mod', + ' class (test_type), intent(inout) :: this', + ' end subroutine userTestMethod', + ' end interface', + '', + 'contains', + '', + ' subroutine runMethod(this)', + ' class (WrapUserTestCase), intent(inout) :: this', + '', + ' call this%testMethodPtr(this)', + ' end subroutine runMethod', + '', + ' function makeCustomTest(methodName, testMethod) ' + + 'result(aTest)', + '#ifdef INTEL_13', + ' use pfunit_mod, only: testCase', + '#endif', + ' type (WrapUserTestCase) :: aTest', + '#ifdef INTEL_13', + ' target :: aTest', + ' class (WrapUserTestCase), pointer :: p', + '#endif', + ' character(len=*), intent(in) :: methodName', + ' procedure(userTestMethod) :: testMethod', + ' aTest%testMethodPtr => testMethod', + '#ifdef INTEL_13', + ' p => aTest', + ' call p%setName(methodName)', + '#else', + ' call aTest%setName(methodName)', + '#endif', + ' end function makeCustomTest', + '', + 'end module Wraptest_mod', + '', + 'function test_mod_suite() result(suite)', + ' use pFUnit_mod', + ' use test_mod', + ' use Wraptest_mod', + ' type (TestSuite) :: suite', + '', + " suite = newTestSuite('test_mod_suite')", + '', + " call suite%addTest(makeCustomTest('testTest', " + + "testTest))", + '', + '', + 'end function test_mod_suite', + ''] + + unit_under_test = Parser(self._source_filename, + self._target_filename, + True) + unit_under_test.run() + unit_under_test.final() + + with open(self._target_filename, 'r') as target: + result = target.read().splitlines() + + while len(expected) > 0: + model = expected.pop(0) + actual = result.pop(0) + + if isinstance(model, self._re_type): + self.assertRegexpMatches(actual, model) + else: + self.assertEqual(actual, model) + + self.assertListEqual([], expected) + self.assertListEqual([], result) + + def testLineDirectives(self): + expected = ['module test_mod', + ' implicit none', + ' private', + ' !@TestCase', + ' type, public, extends(TestCase) :: test_type', + ' contains', + ' procedure setUp', + ' procedure tearDown', + ' procedure testTest', + ' end type test_type', + 'contains', + ' subroutine setUp(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + ' end subroutine setUp', + ' subroutine tearDown(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + ' end subroutine tearDown', + ' !@test', + ' subroutine testTest(this)', + ' implicit none', + ' class(test_type), intent(inout) :: this', + re.compile(r'#line 24 "/(\S+)/test.pf"'), + ' call assertEqual(2, 4, &', + ' & location=SourceLocation( &', + ' & \'test.pf\', &', + ' & 24) )', + ' if (anyExceptions()) return', + re.compile(r'#line 25 "/(\S+)/test.pf"'), + ' end subroutine testTest', + 'end module test_mod', + '', + '', + 'module Wraptest_mod', + ' use pFUnit_mod', + ' use test_mod', + ' implicit none', + ' private', + '', + ' public :: WrapUserTestCase', + ' public :: makeCustomTest', + ' type, extends(test_type) :: WrapUserTestCase', + ' procedure(userTestMethod), nopass, pointer :: ' + + 'testMethodPtr', + ' contains', + ' procedure :: runMethod', + ' end type WrapUserTestCase', + '', + ' abstract interface', + ' subroutine userTestMethod(this)', + ' use test_mod', + ' class (test_type), intent(inout) :: this', + ' end subroutine userTestMethod', + ' end interface', + '', + 'contains', + '', + ' subroutine runMethod(this)', + ' class (WrapUserTestCase), intent(inout) :: this', + '', + ' call this%testMethodPtr(this)', + ' end subroutine runMethod', + '', + ' function makeCustomTest(methodName, testMethod) ' + + 'result(aTest)', + '#ifdef INTEL_13', + ' use pfunit_mod, only: testCase', + '#endif', + ' type (WrapUserTestCase) :: aTest', + '#ifdef INTEL_13', + ' target :: aTest', + ' class (WrapUserTestCase), pointer :: p', + '#endif', + ' character(len=*), intent(in) :: methodName', + ' procedure(userTestMethod) :: testMethod', + ' aTest%testMethodPtr => testMethod', + '#ifdef INTEL_13', + ' p => aTest', + ' call p%setName(methodName)', + '#else', + ' call aTest%setName(methodName)', + '#endif', + ' end function makeCustomTest', + '', + 'end module Wraptest_mod', + '', + 'function test_mod_suite() result(suite)', + ' use pFUnit_mod', + ' use test_mod', + ' use Wraptest_mod', + ' type (TestSuite) :: suite', + '', + " suite = newTestSuite('test_mod_suite')", + '', + " call suite%addTest(makeCustomTest('testTest', " + + "testTest))", + '', + '', + 'end function test_mod_suite', + ''] + + unit_under_test = Parser(self._source_filename, + self._target_filename, + False) + unit_under_test.run() + unit_under_test.final() + + with open(self._target_filename, 'r') as target: + result = target.read().splitlines() + + while len(expected) > 0: + model = expected.pop(0) + actual = result.pop(0) + + if isinstance(model, self._re_type): + self.assertRegexpMatches(actual, model) + else: + self.assertEqual(actual, model) + + self.assertListEqual([], expected) + self.assertListEqual([], result) + + if __name__ == "__main__": - unittest.main() + unittest.main() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index a5736bc2..f7839c60 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -38,7 +38,7 @@ file_compile_configuration() # Perform the install. # -install(FILES GNU.mk IBM.mk INTEL.mk NAG.mk PGI.mk extensions.mk driver.F90 DESTINATION include) +install(FILES CRAY.mk GNU.mk IBM.mk INTEL.mk NAG.mk PGI.mk extensions.mk driver.F90 DESTINATION include) install(FILES base-install.mk DESTINATION include RENAME base.mk) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/configuration.mk DESTINATION include) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/TestUtil.F90 DESTINATION include) diff --git a/include/CRAY.mk b/include/CRAY.mk new file mode 100644 index 00000000..b0c29931 --- /dev/null +++ b/include/CRAY.mk @@ -0,0 +1,29 @@ +export FUFLAGS=-markers + +F90 ?=ftn +MPIF90 ?= ftn + +I=-I +M=-I +L=-L + +# Cray compiler only exists on Cray machines so no Windows support. +FFLAGS += -G0 -K trap=fp,unf + +ifeq ($(USEOPENMP),YES) +FFLAGS += -h omp +endif + + +# Common command line options. + +# The Cray compiler always creates a .i file when run in preprocessor +# mode. None of this stuff seems to be used so I'm commenting it out for +# the moment. +# +# F90_PP_ONLY = -eF +# F90_PP_OUTPUT = ; mv i + +CPPFLAGS +=-DCray +FPPFLAGS +=-DCray + diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 6ccdde87..9f88177f 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -8,7 +8,7 @@ set(srcs Assert.F90) # Generate AssertArray files: AssertArrays.fh, generated.inc, and AssertXYZ?.F90 execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/GenerateAssertsOnArrays.py --maxRank ${MAX_RANK} + COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/GenerateAssertsOnArrays.py" "--maxRank" "${MAX_RANK}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE generated_result OUTPUT_VARIABLE generated_output diff --git a/source/XmlPrinter.F90 b/source/XmlPrinter.F90 index 82237b00..7f67b74e 100644 --- a/source/XmlPrinter.F90 +++ b/source/XmlPrinter.F90 @@ -168,7 +168,7 @@ subroutine printExceptions(this, label, testName, exceptions) 'Location: ', cleanXml(trim(locationString)), ', ' write(this%unit,'(a)',advance='no') & cleanXml(trim(exceptions(j)%getMessage())) - write(this%unit,*) '"/>' + write(this%unit,'(a)') '"/>' end do write(this%unit,'(a)') '' diff --git a/source/pFUnitPackage.F90 b/source/pFUnitPackage.F90 index 35f44d47..7e057c26 100644 --- a/source/pFUnitPackage.F90 +++ b/source/pFUnitPackage.F90 @@ -35,8 +35,19 @@ #define PFUNIT_PREFIX pf_ #endif -#define TOKEN(a) a -#define RENAME(item) TOKEN(PFUNIT_PREFIX)TOKEN(item) => item +! The Cray preprocessor for Fortran does not appear to perform recursive +! expansion. Using the normal macro would lead to +! "PFUNIT_PREFIX => " instead of the expected result +! " => ". +! +! To get round these issues the "pf_" prefix is hard coded. + +#define WORD(word) word +#ifndef Cray +#define RENAME(item) WORD(PFUNIT_PREFIX)item => item +#else +#define RENAME(item) WORD(pf_)item => item +#endif module pFUnit diff --git a/tests/Test_MockRepository.F90 b/tests/Test_MockRepository.F90 index a8e4509c..4f4fb4f6 100644 --- a/tests/Test_MockRepository.F90 +++ b/tests/Test_MockRepository.F90 @@ -40,7 +40,7 @@ module SUT_mod contains subroutine method1(this) - class (SUT), intent(in) :: this + class (SUT), intent(inout) :: this end subroutine method1 end module SUT_mod @@ -84,7 +84,7 @@ subroutine verifyMocking(this) end subroutine verifyMocking subroutine method1(this) - class (MockSUT), intent(in) :: this + class (MockSUT), intent(inout) :: this call this%mocker%hasCalled(this, 'method1') end subroutine method1 diff --git a/tests/Test_XmlPrinter.F90 b/tests/Test_XmlPrinter.F90 index 7b65b88f..bcd7d463 100644 --- a/tests/Test_XmlPrinter.F90 +++ b/tests/Test_XmlPrinter.F90 @@ -106,7 +106,7 @@ end function system ! Validate the file against the de facto JUnit xsd. ! If xmlint not found, just move on quietly. command = 'xmllint --version > /dev/null 2>&1' -#if defined(NAG) || defined(IBM) +#if defined(NAG) || defined(IBM) || defined(Cray) ! Fortran 2008 compliant version. call execute_command_line(command,exitstat=stat) #else @@ -115,7 +115,7 @@ end function system if (stat == 0) then command = 'xmllint --noout --nowarning --schema ' // trim(xsdPath) & // ' ' // trim(fileName) // ' 2> ' // outFile -#if defined(NAG) || defined(IBM) +#if defined(NAG) || defined(IBM) || defined(Cray) ! Fortran 2008 compliant version. call execute_command_line(command,exitstat=stat) #else @@ -149,7 +149,7 @@ subroutine compareXMLFileToExpectation(xmlFile) character(len=100), dimension(9) :: expected expected=(/ character(len=100) :: & -#ifndef PGI +#if !defined( PGI ) && !defined( Cray ) '', & #else '', & '', & -'', & +'', & '', & '', & -'', & +'', & '', & '' /)