Quellcode durchsuchen

single tool deployed with action option. Implemented regions across markers cross-matching.

avkonst vor 12 Jahren
Ursprung
Commit
639c0e9f97
30 geänderte Dateien mit 189 neuen und 90 gelöschten Zeilen
  1. 4 0
      mainline/core/api.py
  2. 54 5
      mainline/core/db/loader.py
  3. 2 2
      mainline/core/loader.py
  4. 2 0
      mainline/ext/std/code/cpp.py
  5. 26 0
      mainline/ext/std/code/test.ini
  6. 37 0
      mainline/ext/std/code/test.py
  7. 1 1
      mainline/tests/common.py
  8. 1 1
      mainline/tests/general/test_basic/test_help_export_default_stdout.gold.txt
  9. 1 1
      mainline/tests/general/test_basic/test_help_info_default_stdout.gold.txt
  10. 1 1
      mainline/tests/general/test_basic/test_help_limit_default_stdout.gold.txt
  11. 1 1
      mainline/tests/general/test_basic/test_workflow_collect_default_stderr.gold.txt
  12. 1 1
      mainline/tests/general/test_basic/test_workflow_collect_second_stderr.gold.txt
  13. 1 1
      mainline/tests/general/test_basic/test_workflow_export_default_stderr.gold.txt
  14. 1 1
      mainline/tests/general/test_basic/test_workflow_export_second_per_file_stderr.gold.txt
  15. 1 1
      mainline/tests/general/test_basic/test_workflow_export_second_stderr.gold.txt
  16. 1 1
      mainline/tests/general/test_basic/test_workflow_info_default_stderr.gold.txt
  17. 1 1
      mainline/tests/general/test_basic/test_workflow_info_second_stderr.gold.txt
  18. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_default_stderr.gold.txt
  19. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_second_stderr.gold.txt
  20. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_second_warn_all_stderr.gold.txt
  21. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_second_warn_new_stderr.gold.txt
  22. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_second_warn_touched_stderr.gold.txt
  23. 1 1
      mainline/tests/general/test_basic/test_workflow_limit_second_warn_trend_stderr.gold.txt
  24. 0 0
      mainline/tools/__init__.py
  25. 8 12
      mainline/collect.py
  26. 8 10
      mainline/debug.py
  27. 8 10
      mainline/export.py
  28. 7 10
      mainline/info.py
  29. 7 10
      mainline/limit.py
  30. 9 14
      mainline/test.py

+ 4 - 0
mainline/core/api.py

@@ -145,5 +145,9 @@ def subscribe_by_parents_interface(interface, child, callback_name='callback'):
             plugin.subscribe(child, callback_name)
 
 
+class ITool(object):
+    
+    def run(self, tool_args):
+        raise InterfaceNotImplemented(self)
 
 

+ 54 - 5
mainline/core/db/loader.py

@@ -189,6 +189,18 @@ class Marker(object):
         STRING          = 0x02
         PREPROCESSOR    = 0x04
         ALL_EXCEPT_CODE = 0x07
+
+        def to_str(self, group):
+            if group == self.NONE:
+                return "none"
+            elif group == self.COMMENT:
+                return "comment"
+            elif group == self.STRING:
+                return "string"
+            elif group == self.PREPROCESSOR:
+                return "preprocessor"
+            else:
+                assert(False)
         
     def __init__(self, offset_begin, offset_end, group):
         self.begin = offset_begin
@@ -315,12 +327,49 @@ class FileData(LoadableData):
         self.loader.db.create_marker(self.file_id, offset_begin, offset_end, group)
         
     def iterate_markers(self, filter_group = Marker.T.COMMENT |
-                         Marker.T.STRING | Marker.T.PREPROCESSOR):
+                         Marker.T.STRING | Marker.T.PREPROCESSOR,
+                         region_id = None, exclude_children = True):
         self.load_markers()
