From 3b6b1993c70b80c980a107ad21e6010bbc8b5054 Mon Sep 17 00:00:00 2001
From: Janik Zikovsky <zikovskyjl@ornl.gov>
Date: Wed, 12 Jan 2011 19:01:03 +0000
Subject: [PATCH] Refs #2190: Select using SVN; sort by time works; console log
 follows

---
 Code/Tools/TestViewer/main_window.py | 58 ++++++++++++++---------
 Code/Tools/TestViewer/test_info.py   | 69 ++++++++++++++++++++++------
 Code/Tools/TestViewer/test_tree.py   | 10 ++--
 3 files changed, 96 insertions(+), 41 deletions(-)

diff --git a/Code/Tools/TestViewer/main_window.py b/Code/Tools/TestViewer/main_window.py
index 5f1eebcc40f..cb6f728faf1 100644
--- a/Code/Tools/TestViewer/main_window.py
+++ b/Code/Tools/TestViewer/main_window.py
@@ -101,13 +101,14 @@ class TestMonitorFilesWorker(QtCore.QThread):
         print "Beginning to monitor files and/or libraries..."
         
         while not self.exiting:
-            if self.monitor_tests:
-                if test_info.all_tests.is_source_modified(selected_only=True):
-                    self.mainWindow.emit( QtCore.SIGNAL("testMonitorChanged()") )
-                pass
-            
-            if self.monitor_libraries:
-                pass
+            if not self.mainWindow.running:
+                # Don't monitor files while a test suite is building or running
+                if self.monitor_tests:
+                    if test_info.all_tests.is_source_modified(selected_only=True):
+                        self.mainWindow.emit( QtCore.SIGNAL("testMonitorChanged()") )
+                
+                if self.monitor_libraries:
+                    pass
             
             time.sleep(self.delay)
             
