Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix the generation of MBI test cases (and compile them with -Wno-unused-variable...
[simgrid.git] / teshsuite / smpi / MBI / MBIutils.py
index 070d3218a86f6323202cb35a5b1f998f13b5c92f..e099d5b7ad7e8b0f7949a8b5f7cb11c267c770a3 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2021-2022. The MBI project. All rights reserved. 
+# Copyright 2021-2022. The MBI project. All rights reserved.
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
 import os
 # This program is free software; you can redistribute it and/or modify it under the terms of the license (GNU GPL).
 
 import os
@@ -12,14 +12,14 @@ import signal
 import hashlib
 
 class AbstractTool:
 import hashlib
 
 class AbstractTool:
-    def ensure_image(self, params=""):
+    def ensure_image(self, params="", dockerparams=""):
         """Verify that this is executed from the right docker image, and complain if not."""
         if os.path.exists("/MBI") or os.path.exists("trust_the_installation"):
             print("This seems to be a MBI docker image. Good.")
         else:
             print("Please run this script in a MBI docker image. Run these commands:")
             print("  docker build -f Dockerfile -t mpi-bugs-initiative:latest . # Only the first time")
         """Verify that this is executed from the right docker image, and complain if not."""
         if os.path.exists("/MBI") or os.path.exists("trust_the_installation"):
             print("This seems to be a MBI docker image. Good.")
         else:
             print("Please run this script in a MBI docker image. Run these commands:")
             print("  docker build -f Dockerfile -t mpi-bugs-initiative:latest . # Only the first time")
-            print(f"  docker run -it --rm --name MIB --volume $(pwd):/MBI mpi-bugs-initiative /MBI/MBI.py {params}")
+            print(f"  docker run -it --rm --name MIB --volume $(pwd):/MBI {dockerparams}mpi-bugs-initiative /MBI/MBI.py {params}")
             sys.exit(1)
 
     def build(self, rootdir, cached=True):
             sys.exit(1)
 
     def build(self, rootdir, cached=True):
@@ -31,18 +31,18 @@ class AbstractTool:
         Ensure that this tool (previously built) is usable in this environment: setup the PATH, etc.
         This is called only once for all tests, from the logs directory.
         """
         Ensure that this tool (previously built) is usable in this environment: setup the PATH, etc.
         This is called only once for all tests, from the logs directory.
         """
-        pass
+        pass
 
 
-    def run(execcmd, filename, binary, id, timeout):
+    def run(execcmd, filename, binary, num_id, timeout):
         """Compile that test code and anaylse it with the Tool if needed (a cache system should be used)"""
         """Compile that test code and anaylse it with the Tool if needed (a cache system should be used)"""
-        pass
+        pass
 
     def teardown(self):
         """
         Clean the results of all test runs: remove temp files and binaries.
         This is called only once for all tests, from the logs directory.
         """
 
     def teardown(self):
         """
         Clean the results of all test runs: remove temp files and binaries.
         This is called only once for all tests, from the logs directory.
         """
-        pass
+        pass
 
     def parse(self, cachefile):
         """Read the result of a previous run from the cache, and compute the test outcome"""
 
     def parse(self, cachefile):
         """Read the result of a previous run from the cache, and compute the test outcome"""
@@ -52,20 +52,20 @@ class AbstractTool:
 possible_details = {
     # scope limited to one call
     'InvalidBuffer':'AInvalidParam', 'InvalidCommunicator':'AInvalidParam', 'InvalidDatatype':'AInvalidParam', 'InvalidRoot':'AInvalidParam', 'InvalidTag':'AInvalidParam', 'InvalidWindow':'AInvalidParam', 'InvalidOperator':'AInvalidParam', 'InvalidOtherArg':'AInvalidParam', 'ActualDatatype':'AInvalidParam',
 possible_details = {
     # scope limited to one call
     'InvalidBuffer':'AInvalidParam', 'InvalidCommunicator':'AInvalidParam', 'InvalidDatatype':'AInvalidParam', 'InvalidRoot':'AInvalidParam', 'InvalidTag':'AInvalidParam', 'InvalidWindow':'AInvalidParam', 'InvalidOperator':'AInvalidParam', 'InvalidOtherArg':'AInvalidParam', 'ActualDatatype':'AInvalidParam',
-    'InvalidSrcDest':'AInvalidParam', 
+    'InvalidSrcDest':'AInvalidParam',
     # scope: Process-wide
     # scope: Process-wide
-#    'OutOfInitFini':'BInitFini', 
+#    'OutOfInitFini':'BInitFini',
     'CommunicatorLeak':'BResLeak', 'DatatypeLeak':'BResLeak', 'GroupLeak':'BResLeak', 'OperatorLeak':'BResLeak', 'TypeLeak':'BResLeak', 'RequestLeak':'BResLeak',
     'MissingStart':'BReqLifecycle', 'MissingWait':'BReqLifecycle',
     'LocalConcurrency':'BLocalConcurrency',
     # scope: communicator
     'CommunicatorLeak':'BResLeak', 'DatatypeLeak':'BResLeak', 'GroupLeak':'BResLeak', 'OperatorLeak':'BResLeak', 'TypeLeak':'BResLeak', 'RequestLeak':'BResLeak',
     'MissingStart':'BReqLifecycle', 'MissingWait':'BReqLifecycle',
     'LocalConcurrency':'BLocalConcurrency',
     # scope: communicator
-    'CallMatching':'DMatch', 
+    'CallMatching':'DMatch',
     'CommunicatorMatching':'CMatch', 'DatatypeMatching':'CMatch', 'OperatorMatching':'CMatch', 'RootMatching':'CMatch', 'TagMatching':'CMatch',
     'CommunicatorMatching':'CMatch', 'DatatypeMatching':'CMatch', 'OperatorMatching':'CMatch', 'RootMatching':'CMatch', 'TagMatching':'CMatch',
-    'MessageRace':'DRace', 
-    
+    'MessageRace':'DRace',
+
     'GlobalConcurrency':'DGlobalConcurrency',
     # larger scope
     'GlobalConcurrency':'DGlobalConcurrency',
     # larger scope
-#    'BufferingHazard':'EBufferingHazard',
+    'BufferingHazard':'EBufferingHazard',
     'OK':'FOK'}
 
 error_scope = {
     'OK':'FOK'}
 
 error_scope = {
@@ -78,7 +78,7 @@ error_scope = {
     'DRace':'multi-processes',
     'DMatch':'multi-processes',
     'DGlobalConcurrency':'multi-processes',
     'DRace':'multi-processes',
     'DMatch':'multi-processes',
     'DGlobalConcurrency':'multi-processes',
-#    'EBufferingHazard':'system',
+    'EBufferingHazard':'system',
     'FOK':'correct executions'
 }
 
     'FOK':'correct executions'
 }
 
@@ -105,10 +105,10 @@ def parse_one_code(filename):
     """
     res = []
     test_num = 0
     """
     res = []
     test_num = 0
-    with open(filename, "r") as input:
+    with open(filename, "r") as input_file:
         state = 0  # 0: before header; 1: in header; 2; after header
         line_num = 1
         state = 0  # 0: before header; 1: in header; 2; after header
         line_num = 1
-        for line in input:
+        for line in input_file:
             if re.match(".*BEGIN_MBI_TESTS.*", line):
                 if state == 0:
                     state = 1
             if re.match(".*BEGIN_MBI_TESTS.*", line):
                 if state == 0:
                     state = 1
@@ -122,7 +122,7 @@ def parse_one_code(filename):
             if state == 1 and re.match("\s+\$ ?.*", line):
                 m = re.match('\s+\$ ?(.*)', line)
                 cmd = m.group(1)
             if state == 1 and re.match("\s+\$ ?.*", line):
                 m = re.match('\s+\$ ?(.*)', line)
                 cmd = m.group(1)
-                nextline = next(input)
+                nextline = next(input_file)
                 detail = 'OK'
                 if re.match('[ |]*OK *', nextline):
                     expect = 'OK'
                 detail = 'OK'
                 if re.match('[ |]*OK *', nextline):
                     expect = 'OK'
@@ -169,7 +169,7 @@ def categorize(tool, toolname, test_id, expected):
             diagnostic = f'hard timeout'
         else:
             diagnostic = f'timeout after {elapsed} sec'
             diagnostic = f'hard timeout'
         else:
             diagnostic = f'timeout after {elapsed} sec'
-    elif outcome == 'failure':
+    elif outcome == 'failure' or outcome == 'segfault':
         res_category = 'failure'
         diagnostic = f'tool error, or test not run'
     elif outcome == 'UNIMPLEMENTED':
         res_category = 'failure'
         diagnostic = f'tool error, or test not run'
     elif outcome == 'UNIMPLEMENTED':
@@ -201,11 +201,11 @@ def categorize(tool, toolname, test_id, expected):
 def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo, read_line_lambda=None):
     """
     Runs the test on need. Returns True if the test was ran, and False if it was cached.
 def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo, read_line_lambda=None):
     """
     Runs the test on need. Returns True if the test was ran, and False if it was cached.
-    
+
     The result is cached if possible, and the test is rerun only if the `test.txt` (containing the tool output) or the `test.elapsed` (containing the timing info) do not exist, or if `test.md5sum` (containing the md5sum of the code to compile) does not match.
 
     Parameters:
     The result is cached if possible, and the test is rerun only if the `test.txt` (containing the tool output) or the `test.elapsed` (containing the timing info) do not exist, or if `test.md5sum` (containing the md5sum of the code to compile) does not match.
 
     Parameters:
-     - buildcmd and execcmd are shell commands to run. buildcmd can be any shell line (incuding && groups), but execcmd must be a single binary to run. 
+     - buildcmd and execcmd are shell commands to run. buildcmd can be any shell line (incuding && groups), but execcmd must be a single binary to run.
      - cachefile is the name of the test
      - filename is the source file containing the code
      - binary the file name in which to compile the code
      - cachefile is the name of the test
      - filename is the source file containing the code
      - binary the file name in which to compile the code
@@ -224,13 +224,12 @@ def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo,
         if olddigest == newdigest:
             print(f" (result cached -- digest: {olddigest})")
             return False
         if olddigest == newdigest:
             print(f" (result cached -- digest: {olddigest})")
             return False
-        else:
-            os.remove(f'{cachefile}.txt')
+        os.remove(f'{cachefile}.txt')
 
     print(f"Wait up to {timeout} seconds")
 
     start_time = time.time()
 
     print(f"Wait up to {timeout} seconds")
 
     start_time = time.time()
-    if buildcmd == None:
+    if buildcmd is None:
         output = f"No need to compile {binary}.c (batchinfo:{batchinfo})\n\n"
     else:
         output = f"Compiling {binary}.c (batchinfo:{batchinfo})\n\n"
         output = f"No need to compile {binary}.c (batchinfo:{batchinfo})\n\n"
     else:
         output = f"Compiling {binary}.c (batchinfo:{batchinfo})\n\n"
@@ -319,5 +318,5 @@ def run_cmd(buildcmd, execcmd, cachefile, filename, binary, timeout, batchinfo,
             for chunk in iter(lambda: sourcefile.read(4096), b""):
                 hashed.update(chunk)
         outfile.write(hashed.hexdigest())
             for chunk in iter(lambda: sourcefile.read(4096), b""):
                 hashed.update(chunk)
         outfile.write(hashed.hexdigest())
-    
+
     return True
     return True