-        for each in self.markers:
-            if each.group & filter_group:
-                yield each
-    
+        if region_id == None:
+            for each in self.markers:
+                if each.group & filter_group:
+                    yield each
+        else:
+            region = self.get_region(region_id)
+            if region != None:
+                if hasattr(region, 'markers_list') == False:
+                    def cache_markers_list_req(data, region_id, marker_start_pos):
+                        region = data.get_region(region_id)
+                        region.markers_list = []
+                        region.first_marker_pos = marker_start_pos
+                        for sub_id in region.iterate_subregion_ids():
+                            subregion = data.get_region(sub_id)
+                            while len(data.markers) > marker_start_pos and \
+                                subregion.get_offset_begin() > data.markers[marker_start_pos].get_offset_begin():
+                                    region.markers_list.append(marker_start_pos)
+                                    marker_start_pos += 1
+                            marker_start_pos = cache_markers_list_req(data, sub_id, marker_start_pos)
+                        while len(data.markers) > marker_start_pos and \
+                            region.get_offset_end() > data.markers[marker_start_pos].get_offset_begin():
+                                region.markers_list.append(marker_start_pos)
+                                marker_start_pos += 1
+                        return marker_start_pos
+                    next_marker_pos = cache_markers_list_req(self, 1, 0)
+                    assert(next_marker_pos == len(self.markers))
+                if exclude_children == True:
+                    for marker_pos in region.markers_list:
+                        marker = self.markers[marker_pos]
+                        if marker.group & filter_group:
+                            yield marker
+                elif len(self.markers) > region.first_marker_pos:
+                    for marker in self.markers[region.first_marker_pos:]:
+                        if marker.get_offset_begin() >= region.get_offset_end():
+                            break
+                        if region.get_offset_begin() > marker.get_offset_begin():
+                            continue
+                        if marker.group & filter_group:
+                            yield marker
+                        
     def get_marker_types(self):
         return Marker.T
 

+ 2 - 2
mainline/core/loader.py

@@ -56,7 +56,7 @@ class Loader(object):
                     return parser[1]
         return None
 
-    def load(self, directory, optparser):
+    def load(self, directory, optparser, args):
         import sys
         sys.path.append(directory)
         
@@ -101,7 +101,7 @@ class Loader(object):
             if (isinstance(item, core.api.IConfigurable)):
                 item.declare_configuration(optparser)
 
-        (options, args) = optparser.parse_args()
+        (options, args) = optparser.parse_args(args)
         for item in self.iterate_plugins():
             if (isinstance(item, core.api.IConfigurable)):
                 item.configure(options)

+ 2 - 0
mainline/ext/std/code/cpp.py