@@ -134,6 +135,7 @@ class TestViewerMainWindow(QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
         # Populate all GUI elements
         self.setupUi(self)
         self.buttonTest.hide()
+        self.set_running(False)
              
         # Create the worker
         self.worker = TestWorker()
@@ -329,20 +331,24 @@ class TestViewerMainWindow(QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
         Parameters:
             obj: either a TestSuite or a TestProject; 
             if it is a string, then it is the stdout of the make command"""
-        val = self.progTest.value()+1 
-        self.progTest.setValue( val )
-        self.progTest.setFormat("%p% : " + text)
 
         # Update the tree's data for the suite
         if not obj is None:
-            if isinstance(obj, TestSingle):
-                if obj.get_fullname() == self.current_results.get_fullname(): self.show_results()
-            elif isinstance(obj, TestSuite):
+            
+            # For test results, increment the progress bar
+            if isinstance(obj, TestSingle) or isinstance(obj, TestSuite) or isinstance(obj, TestProject):
+                val = self.progTest.value()+1 
+                self.progTest.setValue( val )
+                self.progTest.setFormat("%p% : " + text)
+                # Try to update the current results shown
+                if not self.current_results is None:
+                    if obj.get_fullname() == self.current_results.get_fullname(): 
+                        self.show_results()
+            
+            if isinstance(obj, TestSuite):
                 self.model.update_suite(obj)
-                if obj.get_fullname() == self.current_results.get_fullname(): self.show_results()
             elif isinstance(obj, TestProject):
                 self.model.update_project(obj.name)
-                if obj.get_fullname() == self.current_results.get_fullname(): self.show_results()
             elif isinstance(obj, basestring):
                 # String was returned
                 if obj == test_info.MSG_ALL_BUILDS_SUCCESSFUL:
@@ -353,6 +359,8 @@ class TestViewerMainWindow(QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
                     # Accumulated stdout
                     self.stdout += self.markup_console(obj)
                     self.textConsole.setText( self.stdout )
+                    sb = self.textConsole.verticalScrollBar();
+                    sb.setValue(sb.maximum());
                 
                 
 #        # Every second or so, update the tree too
@@ -365,12 +373,19 @@ class TestViewerMainWindow(QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
         """ Update the tree view without resetting all the model data """
         self.treeTests.model().update_all()
         
+    #-----------------------------------------------------------------------------
+    def set_running(self, running):
+        """ Sets whether a test suite is running. Adjusts the GUI as needed"""
+        self.running=running
+        self.buttonAbort.setEnabled(running)
+        self.buttonRunAll.setEnabled(not running)
+        self.buttonRunSelected.setEnabled(not running)
+                
     #-----------------------------------------------------------------------------
     def complete_run(self):
         """ Event called when completing/aborting a test run """
-        self.buttonAbort.setEnabled(False)
-        self.buttonRunAll.setEnabled(True)
-        self.buttonRunSelected.setEnabled(True)
+        self.set_running(False)
+        
         self.progTest.setValue(0)
         self.progTest.setFormat("")
         self.update_tree()
@@ -479,12 +494,11 @@ class TestViewerMainWindow(QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
         if num_steps < 1: num_steps = 1 
         self.progTest.setValue(0)
         self.progTest.setMaximum( num_steps )
-        self.buttonAbort.setEnabled(True)
-        self.buttonRunAll.setEnabled(False)
-        self.buttonRunSelected.setEnabled(False)
+        self.set_running(True)
         self.stdout = ""
         self.textConsole.setText("")
-        # Select the console output tab (for the make output)
+        # Select the console output tab (for the make output)        self.running=True
+
         self.tabWidgetRight.setCurrentIndex(1)
         # Begin the thread in the background
         self.worker.start()
diff --git a/Code/Tools/TestViewer/test_info.py b/Code/Tools/TestViewer/test_info.py
index 0f06adc24a5..3474af96d4b 100644
--- a/Code/Tools/TestViewer/test_info.py
+++ b/Code/Tools/TestViewer/test_info.py
@@ -239,9 +239,11 @@ class TestSuite(object):
         # Source file (BlaBlaTest.h) for this suite
         self.source_file = source_file
         if not os.path.exists(self.source_file):
-            print "Warning! Source file not found - test suite '%s' should be renamed: %s" % (self.name, self.source_file)
-        # Last modified time of the source file
-        self.source_file_mtime = os.path.getmtime(self.source_file)
+            print "Warning! Source file for test %s not found: %s" % (self.name, self.source_file)
+            self.source_file_mtime = time.time()
+        else:
+            # Last modified time of the source file
+            self.source_file_mtime = os.path.getmtime(self.source_file)
         
         # A list of test singles inside this suite
         self.tests = []
@@ -702,7 +704,7 @@ class TestProject(object):
             count += 1
         count += 1
         if count >= len(lines):
-            raise "Error interpreting CXX test output!"
+            print "Error interpreting CXX test output of %s" % (self.executable)
         
         lines = lines[count:]
         
@@ -838,8 +840,40 @@ class MultipleProjects(object):
         """ Do a 'svn st' call and interpret the results to find which tests need to be run. """
         # First, de-select it all
         self.select_all(False)
-        commands.getoutput("svn info %s" % self.source_path )
-        raise NotImplementedError
+        output = commands.getoutput("svn st %s" % self.source_path )
+        lines = output.split('\n')
+        for line in lines:
+            if line.startswith('M') or line.startswith('A') or line.startswith('D') or line.startswith('R'):
+                 #Change to file or stuff.
+                 filename = line[8:].strip()
+                 foundit = None
+                 for pj in self.projects:
+                     for suite in pj.suites:
+                         # If the test file and the source file are the same,  
+                         if os.path.samefile( suite.source_file, filename):
+                             suite.selected = True
+                             pj.selected = True
+                             foundit = suite
+                             break
+                
+                 if foundit is None:
+                     # Ok, not directly a test name. Look for a similar test file
+                     # Get the bare filename, no .h or .cpp
+                     bare_file = os.path.splitext(os.path.basename(filename))[0]
+                     for pj in self.projects:
+                         for suite in pj.suites:
+                             # The words in the source file are inside the Test source file. Might be good.
+                             bare_source = os.path.basename(suite.source_file)
+                             if bare_file in bare_source:
+                                 suite.selected = True
+                                 pj.selected = True
+                                 foundit = suite
+                                 break
+                 if foundit is None:
+                     print "%s: No test found." % (filename)
+                 else:
+                     print "%s: Test found: '%s'" % ( filename, foundit.get_fullname() )
+                 
             
     #--------------------------------------------------------------------------        
     def discover_CXX_projects(self, path, source_path):
@@ -847,11 +881,16 @@ class MultipleProjects(object):
         Populates all the test in it."""
         self.source_path = source_path
         self.projects = []
+
+        # How many cores to use to make projects        
+        num_threads = multiprocessing.cpu_count()-1
+        if num_threads < 1: num_threads = 1
+        
         dirList=os.listdir(path)
         for fname in dirList:
             # Look for executables ending in Test
             if fname.endswith("Test"): # and (fname.startswith("Kernel") or fname.startswith("Geometry")): #!TODO
-                make_command = "cd %s ; make %s -j" % (os.path.join(path, ".."), fname)
+                make_command = "cd %s ; make %s -j%d " % (os.path.join(path, ".."), fname, num_threads)
                 pj = TestProject(fname, os.path.join(path, fname), make_command)
                 print "... Populating project %s ..." % fname
                 pj.populate()
@@ -1122,14 +1161,16 @@ test_age()
 #==================================================================================================
 if __name__ == '__main__':
     all_tests.discover_CXX_projects("/home/8oz/Code/Mantid/Code/Mantid/bin/", "/home/8oz/Code/Mantid/Code/Mantid/Framework/")
-    all_tests.run_tests_in_parallel(selected_only=False, make_tests=True, 
-                          parallel=True, callback_func=test_run_print_callback)
+    all_tests.select_svn()
     
-    for pj in all_tests.projects:
-        print pj.name, pj.get_state_str()
-        for suite in pj.suites:
-            print suite.classname, suite.get_state_str()
-        
+#    all_tests.run_tests_in_parallel(selected_only=False, make_tests=True, 
+#                          parallel=True, callback_func=test_run_print_callback)
+#    
+#    for pj in all_tests.projects:
+#        print pj.name, pj.get_state_str()
+#        for suite in pj.suites:
+#            print suite.classname, suite.get_state_str()
+#        
 #    all_tests.run_tests_in_parallel(selected_only=False, make_tests=True, 
 #                          parallel=False, callback_func=test_run_print_callback)
 
diff --git a/Code/Tools/TestViewer/test_tree.py b/Code/Tools/TestViewer/test_tree.py
index 39b0d6e0158..fb47b528006 100644
--- a/Code/Tools/TestViewer/test_tree.py
+++ b/Code/Tools/TestViewer/test_tree.py
@@ -19,9 +19,9 @@ HORIZONTAL_HEADERS = ("Test", "Status", "Time (sec)")
 def format_time(seconds):
     """Return a string for the # of seconds """
     if seconds < 1e-3:
-        return "<1 ms"
+        return "0.000"
     else:
-        return "%.3f s" % (seconds) 
+        return "%.3f" % (seconds) 
     
     if seconds < 1e-3:
         return "%d us" % (seconds*1000000) 
@@ -159,7 +159,7 @@ class TreeItemProject(TreeItemBase):
             if column == 1:
                 return QtCore.QVariant(self.contents.get_state_str())
             if column == 2:
-                return QtCore.QVariant( format_time( self.contents.get_runtime() ))
+                return QtCore.QVariant( self.contents.get_runtime() )
         return QtCore.QVariant()
 
       
@@ -200,7 +200,7 @@ class TreeItemSuite(TreeItemBase):
             if column == 1:
                 return QtCore.QVariant(self.contents.get_state_str())
             if column == 2:
-                return QtCore.QVariant( format_time( self.contents.get_runtime() ))
+                return QtCore.QVariant( self.contents.get_runtime() )
         return QtCore.QVariant()
 
 
@@ -240,7 +240,7 @@ class TreeItemSingle(TreeItemBase):
             if column == 1:
                 return QtCore.QVariant(self.contents.get_state_str())
             if column == 2:
-                return QtCore.QVariant( format_time( self.contents.runtime ) )
+                return QtCore.QVariant( self.contents.runtime )
         return QtCore.QVariant()
 
 
-- 
GitLab