@@ -88,6 +88,8 @@ class CppCodeParser(object):
             ''',
             re.DOTALL | re.MULTILINE | re.VERBOSE
         )
+    
+    #TODO test false identification of class if function is named my_func_class()
 
     regex_ln = re.compile(r'(\n)|(\r)|(\r\n)')
 

+ 26 - 0
mainline/ext/std/code/test.ini

@@ -0,0 +1,26 @@
+;
+;    Metrix++, Copyright 2009-2013, Metrix++ Project
+;    Link: http://metrixplusplus.sourceforge.net
+;    
+;    This file is a part of Metrix++ Tool.
+;    
+;    Metrix++ is free software: you can redistribute it and/or modify
+;    it under the terms of the GNU General Public License as published by
+;    the Free Software Foundation, version 3 of the License.
+;    
+;    Metrix++ is distributed in the hope that it will be useful,
+;    but WITHOUT ANY WARRANTY; without even the implied warranty of
+;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;    GNU General Public License for more details.
+;    
+;    You should have received a copy of the GNU General Public License
+;    along with Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+;
+
+[Plugin]
+version: 1.0
+package: std.code
+module:  test
+class:   Plugin
+depends: None
+enabled: True

+ 37 - 0
mainline/ext/std/code/test.py

@@ -0,0 +1,37 @@
+#
+#    Metrix++, Copyright 2009-2013, Metrix++ Project
+#    Link: http://metrixplusplus.sourceforge.net
+#    
+#    This file is a part of Metrix++ Tool.
+#    
+#    Metrix++ is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, version 3 of the License.
+#    
+#    Metrix++ is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#    GNU General Public License for more details.
+#    
+#    You should have received a copy of the GNU General Public License
+#    along with Metrix++.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import core.api
+
+
+# used for testing and development purposes
+class Plugin(core.api.Plugin, core.api.Child):
+    
+    def initialize(self):
+        return
+        # do not trigger version property set, it is a module for testing purposes
+        core.api.subscribe_by_parents_interface(core.api.ICode, self)
+
+    def callback(self, parent, data, is_updated):
+
+        text = data.get_content()
+        for region in data.iterate_regions():
+            print "Region:", region.get_name(), region.get_cursor()
+            for marker in data.iterate_markers(region_id=region.get_id(), exclude_children = True):
+                print "\tMarker:", data.get_marker_types()().to_str(marker.get_type()), text[marker.get_offset_begin():marker.get_offset_end()]

+ 1 - 1
mainline/tests/common.py

@@ -74,7 +74,7 @@ class ToolRunner(object):
             for each in dirs_list:
                 self.dirs_list.append(each)
                
-        self.call_args = ['python', os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], tool_name + ".py")] \
+        self.call_args = ['python', os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], "metrixpp.py"), tool_name] \
                     + db_opts + opts_list + ['--'] + self.dirs_list
         self.cmd = " ".join(self.call_args)
         self.exit_code_expected = exit_code

+ 1 - 1
mainline/tests/general/test_basic/test_help_export_default_stdout.gold.txt

@@ -1,4 +1,4 @@
-Usage: export.py [options] -- [path 1] ... [path N]
+Usage: metrixpp.py export [options] -- [path 1] ... [path N]
 
 Options:
   -h, --help            show this help message and exit

+ 1 - 1
mainline/tests/general/test_basic/test_help_info_default_stdout.gold.txt

@@ -1,4 +1,4 @@
-Usage: info.py [options] -- [path 1] ... [path N]
+Usage: metrixpp.py info [options] -- [path 1] ... [path N]
 
 Options:
   -h, --help            show this help message and exit

+ 1 - 1
mainline/tests/general/test_basic/test_help_limit_default_stdout.gold.txt

@@ -1,4 +1,4 @@
-Usage: limit.py [options] -- [path 1] ... [path N]
+Usage: metrixpp.py limit [options] -- [path 1] ... [path N]
 
 Options:
   -h, --help            show this help message and exit

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_collect_default_stderr.gold.txt

@@ -2,4 +2,4 @@
 [LOG]: INFO:	Excluding: ./.unused.cpp
 [LOG]: INFO:	Skipping: ./dummy.txt
 [LOG]: INFO:	Processing: ./simple.cpp
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.11 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 1.92 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_collect_second_stderr.gold.txt

@@ -2,4 +2,4 @@
 [LOG]: INFO:	Excluding: ./.unused.cpp
 [LOG]: INFO:	Processing: ./simple.cpp
 [LOG]: INFO:	Processing: ./simple2.cpp
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.05 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.18 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_export_default_stderr.gold.txt

@@ -1,3 +1,3 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: 
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.0 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.02 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_export_second_per_file_stderr.gold.txt

@@ -1,3 +1,3 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: ./simple.cpp
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.04 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_export_second_stderr.gold.txt

@@ -1,3 +1,3 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: 
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.02 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_info_default_stderr.gold.txt

@@ -1,2 +1,2 @@
 [LOG]: WARNING:	Logging enabled with INFO level
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.0 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.01 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_info_second_stderr.gold.txt

@@ -1,2 +1,2 @@
 [LOG]: WARNING:	Logging enabled with INFO level
-[LOG]: WARNING:	Exit code: 0. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 0. Time spent: 0.02 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_default_stderr.gold.txt

@@ -1,4 +1,4 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 4. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 4. Time spent: 0.02 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_second_stderr.gold.txt

@@ -1,4 +1,4 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 6. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 6. Time spent: 0.03 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_second_warn_all_stderr.gold.txt

@@ -1,4 +1,4 @@
 [LOG]: WARNING:	Logging enabled with INFO level
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 6. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 6. Time spent: 0.03 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_second_warn_new_stderr.gold.txt

@@ -2,4 +2,4 @@
 [LOG]: INFO:	Identifying changed files...
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 2. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 2. Time spent: 0.03 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_second_warn_touched_stderr.gold.txt

@@ -2,4 +2,4 @@
 [LOG]: INFO:	Identifying changed files...
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 4. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 4. Time spent: 0.03 seconds. Done

+ 1 - 1
mainline/tests/general/test_basic/test_workflow_limit_second_warn_trend_stderr.gold.txt

@@ -2,4 +2,4 @@
 [LOG]: INFO:	Identifying changed files...
 [LOG]: INFO:	Processing: 
 [LOG]: INFO:	Applying limit: namespace 'std.code.complexity', filter '('cyclomatic', '>', 0.0)'
-[LOG]: WARNING:	Exit code: 3. Time spent: 0.01 seconds. Done
+[LOG]: WARNING:	Exit code: 3. Time spent: 0.03 seconds. Done

+ 0 - 0
mainline/tools/__init__.py


+ 8 - 12
mainline/collect.py

@@ -20,26 +20,22 @@
 
 import logging
 import os.path
-import time
 
 import core.loader
-import core.log
 import core.cmdparser
 
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
 
-def main():
+def main(tool_args):
     loader = core.loader.Loader()
-    parser =core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [path 1] ... [path N]")
-    args = loader.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'ext'), parser)
+    parser =core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] collect -- [path 1] ... [path N]")
+    args = loader.load(os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], 'ext'), parser, tool_args)
     logging.debug("Registered plugins:")
     logging.debug(loader)
     exit_code = loader.run(args)
     loader.unload()
     return exit_code
-            
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code) # number of reported messages, errors are reported as non-handled exceptions
+    

+ 8 - 10
mainline/debug.py

@@ -19,7 +19,6 @@
 
 
 import logging
-import time
 import cgi
 
 import core.log
@@ -27,17 +26,22 @@ import core.cmdparser
 import core.db.post
 import core.db.loader
 
-def main():
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
+
+def main(tool_args):
     log_plugin = core.log.Plugin()
     db_plugin = core.db.post.Plugin()
 
-    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [path 1] ... [path N]")
+    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog debug [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)
     db_plugin.declare_configuration(parser)
     parser.add_option("-m", "--general.mode", default='dumphtml', choices=['dumphtml'],
                          help="'dumphtml' - prints html code with code highlights for each given path [default: %default]")
 
-    (options, args) = parser.parse_args()
+    (options, args) = parser.parse_args(tool_args)
     log_plugin.configure(options)
     db_plugin.configure(options)
 
@@ -121,9 +125,3 @@ def dumphtml(args, loader):
     print result
     return exit_code
             
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code) # number of reported messages, errors are reported as non-handled exceptions

+ 8 - 10
mainline/export.py

@@ -20,7 +20,6 @@
 
 
 import logging
-import time
 import re
 
 import core.log
@@ -30,12 +29,17 @@ import core.db.utils
 import core.cmdparser
 import core.export.convert
 
-def main():
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
+
+def main(tool_args):
     
     log_plugin = core.log.Plugin()
     db_plugin = core.db.post.Plugin()
 
-    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [path 1] ... [path N]")
+    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog export [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)
     db_plugin.declare_configuration(parser)
     parser.add_option("--general.format", default='xml', choices=['txt', 'xml', 'python'], help="Format of the output data. "
@@ -48,7 +52,7 @@ def main():
                       help="If the option is set (True), data for regions is exported in the form of a tree. "
                       "Otherwise, all regions are exported in plain list. [default: %default]")
 
-    (options, args) = parser.parse_args()
+    (options, args) = parser.parse_args(tool_args)
     log_plugin.configure(options)
     db_plugin.configure(options)
     out_format = options.__dict__['general.format']
@@ -221,12 +225,6 @@ def append_diff(main_tree, prev_tree):
                 main_tree[name]['__diff__'][field] = main_tree[name][field] - prev_tree[name][field]
     return main_tree
 
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code)
     
     
   

+ 7 - 10
mainline/info.py

@@ -19,24 +19,27 @@
 
 
 import logging
-import time
 
 import core.db.loader
 import core.db.post
 import core.log
 import core.cmdparser
 
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
 
-def main():
+def main(tool_args):
     exit_code = 0
     log_plugin = core.log.Plugin()
     db_plugin = core.db.post.Plugin()
 
-    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [path 1] ... [path N]")
+    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog info [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)
     db_plugin.declare_configuration(parser)
 
-    (options, args) = parser.parse_args()
+    (options, args) = parser.parse_args(tool_args)
     log_plugin.configure(options)
     db_plugin.configure(options)
     
@@ -104,9 +107,3 @@ def main():
         
     return exit_code
             
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code) # number of reported messages, errors are reported as non-handled exceptions

+ 7 - 10
mainline/limit.py

@@ -19,7 +19,6 @@
 
 
 import logging
-import time
 import re
 
 import core.log
@@ -30,20 +29,24 @@ import core.export.cout
 import core.warn
 import core.cmdparser
 
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
 
-def main():
+def main(tool_args):
     
     exit_code = 0
     log_plugin = core.log.Plugin()
     db_plugin = core.db.post.Plugin()
     warn_plugin = core.warn.Plugin()
 
-    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [path 1] ... [path N]")
+    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog limit [options] -- [path 1] ... [path N]")
     log_plugin.declare_configuration(parser)
     db_plugin.declare_configuration(parser)
     warn_plugin.declare_configuration(parser)
 
-    (options, args) = parser.parse_args()
+    (options, args) = parser.parse_args(tool_args)
     log_plugin.configure(options)
     db_plugin.configure(options)
     warn_plugin.configure(options)
@@ -171,12 +174,6 @@ def report_limit_exceeded(path, cursor, namespace, field, region_name, stat_leve
                ("Limit", stat_limit)]
     core.export.cout.cout(path, cursor, core.export.cout.SEVERITY_WARNING, message, details)
 
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code)
     
     
   

+ 9 - 14
mainline/test.py

@@ -18,8 +18,6 @@
 #
 
 
-import logging
-import time
 import subprocess
 import os.path
 import itertools
@@ -27,23 +25,26 @@ import itertools
 import core.log
 import core.cmdparser
 
-def main():
+import core.api
+class Tool(core.api.ITool):
+    def run(self, tool_args):
+        return main(tool_args)
+
+def main(tool_args):
     exit_code = 0
     log_plugin = core.log.Plugin()
 
-    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog [options] -- [testgroup-dir-path-1[/testsuite-file-path-1]] ... [...path-N]")
+    parser = core.cmdparser.MultiOptionParser(usage="Usage: %prog test [options] -- [testgroup-dir-path-1[/testsuite-file-path-1]] ... [...path-N]")
     log_plugin.declare_configuration(parser, default_value='ERROR')
     parser.add_option("-g", "--general.generate-golds", action="store_true", default=False,
                          help="If the option is set (True), new gold files are generated (replacing existing) [default: %default]")
 
-    (options, args) = parser.parse_args()
+    (options, args) = parser.parse_args(tool_args)
     log_plugin.configure(options)
     
     os.environ['METRIXPLUSPLUS_TEST_GENERATE_GOLDS'] = str(options.__dict__['general.generate_golds'])
     
-    install_dir = os.path.dirname(os.path.abspath(__file__))
-    tests_dir = os.path.join(install_dir, 'tests')
-    os.environ['METRIXPLUSPLUS_INSTALL_DIR'] = install_dir
+    tests_dir = os.path.join(os.environ['METRIXPLUSPLUS_INSTALL_DIR'], 'tests')
     process_data= ["python", "-m", "unittest", "discover", "-v", "-s"]
     if len(args) == 0 or tests_dir == os.path.abspath(args[0]):
         for fname in os.listdir(tests_dir):
@@ -63,9 +64,3 @@ def main():
                                              cwd=os.environ['METRIXPLUSPLUS_INSTALL_DIR'])
     return exit_code
             
-if __name__ == '__main__':
-    ts = time.time()
-    core.log.set_default_format()
-    exit_code = main()
-    logging.warning("Exit code: " + str(exit_code) + ". Time spent: " + str(round((time.time() - ts), 2)) + " seconds. Done")
-    exit(exit_code) # number of reported messages, errors are reported as non-handled exceptions