summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Gorenkov2012-04-17 23:50:07 (EDT)
committerMarc-Andre Laperle2012-04-17 23:50:07 (EDT)
commitf16f0dbe483fd8fe1b2c5ab343d03201bfcccbf9 (patch)
treef4c19f2733b05d642eeb14ec90a79065640ae23e
parent83cf5dc8303da5df560bde6ebb602b1e5cc59fb8 (diff)
downloadorg.eclipse.cdt-f16f0dbe483fd8fe1b2c5ab343d03201bfcccbf9.zip
org.eclipse.cdt-f16f0dbe483fd8fe1b2c5ab343d03201bfcccbf9.tar.gz
org.eclipse.cdt-f16f0dbe483fd8fe1b2c5ab343d03201bfcccbf9.tar.bz2
Bug 210366 - CDT should have Unit Testing and Component Testing like JDT
-rw-r--r--pom.xml8
-rw-r--r--releng/org.eclipse.cdt.repo/category.xml6
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/.project34
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/META-INF/MANIFEST.MF13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/build.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.properties15
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.xml13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/pom.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.java30
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.properties16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerPlugin.java67
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerProvider.java113
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostXmlLogHandler.java229
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/.project17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/build.properties16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/eclipse_update_120.jpgbin0 -> 21695 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/epl-v10.html328
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties168
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml52
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/license.html108
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml18
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.project34
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties15
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java35
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java67
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java97
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java645
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/.project34
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties21
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties15
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java37
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties23
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java66
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java129
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java399
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties5
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpgbin0 -> 21695 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/epl-v10.html328
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties168
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml51
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html108
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml18
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/.project28
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties13
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/build.properties20
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml42
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java123
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java39
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java55
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java48
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java99
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java481
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java698
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java221
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java693
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner.test/test.xml56
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/.classpath7
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/.project34
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs82
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF37
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/about.html24
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/build.properties23
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gifbin0 -> 225 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gifbin0 -> 338 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_horizontal.gifbin0 -> 354 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gifbin0 -> 219 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gifbin0 -> 580 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/scroll_lock.gifbin0 -> 588 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gifbin0 -> 204 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gifbin0 -> 152 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/sort.gifbin0 -> 137 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/stop.gifbin0 -> 152 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gifbin0 -> 586 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gifbin0 -> 358 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gifbin0 -> 374 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gifbin0 -> 352 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gifbin0 -> 590 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/scroll_lock.gifbin0 -> 626 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gifbin0 -> 332 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gifbin0 -> 323 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gifbin0 -> 101 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gifbin0 -> 157 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gifbin0 -> 215 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gifbin0 -> 219 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/show_failed_only.gifbin0 -> 163 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gifbin0 -> 374 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gifbin0 -> 374 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_notrun.gifbin0 -> 362 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_passed.gifbin0 -> 380 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gifbin0 -> 594 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_skipped.gifbin0 -> 365 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gifbin0 -> 376 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gifbin0 -> 376 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gifbin0 -> 358 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_passed.gifbin0 -> 382 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_run.gifbin0 -> 589 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gifbin0 -> 82 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gifbin0 -> 82 bytes
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/plugin.properties30
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/plugin.xml255
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/pom.xml17
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd178
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java239
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java26
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java26
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java36
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java26
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties12
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java115
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java111
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java167
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java80
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java30
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java28
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties14
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java102
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java56
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java41
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java57
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java480
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java85
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java280
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java215
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java200
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java29
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java29
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties15
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java147
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java85
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java573
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java183
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java87
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java245
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java366
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java115
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java554
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java517
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java36
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties22
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java77
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties63
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java65
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java65
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java448
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessageLevelFilterAction.java58
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/MessagesOrderingAction.java42
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/OpenInEditorAction.java181
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RedebugSelectedAction.java36
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RelaunchSelectedAction.java96
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunAction.java50
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/RerunSelectedAction.java36
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ScrollLockAction.java41
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFailedOnlyAction.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowFileNameOnlyAction.java38
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowNextFailureAction.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowPreviousFailureAction.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTestsInHierarchyAction.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ShowTimeAction.java37
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/StopAction.java46
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyCollapseAllAction.java37
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/TestsHierarchyExpandAllAction.java37
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ToggleOrientationAction.java60
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/BaseTestsLaunchDelegate.java255
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerConstants.java40
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProvider.java54
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/launcher/ITestsRunnerProviderInfo.java68
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/IModelVisitor.java33
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestCase.java31
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestItem.java95
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestLocation.java35
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestMessage.java72
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelAccessor.java52
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestModelUpdater.java94
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestSuite.java22
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSession.java135
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ITestingSessionListener.java66
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.java30
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/ModelMessages.properties16
-rw-r--r--testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/model/TestingException.java28
202 files changed, 15775 insertions, 0 deletions
diff --git a/pom.xml b/pom.xml
index dd54c31..1ab4aa8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -171,6 +171,14 @@
<module>build/org.eclipse.cdt.autotools.source-feature</module>
<module>build/org.eclipse.linuxtools.cdt.autotools.core</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.boost</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.gtest</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.qttest</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.test</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.feature</module>
+ <module>testsrunner/org.eclipse.cdt.testsrunner.source.feature</module>
+
<!--
<module>lrparser/org.eclipse.cdt.core.lrparser.tests</module>
<module>upc/org.eclipse.cdt.core.parser.upc.tests</module>
diff --git a/releng/org.eclipse.cdt.repo/category.xml b/releng/org.eclipse.cdt.repo/category.xml
index 02a0090..8827c72 100644
--- a/releng/org.eclipse.cdt.repo/category.xml
+++ b/releng/org.eclipse.cdt.repo/category.xml
@@ -65,4 +65,10 @@
<feature url="features/org.eclipse.cdt.autotools.source_0.0.0.qualifier.jar" id="org.eclipse.cdt.autotools.source" version="0.0.0">
<category name="extra"/>
</feature>
+ <feature url="features/org.eclipse.cdt.testsrunner.feature_0.0.0.qualifier.jar" id="org.eclipse.cdt.testsrunner.feature" version="0.0.0">
+ <category name="extra"/>
+ </feature>
+ <feature url="features/org.eclipse.cdt.testsrunner.source.feature_0.0.0.qualifier.jar" id="org.eclipse.cdt.testsrunner.source.feature" version="0.0.0">
+ <category name="extra"/>
+ </feature>
</site>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.boost/.classpath
new file mode 100644
index 0000000..deb6736
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/.project b/testsrunner/org.eclipse.cdt.testsrunner.boost/.project
new file mode 100644
index 0000000..1ec504c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.boost</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.boost/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0e860bf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,82 @@
+#Mon Apr 16 13:01:24 EEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.boost/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..d4bd6da
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner.boost;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.internal.boost.BoostTestsRunnerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0",
+ org.eclipse.cdt.testsrunner;bundle-version="3.5.0"
+Export-Package: org.eclipse.cdt.testsrunner.internal.boost;x-friends:="org.eclipse.cdt.testsrunner.test"
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/about.html b/testsrunner/org.eclipse.cdt.testsrunner.boost/about.html
new file mode 100644
index 0000000..d7c5118
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.boost/build.properties
new file mode 100644
index 0000000..55d9be8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+
+bin.includes = plugin.xml,\
+ plugin.properties,\
+ about.html,\
+ .,\
+ META-INF/
+javadoc.packages = org.eclipse.cdt.launch.ui.*,\
+ org.eclipse.cdt.launch.sourcelookup*,\
+ org.eclipse.cdt.launch.*
+source.. = src/
+src.includes = about.html
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.properties
new file mode 100644
index 0000000..5b8613d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+pluginName=C/C++ Development Tools Boost Tests Runner Support
+providerName=Eclipse CDT
+
+BoostTestsRunner.name=Boost Tests Runner
+BoostTestsRunner.description=Tests runner for a test module based on Boost.Test library
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.xml
new file mode 100644
index 0000000..386f083
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/plugin.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.cdt.testsrunner.TestsRunner">
+ <runner
+ class="org.eclipse.cdt.testsrunner.internal.boost.BoostTestsRunnerProvider"
+ description="%BoostTestsRunner.description"
+ id="org.eclipse.cdt.testsrunner.boost"
+ name="%BoostTestsRunner.name">
+ </runner>
+ </extension>
+</plugin>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.boost/pom.xml
new file mode 100644
index 0000000..25e9d53
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.boost</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.java
new file mode 100644
index 0000000..49d3329
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.boost;
+
+import org.eclipse.osgi.util.NLS;
+
+public class BoostTestsRunnerMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.boost.BoostTestsRunnerMessages"; //$NON-NLS-1$
+ public static String BoostTestsRunner_error_format;
+ public static String BoostTestsRunner_io_error_prefix;
+ public static String BoostTestsRunner_wrong_tests_paths_count;
+ public static String BoostTestsRunner_xml_error_prefix;
+ public static String BoostXmlLogHandler_exception_suffix;
+ public static String BoostXmlLogHandler_wrong_tag_name;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, BoostTestsRunnerMessages.class);
+ }
+
+ private BoostTestsRunnerMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.properties
new file mode 100644
index 0000000..38b0bdb
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerMessages.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+BoostTestsRunner_error_format={0}: {1}
+BoostTestsRunner_io_error_prefix=I/O Error
+BoostTestsRunner_wrong_tests_paths_count=Only on test suite or test case should be specified to rerun
+BoostTestsRunner_xml_error_prefix=XML parse error
+BoostXmlLogHandler_exception_suffix=\nLast check point was here.
+BoostXmlLogHandler_wrong_tag_name=Invalid XML format: Element "{0}" is not accepted\!
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerPlugin.java
new file mode 100644
index 0000000..0e0545e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerPlugin.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.boost;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class BoostTestsRunnerPlugin extends Plugin {
+
+ /** The plug-in ID .*/
+ public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.boost"; //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static BoostTestsRunnerPlugin plugin;
+
+
+ public BoostTestsRunnerPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * Returns the Boost Tests Runner provider plug-in instance.
+ *
+ * @return the plug-in instance
+ */
+ public static BoostTestsRunnerPlugin getDefault() {
+ return plugin;
+ }
+
+ /** Convenience method which returns the unique identifier of this plugin. */
+ public static String getUniqueIdentifier() {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ /**
+ * Logs an internal error with the specified throwable
+ *
+ * @param e the exception to be logged
+ */
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerProvider.java
new file mode 100644
index 0000000..48d5fda
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostTestsRunnerProvider.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.boost;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.xml.sax.SAXException;
+
+/**
+ * The Tests Runner provider plug-in to run tests with Boost.Test framework.
+ *
+ * Configures the test module to output in XML format, parses the output and
+ * provides the data for the Tests Runner Core.
+ *
+ * @note There is a note about Tests Runner provider plug-in accuracy. Communication
+ * between Boost test module and Boost Tests Runner provider plug-in is done through
+ * standard output (which is buffered by default). Boost.Test (at least current
+ * version - 1.48.0) does not provide a way to flush the data about tests
+ * execution when they are available, so there may be a delay between test event
+ * happening (e.g. test case is started) and its displaying in the results view.
+ * The possible solution is to turn off the standard output buffering like this:
+ * <pre>
+ * static struct DisableStdCoutBuffering
+ * {
+ * DisableStdCoutBuffering()
+ * {
+ * std::cout.setf(std::ios_base::unitbuf);
+ * }
+ * } s_disableStdCoutBuffering;
+ * </pre>
+ * It will make the results view showing progress more accurate.
+ */
+public class BoostTestsRunnerProvider implements ITestsRunnerProvider {
+
+ @Override
+ public String[] getAdditionalLaunchParameters(String[][] testPaths) throws TestingException {
+ final String[] boostParameters = {
+ "--output_format=xml", //$NON-NLS-1$
+ "--log_level=all", //$NON-NLS-1$
+ "--report_level=no" //$NON-NLS-1$
+ };
+ String[] result = boostParameters;
+
+ // Build tests filter
+ if (testPaths != null && testPaths.length >= 1) {
+ if (testPaths.length != 1) {
+ throw new TestingException(BoostTestsRunnerMessages.BoostTestsRunner_wrong_tests_paths_count);
+ }
+ StringBuilder sb = new StringBuilder("--run_test="); //$NON-NLS-1$
+ String[] testPath = testPaths[0];
+ for (int i = 1; i < testPath.length; i++) {
+ if (i != 1) {
+ sb.append("/"); //$NON-NLS-1$
+ }
+ sb.append(testPath[i]);
+ }
+ result = new String[boostParameters.length + 1];
+ System.arraycopy(boostParameters, 0, result, 0, boostParameters.length);
+ result[boostParameters.length] = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Construct the error message from prefix and detailed description.
+ *
+ * @param prefix prefix
+ * @param description detailed description
+ * @return the full message
+ */
+ private String getErrorText(String prefix, String description) {
+ return MessageFormat.format(BoostTestsRunnerMessages.BoostTestsRunner_error_format, prefix, description);
+ }
+
+ @Override
+ public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException {
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser sp = spf.newSAXParser();
+ sp.parse(inputStream, new BoostXmlLogHandler(modelUpdater));
+
+ } catch (IOException e) {
+ throw new TestingException(getErrorText(BoostTestsRunnerMessages.BoostTestsRunner_io_error_prefix, e.getLocalizedMessage()));
+
+ } catch (NumberFormatException e) {
+ throw new TestingException(getErrorText(BoostTestsRunnerMessages.BoostTestsRunner_xml_error_prefix, e.getLocalizedMessage()));
+
+ } catch (ParserConfigurationException e) {
+ throw new TestingException(getErrorText(BoostTestsRunnerMessages.BoostTestsRunner_xml_error_prefix, e.getLocalizedMessage()));
+
+ } catch (SAXException e) {
+ throw new TestingException(getErrorText(BoostTestsRunnerMessages.BoostTestsRunner_xml_error_prefix, e.getLocalizedMessage()));
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostXmlLogHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostXmlLogHandler.java
new file mode 100644
index 0000000..08b40e8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.boost/src/org/eclipse/cdt/testsrunner/internal/boost/BoostXmlLogHandler.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.boost;
+
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestItem.Status;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * Parses the Boost.Test XML log and notifies the Tests Runner Core about how
+ * the testing process is going.
+ */
+public class BoostXmlLogHandler extends DefaultHandler {
+
+ // Boost.Test XML log tags
+ private static final String XML_NODE_TEST_LOG = "TestLog"; //$NON-NLS-1$
+ private static final String XML_NODE_TEST_SUITE = "TestSuite"; //$NON-NLS-1$
+ private static final String XML_NODE_TEST_CASE = "TestCase"; //$NON-NLS-1$
+ private static final String XML_NODE_TESTING_TIME = "TestingTime"; //$NON-NLS-1$
+ private static final String XML_NODE_LAST_CHECKPOINT = "LastCheckpoint"; //$NON-NLS-1$
+
+ // Boost.Test XML log message levels representation
+ private static final String XML_NODE_INFO = "Info"; //$NON-NLS-1$
+ private static final String XML_NODE_MESSAGE = "Message"; //$NON-NLS-1$
+ private static final String XML_NODE_WARNING = "Warning"; //$NON-NLS-1$
+ private static final String XML_NODE_ERROR = "Error"; //$NON-NLS-1$
+ private static final String XML_NODE_FATAL_ERROR = "FatalError"; //$NON-NLS-1$
+ private static final String XML_NODE_EXCEPTION = "Exception"; //$NON-NLS-1$
+
+ // Boost.Test XML log attributes
+ private static final String XML_ATTR_TEST_SUITE_NAME = "name"; //$NON-NLS-1$
+ private static final String XML_ATTR_TEST_CASE_NAME = "name"; //$NON-NLS-1$
+ private static final String XML_ATTR_MESSAGE_FILE = "file"; //$NON-NLS-1$
+ private static final String XML_ATTR_MESSAGE_LINE = "line"; //$NON-NLS-1$
+
+ /** Maps the string message level representation to the Tests Runner internal enum code. */
+ private static final Map<String, ITestMessage.Level> STRING_TO_MESSAGE_LEVEL;
+ static {
+ Map<String, ITestMessage.Level> aMap = new HashMap<String, ITestMessage.Level>();
+ aMap.put(XML_NODE_INFO, ITestMessage.Level.Info);
+ aMap.put(XML_NODE_MESSAGE, ITestMessage.Level.Message);
+ aMap.put(XML_NODE_WARNING, ITestMessage.Level.Warning);
+ aMap.put(XML_NODE_ERROR, ITestMessage.Level.Error);
+ aMap.put(XML_NODE_FATAL_ERROR, ITestMessage.Level.FatalError);
+ // NOTE: Exception node is processed separately
+ STRING_TO_MESSAGE_LEVEL = Collections.unmodifiableMap(aMap);
+ }
+
+ /** The default file name for test message location. */
+ private static final String DEFAULT_LOCATION_FILE = null;
+
+ /** The default line number for test message location. */
+ private static final int DEFAULT_LOCATION_LINE = -1;
+
+ /** The interface to notify the Tests Runner Core */
+ private ITestModelUpdater modelUpdater;
+
+ /** Stores the text between XML tags. */
+ private Stack<StringBuilder> elementDataStack = new Stack<StringBuilder>();
+
+ /** File name for current test message location. */
+ private String fileName;
+
+ /** Line number for current test message location. */
+ private int lineNumber;
+
+ /** Current test case status. */
+ private ITestItem.Status testStatus;
+
+
+ BoostXmlLogHandler(ITestModelUpdater modelUpdater) {
+ this.modelUpdater = modelUpdater;
+ }
+
+ @Override
+ public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException {
+
+ elementDataStack.push(new StringBuilder());
+ if (qName == XML_NODE_TEST_SUITE) {
+ String testSuiteName = attrs.getValue(XML_ATTR_TEST_SUITE_NAME);
+ modelUpdater.enterTestSuite(testSuiteName);
+
+ } else if (qName == XML_NODE_TEST_CASE) {
+ String testCaseName = attrs.getValue(XML_ATTR_TEST_CASE_NAME);
+ modelUpdater.enterTestCase(testCaseName);
+ testStatus = Status.Passed;
+
+ } else if (STRING_TO_MESSAGE_LEVEL.containsKey(qName)
+ || qName == XML_NODE_LAST_CHECKPOINT) {
+ fileName = attrs.getValue(XML_ATTR_MESSAGE_FILE);
+ String lineNumberStr = attrs.getValue(XML_ATTR_MESSAGE_LINE);
+ lineNumber = lineNumberStr != null ? Integer.parseInt(lineNumberStr.trim()) : DEFAULT_LOCATION_LINE;
+
+ } else if (qName == XML_NODE_EXCEPTION) {
+ fileName = DEFAULT_LOCATION_FILE;
+ lineNumber = DEFAULT_LOCATION_LINE;
+
+ } else if (qName == XML_NODE_TESTING_TIME ) {
+
+ } else if (qName == XML_NODE_TEST_LOG) {
+ /* just skip, do nothing */
+
+ } else {
+ logAndThrowErrorForElement(qName);
+ }
+ }
+
+ /**
+ * Common routing: notifies the Tests Runner core about new test message
+ * and resets the internal state.
+ *
+ * @param level test message level
+ */
+ private void addCurrentMessage(ITestMessage.Level level) {
+ modelUpdater.addTestMessage(fileName, lineNumber, level, elementDataStack.peek().toString());
+ fileName = DEFAULT_LOCATION_FILE;
+ lineNumber = DEFAULT_LOCATION_LINE;
+ if (level == ITestMessage.Level.Error || level == ITestMessage.Level.FatalError) {
+ if (testStatus != ITestItem.Status.Aborted) {
+ testStatus = ITestItem.Status.Failed;
+ }
+
+ } else if (level == ITestMessage.Level.Exception) {
+ testStatus = ITestItem.Status.Aborted;
+ }
+ }
+
+ @Override
+ public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+
+ if (qName == XML_NODE_TEST_SUITE) {
+ modelUpdater.exitTestSuite();
+
+ } else if (qName == XML_NODE_TEST_CASE) {
+ modelUpdater.setTestStatus(testStatus);
+ modelUpdater.exitTestCase();
+
+ } else if (qName == XML_NODE_TESTING_TIME) {
+ modelUpdater.setTestingTime(Integer.parseInt(elementDataStack.peek().toString().trim())/1000);
+
+ } else if (STRING_TO_MESSAGE_LEVEL.containsKey(qName)) {
+ addCurrentMessage(STRING_TO_MESSAGE_LEVEL.get(qName));
+
+ } else if (qName == XML_NODE_EXCEPTION) {
+ if (fileName != DEFAULT_LOCATION_FILE && !fileName.isEmpty() && lineNumber >= 0) {
+ elementDataStack.peek().append(BoostTestsRunnerMessages.BoostXmlLogHandler_exception_suffix);
+ }
+ addCurrentMessage(ITestMessage.Level.Exception);
+
+ } else if (qName == XML_NODE_TEST_LOG || qName == XML_NODE_LAST_CHECKPOINT) {
+ /* just skip, do nothing */
+
+ } else {
+ logAndThrowErrorForElement(qName);
+ }
+ elementDataStack.pop();
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ StringBuilder builder = elementDataStack.peek();
+ for (int i = start; i < start + length; i++) {
+ builder.append(ch[i]);
+ }
+ }
+
+ /**
+ * Throws the testing exception for the specified XML tag.
+ *
+ * @param tagName XML tag name
+ * @throws SAXException the exception that will be thrown
+ */
+ private void logAndThrowErrorForElement(String tagName) throws SAXException {
+ logAndThrowError(
+ MessageFormat.format(BoostTestsRunnerMessages.BoostXmlLogHandler_wrong_tag_name, tagName)
+ );
+ }
+
+ /**
+ * Throws the testing exception with the specified message.
+ *
+ * @param message the reason
+ * @throws SAXException the exception that will be thrown
+ */
+ private void logAndThrowError(String message) throws SAXException {
+ SAXException e = new SAXException(message);
+ BoostTestsRunnerPlugin.log(e);
+ throw e;
+ }
+
+
+ @Override
+ public void warning(SAXParseException ex) throws SAXException {
+ BoostTestsRunnerPlugin.log(ex);
+ }
+
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ BoostTestsRunnerPlugin.log(ex);
+ throw ex;
+ }
+
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ BoostTestsRunnerPlugin.log(ex);
+ throw ex;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/.project b/testsrunner/org.eclipse.cdt.testsrunner.feature/.project
new file mode 100644
index 0000000..0a31f3b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.feature/build.properties
new file mode 100644
index 0000000..b10b7a3
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/build.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2012 Marc-Andre Laperle and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Marc-Andre Laperle - initial API and implementation
+###############################################################################
+bin.includes = feature.xml,\
+ epl-v10.html,\
+ eclipse_update_120.jpg,\
+ feature.properties,\
+ license.html
+
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/eclipse_update_120.jpg b/testsrunner/org.eclipse.cdt.testsrunner.feature/eclipse_update_120.jpg
new file mode 100644
index 0000000..bfdf708
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/eclipse_update_120.jpg
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/epl-v10.html b/testsrunner/org.eclipse.cdt.testsrunner.feature/epl-v10.html
new file mode 100644
index 0000000..ed4b196
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/epl-v10.html
@@ -0,0 +1,328 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=ProgId content=Word.Document>
+<meta name=Generator content="Microsoft Word 9">
+<meta name=Originator content="Microsoft Word 9">
+<link rel=File-List
+href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
+<title>Eclipse Public License - Version 1.0</title>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+ <o:Revision>2</o:Revision>
+ <o:TotalTime>3</o:TotalTime>
+ <o:Created>2004-03-05T23:03:00Z</o:Created>
+ <o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
+ <o:Pages>4</o:Pages>
+ <o:Words>1626</o:Words>
+ <o:Characters>9270</o:Characters>
+ <o:Lines>77</o:Lines>
+ <o:Paragraphs>18</o:Paragraphs>
+ <o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
+ <o:Version>9.4402</o:Version>
+ </o:DocumentProperties>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <w:WordDocument>
+ <w:TrackRevisions/>
+ </w:WordDocument>
+</xml><![endif]-->
+<style>
+<!--
+ /* Font Definitions */
+@font-face
+ {font-family:Tahoma;
+ panose-1:2 11 6 4 3 5 4 4 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:swiss;
+ mso-font-pitch:variable;
+ mso-font-signature:553679495 -2147483648 8 0 66047 0;}
+ /* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {mso-style-parent:"";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+p
+ {margin-right:0in;
+ mso-margin-top-alt:auto;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+p.BalloonText, li.BalloonText, div.BalloonText
+ {mso-style-name:"Balloon Text";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:8.0pt;
+ font-family:Tahoma;
+ mso-fareast-font-family:"Times New Roman";}
+@page Section1
+ {size:8.5in 11.0in;
+ margin:1.0in 1.25in 1.0in 1.25in;
+ mso-header-margin:.5in;
+ mso-footer-margin:.5in;
+ mso-paper-source:0;}
+div.Section1
+ {page:Section1;}
+-->
+</style>
+</head>
+
+<body lang=EN-US style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
+</p>
+
+<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Contribution&quot; means:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and<br clear=left>
+b) in the case of each subsequent Contributor:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+changes to the Program, and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+additions to the Program;</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Contributor&quot; means any person or
+entity that distributes the Program.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Licensed Patents &quot; mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Program&quot; means the Contributions
+distributed in accordance with this Agreement.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Recipient&quot; means anyone who
+receives the Program under this Agreement, including all Contributors.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to<span
+style='color:red'> </span>reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. </span></p>
+
+<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:</span>
+</p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it complies with the terms and conditions of this Agreement; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+its license agreement:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
+
+<p><span style='font-size:10.0pt'>When the Program is made available in source
+code form:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it must be made available under this Agreement; and </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
+copy of this Agreement must be included with each copy of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
+copyright notices contained within the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. </span></p>
+
+<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
+
+<p><span style='font-size:10.0pt'>Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor (&quot;Commercial
+Contributor&quot;) hereby agrees to defend and indemnify every other
+Contributor (&quot;Indemnified Contributor&quot;) against any losses, damages and
+costs (collectively &quot;Losses&quot;) arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense.</span> </p>
+
+<p><span style='font-size:10.0pt'>For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. </span></p>
+
+<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
+
+<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</span> </p>
+
+<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </span></p>
+
+<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. </span></p>
+
+<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.</span> </p>
+
+<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.</span> </p>
+
+<p class=MsoNormal><![if !supportEmptyParas]>&nbsp;<![endif]><o:p></o:p></p>
+
+</div>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties
new file mode 100644
index 0000000..7677311
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.properties
@@ -0,0 +1,168 @@
+###############################################################################
+# Copyright (c) 2012 Anton Gorenkov and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - initial API and implementation
+# Marc-Andre Laperle
+###############################################################################
+# features.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=C/C++ Unit Testing Support
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse CDT
+
+# "updateSiteName" property - label for the update site
+updateSiteName=Eclipse CDT Update Site
+
+# "description" property - description of the feature
+description=Support for running unit tests
+
+# copyright
+copyright=\
+Copyright (c) 2012 Anton Gorenkov and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+February 1, 2011\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+ 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+ the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+ extending or updating the functionality of an Eclipse-based product.\n\
+ 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+ Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+ 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+ govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+ Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+ with the Specification. Such Installable Software Agreement must inform the user of the\n\
+ terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+ the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+ indication of agreement by the user, the provisioning Technology will complete installation\n\
+ of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml
new file mode 100644
index 0000000..2c9b6ce
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/feature.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.cdt.testsrunner.feature"
+ label="%featureName"
+ version="7.0.0.qualifier"
+ provider-name="%providerName">
+
+ <description>
+ %description
+ </description>
+
+ <copyright>
+ %copyright
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <url>
+ <update label="%updateSiteName" url="http://download.eclipse.org/tools/cdt/releases/indigo"/>
+ </url>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.boost"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.gtest"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.qttest"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html b/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html
new file mode 100644
index 0000000..f19c483
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/license.html
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>February 1, 2011</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ (&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+ href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+ (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+ <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+ on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+ product.</li>
+ <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+ accessed and copied to the Target Machine.</li>
+ <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+ Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+ Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+ the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+ indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml
new file mode 100644
index 0000000..dfbd02d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.feature/pom.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.cdt.features</groupId>
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.feature</artifactId>
+ <packaging>eclipse-feature</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath
new file mode 100644
index 0000000..deb6736
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project
new file mode 100644
index 0000000..174ece0
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.gtest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0e860bf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,82 @@
+#Mon Apr 16 13:01:24 EEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..6138224
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner.gtest;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0",
+ org.eclipse.cdt.testsrunner;bundle-version="3.5.0"
+Export-Package: org.eclipse.cdt.testsrunner.internal.gtest;x-friends:="org.eclipse.cdt.testsrunner.test"
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html
new file mode 100644
index 0000000..d7c5118
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties
new file mode 100644
index 0000000..55d9be8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+
+bin.includes = plugin.xml,\
+ plugin.properties,\
+ about.html,\
+ .,\
+ META-INF/
+javadoc.packages = org.eclipse.cdt.launch.ui.*,\
+ org.eclipse.cdt.launch.sourcelookup*,\
+ org.eclipse.cdt.launch.*
+source.. = src/
+src.includes = about.html
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties
new file mode 100644
index 0000000..f96761d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+pluginName=C/C++ Development Tools Google Tests Runner Support
+providerName=Eclipse CDT
+
+GoogleTestsRunner.name=Google Tests Runner
+GoogleTestsRunner.description=Tests runner for a test module based on Google C++ Testing Framework
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml
new file mode 100644
index 0000000..152f28a
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/plugin.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.cdt.testsrunner.TestsRunner">
+ <runner
+ class="org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerProvider"
+ description="%GoogleTestsRunner.description"
+ id="org.eclipse.cdt.testsrunner.gtest"
+ name="%GoogleTestsRunner.name">
+ <features
+ multipleTestFilter="true">
+ </features>
+ </runner>
+ </extension>
+</plugin>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml
new file mode 100644
index 0000000..50dd36f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.gtest</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java
new file mode 100644
index 0000000..6aa1056
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.gtest;
+
+import org.eclipse.osgi.util.NLS;
+
+public class GoogleTestsRunnerMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerMessages"; //$NON-NLS-1$
+ public static String GoogleTestsRunner_error_format;
+ public static String GoogleTestsRunner_io_error_prefix;
+ public static String OutputHandler_getparam_message;
+ public static String OutputHandler_unexpected_case_end;
+ public static String OutputHandler_unexpected_output;
+ public static String OutputHandler_unexpected_suite_end;
+ public static String OutputHandler_unknown_error_prefix;
+ public static String OutputHandler_unknown_location_format;
+ public static String OutputHandler_unknown_test_status;
+ public static String OutputHandler_wrong_groups_count;
+ public static String OutputHandler_wrong_suite_name;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, GoogleTestsRunnerMessages.class);
+ }
+
+ private GoogleTestsRunnerMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties
new file mode 100644
index 0000000..e329ed2
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerMessages.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+GoogleTestsRunner_error_format={0}: {1}
+GoogleTestsRunner_io_error_prefix=I/O Error:
+OutputHandler_getparam_message=Instantiated with GetParam() = {0}
+OutputHandler_unexpected_case_end=End of test case "{0}" is not expected, because the last started case is "{1}".
+OutputHandler_unexpected_output=Unexpected test module output.
+OutputHandler_unexpected_suite_end=End of test suite "{0}" is not expected, because the last started suite is "{1}".
+OutputHandler_unknown_error_prefix=Unknown error during parsing Google Test module output:
+OutputHandler_unknown_location_format=Unknown location format.
+OutputHandler_unknown_test_status=Test status value "{0}" is unknown.
+OutputHandler_wrong_groups_count=State with pattern "{0}" should has {1} groups but has {2}.
+OutputHandler_wrong_suite_name=A test case "{0}" belongs to test suite "{1}", but the last started suite is "{2}".
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java
new file mode 100644
index 0000000..1ddb743
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerPlugin.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.gtest;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class GoogleTestsRunnerPlugin extends Plugin {
+
+ /** The plug-in ID .*/
+ public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.gtest"; //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static GoogleTestsRunnerPlugin plugin;
+
+
+ public GoogleTestsRunnerPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * Returns the Boost Tests Runner provider plug-in instance.
+ *
+ * @return the plug-in instance
+ */
+ public static GoogleTestsRunnerPlugin getDefault() {
+ return plugin;
+ }
+
+ /** Convenience method which returns the unique identifier of this plugin. */
+ public static String getUniqueIdentifier() {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ /**
+ * Logs an internal error with the specified throwable
+ *
+ * @param e the exception to be logged
+ */
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java
new file mode 100644
index 0000000..17ca3bd
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/GoogleTestsRunnerProvider.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.gtest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+
+
+/**
+ * The Tests Runner provider plug-in to run tests with Google Testing framework.
+ *
+ * Parses the text test module to output and provides the data for the Tests
+ * Runner Plug-In.
+ */
+public class GoogleTestsRunnerProvider implements ITestsRunnerProvider {
+
+ private static final String TEST_PATHS_DELIMITED = ":"; //$NON-NLS-1$
+ private static final String TEST_PATH_PARTS_DELIMITED = "."; //$NON-NLS-1$
+ private static final String ALL_TESTS= ".*"; //$NON-NLS-1$
+
+
+ @Override
+ public String[] getAdditionalLaunchParameters(String[][] testPaths) {
+ final String[] gtestParameters = {
+ "--gtest_repeat=1", //$NON-NLS-1$
+ "--gtest_print_time=1", //$NON-NLS-1$
+ "--gtest_color=no", //$NON-NLS-1$
+ };
+ String[] result = gtestParameters;
+
+ // Build tests filter
+ if (testPaths != null && testPaths.length >= 1) {
+ StringBuilder sb = new StringBuilder("--gtest_filter="); //$NON-NLS-1$
+ boolean needTestPathDelimiter = false;
+ for (String[] testPath : testPaths) {
+ if (needTestPathDelimiter) {
+ sb.append(TEST_PATHS_DELIMITED);
+ } else {
+ needTestPathDelimiter = true;
+ }
+ boolean needTestPathPartDelimiter = false;
+ for (String testPathPart : testPath) {
+ if (needTestPathPartDelimiter) {
+ sb.append(TEST_PATH_PARTS_DELIMITED);
+ } else {
+ needTestPathPartDelimiter = true;
+ }
+ sb.append(testPathPart);
+ }
+ // If it is a test suite
+ if (testPath.length <= 1) {
+ sb.append(ALL_TESTS);
+ }
+ }
+ result = new String[gtestParameters.length + 1];
+ System.arraycopy(gtestParameters, 0, result, 0, gtestParameters.length);
+ result[gtestParameters.length] = sb.toString();
+ }
+ return result;
+ }
+
+ /**
+ * Construct the error message from prefix and detailed description.
+ *
+ * @param prefix prefix
+ * @param description detailed description
+ * @return the full message
+ */
+ private String getErrorText(String prefix, String description) {
+ return MessageFormat.format(GoogleTestsRunnerMessages.GoogleTestsRunner_error_format, prefix, description);
+ }
+
+ @Override
+ public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException {
+
+ try {
+ OutputHandler ouputHandler = new OutputHandler(modelUpdater);
+ ouputHandler.run(inputStream);
+ } catch (IOException e) {
+ throw new TestingException(getErrorText(GoogleTestsRunnerMessages.GoogleTestsRunner_io_error_prefix, e.getLocalizedMessage()));
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java
new file mode 100644
index 0000000..3a58563
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.gtest/src/org/eclipse/cdt/testsrunner/internal/gtest/OutputHandler.java
@@ -0,0 +1,645 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.gtest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.xml.sax.SAXException;
+
+
+/**
+ * <p>
+ * Parses the output of Google Testing Framework and notifies the Tests Runner
+ * Core about how the testing process is going.
+ * </p>
+ * <p>
+ * Unfortunately, gtest does not provide a realtime XML output (yes, it has XML
+ * output, but it is generated after testing process is done), so we have to
+ * parse its output that is less reliable.
+ * </p>
+ * <p>
+ * The parsing is done with a simple FSM (Final State Machine). There is an
+ * internal state that changes when input tokens (gtest output lines) come.
+ * There is a transitions table that is used to determine what is the next state
+ * depending on the current one and the input token. The state may define
+ * onEnter and onExit actions to do the useful job.
+ * </p>
+ */
+public class OutputHandler {
+
+ /**
+ * Base class for the FSM internal state.
+ */
+ class State {
+
+ /** Stores the regular expression by which the state should be entered. */
+ private Pattern enterPattern;
+
+ /** The regular expression matcher. */
+ private Matcher matcher;
+
+ /** Groups count in a regular expression. */
+ private int groupCount;
+
+ /**
+ * The constructor.
+ *
+ * @param enterRegex the regular expression by which the state should be
+ * entered
+ */
+ State(String enterRegex) {
+ this(enterRegex, -1);
+ }
+
+ /**
+ * The constructor.
+ *
+ * @param enterRegex the regular expression by which the state should be
+ * entered
+ * @param groupCount groups count in a regular expression. It is used
+ * just to make debug easier and the parser more reliable.
+ */
+ State(String enterRegex, int groupCount) {
+ enterPattern = Pattern.compile(enterRegex);
+ this.groupCount = groupCount;
+ }
+
+ /**
+ * Checks whether the specified string matches the enter pattern
+ * (regular expression). If it is so the state should be entered.
+ *
+ * @param line input line (token)
+ * @return true if matches and false otherwise
+ * @throws TestingException if groups count does not match the defined
+ * in constructor number.
+ */
+ public boolean match(String line) throws TestingException {
+ matcher = enterPattern.matcher(line);
+ boolean groupsCountOk = groupCount == -1 || matcher.groupCount() == groupCount;
+ if (!groupsCountOk) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_groups_count,
+ enterPattern.pattern(), matcher.groupCount(), groupCount
+ )
+ );
+ }
+ boolean matches = matcher.matches();
+ if (!matches || !groupsCountOk) {
+ // Do not keep the reference - it will be unnecessary anyway
+ matcher = null;
+ }
+ return matches;
+ }
+
+ /**
+ * Returns the matched group value by index.
+ *
+ * @param groupNumber group index
+ * @return group value
+ */
+ protected String group(int groupNumber) {
+ return matcher.group(groupNumber);
+ }
+
+ /**
+ * Action that triggers on state enter.
+ *
+ * @param previousState previous state
+ * @throws TestingException if testing error is detected
+ */
+ public void onEnter(State previousState) throws TestingException {}
+
+ /**
+ * Action that triggers on state exit.
+ *
+ * @param previousState next state
+ * @throws TestingException if testing error is detected
+ */
+ public void onExit(State nextState) {}
+
+ /**
+ * Common routine that constructs full test suite name by name and type
+ * parameter.
+ *
+ * @param name test suite name
+ * @param typeParameter type parameter
+ * @return full test suite name
+ */
+ protected String getTestSuiteName(String name, String typeParameter) {
+ return (typeParameter != null) ? MessageFormat.format("{0}({1})", name, typeParameter.trim()) : name; //$NON-NLS-1$
+ }
+ }
+
+
+ /**
+ * The state is activated when a new test suite is started.
+ */
+ class TestSuiteStart extends State {
+
+ /** Stores the matched type parameter. */
+ private String typeParameter;
+
+ TestSuiteStart(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Stores type parameter and notify Tests Runner Core about test suite
+ * start.
+ */
+ @Override
+ public void onEnter(State previousState) {
+ typeParameter = group(3);
+ modelUpdater.enterTestSuite(getTestSuiteName(group(1), typeParameter));
+ }
+
+ /**
+ * Provides access to the matched type parameter.
+ *
+ * @return type parameter value
+ */
+ public String getTypeParameter() {
+ return typeParameter;
+ }
+ }
+
+
+ /**
+ * The state is activated when a new test case is started.
+ */
+ class TestCaseStart extends State {
+
+ TestCaseStart(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Extract current test case and test suite names and notify Tests
+ * Runner Core about test case start.
+ *
+ * @throws TestingException if extracted test suite name does not match
+ * last entered test suite name.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String testCaseName = group(2);
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter());
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name,
+ testCaseName, currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ modelUpdater.enterTestCase(testCaseName);
+ }
+ }
+
+
+ /**
+ * The state is activated when an error message's location is started.
+ */
+ class ErrorMessageLocation extends State {
+
+ /** Stores the message location file name. */
+ private String messageFileName;
+
+ /** Stores the message location line number. */
+ private int messageLineNumber;
+
+ /** Stores the first part of the message. */
+ private String messagePart;
+
+ ErrorMessageLocation(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Extract the data for the message location (file name, line number).
+ * The data may be provided in a common style ("/path/file:line" with
+ * the message text starting on the next line) or Visual Studio style
+ * ("/path/file(line):" with the message text continuing on the same
+ * line). It is also possible not to specify line number at all
+ * ("/path/file:").
+ *
+ * @throws TestingException if location format cannot be recognized.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String fileNameIfLinePresent = group(2);
+ String fileNameIfLineAbsent = group(6);
+ String lineNumberCommon = group(4);
+ String lineNumberVS = group(5);
+ if (fileNameIfLinePresent != null) {
+ if (lineNumberCommon != null) {
+ messageFileName = fileNameIfLinePresent;
+ messageLineNumber = Integer.parseInt(lineNumberCommon.trim());
+ } else if (lineNumberVS != null) {
+ messageFileName = fileNameIfLinePresent;
+ messageLineNumber = Integer.parseInt(lineNumberVS.trim());
+ } else {
+ if (!modelUpdater.currentTestSuite().getName().equals(group(1))) {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format);
+ }
+ }
+ } else if (fileNameIfLineAbsent != null) {
+ if (lineNumberCommon == null && lineNumberVS == null) {
+ messageFileName = fileNameIfLineAbsent;
+ messageLineNumber = DEFAULT_LOCATION_LINE;
+ } else {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unknown_location_format);
+ }
+ }
+ // Check special case when file is not known - reset location
+ if (messageFileName.equals("unknown file")) { //$NON-NLS-1$
+ messageFileName = DEFAULT_LOCATION_FILE;
+ }
+ // NOTE: For Visual Studio style there is also first part of the message at this line
+ messagePart = group(8);
+ }
+
+ /**
+ * Provides access to the message location file name.
+ *
+ * @return file name
+ */
+ public String getMessageFileName() {
+ return messageFileName;
+ }
+
+ /**
+ * Provides access to the message location line number.
+ *
+ * @return line number
+ */
+ public int getMessageLineNumber() {
+ return messageLineNumber;
+ }
+
+ /**
+ * Provides access to the first part of the message.
+ *
+ * @return message part
+ */
+ public String getMessagePart() {
+ return messagePart;
+ }
+ }
+
+
+ /**
+ * The state is activated when an error message text is started or continued.
+ */
+ class ErrorMessage extends State {
+
+ /** Stores the error message text that was already read. */
+ private StringBuilder messagePart = new StringBuilder();
+
+ ErrorMessage(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Collects the error message parts into internal buffer. If the
+ * previous state is not the same (it should be
+ * stateErrorMessageLocation) - get the message part from it.
+ */
+ @Override
+ public void onEnter(State previousState) {
+ boolean needEndOfLine = (this == previousState);
+ if (this != previousState) {
+ String firstMessagePart = stateErrorMessageLocation.getMessagePart();
+ if (firstMessagePart != null) {
+ messagePart.append(firstMessagePart);
+ needEndOfLine = true;
+ }
+ }
+ if (needEndOfLine) {
+ messagePart.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ }
+ messagePart.append(group(1));
+ }
+
+ /**
+ * Notifies the Tests Runner Core about new test message.
+ */
+ @Override
+ public void onExit(State nextState) {
+ if (this != nextState) {
+ modelUpdater.addTestMessage(
+ stateErrorMessageLocation.getMessageFileName(),
+ stateErrorMessageLocation.getMessageLineNumber(),
+ ITestMessage.Level.Error,
+ messagePart.toString()
+ );
+ messagePart.setLength(0);
+ }
+ }
+ }
+
+
+ /**
+ * The state is activated when a test trace is started or continued.
+ */
+ class TestTrace extends ErrorMessageLocation {
+
+ TestTrace(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Notifies the Tests Runner Core about new test message with test trace
+ * info.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ super.onEnter(previousState);
+ modelUpdater.addTestMessage(
+ getMessageFileName(),
+ getMessageLineNumber(),
+ ITestMessage.Level.Info,
+ getMessagePart()
+ );
+ }
+ }
+
+
+ /**
+ * The state is activated when a test case is finished.
+ */
+ class TestCaseEnd extends State {
+
+ TestCaseEnd(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Sets the test case execution time, status and notify Tests Runner
+ * Core about test case end.
+ *
+ * @throws TestingException if current test suite or case name does not
+ * match last entered test suite or case name or if test status is not
+ * known.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String explicitTypeParameter = group(5);
+ String typeParameter = explicitTypeParameter != null ? explicitTypeParameter : stateTestSuiteStart.getTypeParameter();
+ String currTestSuiteName = getTestSuiteName(group(2), typeParameter);
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_wrong_suite_name,
+ group(2), currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ String lastTestCaseName = modelUpdater.currentTestCase().getName();
+ if (!lastTestCaseName.equals(group(3))) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_unexpected_case_end,
+ group(3), lastTestCaseName
+ )
+ );
+ }
+ String testStatusStr = group(1);
+ ITestItem.Status testStatus = ITestItem.Status.Skipped;
+ if (testStatusStr.equals(testStatusOk)) {
+ testStatus = ITestItem.Status.Passed;
+ } else if (testStatusStr.equals(testStatusFailed)) {
+ testStatus = ITestItem.Status.Failed;
+ } else {
+ generateInternalError(MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_unknown_test_status, testStatusStr));
+ }
+ String getParamValue = group(7);
+ if (getParamValue != null) {
+ modelUpdater.addTestMessage(
+ DEFAULT_LOCATION_FILE,
+ DEFAULT_LOCATION_LINE,
+ ITestMessage.Level.Info,
+ MessageFormat.format(GoogleTestsRunnerMessages.OutputHandler_getparam_message, getParamValue)
+ );
+
+ }
+ modelUpdater.setTestingTime(Integer.parseInt(group(8)));
+ modelUpdater.setTestStatus(testStatus);
+ modelUpdater.exitTestCase();
+ }
+ }
+
+
+ /**
+ * The state is activated when a test suite is finished.
+ */
+ class TestSuiteEnd extends State {
+
+ TestSuiteEnd(String enterRegex, int groupCount) {
+ super(enterRegex, groupCount);
+ }
+
+ /**
+ * Notify Tests Runner Core about test suite end.
+ *
+ * @throws TestingException if current test suite name does not match
+ * last entered test suite name.
+ */
+ @Override
+ public void onEnter(State previousState) throws TestingException {
+ String lastTestSuiteName = modelUpdater.currentTestSuite().getName();
+ String currTestSuiteName = getTestSuiteName(group(1), stateTestSuiteStart.getTypeParameter());
+ if (!lastTestSuiteName.equals(currTestSuiteName)) {
+ generateInternalError(
+ MessageFormat.format(
+ GoogleTestsRunnerMessages.OutputHandler_unexpected_suite_end,
+ currTestSuiteName, lastTestSuiteName
+ )
+ );
+ }
+ modelUpdater.exitTestSuite();
+ }
+ }
+
+
+ /** The default file name for test message location. */
+ private static final String DEFAULT_LOCATION_FILE = null;
+
+ /** The default line number for test message location. */
+ private static final int DEFAULT_LOCATION_LINE = 1;
+
+ // Common regular expression parts
+ static private String regexTestSuiteName = "([^,]+)"; //$NON-NLS-1$
+ static private String regexParameterInstantiation = "(\\s*,\\s+where\\s+TypeParam\\s*=([^,(]+))?"; //$NON-NLS-1$
+ static private String regexTestName = regexTestSuiteName+"\\.([^,]+)"; //$NON-NLS-1$
+ static private String regexTestCount = "\\d+\\s+tests?"; //$NON-NLS-1$
+ static private String regexTestTime = "(\\d+)\\s+ms"; //$NON-NLS-1$
+ /* Matches location in the following formats:
+ * - /file:line:
+ * - /file(line):
+ * - /file: (with no line number specified)
+ * Groups:
+ * 1 - all except ":"
+ * 2 - file name (if line present) *
+ * 3 - line number with delimiters
+ * 4 - line number (common style) *
+ * 5 - line number (Visual Studio style) *
+ * 6 - file name (if no line number specified) *
+ * Using:
+ * - group 2 with 4 or 5 (if line number was specified)
+ * - group 6 (if filename only was specified)
+ */
+ static private String regexLocation = "((.*)(:(\\d+)|\\((\\d+)\\))|(.*[^):])):"; //$NON-NLS-1$
+
+ // Test statuses representation
+ static private String testStatusOk = "OK"; //$NON-NLS-1$
+ static private String testStatusFailed = "FAILED"; //$NON-NLS-1$
+
+
+ // All available states in FSM
+ private State stateInitial = new State(""); //$NON-NLS-1$
+ private State stateInitialized = new State(".*Global test environment set-up.*"); //$NON-NLS-1$
+ private TestSuiteStart stateTestSuiteStart = new TestSuiteStart("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+regexParameterInstantiation, 3); //$NON-NLS-1$ //$NON-NLS-2$
+ private State stateTestCaseStart = new TestCaseStart("\\[\\s*RUN\\s*\\]\\s+"+regexTestName, 2); //$NON-NLS-1$
+ private ErrorMessageLocation stateErrorMessageLocation = new ErrorMessageLocation(regexLocation+"\\s+(Failure|error: (.*))", 8); //$NON-NLS-1$
+ private State stateErrorMessage = new ErrorMessage("(.*)", 1); //$NON-NLS-1$
+ private State stateTestTraceStart = new State(".*Google Test trace.*"); //$NON-NLS-1$
+ // NOTE: Use 8 groups instead of 7 cause we need to be consistent with ErrorMessageLocation (as we subclass it)
+ private State stateTestTrace = new TestTrace(regexLocation+"\\s+((.*))", 8); //$NON-NLS-1$
+ private State stateTestCaseEnd = new TestCaseEnd("\\[\\s*("+testStatusOk+"|"+testStatusFailed+")\\s*\\]\\s+"+regexTestName+regexParameterInstantiation+"(\\s*,\\s+where\\s+GetParam\\s*\\(\\s*\\)\\s*=\\s*(.+))?\\s+\\("+regexTestTime+"\\)", 8); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ private State stateTestSuiteEnd = new TestSuiteEnd("\\[-*\\]\\s+"+regexTestCount+"\\s+from\\s+"+regexTestSuiteName+"\\s+\\("+regexTestTime+"\\s+total\\)", 2); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ private State stateFinal = new State(".*Global test environment tear-down.*"); //$NON-NLS-1$
+ // NOTE: This state is a special workaround for empty test modules (they haven't got global test environment set-up/tear-down). They should be always passed.
+ private State stateEmptyTestModuleFinal = new State(".*\\[\\s*PASSED\\s*\\]\\s+0\\s+tests.*"); //$NON-NLS-1$
+
+ // Transitions table
+ private Map<State, State[] > transitions = new HashMap<State, State[]>();
+ {
+ // NOTE: Next states order is important!
+ transitions.put( from(stateInitial), to(stateInitialized, stateEmptyTestModuleFinal) );
+ transitions.put( from(stateInitialized), to(stateTestSuiteStart) );
+ transitions.put( from(stateTestSuiteStart), to(stateTestCaseStart) );
+ transitions.put( from(stateTestCaseStart), to(stateTestCaseEnd, stateErrorMessageLocation) );
+ transitions.put( from(stateErrorMessageLocation), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) );
+ transitions.put( from(stateErrorMessage), to(stateTestTraceStart, stateTestCaseEnd, stateErrorMessageLocation, stateErrorMessage) );
+ transitions.put( from(stateTestTraceStart), to(stateTestTrace) );
+ transitions.put( from(stateTestTrace), to(stateTestCaseEnd, stateErrorMessageLocation, stateTestTrace) );
+ transitions.put( from(stateTestCaseEnd), to(stateTestCaseStart, stateTestSuiteEnd) );
+ transitions.put( from(stateTestSuiteEnd), to(stateTestSuiteStart, stateFinal) );
+ }
+
+ /** Current FSM state. */
+ private State currentState;
+
+ /** The interface to notify the Tests Runner Core */
+ private ITestModelUpdater modelUpdater;
+
+
+ OutputHandler(ITestModelUpdater modelUpdater) {
+ this.modelUpdater = modelUpdater;
+ }
+
+ /**
+ * Runs the parsing process. Initializes the FSM, selects new states with
+ * transitions table and checks whether the parsing completes successfully.
+ *
+ * @param inputStream gtest test module output stream
+ * @throws IOException if stream reading error happens
+ * @throws TestingException if testing error happens
+ */
+ public void run(InputStream inputStream) throws IOException, TestingException {
+ // Initialize input stream reader
+ InputStreamReader streamReader = new InputStreamReader(inputStream);
+ BufferedReader reader = new BufferedReader(streamReader);
+ String line;
+ boolean finalizedProperly = false;
+
+ // Initialize internal state
+ currentState = stateInitial;
+ while ( ( line = reader.readLine() ) != null ) {
+ // Search for the next possible state
+ State[] possibleNextStates = transitions.get(currentState);
+ if (possibleNextStates == null) {
+ // Final state, stop running
+ finalizedProperly = true;
+ break;
+ }
+ for (State nextState : possibleNextStates) {
+ if (nextState.match(line)) {
+ // Next state found - send notifications to the states
+ currentState.onExit(nextState);
+ State previousState = currentState;
+ currentState = nextState;
+ nextState.onEnter(previousState);
+ break;
+ }
+ }
+ // NOTE: We cannot be sure that we cover all the output of gtest with our regular expressions
+ // (e.g. some framework notes or warnings may be uncovered etc.), so we just skip unmatched
+ // lines without an error
+ }
+ // Check whether the last line leads to the final state
+ if (transitions.get(currentState) == null) {
+ finalizedProperly = true;
+ }
+ if (!finalizedProperly) {
+ generateInternalError(GoogleTestsRunnerMessages.OutputHandler_unexpected_output);
+ }
+ }
+
+ /**
+ * Throws the testing exception with unknown internal error prefix and the specified description.
+ *
+ * @param additionalInfo additional description of what happens
+ * @throws SAXException the exception that will be thrown
+ */
+ private void generateInternalError(String additionalInfo) throws TestingException {
+ TestingException e = new TestingException(GoogleTestsRunnerMessages.OutputHandler_unknown_error_prefix+additionalInfo);
+ GoogleTestsRunnerPlugin.log(e);
+ throw e;
+ }
+
+ /**
+ * Helper functions to make code more readable.
+ *
+ * @param fromState state to return
+ * @return passed state
+ */
+ private State from(State fromState) {
+ return fromState;
+ }
+
+ /**
+ * Helper functions to make code more readable.
+ *
+ * @param toStates states array to return
+ * @return passed states array
+ */
+ private State[] to(State... toStates) {
+ return toStates;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath
new file mode 100644
index 0000000..deb6736
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project
new file mode 100644
index 0000000..0a08b2e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.qttest</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0e860bf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,82 @@
+#Mon Apr 16 13:01:24 EEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c78021d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner.qttest;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.core.runtime;bundle-version="3.5.0",
+ org.eclipse.cdt.testsrunner;bundle-version="3.5.0"
+Export-Package: org.eclipse.cdt.testsrunner.internal.qttest;x-friends:="org.eclipse.cdt.testsrunner.test"
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html b/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html
new file mode 100644
index 0000000..d7c5118
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties
new file mode 100644
index 0000000..55d9be8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/build.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+
+bin.includes = plugin.xml,\
+ plugin.properties,\
+ about.html,\
+ .,\
+ META-INF/
+javadoc.packages = org.eclipse.cdt.launch.ui.*,\
+ org.eclipse.cdt.launch.sourcelookup*,\
+ org.eclipse.cdt.launch.*
+source.. = src/
+src.includes = about.html
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties
new file mode 100644
index 0000000..1b0e34c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+pluginName=C/C++ Development Tools Qt Tests Runner Support
+providerName=Eclipse CDT
+
+QtTestsRunner.name=Qt Tests Runner
+QtTestsRunner.description=Tests runner for a test module based on Qt4 Testing framework
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml
new file mode 100644
index 0000000..54ac1fe
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/plugin.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.cdt.testsrunner.TestsRunner">
+ <runner
+ class="org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerProvider"
+ description="%QtTestsRunner.description"
+ id="org.eclipse.cdt.testsrunner.qttest"
+ name="%QtTestsRunner.name">
+ <features
+ multipleTestFilter="true"
+ testingTimeMeasurement="true">
+ </features>
+ </runner>
+ </extension>
+</plugin>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml
new file mode 100644
index 0000000..440914f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.qttest</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java
new file mode 100644
index 0000000..6357687
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.qttest;
+
+import org.eclipse.osgi.util.NLS;
+
+public class QtTestsRunnerMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerMessages"; //$NON-NLS-1$
+ public static String QtTestsRunner_error_format;
+ public static String QtTestsRunner_io_error_prefix;
+ public static String QtTestsRunner_no_test_cases_to_rerun;
+ public static String QtTestsRunner_xml_error_prefix;
+ public static String QtXmlLogHandler_benchmark_result_message;
+ public static String QtXmlLogHandler_datatag_format;
+ public static String QtXmlLogHandler_metrics_unit_events;
+ public static String QtXmlLogHandler_metrics_unit_instructions;
+ public static String QtXmlLogHandler_metrics_unit_msec;
+ public static String QtXmlLogHandler_metrics_unit_ticks;
+ public static String QtXmlLogHandler_unknown_benchmarck_metric;
+ public static String QtXmlLogHandler_unknown_message_level;
+ public static String QtXmlLogHandler_wrong_tag_name;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, QtTestsRunnerMessages.class);
+ }
+
+ private QtTestsRunnerMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties
new file mode 100644
index 0000000..6a5196e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerMessages.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+QtTestsRunner_error_format={0}: {1}
+QtTestsRunner_io_error_prefix=I/O Error:
+QtTestsRunner_no_test_cases_to_rerun=There is no test cases to rerun (initialization and finalization test cases are not taken into account)
+QtTestsRunner_xml_error_prefix=XML parse error:
+QtXmlLogHandler_benchmark_result_message={0,number,\#.\#\#\#\#} {1} per iteration (total: {2}, iterations: {3})
+QtXmlLogHandler_datatag_format=({0})
+QtXmlLogHandler_metrics_unit_events=events
+QtXmlLogHandler_metrics_unit_instructions=instr.
+QtXmlLogHandler_metrics_unit_msec=msec
+QtXmlLogHandler_metrics_unit_ticks=ticks
+QtXmlLogHandler_unknown_benchmarck_metric=Benchmarck metric value "{0}" is not supported\!
+QtXmlLogHandler_unknown_message_level=String "{0}" cannot be converted to a message level\!
+QtXmlLogHandler_wrong_tag_name=Invalid XML format: Element "{0}" is not accepted\!
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java
new file mode 100644
index 0000000..705b631
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerPlugin.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.qttest;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class QtTestsRunnerPlugin extends Plugin {
+
+ /** The plug-in ID .*/
+ public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.qttest"; //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static QtTestsRunnerPlugin plugin;
+
+ public QtTestsRunnerPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * Returns the Qt Tests Runner provider plug-in instance.
+ *
+ * @return the plug-in instance
+ */
+ public static QtTestsRunnerPlugin getDefault() {
+ return plugin;
+ }
+
+ /** Convenience method which returns the unique identifier of this plugin. */
+ public static String getUniqueIdentifier() {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ /**
+ * Logs an internal error with the specified throwable
+ *
+ * @param e the exception to be logged
+ */
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java
new file mode 100644
index 0000000..7fb9fa8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtTestsRunnerProvider.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.qttest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.xml.sax.SAXException;
+
+/**
+ * The Tests Runner provider plug-in to run tests with Qt Test library.
+ *
+ * Configures the test module to output in XML format, parses the output and
+ * provides the data for the Tests Runner Plug-in.
+ */
+public class QtTestsRunnerProvider implements ITestsRunnerProvider {
+
+ /**
+ * Checks whether the specified path is "special" one ("initTestCase" or
+ * "cleanupTestCase").
+ *
+ * @param testPath test path to check
+ * @return true if the path is special and false otherwise
+ */
+ private boolean isSpecialTestPath(String[] testPath) {
+ // Root test suite should not be explicitly specified for rerun
+ if (testPath.length <= 1) {
+ return true;
+ }
+ // "initTestCase" & "cleanupTestCase" are special test case names and they should be skipped too
+ String testName = testPath[testPath.length-1];
+ return testName.equals("initTestCase") || testName.equals("cleanupTestCase"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Returns the count of not "special" test paths.
+ *
+ * @param testPaths test paths array
+ * @return the count
+ * @see isSpecialTestPath()
+ */
+ private int getNonSpecialTestsCount(String[][] testPaths) {
+ int result = 0;
+ for (int i = 0; i < testPaths.length; i++) {
+ String[] testPath = testPaths[i];
+ result += isSpecialTestPath(testPath) ? 0 : 1;
+ }
+ return result;
+ }
+
+ @Override
+ public String[] getAdditionalLaunchParameters(String[][] testPaths) throws TestingException {
+ final String[] qtParameters = {
+ "-xml", //$NON-NLS-1$
+ "-flush", //$NON-NLS-1$
+ };
+ String[] result = qtParameters;
+
+ if (testPaths != null) {
+ int testPathsLength = getNonSpecialTestsCount(testPaths);
+ // If there are only special test cases specified
+ if ((testPathsLength == 0) != (testPaths.length == 0)) {
+ throw new TestingException(QtTestsRunnerMessages.QtTestsRunner_no_test_cases_to_rerun);
+ }
+
+ // Build tests filter
+ if (testPathsLength >= 1) {
+ result = new String[qtParameters.length + testPathsLength];
+ System.arraycopy(qtParameters, 0, result, 0, qtParameters.length);
+ int resultIdx = qtParameters.length;
+ for (int i = 0; i < testPaths.length; i++) {
+ String[] testPath = testPaths[i];
+ if (!isSpecialTestPath(testPath)) {
+ result[resultIdx] = testPath[testPath.length-1];
+ resultIdx++;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Construct the error message from prefix and detailed description.
+ *
+ * @param prefix prefix
+ * @param description detailed description
+ * @return the full message
+ */
+ private String getErrorText(String prefix, String description) {
+ return MessageFormat.format(QtTestsRunnerMessages.QtTestsRunner_error_format, prefix, description);
+ }
+
+ @Override
+ public void run(ITestModelUpdater modelUpdater, InputStream inputStream) throws TestingException {
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser sp = spf.newSAXParser();
+ sp.parse(inputStream, new QtXmlLogHandler(modelUpdater));
+
+ } catch (IOException e) {
+ throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_io_error_prefix, e.getLocalizedMessage()));
+
+ } catch (ParserConfigurationException e) {
+ throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_xml_error_prefix, e.getLocalizedMessage()));
+
+ } catch (SAXException e) {
+ throw new TestingException(getErrorText(QtTestsRunnerMessages.QtTestsRunner_xml_error_prefix, e.getLocalizedMessage()));
+ }
+
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java
new file mode 100644
index 0000000..d1d17b7
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.qttest/src/org/eclipse/cdt/testsrunner/internal/qttest/QtXmlLogHandler.java
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.qttest;
+
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage.Level;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * Parses the Qt Test XML log and notifies the Tests Runner Core about how the
+ * testing process is going.
+ *
+ * @note There is a terminology conflict between Qt Test library and Test
+ * Runner. Qt Test's "test case" is a "test suite" in Test Runner's terminology,
+ * Qt's "test function" is a "test case", the "incident" and "message" are
+ * "test messages". Be careful with it!
+ */
+public class QtXmlLogHandler extends DefaultHandler {
+
+ // Qt Test XML log tags
+ private static final String XML_NODE_TEST_CASE = "TestCase"; //$NON-NLS-1$
+ private static final String XML_NODE_TEST_FUNCTION = "TestFunction"; //$NON-NLS-1$
+ private static final String XML_NODE_INCIDENT = "Incident"; //$NON-NLS-1$
+ private static final String XML_NODE_MESSAGE = "Message"; //$NON-NLS-1$
+ private static final String XML_NODE_DESCRIPTION = "Description"; //$NON-NLS-1$
+ private static final String XML_NODE_ENVIRONMENT = "Environment"; //$NON-NLS-1$
+ private static final String XML_NODE_QTVERSION = "QtVersion"; //$NON-NLS-1$
+ private static final String XML_NODE_QTESTVERSION = "QTestVersion"; //$NON-NLS-1$
+ private static final String XML_NODE_BENCHMARK = "BenchmarkResult"; //$NON-NLS-1$
+ private static final String XML_NODE_DATATAG = "DataTag"; //$NON-NLS-1$
+
+ // Qt Test XML case statuses representation
+ private static final String XML_VALUE_INCIDENT_PASS = "pass"; //$NON-NLS-1$
+ private static final String XML_VALUE_INCIDENT_XFAIL = "xfail"; //$NON-NLS-1$
+ private static final String XML_VALUE_INCIDENT_FAIL = "fail"; //$NON-NLS-1$
+ private static final String XML_VALUE_INCIDENT_XPASS = "xpass"; //$NON-NLS-1$
+ private static final String XML_VALUE_INCIDENT_UNKNOWN = "??????"; //$NON-NLS-1$
+
+ // Qt Test XML log message levels representation
+ private static final String XML_VALUE_MESSAGE_WARN = "warn"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_SYSTEM = "system"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_QDEBUG = "qdebug"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_QWARN = "qwarn"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_QFATAL = "qfatal"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_SKIP = "skip"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_INFO = "info"; //$NON-NLS-1$
+ private static final String XML_VALUE_MESSAGE_UNKNOWN = "??????"; //$NON-NLS-1$
+
+ // Qt Test XML log attributes
+ private static final String XML_ATTR_TEST_CASE_NAME = "name"; //$NON-NLS-1$
+ private static final String XML_ATTR_TEST_FUNCTION_NAME = "name"; //$NON-NLS-1$
+ private static final String XML_ATTR_TYPE = "type"; //$NON-NLS-1$
+ private static final String XML_ATTR_FILE = "file"; //$NON-NLS-1$
+ private static final String XML_ATTR_LINE = "line"; //$NON-NLS-1$
+ private static final String XML_ATTR_BENCHMARK_METRIC = "metric"; //$NON-NLS-1$
+ private static final String XML_ATTR_BENCHMARK_VALUE = "value"; //$NON-NLS-1$
+ private static final String XML_ATTR_BENCHMARK_ITERATIONS = "iterations"; //$NON-NLS-1$
+ private static final String XML_ATTR_DATA_TAG = "tag"; //$NON-NLS-1$
+
+ /** Maps the string message level representation to the Tests Runner internal enum code. */
+ private static final Map<String, ITestMessage.Level> STRING_TO_MESSAGE_LEVEL;
+ static {
+ Map<String, ITestMessage.Level> aMap = new HashMap<String, ITestMessage.Level>();
+ aMap.put(XML_VALUE_MESSAGE_WARN, ITestMessage.Level.Warning);
+ aMap.put(XML_VALUE_MESSAGE_SYSTEM, ITestMessage.Level.Message);
+ aMap.put(XML_VALUE_MESSAGE_QDEBUG, ITestMessage.Level.Message);
+ aMap.put(XML_VALUE_MESSAGE_QWARN, ITestMessage.Level.Warning);
+ aMap.put(XML_VALUE_MESSAGE_QFATAL, ITestMessage.Level.FatalError);
+ aMap.put(XML_VALUE_MESSAGE_SKIP, ITestMessage.Level.Info);
+ aMap.put(XML_VALUE_MESSAGE_INFO, ITestMessage.Level.Info);
+ aMap.put(XML_VALUE_MESSAGE_UNKNOWN, ITestMessage.Level.FatalError);
+ // NOTE: Exception node is processed separately
+ STRING_TO_MESSAGE_LEVEL = Collections.unmodifiableMap(aMap);
+ }
+
+ /** Maps the string incident status representation to the test case status. */
+ private static final Map<String, ITestCase.Status> STRING_TO_TEST_STATUS;
+ static {
+ Map<String, ITestCase.Status> aMap = new HashMap<String, ITestCase.Status>();
+ aMap.put(XML_VALUE_INCIDENT_PASS, ITestCase.Status.Passed);
+ aMap.put(XML_VALUE_INCIDENT_XFAIL, ITestCase.Status.Failed);
+ aMap.put(XML_VALUE_INCIDENT_FAIL, ITestCase.Status.Failed);
+ aMap.put(XML_VALUE_INCIDENT_XPASS, ITestCase.Status.Failed);
+ aMap.put(XML_VALUE_INCIDENT_UNKNOWN, ITestCase.Status.Aborted);
+ // NOTE: Exception node is processed separately
+ STRING_TO_TEST_STATUS = Collections.unmodifiableMap(aMap);
+ }
+
+ /** Maps the string incident status representation to the test message level to log about it. */
+ private static final Map<String, ITestMessage.Level> STRING_INCIDENT_TO_MESSAGE_LEVEL;
+ static {
+ Map<String, ITestMessage.Level> aMap = new HashMap<String, ITestMessage.Level>();
+ aMap.put(XML_VALUE_INCIDENT_PASS, ITestMessage.Level.Info);
+ aMap.put(XML_VALUE_INCIDENT_XFAIL, ITestMessage.Level.Error);
+ aMap.put(XML_VALUE_INCIDENT_FAIL, ITestMessage.Level.FatalError);
+ aMap.put(XML_VALUE_INCIDENT_XPASS, ITestMessage.Level.Error);
+ aMap.put(XML_VALUE_INCIDENT_UNKNOWN, ITestMessage.Level.FatalError);
+ // NOTE: Exception node is processed separately
+ STRING_INCIDENT_TO_MESSAGE_LEVEL = Collections.unmodifiableMap(aMap);
+ }
+
+ /** Maps the metrics unit ids to the user readable names. */
+ private static final Map<String, String> XML_METRICS_TO_UNIT_NAME;
+ static {
+ Map<String,String> aMap = new HashMap<String, String>();
+ aMap.put("events", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_events); //$NON-NLS-1$
+ aMap.put("callgrind", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_instructions); //$NON-NLS-1$
+ aMap.put("walltime", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_msec); //$NON-NLS-1$
+ aMap.put("cputicks", QtTestsRunnerMessages.QtXmlLogHandler_metrics_unit_ticks); //$NON-NLS-1$
+ // NOTE: Exception node is processed separately
+ XML_METRICS_TO_UNIT_NAME = Collections.unmodifiableMap(aMap);
+ }
+
+ /** The interface to notify the Tests Runner Core */
+ private ITestModelUpdater modelUpdater;
+
+ /** Stores the text between current XML tag. */
+ private String elementData;
+
+ /** Stores the text for currently parsed test message. */
+ private String messageText;
+
+ /** Stores the file name part of location for currently parsed test message. */
+ private String fileName;
+
+ /** Stores the line number part of location for currently parsed test message. */
+ private int lineNumber;
+
+ /** Stores the message level for currently parsed test message. */
+ private ITestMessage.Level messageLevel;
+
+ /** Stores the status for currently parsed test case. */
+ private ITestItem.Status testCaseStatus;
+
+ /** Stores the name for currently parsed test case. */
+ private String testCaseName;
+
+ /** Stores the currently parsing data tag. */
+ private String currentDataTag;
+
+ /** Stores the last parsed data tag. */
+ private String lastDataTag;
+
+ /** Stores whether the test case was already added (means Tests Runner Core notified). */
+ private boolean testCaseAdded;
+
+
+ QtXmlLogHandler(ITestModelUpdater modelUpdater) {
+ this.modelUpdater = modelUpdater;
+ }
+
+ /**
+ * Notifies about test case exiting (if it was entered).
+ */
+ private void exitTestCaseIfNecessary() {
+ if (testCaseAdded) {
+ modelUpdater.setTestStatus(testCaseStatus);
+ modelUpdater.exitTestCase();
+ testCaseAdded = false;
+ }
+ }
+
+ /**
+ * Creates a new test case if a new data tag is met.
+ */
+ private void createTestCaseIfNecessary() {
+ if (!lastDataTag.equals(currentDataTag)) {
+ exitTestCaseIfNecessary();
+ currentDataTag = lastDataTag;
+ String suffix = !currentDataTag.isEmpty() ? MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_datatag_format, currentDataTag) : ""; //$NON-NLS-1$
+ modelUpdater.enterTestCase(testCaseName+suffix);
+ testCaseAdded = true;
+ }
+ }
+
+ /**
+ * Adds a new test message if there is a text for it.
+ */
+ private void addTestMessageIfNecessary() {
+ if (messageText != null) {
+ modelUpdater.addTestMessage(fileName, lineNumber, messageLevel, messageText);
+ }
+ }
+
+ /**
+ * Sets a new status for the currently parsing test case.
+ *
+ * @param newStatus new test status
+ *
+ * @note Passed status is set by default and should not be set explicitly.
+ * But in case of errors it should not override Failed or Skipped statuses.
+ */
+ private void setCurrentTestCaseStatus(ITestItem.Status newStatus) {
+ // Passed status is set by default and should not be set explicitly.
+ // But in case of errors it should not override Failed or Skipped statuses.
+ if (newStatus != ITestItem.Status.Passed) {
+ testCaseStatus = newStatus;
+ }
+ }
+
+ /**
+ * Converts the metric unit ids to user readable names.
+ *
+ * @param benchmarkMetric metric unit id
+ * @return user readable name
+ * @throws SAXException if metric unit id is not known
+ */
+ private String getUnitsByBenchmarkMetric(String benchmarkMetric) throws SAXException {
+ String units = XML_METRICS_TO_UNIT_NAME.get(benchmarkMetric);
+ if (units == null) {
+ logAndThrowError(MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_unknown_benchmarck_metric, benchmarkMetric));
+ }
+ return units;
+ }
+
+ /**
+ * Converts the message level string to the internal enumeration core.
+ *
+ * @param map map to use
+ * @param incidentTypeStr message level string
+ * @return message level code
+ * @throws SAXException if message level string is not known
+ */
+ private ITestMessage.Level getMessageLevel(Map<String, ITestMessage.Level> map, String incidentTypeStr) throws SAXException {
+ Level result = map.get(incidentTypeStr);
+ if (result == null) {
+ logAndThrowError(MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_unknown_message_level, incidentTypeStr));
+ }
+ return result;
+ }
+
+ @Override
+ public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException {
+
+ elementData = null;
+ if (qName == XML_NODE_TEST_CASE) {
+ // NOTE: Terminology mapping: Qt Test Case is actually a Test Suite
+ String testSuiteName = attrs.getValue(XML_ATTR_TEST_CASE_NAME);
+ modelUpdater.enterTestSuite(testSuiteName);
+
+ } else if (qName == XML_NODE_TEST_FUNCTION) {
+ // NOTE: Terminology mapping: Qt Test Function is actually a Test Case
+ testCaseName = attrs.getValue(XML_ATTR_TEST_FUNCTION_NAME);
+ currentDataTag = null;
+ lastDataTag = ""; //$NON-NLS-1$
+ testCaseAdded = false;
+ testCaseStatus = ITestItem.Status.Passed;
+
+ } else if (qName == XML_NODE_MESSAGE) {
+ String messageLevelStr = attrs.getValue(XML_ATTR_TYPE);
+ fileName = attrs.getValue(XML_ATTR_FILE);
+ lineNumber = Integer.parseInt(attrs.getValue(XML_ATTR_LINE).trim());
+ messageLevel = getMessageLevel(STRING_TO_MESSAGE_LEVEL, messageLevelStr);
+ messageText = null;
+ if (messageLevelStr.equals(XML_VALUE_MESSAGE_SKIP)) {
+ setCurrentTestCaseStatus(ITestCase.Status.Skipped);
+ }
+
+ } else if (qName == XML_NODE_INCIDENT) {
+ String strType = attrs.getValue(XML_ATTR_TYPE);
+ fileName = attrs.getValue(XML_ATTR_FILE);
+ lineNumber = Integer.parseInt(attrs.getValue(XML_ATTR_LINE).trim());
+ messageLevel = getMessageLevel(STRING_INCIDENT_TO_MESSAGE_LEVEL, strType);
+ messageText = null;
+ setCurrentTestCaseStatus(STRING_TO_TEST_STATUS.get(strType));
+
+ } else if (qName == XML_NODE_BENCHMARK) {
+ lastDataTag = attrs.getValue(XML_ATTR_DATA_TAG);
+ createTestCaseIfNecessary();
+ int benchmarkResultIteratations = Integer.parseInt(attrs.getValue(XML_ATTR_BENCHMARK_ITERATIONS).trim());
+ float benchmarkResultValue = Integer.parseInt(attrs.getValue(XML_ATTR_BENCHMARK_VALUE).trim());
+ String units = getUnitsByBenchmarkMetric(attrs.getValue(XML_ATTR_BENCHMARK_METRIC).trim());
+ modelUpdater.addTestMessage("", 0, ITestMessage.Level.Info, //$NON-NLS-1$
+ MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_benchmark_result_message,
+ benchmarkResultValue/benchmarkResultIteratations, units, benchmarkResultValue, benchmarkResultIteratations
+ )
+ );
+
+ } else if (qName == XML_NODE_DATATAG) {
+ lastDataTag = ""; //$NON-NLS-1$
+
+ } else if (qName == XML_NODE_DESCRIPTION
+ || qName == XML_NODE_ENVIRONMENT
+ || qName == XML_NODE_QTVERSION
+ || qName == XML_NODE_QTESTVERSION) {
+ /* just skip, do nothing */
+
+ } else {
+ logAndThrowErrorForElement(qName);
+ }
+ }
+
+ @Override
+ public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+
+ if (qName == XML_NODE_TEST_CASE) {
+ modelUpdater.exitTestSuite();
+
+ } else if (qName == XML_NODE_TEST_FUNCTION) {
+ createTestCaseIfNecessary();
+ exitTestCaseIfNecessary();
+
+ } else if (qName == XML_NODE_DATATAG) {
+ lastDataTag = elementData;
+
+ } else if (qName == XML_NODE_INCIDENT) {
+ createTestCaseIfNecessary();
+ addTestMessageIfNecessary();
+
+ } else if (qName == XML_NODE_MESSAGE) {
+ createTestCaseIfNecessary();
+ addTestMessageIfNecessary();
+
+ } else if (qName == XML_NODE_DESCRIPTION) {
+ messageText = elementData == null || elementData.isEmpty() ? "" : elementData; //$NON-NLS-1$
+
+ } else if (qName == XML_NODE_ENVIRONMENT
+ || qName == XML_NODE_QTVERSION
+ || qName == XML_NODE_QTESTVERSION
+ || qName == XML_NODE_BENCHMARK) {
+ /* just skip, do nothing */
+
+ } else {
+ logAndThrowErrorForElement(qName);
+ }
+ elementData = null;
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = start; i < start + length; i++) {
+ sb.append(ch[i]);
+ }
+ elementData = sb.toString();
+ }
+
+ /**
+ * Throws the testing exception for the specified XML tag.
+ *
+ * @param tagName XML tag name
+ * @throws SAXException the exception that will be thrown
+ */
+ private void logAndThrowErrorForElement(String tagName) throws SAXException {
+ logAndThrowError(
+ MessageFormat.format(QtTestsRunnerMessages.QtXmlLogHandler_wrong_tag_name, tagName)
+ );
+ }
+
+ /**
+ * Throws the testing exception with the specified message.
+ *
+ * @param message the reason
+ * @throws SAXException the exception that will be thrown
+ */
+ private void logAndThrowError(String message) throws SAXException {
+ SAXException e = new SAXException(message);
+ QtTestsRunnerPlugin.log(e);
+ throw e;
+ }
+
+ @Override
+ public void warning(SAXParseException ex) throws SAXException {
+ QtTestsRunnerPlugin.log(ex);
+ }
+
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ QtTestsRunnerPlugin.log(ex);
+ throw ex;
+ }
+
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ QtTestsRunnerPlugin.log(ex);
+ throw ex;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project
new file mode 100644
index 0000000..cc09c44
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.source.feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties
new file mode 100644
index 0000000..c6af93f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/build.properties
@@ -0,0 +1,5 @@
+bin.includes = feature.xml,\
+ eclipse_update_120.jpg,\
+ epl-v10.html,\
+ feature.properties,\
+ license.html
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg
new file mode 100644
index 0000000..bfdf708
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/eclipse_update_120.jpg
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/epl-v10.html b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/epl-v10.html
new file mode 100644
index 0000000..ed4b196
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/epl-v10.html
@@ -0,0 +1,328 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
+<meta name=ProgId content=Word.Document>
+<meta name=Generator content="Microsoft Word 9">
+<meta name=Originator content="Microsoft Word 9">
+<link rel=File-List
+href="./Eclipse%20EPL%202003_11_10%20Final_files/filelist.xml">
+<title>Eclipse Public License - Version 1.0</title>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+ <o:Revision>2</o:Revision>
+ <o:TotalTime>3</o:TotalTime>
+ <o:Created>2004-03-05T23:03:00Z</o:Created>
+ <o:LastSaved>2004-03-05T23:03:00Z</o:LastSaved>
+ <o:Pages>4</o:Pages>
+ <o:Words>1626</o:Words>
+ <o:Characters>9270</o:Characters>
+ <o:Lines>77</o:Lines>
+ <o:Paragraphs>18</o:Paragraphs>
+ <o:CharactersWithSpaces>11384</o:CharactersWithSpaces>
+ <o:Version>9.4402</o:Version>
+ </o:DocumentProperties>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <w:WordDocument>
+ <w:TrackRevisions/>
+ </w:WordDocument>
+</xml><![endif]-->
+<style>
+<!--
+ /* Font Definitions */
+@font-face
+ {font-family:Tahoma;
+ panose-1:2 11 6 4 3 5 4 4 2 4;
+ mso-font-charset:0;
+ mso-generic-font-family:swiss;
+ mso-font-pitch:variable;
+ mso-font-signature:553679495 -2147483648 8 0 66047 0;}
+ /* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+ {mso-style-parent:"";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+p
+ {margin-right:0in;
+ mso-margin-top-alt:auto;
+ mso-margin-bottom-alt:auto;
+ margin-left:0in;
+ mso-pagination:widow-orphan;
+ font-size:12.0pt;
+ font-family:"Times New Roman";
+ mso-fareast-font-family:"Times New Roman";}
+p.BalloonText, li.BalloonText, div.BalloonText
+ {mso-style-name:"Balloon Text";
+ margin:0in;
+ margin-bottom:.0001pt;
+ mso-pagination:widow-orphan;
+ font-size:8.0pt;
+ font-family:Tahoma;
+ mso-fareast-font-family:"Times New Roman";}
+@page Section1
+ {size:8.5in 11.0in;
+ margin:1.0in 1.25in 1.0in 1.25in;
+ mso-header-margin:.5in;
+ mso-footer-margin:.5in;
+ mso-paper-source:0;}
+div.Section1
+ {page:Section1;}
+-->
+</style>
+</head>
+
+<body lang=EN-US style='tab-interval:.5in'>
+
+<div class=Section1>
+
+<p align=center style='text-align:center'><b>Eclipse Public License - v 1.0</b>
+</p>
+
+<p><span style='font-size:10.0pt'>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER
+THE TERMS OF THIS ECLIPSE PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE,
+REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE
+OF THIS AGREEMENT.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>1. DEFINITIONS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Contribution&quot; means:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+in the case of the initial Contributor, the initial code and documentation
+distributed under this Agreement, and<br clear=left>
+b) in the case of each subsequent Contributor:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+changes to the Program, and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+additions to the Program;</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>where
+such changes and/or additions to the Program originate from and are distributed
+by that particular Contributor. A Contribution 'originates' from a Contributor
+if it was added to the Program by such Contributor itself or anyone acting on
+such Contributor's behalf. Contributions do not include additions to the
+Program which: (i) are separate modules of software distributed in conjunction
+with the Program under their own license agreement, and (ii) are not derivative
+works of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Contributor&quot; means any person or
+entity that distributes the Program.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Licensed Patents &quot; mean patent
+claims licensable by a Contributor which are necessarily infringed by the use
+or sale of its Contribution alone or when combined with the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>&quot;Program&quot; means the Contributions
+distributed in accordance with this Agreement.</span> </p>
+
+<p><span style='font-size:10.0pt'>&quot;Recipient&quot; means anyone who
+receives the Program under this Agreement, including all Contributors.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>2. GRANT OF RIGHTS</span></b> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+Subject to the terms of this Agreement, each Contributor hereby grants Recipient
+a non-exclusive, worldwide, royalty-free copyright license to<span
+style='color:red'> </span>reproduce, prepare derivative works of, publicly
+display, publicly perform, distribute and sublicense the Contribution of such
+Contributor, if any, and such derivative works, in source code and object code
+form.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+Subject to the terms of this Agreement, each Contributor hereby grants
+Recipient a non-exclusive, worldwide,<span style='color:green'> </span>royalty-free
+patent license under Licensed Patents to make, use, sell, offer to sell, import
+and otherwise transfer the Contribution of such Contributor, if any, in source
+code and object code form. This patent license shall apply to the combination
+of the Contribution and the Program if, at the time the Contribution is added
+by the Contributor, such addition of the Contribution causes such combination
+to be covered by the Licensed Patents. The patent license shall not apply to
+any other combinations which include the Contribution. No hardware per se is
+licensed hereunder. </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>c)
+Recipient understands that although each Contributor grants the licenses to its
+Contributions set forth herein, no assurances are provided by any Contributor
+that the Program does not infringe the patent or other intellectual property
+rights of any other entity. Each Contributor disclaims any liability to Recipient
+for claims brought by any other entity based on infringement of intellectual
+property rights or otherwise. As a condition to exercising the rights and
+licenses granted hereunder, each Recipient hereby assumes sole responsibility
+to secure any other intellectual property rights needed, if any. For example,
+if a third party patent license is required to allow Recipient to distribute
+the Program, it is Recipient's responsibility to acquire that license before
+distributing the Program.</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>d)
+Each Contributor represents that to its knowledge it has sufficient copyright
+rights in its Contribution, if any, to grant the copyright license set forth in
+this Agreement. </span></p>
+
+<p><b><span style='font-size:10.0pt'>3. REQUIREMENTS</span></b> </p>
+
+<p><span style='font-size:10.0pt'>A Contributor may choose to distribute the
+Program in object code form under its own license agreement, provided that:</span>
+</p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it complies with the terms and conditions of this Agreement; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b)
+its license agreement:</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>i)
+effectively disclaims on behalf of all Contributors all warranties and
+conditions, express and implied, including warranties or conditions of title
+and non-infringement, and implied warranties or conditions of merchantability
+and fitness for a particular purpose; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>ii)
+effectively excludes on behalf of all Contributors all liability for damages,
+including direct, indirect, special, incidental and consequential damages, such
+as lost profits; </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iii)
+states that any provisions which differ from this Agreement are offered by that
+Contributor alone and not by any other party; and</span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>iv)
+states that source code for the Program is available from such Contributor, and
+informs licensees how to obtain it in a reasonable manner on or through a
+medium customarily used for software exchange.<span style='color:blue'> </span></span></p>
+
+<p><span style='font-size:10.0pt'>When the Program is made available in source
+code form:</span> </p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>a)
+it must be made available under this Agreement; and </span></p>
+
+<p class=MsoNormal style='margin-left:.5in'><span style='font-size:10.0pt'>b) a
+copy of this Agreement must be included with each copy of the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Contributors may not remove or alter any
+copyright notices contained within the Program. </span></p>
+
+<p><span style='font-size:10.0pt'>Each Contributor must identify itself as the
+originator of its Contribution, if any, in a manner that reasonably allows
+subsequent Recipients to identify the originator of the Contribution. </span></p>
+
+<p><b><span style='font-size:10.0pt'>4. COMMERCIAL DISTRIBUTION</span></b> </p>
+
+<p><span style='font-size:10.0pt'>Commercial distributors of software may
+accept certain responsibilities with respect to end users, business partners
+and the like. While this license is intended to facilitate the commercial use
+of the Program, the Contributor who includes the Program in a commercial
+product offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes the
+Program in a commercial product offering, such Contributor (&quot;Commercial
+Contributor&quot;) hereby agrees to defend and indemnify every other
+Contributor (&quot;Indemnified Contributor&quot;) against any losses, damages and
+costs (collectively &quot;Losses&quot;) arising from claims, lawsuits and other
+legal actions brought by a third party against the Indemnified Contributor to
+the extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor
+to control, and cooperate with the Commercial Contributor in, the defense and
+any related settlement negotiations. The Indemnified Contributor may participate
+in any such claim at its own expense.</span> </p>
+
+<p><span style='font-size:10.0pt'>For example, a Contributor might include the
+Program in a commercial product offering, Product X. That Contributor is then a
+Commercial Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance claims and
+warranties are such Commercial Contributor's responsibility alone. Under this
+section, the Commercial Contributor would have to defend claims against the
+other Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>5. NO WARRANTY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, THE PROGRAM IS PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
+WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+responsible for determining the appropriateness of using and distributing the
+Program and assumes all risks associated with its exercise of rights under this
+Agreement , including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs or
+equipment, and unavailability or interruption of operations. </span></p>
+
+<p><b><span style='font-size:10.0pt'>6. DISCLAIMER OF LIABILITY</span></b> </p>
+
+<p><span style='font-size:10.0pt'>EXCEPT AS EXPRESSLY SET FORTH IN THIS
+AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF
+THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGES.</span> </p>
+
+<p><b><span style='font-size:10.0pt'>7. GENERAL</span></b> </p>
+
+<p><span style='font-size:10.0pt'>If any provision of this Agreement is invalid
+or unenforceable under applicable law, it shall not affect the validity or
+enforceability of the remainder of the terms of this Agreement, and without
+further action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.</span> </p>
+
+<p><span style='font-size:10.0pt'>If Recipient institutes patent litigation
+against any entity (including a cross-claim or counterclaim in a lawsuit)
+alleging that the Program itself (excluding combinations of the Program with
+other software or hardware) infringes such Recipient's patent(s), then such
+Recipient's rights granted under Section 2(b) shall terminate as of the date
+such litigation is filed. </span></p>
+
+<p><span style='font-size:10.0pt'>All Recipient's rights under this Agreement
+shall terminate if it fails to comply with any of the material terms or
+conditions of this Agreement and does not cure such failure in a reasonable
+period of time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use and
+distribution of the Program as soon as reasonably practicable. However,
+Recipient's obligations under this Agreement and any licenses granted by
+Recipient relating to the Program shall continue and survive. </span></p>
+
+<p><span style='font-size:10.0pt'>Everyone is permitted to copy and distribute
+copies of this Agreement, but in order to avoid inconsistency the Agreement is
+copyrighted and may only be modified in the following manner. The Agreement
+Steward reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement Steward has
+the right to modify this Agreement. The Eclipse Foundation is the initial
+Agreement Steward. The Eclipse Foundation may assign the responsibility to
+serve as the Agreement Steward to a suitable separate entity. Each new version
+of the Agreement will be given a distinguishing version number. The Program
+(including Contributions) may always be distributed subject to the version of
+the Agreement under which it was received. In addition, after a new version of
+the Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly stated
+in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to
+the intellectual property of any Contributor under this Agreement, whether
+expressly, by implication, estoppel or otherwise. All rights in the Program not
+expressly granted under this Agreement are reserved.</span> </p>
+
+<p><span style='font-size:10.0pt'>This Agreement is governed by the laws of the
+State of New York and the intellectual property laws of the United States of
+America. No party to this Agreement will bring a legal action under this
+Agreement more than one year after the cause of action arose. Each party waives
+its rights to a jury trial in any resulting litigation.</span> </p>
+
+<p class=MsoNormal><![if !supportEmptyParas]>&nbsp;<![endif]><o:p></o:p></p>
+
+</div>
+
+</body>
+
+</html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties
new file mode 100644
index 0000000..25ff11f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.properties
@@ -0,0 +1,168 @@
+###############################################################################
+# Copyright (c) 2012 Anton Gorenkov and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - initial API and implementation
+# Marc-Andre Laperle
+###############################################################################
+# feature.properties
+# contains externalized strings for feature.xml
+# "%foo" in feature.xml corresponds to the key "foo" in this file
+# java.io.Properties file (ISO 8859-1 with "\" escapes)
+# This file should be translated.
+
+# "featureName" property - name of the feature
+featureName=C/C++ Unit Testing Support Source
+
+# "providerName" property - name of the company that provides the feature
+providerName=Eclipse CDT
+
+# "updateSiteName" property - label for the update site
+updateSiteName=Eclipse CDT Update Site
+
+# "description" property - description of the feature
+description=Support for running unit tests. Source code.
+
+# copyright
+copyright=\
+Copyright (c) 2012 Anton Gorenkov and others.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+Eclipse Foundation Software User Agreement\n\
+February 1, 2011\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the\n\
+Eclipse Foundation is provided to you under the terms and conditions of\n\
+the Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is\n\
+provided with this Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse Foundation source code\n\
+repository ("Repository") in software modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java(TM) ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Provisioning Technology (as defined below), you must agree to a license ("Feature \n\
+Update License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties" found within a Feature.\n\
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the\n\
+terms and conditions (or references to such terms and conditions) that\n\
+govern your use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Eclipse Distribution License Version 1.0 (available at http://www.eclipse.org/licenses/edl-v1.0.html)\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+\n\Use of Provisioning Technology\n\
+\n\
+The Eclipse Foundation makes available provisioning software, examples of which include,\n\
+but are not limited to, p2 and the Eclipse Update Manager ("Provisioning Technology") for\n\
+the purpose of allowing users to install software, documentation, information and/or\n\
+other materials (collectively "Installable Software"). This capability is provided with\n\
+the intent of allowing such users to install, extend and update Eclipse-based products.\n\
+Information about packaging Installable Software is available at\n\
+http://eclipse.org/equinox/p2/repository_packaging.html ("Specification").\n\
+\n\
+You may use Provisioning Technology to allow other parties to install Installable Software.\n\
+You shall be responsible for enabling the applicable license agreements relating to the\n\
+Installable Software to be presented to, and accepted by, the users of the Provisioning Technology\n\
+in accordance with the Specification. By using Provisioning Technology in such a manner and\n\
+making it available in accordance with the Specification, you further acknowledge your\n\
+agreement to, and the acquisition of all necessary rights to permit the following:\n\
+\n\
+ 1. A series of actions may occur ("Provisioning Process") in which a user may execute\n\
+ the Provisioning Technology on a machine ("Target Machine") with the intent of installing,\n\
+ extending or updating the functionality of an Eclipse-based product.\n\
+ 2. During the Provisioning Process, the Provisioning Technology may cause third party\n\
+ Installable Software or a portion thereof to be accessed and copied to the Target Machine.\n\
+ 3. Pursuant to the Specification, you will provide to the user the terms and conditions that\n\
+ govern the use of the Installable Software ("Installable Software Agreement") and such\n\
+ Installable Software Agreement shall be accessed from the Target Machine in accordance\n\
+ with the Specification. Such Installable Software Agreement must inform the user of the\n\
+ terms and conditions that govern the Installable Software and must solicit acceptance by\n\
+ the end user in the manner prescribed in such Installable Software Agreement. Upon such\n\
+ indication of agreement by the user, the provisioning Technology will complete installation\n\
+ of the Installable Software.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use, and\n\
+re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.\n
+########### end of license property ##########################################
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml
new file mode 100644
index 0000000..4c3d095
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/feature.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.cdt.testsrunner.source.feature"
+ label="%featureName"
+ version="7.0.0.qualifier"
+ provider-name="%providerName">
+
+ <description>
+ %description
+ </description>
+
+ <copyright>
+ %copyright
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <url>
+ <update label="%updateSiteName" url="http://download.eclipse.org/tools/cdt/releases/indigo"/>
+ </url>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.boost.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.gtest.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.cdt.testsrunner.qttest.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+</feature>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html
new file mode 100644
index 0000000..f19c483
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/license.html
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>Eclipse Foundation Software User Agreement</title>
+</head>
+
+<body lang="EN-US">
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>February 1, 2011</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ (&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse Foundation source code
+ repository (&quot;Repository&quot;) in software modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Provisioning Technology (as defined below), you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Eclipse Distribution License Version 1.0 (available at <a href="http://www.eclipse.org/licenses/edl-v10.html">http://www.eclipse.org/licenses/edl-v1.0.html</a>)</li>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+
+<h3>Use of Provisioning Technology</h3>
+
+<p>The Eclipse Foundation makes available provisioning software, examples of which include, but are not limited to, p2 and the Eclipse
+ Update Manager (&quot;Provisioning Technology&quot;) for the purpose of allowing users to install software, documentation, information and/or
+ other materials (collectively &quot;Installable Software&quot;). This capability is provided with the intent of allowing such users to
+ install, extend and update Eclipse-based products. Information about packaging Installable Software is available at <a
+ href="http://eclipse.org/equinox/p2/repository_packaging.html">http://eclipse.org/equinox/p2/repository_packaging.html</a>
+ (&quot;Specification&quot;).</p>
+
+<p>You may use Provisioning Technology to allow other parties to install Installable Software. You shall be responsible for enabling the
+ applicable license agreements relating to the Installable Software to be presented to, and accepted by, the users of the Provisioning Technology
+ in accordance with the Specification. By using Provisioning Technology in such a manner and making it available in accordance with the
+ Specification, you further acknowledge your agreement to, and the acquisition of all necessary rights to permit the following:</p>
+
+<ol>
+ <li>A series of actions may occur (&quot;Provisioning Process&quot;) in which a user may execute the Provisioning Technology
+ on a machine (&quot;Target Machine&quot;) with the intent of installing, extending or updating the functionality of an Eclipse-based
+ product.</li>
+ <li>During the Provisioning Process, the Provisioning Technology may cause third party Installable Software or a portion thereof to be
+ accessed and copied to the Target Machine.</li>
+ <li>Pursuant to the Specification, you will provide to the user the terms and conditions that govern the use of the Installable
+ Software (&quot;Installable Software Agreement&quot;) and such Installable Software Agreement shall be accessed from the Target
+ Machine in accordance with the Specification. Such Installable Software Agreement must inform the user of the terms and conditions that govern
+ the Installable Software and must solicit acceptance by the end user in the manner prescribed in such Installable Software Agreement. Upon such
+ indication of agreement by the user, the provisioning Technology will complete installation of the Installable Software.</li>
+</ol>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<p><small>Java and all Java-based trademarks are trademarks of Oracle Corporation in the United States, other countries, or both.</small></p>
+</body>
+</html>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml
new file mode 100644
index 0000000..8bf6a12
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.source.feature/pom.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.cdt.features</groupId>
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.source.feature</artifactId>
+ <packaging>eclipse-feature</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath b/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.project b/testsrunner/org.eclipse.cdt.testsrunner.test/.project
new file mode 100644
index 0000000..fcfb09a
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner.test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0e860bf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,82 @@
+#Mon Apr 16 13:01:24 EEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8753f5d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %Bundle-Name
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner.test
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.test.TestsRunnerTestActivator
+Require-Bundle: org.junit,
+ org.eclipse.core.runtime,
+ org.eclipse.cdt.core.tests,
+ org.eclipse.cdt.testsrunner;bundle-version="7.0.0",
+ org.eclipse.cdt.testsrunner.boost;bundle-version="7.0.0",
+ org.eclipse.cdt.testsrunner.qttest;bundle-version="7.0.0",
+ org.eclipse.cdt.testsrunner.gtest;bundle-version="7.0.0"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-Vendor: %Bundle-Vendor
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties b/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties
new file mode 100644
index 0000000..c93c676
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/OSGI-INF/l10n/bundle.properties
@@ -0,0 +1,13 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+#Properties file for org.eclipse.cdt.testsrunner.test
+Bundle-Name = C/C++ Development Tools Tests Running Support Tests
+Bundle-Vendor = Eclipse CDT \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/about.html b/testsrunner/org.eclipse.cdt.testsrunner.test/about.html
new file mode 100644
index 0000000..d7c5118
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties
new file mode 100644
index 0000000..6717294
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/build.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ src/,\
+ OSGI-INF/,\
+ test.xml,\
+ about.html
+jre.compilation.profile = J2SE-1.5
+src.includes = about.html
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml
new file mode 100644
index 0000000..0606be0
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>1.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner.test</artifactId>
+ <packaging>eclipse-test-plugin</packaging>
+
+ <repositories>
+ <repository>
+ <id>cdt.repo</id>
+ <url>file:/${basedir}/../../releng/org.eclipse.cdt.repo/target/repository</url>
+ <layout>p2</layout>
+ </repository>
+</repositories>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.tycho</groupId>
+ <artifactId>tycho-surefire-plugin</artifactId>
+ <version>${tycho-version}</version>
+ <configuration>
+ <useUIHarness>true</useUIHarness>
+ <includes>
+ <include>**/TestsRunnerSuite.*</include>
+ </includes>
+ <testFailureIgnore>true</testFailureIgnore>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java
new file mode 100644
index 0000000..5d9713b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerBaseReorderingTestCase.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.cdt.testsrunner.internal.model.TestModelManager;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+
+/**
+ * Base test case for test suites & test cases reordering in TestModelManager.
+ */
+@SuppressWarnings("nls")
+public abstract class TestModelManagerBaseReorderingTestCase extends TestCase {
+
+ protected TestModelManager modelManager;
+ protected List<String> expectedSuitesOrder = new ArrayList<String>();
+
+
+ protected abstract ITestSuite createTestsHierarchy();
+
+ protected abstract void visitTestItem(String name);
+
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ modelManager = new TestModelManager(createTestsHierarchy(), false);
+ modelManager.testingStarted();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ modelManager.testingFinished();
+ ITestItem[] rootTestSuiteChildren = modelManager.getRootSuite().getChildren();
+ assertEquals("Unexpected children count", expectedSuitesOrder.size(), rootTestSuiteChildren.length);
+ for (int i = 0; i < rootTestSuiteChildren.length; i++) {
+ assertEquals("Unexpected child name", expectedSuitesOrder.get(i), rootTestSuiteChildren[i].getName());
+ }
+ }
+
+ private void visitTestItemWithExpectation(String name) {
+ visitTestItem(name);
+ expectedSuitesOrder.add(name);
+ }
+
+ public void testNoReordering() {
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("item2");
+ visitTestItemWithExpectation("item3");
+ }
+
+ public void testItemAdd() {
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("itemNew");
+ visitTestItemWithExpectation("item2");
+ visitTestItemWithExpectation("item3");
+ }
+
+ public void testItemAddToBeginAndEnd() {
+ visitTestItemWithExpectation("itemNew");
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("item2");
+ visitTestItemWithExpectation("item3");
+ visitTestItemWithExpectation("itemNew2");
+ }
+
+ public void testItemRemove() {
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("item3");
+ }
+
+ public void testItemRemoveFromBeginAndEnd() {
+ visitTestItemWithExpectation("item2");
+ }
+
+ public void testItemRemoveAndAdd() {
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("itemNew");
+ visitTestItemWithExpectation("item3");
+ }
+
+ public void testItemOrderChange() {
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("item3");
+ visitTestItemWithExpectation("item2");
+ }
+
+ public void testItemReverse() {
+ visitTestItemWithExpectation("item3");
+ visitTestItemWithExpectation("item2");
+ visitTestItemWithExpectation("item1");
+ }
+
+ public void testItemVisitTwice() {
+ visitTestItem("item1");
+ visitTestItemWithExpectation("item2");
+ visitTestItemWithExpectation("item1");
+ visitTestItem("item3");
+ visitTestItemWithExpectation("item3");
+ }
+
+ public void testItemVisitTwiceAndReorder() {
+ visitTestItem("item3");
+ visitTestItemWithExpectation("item1");
+ visitTestItemWithExpectation("item3");
+ visitTestItemWithExpectation("item2");
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java
new file mode 100644
index 0000000..31c382e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerCasesReorderingTestCase.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.core;
+
+import org.eclipse.cdt.testsrunner.internal.model.TestCase;
+import org.eclipse.cdt.testsrunner.internal.model.TestModelManager;
+import org.eclipse.cdt.testsrunner.internal.model.TestSuite;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+
+/**
+ * Tests on the test cases reordering in TestModelManager.
+ */
+@SuppressWarnings("nls")
+public class TestModelManagerCasesReorderingTestCase extends TestModelManagerBaseReorderingTestCase {
+
+ @Override
+ protected ITestSuite createTestsHierarchy() {
+ TestSuite rootTestSuite = new TestSuite(TestModelManager.ROOT_TEST_SUITE_NAME, null);
+ rootTestSuite.getChildrenList().add(new TestCase("item1", rootTestSuite));
+ rootTestSuite.getChildrenList().add(new TestCase("item2", rootTestSuite));
+ rootTestSuite.getChildrenList().add(new TestCase("item3", rootTestSuite));
+ return rootTestSuite;
+ }
+
+ @Override
+ protected void visitTestItem(String name) {
+ modelManager.enterTestCase(name);
+ modelManager.exitTestCase();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java
new file mode 100644
index 0000000..3a1332e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/core/TestModelManagerSuitesReorderingTestCase.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.core;
+
+import org.eclipse.cdt.testsrunner.internal.model.TestModelManager;
+import org.eclipse.cdt.testsrunner.internal.model.TestSuite;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+
+/**
+ * Tests on the test suites reordering in TestModelManager.
+ */
+@SuppressWarnings("nls")
+public class TestModelManagerSuitesReorderingTestCase extends TestModelManagerBaseReorderingTestCase {
+
+ @Override
+ protected ITestSuite createTestsHierarchy() {
+ TestSuite rootTestSuite = new TestSuite(TestModelManager.ROOT_TEST_SUITE_NAME, null);
+ rootTestSuite.getChildrenList().add(new TestSuite("item1", rootTestSuite));
+ rootTestSuite.getChildrenList().add(new TestSuite("item2", rootTestSuite));
+ rootTestSuite.getChildrenList().add(new TestSuite("item3", rootTestSuite));
+ return rootTestSuite;
+ }
+
+ @Override
+ protected void visitTestItem(String name) {
+ modelManager.enterTestSuite(name);
+ modelManager.exitTestSuite();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java
new file mode 100644
index 0000000..1d4b249
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerSuite.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.test;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.testsrunner.core.TestModelManagerCasesReorderingTestCase;
+import org.eclipse.cdt.testsrunner.core.TestModelManagerSuitesReorderingTestCase;
+import org.eclipse.cdt.testsrunner.testsrunners.BoostTestCase;
+import org.eclipse.cdt.testsrunner.testsrunners.GoogleTestCase;
+import org.eclipse.cdt.testsrunner.testsrunners.QtTestCase;
+
+
+/**
+ * Test suite with all the tests on Tests Runner.
+ */
+public class TestsRunnerSuite extends TestSuite {
+
+ public TestsRunnerSuite() {
+ }
+
+ public TestsRunnerSuite(Class<? extends TestCase> theClass, String name) {
+ super(theClass, name);
+ }
+
+ public TestsRunnerSuite(Class<? extends TestCase> theClass) {
+ super(theClass);
+ }
+
+ public TestsRunnerSuite(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ final TestsRunnerSuite suite = new TestsRunnerSuite();
+ // Core
+ suite.addTestSuite(TestModelManagerSuitesReorderingTestCase.class);
+ suite.addTestSuite(TestModelManagerCasesReorderingTestCase.class);
+ // Tests Runners Plug-ins
+ suite.addTestSuite(BoostTestCase.class);
+ suite.addTestSuite(GoogleTestCase.class);
+ suite.addTestSuite(QtTestCase.class);
+ return suite;
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java
new file mode 100644
index 0000000..375b750
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/test/TestsRunnerTestActivator.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.test;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class TestsRunnerTestActivator extends Plugin {
+
+ /** The plug-in ID .*/
+ public static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner.test"; //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static TestsRunnerTestActivator plugin;
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared plug-in instance.
+ *
+ * @return the plug-in instance
+ */
+ public static TestsRunnerTestActivator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java
new file mode 100644
index 0000000..1d6be7e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BaseTestCase.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.testsrunners;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import junit.framework.TestCase;
+
+import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.eclipse.cdt.testsrunner.test.TestsRunnerTestActivator;
+import org.eclipse.core.runtime.Plugin;
+
+
+/**
+ * Base test case for Tests Runner provider plug-ins testing.
+ */
+@SuppressWarnings("nls")
+public abstract class BaseTestCase extends TestCase {
+
+ protected static final String EOL = System.getProperty("line.separator");
+
+ protected MockTestModelUpdater mockModelUpdater = new MockTestModelUpdater();
+ protected ITestsRunnerProvider testsRunner = createTestsRunner();
+ protected boolean expectTestingException = false;
+
+
+ protected abstract ITestsRunnerProvider createTestsRunner();
+
+ protected String getAboveComment() {
+ return getContents(1)[0].toString();
+ }
+
+ private StringBuilder[] getContents(int sections) {
+ try {
+ return TestSourceReader.getContentsForTest(getPlugin().getBundle(), getSourcePrefix(), getClass(), getName(), sections);
+ } catch (IOException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ }
+
+ protected Plugin getPlugin() {
+ return TestsRunnerTestActivator.getDefault();
+ }
+
+ protected String getSourcePrefix() {
+ return "src";
+ }
+
+ protected void runTestsRunner() throws TestingException {
+ try {
+ mockModelUpdater.replay();
+ String inputString = getAboveComment();
+ InputStream inStream = new ByteArrayInputStream(inputString.getBytes("UTF-8"));
+ boolean testingExceptionHappen = false;
+ String exceptionMessage = null;
+ try {
+ testsRunner.run(mockModelUpdater, inStream);
+
+ } catch (TestingException e) {
+ testingExceptionHappen = true;
+ exceptionMessage = e.getMessage();
+ }
+ if (expectTestingException != testingExceptionHappen) {
+ if (testingExceptionHappen) {
+ fail("Unexpected exception: "+exceptionMessage);
+ } else {
+ fail("TestingException is expected, but did not happen!");
+ }
+ }
+
+ } catch (UnsupportedEncodingException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ protected void expectTestingException() {
+ expectTestingException = true;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ runTestsRunner();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java
new file mode 100644
index 0000000..053a5ea
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/BoostTestCase.java
@@ -0,0 +1,481 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.testsrunners;
+
+import org.eclipse.cdt.testsrunner.internal.boost.BoostTestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+
+
+/**
+ * Tests for {@see BoostTestsRunner} class
+ */
+@SuppressWarnings("nls")
+public class BoostTestCase extends BaseTestCase {
+
+ private static final String DEFAULT_LOCATION_FILE = null;
+ private static final int DEFAULT_LOCATION_LINE = -1;
+ private static final String EXCEPTION_CHECKPOINT_SUFFIX = "\nLast check point was here.";
+
+ @Override
+ public ITestsRunnerProvider createTestsRunner() {
+ return new BoostTestsRunnerProvider();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test"/>
+ // </TestSuite>
+ //</TestLog>
+ public void testTheOnlyTestCase() {
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test1"/>
+ // <TestCase name="test2"/>
+ // <TestCase name="test3"/>
+ // </TestSuite>
+ //</TestLog>
+ public void testAFewTestCases() {
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test3");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestSuite name="InnerTS"/>
+ // </TestSuite>
+ //</TestLog>
+ public void testEmptyTestSuite() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestSuite("InnerTS");
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestSuite name="InnerTS">
+ // <TestCase name="test1"/>
+ // <TestCase name="test2"/>
+ // <TestCase name="test3"/>
+ // </TestSuite>
+ // </TestSuite>
+ //</TestLog>
+ public void testAFewTestCasesInTestSuite() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestSuite("InnerTS");
+ mockModelUpdater.enterTestCase("test1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test3");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestSuite name="InnerTS">
+ // <TestSuite name="InnerInnerTS"/>
+ // </TestSuite>
+ // </TestSuite>
+ //</TestLog>
+ public void testEmptyTestSuiteInTestSuite() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestSuite("InnerTS");
+ mockModelUpdater.enterTestSuite("InnerInnerTS");
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestSuite name="InnerTS">
+ // <TestSuite name="InnerInnerTS">
+ // <TestCase name="test1"/>
+ // </TestSuite>
+ // <TestCase name="test2"/>
+ // <TestCase name="test3"/>
+ // </TestSuite>
+ // </TestSuite>
+ // <TestCase name="test4">
+ // </TestCase>
+ //</TestLog>
+ public void testSimpleTestsHierarchy() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestSuite("InnerTS");
+ mockModelUpdater.enterTestSuite("InnerInnerTS");
+ mockModelUpdater.enterTestCase("test1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestCase("test2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test3");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestCase("test4");
+ mockModelUpdater.exitTestCase();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ // <Info file="file.cpp" line="22">check 1 passed</Info>
+ // </TestCase>
+ // <TestCase name="testPassWithWarning">
+ // <Warning file="file.cpp" line="27">condition 0 is not satisfied</Warning>
+ // <Message file="file2.h" line="220">Test case testPassWithWarning did not run any assertions</Message>
+ // </TestCase>
+ // <TestCase name="testPassIfEmpty">
+ // <Message file="file2.h" line="220">Test case testPassIfEmpty did not run any assertions</Message>
+ // </TestCase>
+ // <TestCase name="testFailWithCheck">
+ // <Error file="file.cpp" line="32">check 0 failed</Error>
+ // <Info file="file.cpp" line="33">check 1 passed</Info>
+ // </TestCase>
+ // <TestCase name="testFailWithRequire">
+ // <FatalError file="file.cpp" line="38">critical check 0 failed</FatalError>
+ // </TestCase>
+ // <TestCase name="testAbortedOnException">
+ // <Exception>unknown type</Exception>
+ // </TestCase>
+ // <TestCase name="testAbortedOnNullDereference">
+ // <Exception>memory access violation at address: 0x00000000: no mapping at fault address</Exception>
+ // <Message file="file2.h" line="164">Test is aborted</Message>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testDifferentTestStatuses() {
+ mockModelUpdater.skipCalls("addTestMessage");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("testPass");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testPassWithWarning");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testPassIfEmpty");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testFailWithCheck");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testFailWithRequire");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testAbortedOnException");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Aborted);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testAbortedOnNullDereference");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Aborted);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test">
+ // <Info file="file.cpp" line="22"/>
+ // <Exception><LastCheckpoint file="file2.cpp" line="47"/></Exception>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testEmptyMessage() {
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test");
+ mockModelUpdater.addTestMessage("file.cpp", 22, ITestMessage.Level.Info, "");
+ mockModelUpdater.addTestMessage("file2.cpp", 47, ITestMessage.Level.Exception, EXCEPTION_CHECKPOINT_SUFFIX);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test">
+ // <Warning file="file" line="42"> Custom warning </Warning>
+ // <Exception> Exception message <LastCheckpoint file="file2" line="47"/> end </Exception>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testSpacesInBeginAndEndOfMessage() {
+ // NOTE: Last checkpoint tag cannot be in the middle of exception (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test");
+ mockModelUpdater.addTestMessage("file", 42, ITestMessage.Level.Warning, " Custom warning ");
+ mockModelUpdater.addTestMessage("file2", 47, ITestMessage.Level.Exception, " Exception message end "+EXCEPTION_CHECKPOINT_SUFFIX);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test">
+ // <Warning>Custom warning</Warning>
+ // <Exception file="file.cpp" line="1">Exceptions should be located by pass point</Exception>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testMessageWithoutLocation() {
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "Custom warning");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exceptions should be located by pass point");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test">
+ // <Warning file="file.cpp">No line number</Warning>
+ // <Warning file="" line="1">Empty file name</Warning>
+ // <Warning line="2">No file name</Warning>
+ // <Exception>Exception without line number<LastCheckpoint file="file2.cpp"/></Exception>
+ // <Exception>Exception with empty file name<LastCheckpoint file="" line="3"/></Exception>
+ // <Exception>Exception without file name<LastCheckpoint line="4"/></Exception>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testMessageWithLocation() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test");
+ mockModelUpdater.addTestMessage("file.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "No line number");
+ mockModelUpdater.addTestMessage("", 1, ITestMessage.Level.Warning, "Empty file name");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 2, ITestMessage.Level.Warning, "No file name");
+ // NOTE: Last check point is not available, so EXCEPTION_CHECKPOINT_SUFFIX should not be added
+ mockModelUpdater.addTestMessage("file2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exception without line number");
+ mockModelUpdater.addTestMessage("", 3, ITestMessage.Level.Exception, "Exception with empty file name");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 4, ITestMessage.Level.Exception, "Exception without file name");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="test1">
+ // <Error file="file1.cpp" line="1">Message with location</Error>
+ // <Error>Message without location</Error>
+ // </TestCase>
+ // <TestCase name="test2">
+ // <Exception>Exception with location<LastCheckpoint file="file2.cpp" line="2"/></Exception>
+ // <Exception>Exception without location<LastCheckpoint/></Exception>
+ // </TestCase>
+ // <TestCase name="test3">
+ // <Error file="file3.cpp" line="3">Another message with location</Error>
+ // <Exception>Another exception without location</Exception>
+ // </TestCase>
+ // <TestCase name="test4">
+ // <Exception>Another exception with location<LastCheckpoint file="file4.cpp" line="4"/></Exception>
+ // <Error>Another message without location</Error>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testMessagesWithAndWithoutLocation() {
+ // NOTE: This is impossible input data (at least, for current version of Boost), but we check it anyway
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("test1");
+ mockModelUpdater.addTestMessage("file1.cpp", 1, ITestMessage.Level.Error, "Message with location");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Message without location");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test2");
+ mockModelUpdater.addTestMessage("file2.cpp", 2, ITestMessage.Level.Exception, "Exception with location"+EXCEPTION_CHECKPOINT_SUFFIX);
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Exception without location");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test3");
+ mockModelUpdater.addTestMessage("file3.cpp", 3, ITestMessage.Level.Error, "Another message with location");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "Another exception without location");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("test4");
+ mockModelUpdater.addTestMessage("file4.cpp", 4, ITestMessage.Level.Exception, "Another exception with location"+EXCEPTION_CHECKPOINT_SUFFIX);
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Another message without location");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ // <Info file="file.cpp" line="22">check 1 passed</Info>
+ // <TestingTime>1000</TestingTime>
+ // </TestCase>
+ // <TestCase name="testFail">
+ // <FatalError file="file2.cpp" line="38">critical check 0 failed</FatalError>
+ // <TestingTime>2000</TestingTime>
+ // </TestCase>
+ // <TestCase name="testAbortedOnException">
+ // <Exception>exception message</Exception>
+ // <TestingTime>3000</TestingTime>
+ // </TestCase>
+ // <TestCase name="testAbortedOnNullDereference">
+ // <Exception>another exception message</Exception>
+ // <Message file="file3.h" line="164">Test is aborted</Message>
+ // <TestingTime>4000</TestingTime>
+ // </TestCase>
+ // <TestCase name="testAbortedOnExceptionWithLocation">
+ // <Exception>yet another exception message<LastCheckpoint file="file4.cpp" line="47"/></Exception>
+ // <TestingTime>5000</TestingTime>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testExecutionTimePresence() {
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("testPass");
+ mockModelUpdater.addTestMessage("file.cpp", 22, ITestMessage.Level.Info, "check 1 passed");
+ mockModelUpdater.setTestingTime(1);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testFail");
+ mockModelUpdater.addTestMessage("file2.cpp", 38, ITestMessage.Level.FatalError, "critical check 0 failed");
+ mockModelUpdater.setTestingTime(2);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testAbortedOnException");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "exception message");
+ mockModelUpdater.setTestingTime(3);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testAbortedOnNullDereference");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Exception, "another exception message");
+ mockModelUpdater.addTestMessage("file3.h", 164, ITestMessage.Level.Message, "Test is aborted");
+ mockModelUpdater.setTestingTime(4);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testAbortedOnExceptionWithLocation");
+ mockModelUpdater.addTestMessage("file4.cpp", 47, ITestMessage.Level.Exception, "yet another exception message"+EXCEPTION_CHECKPOINT_SUFFIX);
+ mockModelUpdater.setTestingTime(5);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //
+ public void testNoInput() {
+ // NOTE: The comment above is left blank intentionally
+ expectTestingException();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ // <!-- TestCase is not closed -->
+ // </TestSuite>
+ //</TestLog>
+ public void testBadFormedXml() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ public void testUnexceptedXmlEnd() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <UnexpectedXmlElement name="testPass">
+ // <Info file="file.cpp" line="22">check 1 passed</Info>
+ // <TestingTime>100</TestingTime>
+ // </UnexpectedXmlElement>
+ // </TestSuite>
+ //</TestLog>
+ public void testUnexpectedXmlElement() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ expectTestingException();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ // <Info file="file.cpp" line="wrong_value">check 1 passed</Info>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testWrongLineNumberValue() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<TestLog>
+ // <TestSuite name="MainTS">
+ // <TestCase name="testPass">
+ // <TestingTime>wrong value</TestingTime>
+ // </TestCase>
+ // </TestSuite>
+ //</TestLog>
+ public void testWrongExecutionTimeValue() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java
new file mode 100644
index 0000000..ef561b6
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/GoogleTestCase.java
@@ -0,0 +1,698 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.testsrunners;
+
+import org.eclipse.cdt.testsrunner.internal.gtest.GoogleTestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+
+
+/**
+ * Tests for {@see GoogleTestsRunner} class
+ */
+@SuppressWarnings("nls")
+public class GoogleTestCase extends BaseTestCase {
+
+ private static final String DEFAULT_LOCATION_FILE = null;
+ private static final int DEFAULT_LOCATION_LINE = 1;
+
+ @Override
+ protected ITestsRunnerProvider createTestsRunner() {
+ return new GoogleTestsRunnerProvider();
+ }
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 0 tests from 0 test cases.
+ //[==========] 0 tests from 0 test cases ran. (0 ms total)
+ //[ PASSED ] 0 tests.
+ public void testNoTestCases() {
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //[ OK ] DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testTheOnlyTestCase() {
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("setTestingTime");
+
+ mockModelUpdater.enterTestSuite("DemoTestCase");
+ mockModelUpdater.enterTestCase("DemoTest");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 3 tests from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 3 tests from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest1
+ //[ OK ] DemoTestCase.DemoTest1 (0 ms)
+ //[ RUN ] DemoTestCase.DemoTest2
+ //[ OK ] DemoTestCase.DemoTest2 (0 ms)
+ //[ RUN ] DemoTestCase.DemoTest3
+ //[ OK ] DemoTestCase.DemoTest3 (0 ms)
+ //[----------] 3 tests from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 3 tests from 1 test case ran. (0 ms total)
+ //[ PASSED ] 3 tests.
+ public void testAFewTestCasesInTheOnlyTestSuites() {
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("setTestingTime");
+
+ mockModelUpdater.enterTestSuite("DemoTestCase");
+ mockModelUpdater.enterTestCase("DemoTest1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("DemoTest2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("DemoTest3");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 2 tests from 2 test cases.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //[ OK ] DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] 1 test from DemoTestCase2
+ //[ RUN ] DemoTestCase2.DemoTest2
+ //[ OK ] DemoTestCase2.DemoTest2 (0 ms)
+ //[----------] 1 test from DemoTestCase2 (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 2 tests from 2 test cases ran. (0 ms total)
+ //[ PASSED ] 2 tests.
+ public void testTheOnlyTestCasesInAFewTestSuites() {
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("setTestingTime");
+
+ mockModelUpdater.enterTestSuite("DemoTestCase");
+ mockModelUpdater.enterTestCase("DemoTest");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestSuite("DemoTestCase2");
+ mockModelUpdater.enterTestCase("DemoTest2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 4 tests from 2 test cases.
+ //[----------] Global test environment set-up.
+ //[----------] 2 tests from DemoTestCase1
+ //[ RUN ] DemoTestCase1.DemoTest1
+ //[ OK ] DemoTestCase1.DemoTest1 (0 ms)
+ //[ RUN ] DemoTestCase1.DemoTest2
+ //[ OK ] DemoTestCase1.DemoTest2 (0 ms)
+ //[----------] 2 tests from DemoTestCase1 (0 ms total)
+ //
+ //[----------] 2 tests from DemoTestCase2
+ //[ RUN ] DemoTestCase2.DemoTest1
+ //[ OK ] DemoTestCase2.DemoTest1 (0 ms)
+ //[ RUN ] DemoTestCase2.DemoTest2
+ //[ OK ] DemoTestCase2.DemoTest2 (0 ms)
+ //[----------] 2 tests from DemoTestCase2 (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 4 tests from 2 test cases ran. (0 ms total)
+ //[ PASSED ] 4 tests.
+ public void testAFewTestCasesWithTheSameNameInDifferentTestSuites() {
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("setTestingTime");
+
+ mockModelUpdater.enterTestSuite("DemoTestCase1");
+ mockModelUpdater.enterTestCase("DemoTest1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("DemoTest2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestSuite("DemoTestCase2");
+ mockModelUpdater.enterTestCase("DemoTest1");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("DemoTest2");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 4 tests from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 4 tests from DemoTestCase
+ //[ RUN ] DemoTestCase.TestPass
+ //[ OK ] DemoTestCase.TestPass (0 ms)
+ //[ RUN ] DemoTestCase.TestFail
+ //demo_file.cc:38: Failure
+ //Value of: 2
+ //Expected: 1
+ //[ FAILED ] DemoTestCase.TestFail (0 ms)
+ //[ RUN ] DemoTestCase.TestAFewFails
+ //demo_file.cc:42: Failure
+ //Value of: 2
+ //Expected: 1
+ //demo_file.cc:43: Failure
+ //Value of: 2
+ //Expected: 1
+ //[ FAILED ] DemoTestCase.TestAFewFails (0 ms)
+ //[ RUN ] DemoTestCase.TestCustomFails
+ //demo_file.cc:47: Failure
+ //Failed
+ //Custom fatal fail!
+ //demo_file.cc:48: Failure
+ //Failed
+ //Another custom fatal fail!
+ //demo_file.cc:49: Failure
+ //Failed
+ //Yet another custom fatal fail!
+ //[ FAILED ] DemoTestCase.TestCustomFails (0 ms)
+ //[----------] 4 tests from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 4 tests from 1 test case ran. (1 ms total)
+ //[ PASSED ] 1 test.
+ //[ FAILED ] 3 tests, listed below:
+ //[ FAILED ] DemoTestCase.TestFail
+ //[ FAILED ] DemoTestCase.TestAFewFails
+ //[ FAILED ] DemoTestCase.TestCustomFails
+ //
+ // 3 FAILED TESTS
+ public void testDifferentTestStatuses() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("setTestingTime");
+
+ mockModelUpdater.enterTestCase("TestPass");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("TestFail");
+ mockModelUpdater.addTestMessage("demo_file.cc", 38, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("TestAFewFails");
+ mockModelUpdater.addTestMessage("demo_file.cc", 42, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.addTestMessage("demo_file.cc", 43, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("TestCustomFails");
+ mockModelUpdater.addTestMessage("demo_file.cc", 47, ITestMessage.Level.Error, "Failed"+EOL+"Custom fatal fail!");
+ mockModelUpdater.addTestMessage("demo_file.cc", 48, ITestMessage.Level.Error, "Failed"+EOL+"Another custom fatal fail!");
+ mockModelUpdater.addTestMessage("demo_file.cc", 49, ITestMessage.Level.Error, "Failed"+EOL+"Yet another custom fatal fail!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 2 tests from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 2 tests from DemoTestCase
+ //[ RUN ] DemoTestCase.TestWithSimpleTrace
+ //demo_file.cc:36: Failure
+ //Value of: 2
+ //Expected: 1
+ //Google Test trace:
+ //demo_file.cc:41: Trace point #2 in TestWithSimpleTrace
+ //demo_file.cc:40: Trace point #1 in TestWithSimpleTrace
+ //[ FAILED ] DemoTestCase.TestWithSimpleTrace (1 ms)
+ //[ RUN ] DemoTestCase.TestTraceForMultipleFails
+ //demo_file.cc:36: Failure
+ //Value of: 2
+ //Expected: 1
+ //Google Test trace:
+ //demo_file.cc:46: Trace point #1 in TestTraceForMultipleFails
+ //demo_file.cc:36: Failure
+ //Value of: 2
+ //Expected: 1
+ //Google Test trace:
+ //demo_file.cc:48: Trace point #2 in TestTraceForMultipleFails
+ //demo_file.cc:46: Trace point #1 in TestTraceForMultipleFails
+ //[ FAILED ] DemoTestCase.TestTraceForMultipleFails (0 ms)
+ //[----------] 2 tests from DemoTestCase (1 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 2 tests from 1 test case ran. (1 ms total)
+ //[ PASSED ] 0 tests.
+ //[ FAILED ] 2 tests, listed below:
+ //[ FAILED ] DemoTestCase.TestWithSimpleTrace
+ //[ FAILED ] DemoTestCase.TestTraceForMultipleFails
+ //
+ // 2 FAILED TESTS
+ public void testScopedTraceSupport() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("setTestingTime");
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestCase("TestWithSimpleTrace");
+ mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.addTestMessage("demo_file.cc", 41, ITestMessage.Level.Info, "Trace point #2 in TestWithSimpleTrace");
+ mockModelUpdater.addTestMessage("demo_file.cc", 40, ITestMessage.Level.Info, "Trace point #1 in TestWithSimpleTrace");
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("TestTraceForMultipleFails");
+ mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.addTestMessage("demo_file.cc", 46, ITestMessage.Level.Info, "Trace point #1 in TestTraceForMultipleFails");
+ mockModelUpdater.addTestMessage("demo_file.cc", 36, ITestMessage.Level.Error, "Value of: 2"+EOL+"Expected: 1");
+ mockModelUpdater.addTestMessage("demo_file.cc", 48, ITestMessage.Level.Info, "Trace point #2 in TestTraceForMultipleFails");
+ mockModelUpdater.addTestMessage("demo_file.cc", 46, ITestMessage.Level.Info, "Trace point #1 in TestTraceForMultipleFails");
+ mockModelUpdater.exitTestCase();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.TestMessageLocationFormats
+ //demo_file_name2.cpp:40: Failure
+ //Standard format with file name & line number
+ //unknown file:41: Failure
+ //Standard format with unknown file name
+ //demo_file_name2.cpp(42): Failure
+ //VS-like format with file name & line number
+ //unknown file(43): Failure
+ //VS-like format with unknown file name
+ //demo_file_name2.cpp: Failure
+ //Location with unknown line number
+ //unknown file: Failure
+ //Location with unknown file name & line number
+ //[ FAILED ] DemoTestCase.TestMessageLocationFormats (1 ms)
+ //[----------] 1 test from DemoTestCase (1 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (1 ms total)
+ //[ PASSED ] 0 tests.
+ //[ FAILED ] 1 test, listed below:
+ //[ FAILED ] DemoTestCase.TestMessageLocationFormats
+ //
+ // 1 FAILED TEST
+ public void testDifferentLocationsFormatsWithStandardMessageFormat() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ mockModelUpdater.skipCalls("exitTestCase");
+ mockModelUpdater.skipCalls("setTestingTime");
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", 40, ITestMessage.Level.Error, "Standard format with file name & line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 41, ITestMessage.Level.Error, "Standard format with unknown file name");
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", 42, ITestMessage.Level.Error, "VS-like format with file name & line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 43, ITestMessage.Level.Error, "VS-like format with unknown file name");
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown file name & line number");
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.TestMessageLocationFormats
+ //demo_file_name2.cpp:40: error: Standard format with file name & line number
+ //unknown file:41: error: Standard format with unknown file name
+ //demo_file_name2.cpp(42): error: VS-like format with file name & line number
+ //unknown file(43): error: VS-like format with unknown file name
+ //demo_file_name2.cpp: error: Location with unknown line number
+ //unknown file: error: Location with unknown file name & line number
+ //[ FAILED ] DemoTestCase.TestMessageLocationFormats (1 ms)
+ //[----------] 1 test from DemoTestCase (1 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (1 ms total)
+ //[ PASSED ] 0 tests.
+ //[ FAILED ] 1 test, listed below:
+ //[ FAILED ] DemoTestCase.TestMessageLocationFormats
+ //
+ // 1 FAILED TEST
+ public void testDifferentLocationsFormatsWithVSLikeMessageFormat() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ mockModelUpdater.skipCalls("exitTestCase");
+ mockModelUpdater.skipCalls("setTestingTime");
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", 40, ITestMessage.Level.Error, "Standard format with file name & line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 41, ITestMessage.Level.Error, "Standard format with unknown file name");
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", 42, ITestMessage.Level.Error, "VS-like format with file name & line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, 43, ITestMessage.Level.Error, "VS-like format with unknown file name");
+ mockModelUpdater.addTestMessage("demo_file_name2.cpp", DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown line number");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Error, "Location with unknown file name & line number");
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.TestMultiLineMessage
+ //demo_file.cc:40: Failure
+ //Line 1
+ //Line 2
+ //Line 3
+ //[ FAILED ] DemoTestCase.TestMultiLineMessage (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 0 tests.
+ //[ FAILED ] 1 test, listed below:
+ //[ FAILED ] DemoTestCase.TestMultiLineMessage
+ //
+ // 1 FAILED TEST
+ public void testMultiLineMessage() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("setTestingTime");
+ mockModelUpdater.skipCalls("setTestStatus");
+
+ mockModelUpdater.enterTestCase("TestMultiLineMessage");
+ mockModelUpdater.addTestMessage("demo_file.cc", 40, ITestMessage.Level.Error, "Line 1"+EOL+"Line 2"+EOL+"Line 3");
+ mockModelUpdater.exitTestCase();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 2 tests from 2 test cases.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase1
+ //[ RUN ] DemoTestCase1.Test1
+ //unknown file: Failure
+ //Unknown C++ exception thrown in the test body.
+ //[ FAILED ] DemoTestCase1.Test1 (1000 ms)
+ //[----------] 1 test from DemoTestCase1 (1000 ms total)
+ //
+ //[----------] 1 test from DemoTestCase2
+ //[ RUN ] DemoTestCase2.Test2
+ //[ OK ] DemoTestCase2.Test2 (2000 ms)
+ //[----------] 1 test from DemoTestCase2 (2000 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 2 tests from 2 test cases ran. (3000 ms total)
+ //[ PASSED ] 1 test.
+ //[ FAILED ] 1 test, listed below:
+ //[ FAILED ] DemoTestCase1.Test1
+ //
+ // 1 FAILED TEST
+ public void testTestingTimeSupport() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("exitTestSuite");
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("addTestMessage");
+
+ mockModelUpdater.enterTestCase("Test1");
+ mockModelUpdater.setTestingTime(1000);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("Test2");
+ mockModelUpdater.setTestingTime(2000);
+ mockModelUpdater.exitTestCase();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 3 tests from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 3 tests from Inst/DemoTestCase
+ //[ RUN ] Inst/DemoTestCase.Test/0
+ //demo_file.cc:50: Failure
+ //Failed
+ //Param1
+ //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = "Param1" (0 ms)
+ //[ RUN ] Inst/DemoTestCase.Test/1
+ //[ OK ] Inst/DemoTestCase.Test/1 (0 ms)
+ //[ RUN ] Inst/DemoTestCase.Test/2
+ //demo_file.cc:50: Failure
+ //Failed
+ //Param3
+ //[ FAILED ] Inst/DemoTestCase.Test/2, where GetParam() = "Param3" (0 ms)
+ //[----------] 3 tests from Inst/DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 3 tests from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ //[ FAILED ] 2 tests, listed below:
+ //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = "Param1"
+ //[ FAILED ] Inst/DemoTestCase.Test/2, where GetParam() = "Param3"
+ //
+ // 2 FAILED TESTS
+ public void testParametrizedTestsSupport() {
+ mockModelUpdater.enterTestSuite("Inst/DemoTestCase");
+ mockModelUpdater.enterTestCase("Test/0");
+ mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed"+EOL+"Param1");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = \"Param1\"");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("Test/1");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("Test/2");
+ mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed"+EOL+"Param3");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = \"Param3\"");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from Inst/DemoTestCase
+ //[ RUN ] Inst/DemoTestCase.Test/0
+ //demo_file.cc:50: Failure
+ //Failed
+ //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = 0x4f50cc (0 ms)
+ //[----------] 1 test from Inst/DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 0 tests.
+ //[ FAILED ] 1 test, listed below:
+ //[ FAILED ] Inst/DemoTestCase.Test/0, where GetParam() = 0x4f50cc
+ //
+ // 2 FAILED TESTS
+ public void testParametrizedTestsWithoutQuotesSupport() {
+ mockModelUpdater.enterTestSuite("Inst/DemoTestCase");
+ mockModelUpdater.enterTestCase("Test/0");
+ mockModelUpdater.addTestMessage("demo_file.cc", 50, ITestMessage.Level.Error, "Failed");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info, "Instantiated with GetParam() = 0x4f50cc");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 3 tests from 3 test cases.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase/0, where TypeParam = char
+ //[ RUN ] DemoTestCase/0.Test
+ //demo_file.cc:60: Failure
+ //Failed
+ //char type
+ //[ FAILED ] DemoTestCase/0.Test, where TypeParam = char (0 ms)
+ //[----------] 1 test from DemoTestCase/0 (0 ms total)
+ //
+ //[----------] 1 test from DemoTestCase/1, where TypeParam = int
+ //[ RUN ] DemoTestCase/1.Test
+ //[ OK ] DemoTestCase/1.Test (0 ms)
+ //[----------] 1 test from DemoTestCase/1 (0 ms total)
+ //
+ //[----------] 1 test from DemoTestCase/2, where TypeParam = unsigned int
+ //[ RUN ] DemoTestCase/2.Test
+ //demo_file.cc:60: Failure
+ //Failed
+ //unsigned int type
+ //[ FAILED ] DemoTestCase/2.Test, where TypeParam = unsigned int (0 ms)
+ //[----------] 1 test from DemoTestCase/2 (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 3 tests from 3 test cases ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ //[ FAILED ] 2 tests, listed below:
+ //[ FAILED ] DemoTestCase/0.Test, where TypeParam = char
+ //[ FAILED ] DemoTestCase/2.Test, where TypeParam = unsigned int
+ //
+ // 2 FAILED TESTS
+ public void testTypedTestsSupport() {
+ mockModelUpdater.enterTestSuite("DemoTestCase/0(char)");
+ mockModelUpdater.enterTestCase("Test");
+ mockModelUpdater.addTestMessage("demo_file.cc", 60, ITestMessage.Level.Error, "Failed"+EOL+"char type");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestSuite("DemoTestCase/1(int)");
+ mockModelUpdater.enterTestCase("Test");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ mockModelUpdater.enterTestSuite("DemoTestCase/2(unsigned int)");
+ mockModelUpdater.enterTestCase("Test");
+ mockModelUpdater.addTestMessage("demo_file.cc", 60, ITestMessage.Level.Error, "Failed"+EOL+"unsigned int type");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //Unknown line in the output
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //Another unknown line in the output
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //Yet another unknown line in the output
+ //[ OK ] DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //One more unknown line in the output
+ //
+ //[----------] Global test environment tear-down
+ //And one more unknown line in the output
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testAllUnrecognizedLinesShouldBeSkipped() {
+ mockModelUpdater.enterTestSuite("DemoTestCase");
+ mockModelUpdater.enterTestCase("DemoTest");
+ mockModelUpdater.setTestingTime(0);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //
+ public void testNoInput() {
+ // NOTE: The comment above is left blank intentionally
+ expectTestingException();
+ }
+
+
+ // This is not an input from a Google Test Module
+ public void testAbsolutelyIncorrectInput() {
+ expectTestingException();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] Not_A_DemoTestCase.DemoTest
+ public void testUnexpectedOutputEnd() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+
+ expectTestingException();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] Not_A_DemoTestCase.DemoTest
+ //[ OK ] DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testTestSuiteNameMismatch1() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+
+ expectTestingException();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //[ OK ] Not_A_DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testTestSuiteNameMismatch2() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+
+ expectTestingException();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //[ OK ] DemoTestCase.DemoTest (0 ms)
+ //[----------] 1 test from Not_A_DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testTestSuiteNameMismatch3() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ mockModelUpdater.skipCalls("setTestingTime");
+ mockModelUpdater.skipCalls("setTestStatus");
+ mockModelUpdater.skipCalls("exitTestCase");
+
+ expectTestingException();
+ }
+
+
+ //Running main() from gtest_main.cc
+ //[==========] Running 1 test from 1 test case.
+ //[----------] Global test environment set-up.
+ //[----------] 1 test from DemoTestCase
+ //[ RUN ] DemoTestCase.DemoTest
+ //[ OK ] DemoTestCase.NOT_A_DemoTest (0 ms)
+ //[----------] 1 test from DemoTestCase (0 ms total)
+ //
+ //[----------] Global test environment tear-down
+ //[==========] 1 test from 1 test case ran. (0 ms total)
+ //[ PASSED ] 1 test.
+ public void testTestCaseNameMismatch() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+
+ expectTestingException();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java
new file mode 100644
index 0000000..2182841
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/MockTestModelUpdater.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.testsrunners;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestItem.Status;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestMessage.Level;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+/**
+ * Mock for the {@see ITestModelUpdater}.
+ */
+@SuppressWarnings("nls")
+public class MockTestModelUpdater implements ITestModelUpdater {
+
+ private class FakeTestItem implements ITestItem {
+
+ private String name = null;
+
+ protected void unexpectedMethodCall() {
+ Assert.fail("Unexpected method call");
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void resetName() {
+ name = null;
+ }
+
+ // Unimplemented methods
+ @Override
+ public Status getStatus() { unexpectedMethodCall(); return null; }
+ @Override
+ public int getTestingTime() { unexpectedMethodCall(); return 0; }
+ @Override
+ public ITestSuite getParent() { unexpectedMethodCall(); return null; }
+ @Override
+ public boolean hasChildren() { unexpectedMethodCall(); return false; }
+ @Override
+ public ITestItem[] getChildren() { unexpectedMethodCall(); return null; }
+ @Override
+ public void visit(IModelVisitor visitor) { unexpectedMethodCall(); }
+ }
+
+ private class FakeTestCase extends FakeTestItem implements ITestCase {
+ @Override
+ public ITestMessage[] getTestMessages() { unexpectedMethodCall(); return null; }
+ }
+
+ private class FakeTestSuite extends FakeTestItem implements ITestSuite {
+ }
+
+
+ private class MethodInfo {
+
+ private String methodName;
+ private Object[] args;
+
+ MethodInfo(String methodName, Object[] args) {
+ this.methodName = methodName;
+ this.args = args;
+ }
+
+ private String genArgs(String methodName, Object[] args) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(methodName);
+ sb.append("(");
+ boolean needDelimited = false;
+ for (Object arg : args) {
+ if (needDelimited) {
+ sb.append(", ");
+ } else {
+ needDelimited = true;
+ }
+ if (arg != null) {
+ sb.append('"');
+ sb.append(arg.toString());
+ sb.append('"');
+ } else {
+ sb.append("null");
+ }
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void check(String methodName, Object[] args) {
+ if (!this.methodName.equals(methodName)) {
+ Assert.failNotEquals("Unexpected method call. ",
+ genArgs(this.methodName, this.args), genArgs(methodName, args));
+ }
+ boolean compareFailed = (this.args.length != args.length);
+ if (!compareFailed) {
+ for (int i = 0; i < args.length; i++) {
+ if (this.args[i] == null) {
+ if (args[i] != null) {
+ compareFailed = true;
+ break;
+ }
+ } else if (!this.args[i].equals(args[i])) {
+ compareFailed = true;
+ break;
+ }
+ }
+ }
+ if (compareFailed) {
+ Assert.failNotEquals("Unexpected parameters of method "+this.methodName+"(). ",
+ genArgs(this.methodName, this.args), genArgs(methodName, args));
+ }
+ }
+ }
+
+
+ private LinkedList<MethodInfo> methodCalls = new LinkedList<MethodInfo>();
+ private boolean replayMode = false;
+ private Set<String> skippedMethods = new HashSet<String>();
+
+ // NOTE: Test suites nesting is not supported yet cause there is no need in it
+ private FakeTestSuite currentTestSuite = new FakeTestSuite();
+ private FakeTestCase currentTestCase = new FakeTestCase();
+
+
+ @Override
+ public void enterTestSuite(String name) {
+ genericImpl("enterTestSuite", name);
+ // NOTE: Test suites or cases nesting is not supported for mocking
+ currentTestSuite.setName(name);
+ }
+
+ @Override
+ public void exitTestSuite() {
+ genericImpl("exitTestSuite");
+ currentTestSuite.resetName();
+ }
+
+ @Override
+ public void enterTestCase(String name) {
+ genericImpl("enterTestCase", name);
+ currentTestCase.setName(name);
+ }
+
+
+ @Override
+ public void setTestStatus(Status status) {
+ genericImpl("setTestStatus", status);
+ }
+
+ @Override
+ public void setTestingTime(int testingTime) {
+ genericImpl("setTestingTime", testingTime);
+ }
+
+ @Override
+ public void exitTestCase() {
+ genericImpl("exitTestCase");
+ currentTestCase.resetName();
+ }
+
+ @Override
+ public void addTestMessage(String file, int line, Level level, String text) {
+ genericImpl("addTestMessage", file, line, level, text);
+ }
+
+ @Override
+ public ITestSuite currentTestSuite() {
+ return currentTestSuite;
+ }
+
+ @Override
+ public ITestCase currentTestCase() {
+ return currentTestCase;
+ }
+
+ public void skipCalls(String methodName) {
+ skippedMethods.add(methodName);
+ }
+
+ public void replay() {
+ replayMode = true;
+ }
+
+ private void genericImpl(String methodName, Object... args) {
+ if (!skippedMethods.contains(methodName)) {
+ if (replayMode) {
+ if (methodCalls.isEmpty()) {
+ Assert.fail("Unexpected method call "+methodName+"()");
+ } else {
+ methodCalls.pollFirst().check(methodName, args);
+ }
+ } else {
+ methodCalls.addLast(new MethodInfo(methodName, args));
+ }
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java
new file mode 100644
index 0000000..b5dc9dc
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/src/org/eclipse/cdt/testsrunner/testsrunners/QtTestCase.java
@@ -0,0 +1,693 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.testsrunners;
+
+import java.text.MessageFormat;
+
+import org.eclipse.cdt.testsrunner.internal.qttest.QtTestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+
+
+/**
+ * Test for {@see QtTestsRunner} class
+ */
+@SuppressWarnings("nls")
+public class QtTestCase extends BaseTestCase {
+
+ private static final String DEFAULT_LOCATION_FILE = "";
+ private static final int DEFAULT_LOCATION_LINE = 0;
+
+ @Override
+ protected ITestsRunnerProvider createTestsRunner() {
+ return new QtTestsRunnerProvider();
+ }
+
+
+ private void addStandardBenchmarkMessage(int value, String units, int iterations) {
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Info,
+ MessageFormat.format("{0,number,#.####} {1} per iteration (total: {2}, iterations: {3})",
+ ((float)value)/iterations, units, value, iterations)
+ );
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testNoCustomTestCases() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testTheOnlyPassingCustomTestCase() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Incident type="fail" file="qt_test_demo.cpp" line="6">
+ // <Description><![CDATA[Compared values are not the same
+ // Actual (1): 1
+ // Expected (2): 2]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testTheOnlyFailingCustomTestCase() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 6, ITestMessage.Level.FatalError,
+ "Compared values are not the same\n Actual (1): 1\n Expected (2): 2");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Incident type="fail" file="qtestcase.cpp" line="1675">
+ // <Description><![CDATA[Caught unhandled exception]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //</TestCase>
+ public void testTheOnlyAbortedCustomTestCase() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo");
+ mockModelUpdater.addTestMessage("qtestcase.cpp", 1675, ITestMessage.Level.FatalError,
+ "Caught unhandled exception");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ // NOTE: Qt.Test does not run any other test cases after exception throwing in a test case
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testWarning">
+ //<Message type="warn" file="" line="0">
+ // <Description><![CDATA[Test warning!]]></Description>
+ //</Message>
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testFailure">
+ //<Incident type="fail" file="qt_test_demo.cpp" line="41">
+ // <Description><![CDATA[Test fail!]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="testSkip">
+ //<Message type="skip" file="qt_test_demo.cpp" line="47">
+ // <Description><![CDATA[Test skip!]]></Description>
+ //</Message>
+ //</TestFunction>
+ //<TestFunction name="testExpectedFailWithContinue">
+ //<Incident type="xfail" file="qt_test_demo.cpp" line="60">
+ // <Description><![CDATA[Will fix in the next release]]></Description>
+ //</Incident>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="61">
+ // <Description><![CDATA[Failed!]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="testExpectedFailWithAbort">
+ //<Incident type="xfail" file="qt_test_demo.cpp" line="68">
+ // <Description><![CDATA[Will fix in the next release]]></Description>
+ //</Incident>
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testExpectedFailPassed">
+ //<Incident type="xpass" file="qt_test_demo.cpp" line="70">
+ // <Description><![CDATA[COMPARE()]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="testUnknownIncidentType">
+ //<Incident type="??????" file="qt_test_demo.cpp" line="72">
+ // <Description><![CDATA[Unknown incident test!]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="testUnknownMessageType">
+ //<Message type="??????" file="qt_test_demo.cpp" line="80">
+ // <Description><![CDATA[Unknown message type test!]]></Description>
+ //</Message>
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testDifferentMessageLevels() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testWarning");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "Test warning!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testFailure");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 41, ITestMessage.Level.FatalError, "Test fail!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testSkip");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 47, ITestMessage.Level.Info, "Test skip!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Skipped);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testExpectedFailWithContinue");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 60, ITestMessage.Level.Error, "Will fix in the next release");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 61, ITestMessage.Level.FatalError, "Failed!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testExpectedFailWithAbort");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 68, ITestMessage.Level.Error, "Will fix in the next release");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testExpectedFailPassed");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 70, ITestMessage.Level.Error, "COMPARE()");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testUnknownIncidentType");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 72, ITestMessage.Level.FatalError, "Unknown incident test!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Aborted);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testUnknownMessageType");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 80, ITestMessage.Level.FatalError, "Unknown message type test!");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<BenchmarkResult metric="walltime" tag="" value="28" iterations="8192" />
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBenchmarkBasicSupport() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo");
+ addStandardBenchmarkMessage(28, "msec", 8192);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<BenchmarkResult metric="callgrind" tag="locale aware compare" value="30" iterations="8192" />
+ //<BenchmarkResult metric="callgrind" tag="standard compare" value="24" iterations="10485" />
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBenchmarkWithDataTag() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(locale aware compare)");
+ addStandardBenchmarkMessage(30, "instr.", 8192);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(standard compare)");
+ addStandardBenchmarkMessage(24, "instr.", 10485);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Incident type="fail" file="qt_test_demo.cpp" line="57">
+ // <DataTag><![CDATA[locale aware compare]]></DataTag>
+ // <Description><![CDATA[Failed!]]></Description>
+ //</Incident>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="57">
+ // <DataTag><![CDATA[locale aware compare]]></DataTag>
+ // <Description><![CDATA[Failed!]]></Description>
+ //</Incident>
+ //<BenchmarkResult metric="cputicks" tag="locale aware compare" value="29" iterations="8192" />
+ //<Incident type="fail" file="qt_test_demo.cpp" line="58">
+ // <DataTag><![CDATA[standard compare]]></DataTag>
+ // <Description><![CDATA[Failed!]]></Description>
+ //</Incident>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="58">
+ // <DataTag><![CDATA[standard compare]]></DataTag>
+ // <Description><![CDATA[Failed!]]></Description>
+ //</Incident>
+ //<BenchmarkResult metric="cputicks" tag="standard compare" value="24" iterations="10485" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBenchmarkMixedWithIncidentsWithDataTag() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(locale aware compare)");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 57, ITestMessage.Level.FatalError, "Failed!");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 57, ITestMessage.Level.FatalError, "Failed!");
+ addStandardBenchmarkMessage(29, "ticks", 8192);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(standard compare)");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 58, ITestMessage.Level.FatalError, "Failed!");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 58, ITestMessage.Level.FatalError, "Failed!");
+ addStandardBenchmarkMessage(24, "ticks", 10485);
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Incident type="fail" file="qt_test_demo.cpp" line="20">
+ // <DataTag><![CDATA[all lower]]></DataTag>
+ // <Description><![CDATA[Compared values are not the same
+ // Actual (string.toUpper()): HELLO
+ // Expected (result): HELLO2]]></Description>
+ //</Incident>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="20">
+ // <DataTag><![CDATA[mixed]]></DataTag>
+ // <Description><![CDATA[Compared values are not the same
+ // Actual (string.toUpper()): HELLO
+ // Expected (result): HELLO3]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testIncidentWithDataTag() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(all lower)");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 20, ITestMessage.Level.FatalError,
+ "Compared values are not the same\n Actual (string.toUpper()): HELLO\n Expected (result): HELLO2");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(mixed)");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 20, ITestMessage.Level.FatalError,
+ "Compared values are not the same\n Actual (string.toUpper()): HELLO\n Expected (result): HELLO3");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testDemo">
+ //<Message type="warn" file="" line="0">
+ // <DataTag><![CDATA[all lower]]></DataTag>
+ // <Description><![CDATA[hello]]></Description>
+ //</Message>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="66">
+ // <DataTag><![CDATA[all lower]]></DataTag>
+ // <Description><![CDATA[HELLO2]]></Description>
+ //</Incident>
+ //<Message type="warn" file="" line="0">
+ // <DataTag><![CDATA[mixed]]></DataTag>
+ // <Description><![CDATA[Hello]]></Description>
+ //</Message>
+ //<Incident type="fail" file="qt_test_demo.cpp" line="66">
+ // <DataTag><![CDATA[mixed]]></DataTag>
+ // <Description><![CDATA[HELLO3]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testMessageWithDataTag() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(all lower)");
+ mockModelUpdater.addTestMessage("", 0, ITestMessage.Level.Warning, "hello");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 66, ITestMessage.Level.FatalError, "HELLO2");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testDemo(mixed)");
+ mockModelUpdater.addTestMessage("", 0, ITestMessage.Level.Warning, "Hello");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 66, ITestMessage.Level.FatalError, "HELLO3");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testWithEmptyIncident">
+ //<Incident type="fail" file="qt_test_demo.cpp" line="6">
+ // <Description><![CDATA[]]></Description>
+ //</Incident>
+ //</TestFunction>
+ //<TestFunction name="testWithEmptyMessage">
+ //<Message type="warn" file="" line="0">
+ // <Description><![CDATA[]]></Description>
+ //</Message>
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testWithEmptyMessage() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testWithEmptyIncident");
+ mockModelUpdater.addTestMessage("qt_test_demo.cpp", 6, ITestMessage.Level.FatalError, "");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Failed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testWithEmptyMessage");
+ mockModelUpdater.addTestMessage(DEFAULT_LOCATION_FILE, DEFAULT_LOCATION_LINE, ITestMessage.Level.Warning, "");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //<TestFunction name="testWithoutAnyIncidents">
+ //</TestFunction>
+ //<TestFunction name="cleanupTestCase">
+ //<Incident type="pass" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testWithoutAnyIncidents() {
+ mockModelUpdater.enterTestSuite("MainTS");
+ mockModelUpdater.enterTestCase("initTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("testWithoutAnyIncidents");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.enterTestCase("cleanupTestCase");
+ mockModelUpdater.setTestStatus(ITestItem.Status.Passed);
+ mockModelUpdater.exitTestCase();
+ mockModelUpdater.exitTestSuite();
+ }
+
+
+ //
+ public void testNoInput() {
+ // NOTE: The comment above is left blank intentionally
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2 <!-- QTestVersion is not closed -->
+ //</Environment>
+ //</TestCase>
+ public void testBadFormedXml() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ public void testUnexceptedXmlEnd() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="some_wrong_value" file="" line="0" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBadIncidentTypeValue() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Message type="some_wrong_value" file="" line="0">
+ // <Description><![CDATA[Test warning!]]></Description>
+ //</Message>
+ //</TestFunction>
+ //</TestCase>
+ public void testBadMessageTypeValue() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Incident type="some_wrong_value" file="" line="<wrong_value>" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBadLineNumberValueOfIncident() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="initTestCase">
+ //<Message type="warn" file="" line="<wrong_value>">
+ // <Description><![CDATA[Test warning!]]></Description>
+ //</Message>
+ //</TestFunction>
+ //</TestCase>
+ public void testBadLineNumberValueOfMessage() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+ //<?xml version="1.0" encoding="ISO-8859-1"?>
+ //<TestCase name="MainTS">
+ //<Environment>
+ // <QtVersion>4.6.2</QtVersion>
+ // <QTestVersion>4.6.2</QTestVersion>
+ //</Environment>
+ //<TestFunction name="testDemo">
+ //<BenchmarkResult metric="<wrong_value>" tag="" value="28" iterations="8192" />
+ //</TestFunction>
+ //</TestCase>
+ public void testBadBenchmarkMetricValue() {
+ mockModelUpdater.skipCalls("enterTestSuite");
+ mockModelUpdater.skipCalls("enterTestCase");
+ expectTestingException();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml b/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml
new file mode 100644
index 0000000..eed6389
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner.test/test.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+
+<project name="testsuite" default="run" basedir=".">
+ <!-- The property ${eclipse-home} should be passed into this script -->
+ <!-- Set a meaningful default value for when it is not. -->
+ <property name="eclipse-home" value="${basedir}"/>
+
+ <!-- This is the default name of the org.eclipse.test plugin. -->
+ <!-- We need to be able to override this for the case where the -->
+ <!-- org.eclipse.test plugin was build as part of a feature and -->
+ <!-- will have a name similar to org.eclipse.test_2.1.0 -->
+ <property name="org.eclipse.test" value="org.eclipse.test"/>
+ <!-- sets the properties eclipse-home, and library-file -->
+ <property name="plugin-name" value="org.eclipse.cdt.testsrunner.test"/>
+ <property name="library-file"
+ value="${eclipse-home}/plugins/${org.eclipse.test}/library.xml"/>
+
+ <!-- This target holds all initialization code that needs to be done for -->
+ <!-- all tests that are to be run. Initialization for individual tests -->
+ <!-- should be done within the body of the suite target. -->
+ <target name="init">
+ <tstamp/>
+ <delete>
+ <fileset dir="${eclipse-home}" includes="org*.xml"/>
+ </delete>
+ </target>
+
+ <!-- This target defines the tests that need to be run. -->
+ <target name="suite">
+ <property name="cdt-folder"
+ value="${eclipse-home}/cdt_folder"/>
+ <delete dir="${cdt-folder}" quiet="true"/>
+ <ant target="ui-test" antfile="${library-file}" dir="${eclipse-home}">
+ <property name="data-dir" value="${cdt-folder}"/>
+ <property name="plugin-name" value="${plugin-name}"/>
+ <property name="classname"
+ value="org.eclipse.cdt.testsrunner.test.TestsRunnerSuite"/>
+ </ant>
+ </target>
+
+ <!-- This target holds code to cleanup the testing environment after -->
+ <!-- after all of the tests have been run. You can use this target to -->
+ <!-- delete temporary files that have been created. -->
+ <target name="cleanup">
+ </target>
+
+ <!-- This target runs the test suite. Any actions that need to happen -->
+ <!-- after all the tests have been run should go here. -->
+ <target name="run" depends="init,suite,cleanup">
+ <ant target="collect" antfile="${library-file}" dir="${eclipse-home}">
+ <property name="includes" value="org*.xml"/>
+ <property name="output-file" value="${plugin-name}.xml"/>
+ </ant>
+ </target>
+
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.classpath b/testsrunner/org.eclipse.cdt.testsrunner/.classpath
new file mode 100644
index 0000000..deb6736
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.project b/testsrunner/org.eclipse.cdt.testsrunner/.project
new file mode 100644
index 0000000..e4270dc
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.cdt.testsrunner</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs b/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0e860bf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,82 @@
+#Mon Apr 16 13:01:24 EEST 2012
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
+org.eclipse.jdt.core.compiler.problem.deadCode=warning
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=error
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
+org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF b/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..b7d79fc
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/META-INF/MANIFEST.MF
@@ -0,0 +1,37 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-SymbolicName: org.eclipse.cdt.testsrunner;singleton:=true
+Bundle-Version: 7.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime;bundle-version="3.5.0",
+ org.eclipse.cdt.core;bundle-version="5.1.0",
+ org.eclipse.core.resources;bundle-version="3.5.0",
+ org.eclipse.debug.ui;bundle-version="3.5.0",
+ org.eclipse.cdt.debug.core;bundle-version="6.0.0",
+ org.eclipse.cdt.debug.ui,
+ org.eclipse.cdt.ui,
+ org.eclipse.cdt.dsf.gdb.ui,
+ org.eclipse.cdt.dsf.gdb
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Import-Package: org.eclipse.cdt.dsf.gdb.launching,
+ org.eclipse.cdt.internal.ui.viewsupport,
+ org.eclipse.cdt.launch,
+ org.eclipse.cdt.launch.internal.ui,
+ org.eclipse.cdt.launch.ui,
+ org.eclipse.core.filesystem,
+ org.eclipse.jface.text,
+ org.eclipse.ui.ide,
+ org.eclipse.ui.texteditor
+Export-Package: org.eclipse.cdt.testsrunner.internal,
+ org.eclipse.cdt.testsrunner.internal.launcher,
+ org.eclipse.cdt.testsrunner.internal.model,
+ org.eclipse.cdt.testsrunner.internal.ui.launcher,
+ org.eclipse.cdt.testsrunner.internal.ui.view,
+ org.eclipse.cdt.testsrunner.internal.ui.view.actions,
+ org.eclipse.cdt.testsrunner.launcher,
+ org.eclipse.cdt.testsrunner.model
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/about.html b/testsrunner/org.eclipse.cdt.testsrunner/about.html
new file mode 100644
index 0000000..d7c5118
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/about.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"><head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head>
+
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 22, 2007</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body></html> \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/build.properties b/testsrunner/org.eclipse.cdt.testsrunner/build.properties
new file mode 100644
index 0000000..bc8bffa
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/build.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+
+bin.includes = plugin.xml,\
+ plugin.properties,\
+ icons/,\
+ about.html,\
+ .,\
+ META-INF/
+javadoc.packages = org.eclipse.cdt.launch.ui.*,\
+ org.eclipse.cdt.launch.sourcelookup*,\
+ org.eclipse.cdt.launch.*
+source.. = src/
+src.includes = about.html,\
+ schema/
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif
new file mode 100644
index 0000000..131063c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/history_list.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif
new file mode 100644
index 0000000..1b93aac
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_auto.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_horizontal.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_horizontal.gif
new file mode 100644
index 0000000..ce1a29c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_horizontal.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif
new file mode 100644
index 0000000..5bffca2
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/orientation_vertical.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif
new file mode 100644
index 0000000..bfadfaa
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/rerun.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/scroll_lock.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/scroll_lock.gif
new file mode 100644
index 0000000..b776478
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/scroll_lock.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif
new file mode 100644
index 0000000..388ef91
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_next.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif
new file mode 100644
index 0000000..c00fe05
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/show_previous.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/sort.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/sort.gif
new file mode 100644
index 0000000..a024548
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/sort.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/stop.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/stop.gif
new file mode 100644
index 0000000..4f3dcba
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/dlcl16/stop.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif
new file mode 100644
index 0000000..364c0e7
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/history_list.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif
new file mode 100644
index 0000000..45469ad
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_auto.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif
new file mode 100644
index 0000000..d590470
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_horizontal.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif
new file mode 100644
index 0000000..dee0cbc
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/orientation_vertical.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif
new file mode 100644
index 0000000..afb6fa9
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/rerun.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/scroll_lock.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/scroll_lock.gif
new file mode 100644
index 0000000..68fd6cf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/scroll_lock.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif
new file mode 100644
index 0000000..072b184
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_next.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif
new file mode 100644
index 0000000..0716475
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_previous.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif
new file mode 100644
index 0000000..2344861
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/show_tests_hierarchy.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif
new file mode 100644
index 0000000..7d27529
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/sort.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif
new file mode 100644
index 0000000..dc47edf
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/elcl16/stop.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif
new file mode 100644
index 0000000..883170d
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/eview16/cppunit.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/show_failed_only.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/show_failed_only.gif
new file mode 100644
index 0000000..c182d04
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/show_failed_only.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif
new file mode 100644
index 0000000..f866a2e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_aborted.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif
new file mode 100644
index 0000000..de59bac
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_failed.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_notrun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_notrun.gif
new file mode 100644
index 0000000..8f73ccb
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_notrun.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_passed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_passed.gif
new file mode 100644
index 0000000..f824bd8
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_passed.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif
new file mode 100644
index 0000000..ad88296
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_run.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_skipped.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_skipped.gif
new file mode 100644
index 0000000..e1465e3
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/test_skipped.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif
new file mode 100644
index 0000000..7cd107c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_aborted.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif
new file mode 100644
index 0000000..d247a8f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_failed.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif
new file mode 100644
index 0000000..5198579
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_notrun.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_passed.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_passed.gif
new file mode 100644
index 0000000..e3db1eb
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_passed.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_run.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_run.gif
new file mode 100644
index 0000000..0db16d9
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/obj16/tsuite_run.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif
new file mode 100644
index 0000000..8f12861
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/aborted_counter.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif
new file mode 100644
index 0000000..c112416
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/icons/ovr16/failed_counter.gif
Binary files differ
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties b/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties
new file mode 100644
index 0000000..d968486
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/plugin.properties
@@ -0,0 +1,30 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+pluginName=C/C++ Development Tools Tests Running Support
+providerName=Eclipse CDT
+
+MainLaunchTab.name=Main
+ArgumentsLaunchTab.name=Arguments
+CTestingLaunchTab.name=C/C++ Testing
+EnvironmentLaunchTab.name=Environment
+DebuggerLaunchTab.name=Debugger
+SourceLookupLaunchTab.name=Source
+CommonLaunchTab.name=Common
+RefreshLaunchTab.name=Refresh
+
+ResultsView.name=C/C++ Unit
+
+CPPUnitLaunchConfigurationType.name=C/C++ Unit
+
+CPPUnitLaunch.name=Standard C/C++ Tests Launcher
+CPPUnitLaunch.description=Run C/C++ tests optionally under control of the standard debugger.
+CPPUnitLaunchDSF.name=GDB (DSF) C/C++ Tests Launcher
+CPPUnitLaunchDSF.description=Run C/C++ Tests under control of GDB debugger integrated using the Debugger Services Framework (DSF).
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml b/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml
new file mode 100644
index 0000000..13d2905
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/plugin.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension-point id="TestsRunner" name="Provides additional tests runner" schema="schema/TestsRunner.exsd"/>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ category="org.eclipse.cdt.ui.views"
+ class="org.eclipse.cdt.testsrunner.internal.ui.view.ResultsView"
+ icon="$nl$/icons/eview16/cppunit.gif"
+ id="org.eclipse.cdt.testsrunner.resultsview"
+ name="%ResultsView.name"
+ restorable="true">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.debug.core.launchConfigurationTypes">
+ <launchConfigurationType
+ id="org.eclipse.cdt.testsrunner.launch.CTestsRunner"
+ name="%CPPUnitLaunchConfigurationType.name"
+ public="true">
+ </launchConfigurationType>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+ <launchConfigurationTabGroup
+ class="org.eclipse.cdt.testsrunner.internal.ui.launcher.EmptyConfigurationTabGroup"
+ id="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ type="org.eclipse.cdt.testsrunner.launch.CTestsRunner">
+ <launchMode mode="run"/>
+ </launchConfigurationTabGroup>
+ <launchConfigurationTabGroup
+ class="org.eclipse.cdt.testsrunner.internal.ui.launcher.EmptyConfigurationTabGroup"
+ id="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ type="org.eclipse.cdt.testsrunner.launch.CTestsRunner">
+ <launchMode mode="debug"/>
+ </launchConfigurationTabGroup>
+ </extension>
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+ <launchConfigurationTypeImage
+ configTypeID="org.eclipse.cdt.testsrunner.launch.CTestsRunner"
+ icon="$nl$/icons/eview16/cppunit.gif"
+ id="org.eclipse.cdt.testsrunner.launch.CTestsRunner.image">
+ </launchConfigurationTypeImage>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.launchDelegates">
+ <launchDelegate
+ id="org.eclipse.cdt.testsrunner.launch.runTests"
+ type="org.eclipse.cdt.testsrunner.launch.CTestsRunner"
+ delegate="org.eclipse.cdt.testsrunner.internal.launcher.CdiRunTestsLaunchDelegate"
+ modes="run,debug"
+ name="%CPPUnitLaunch.name"
+ delegateDescription="%CPPUnitLaunch.description"
+ sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
+ sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer">
+ </launchDelegate>
+ <launchDelegate
+ id="org.eclipse.cdt.testsrunner.launch.dsf.runTests"
+ type="org.eclipse.cdt.testsrunner.launch.CTestsRunner"
+ delegate="org.eclipse.cdt.testsrunner.internal.launcher.DsfGdbRunTestsLaunchDelegate"
+ modes="debug"
+ name="%CPPUnitLaunchDSF.name"
+ delegateDescription="%CPPUnitLaunchDSF.description"
+ sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
+ sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer">
+ </launchDelegate>
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.ui.launchConfigurationTabs">
+ <!-- Tests run tabs-->
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.mainTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%MainLaunchTab.name"
+ class="org.eclipse.cdt.launch.ui.CMainTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.argumentsTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%ArgumentsLaunchTab.name"
+ class="org.eclipse.cdt.launch.ui.CArgumentsTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.mainTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.testingTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%CTestingLaunchTab.name"
+ class="org.eclipse.cdt.testsrunner.internal.ui.launcher.CTestingTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.argumentsTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.environmentTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%EnvironmentLaunchTab.name"
+ class="org.eclipse.debug.ui.EnvironmentTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.testsrunner.testingTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.sourceLookupTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%SourceLookupLaunchTab.name"
+ class="org.eclipse.debug.ui.sourcelookup.SourceLookupTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.environmentTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.launch.commonTab"
+ group="org.eclipse.cdt.testsrunner.launch.runTestsTabGroup"
+ name="%CommonLaunchTab.name"
+ class="org.eclipse.debug.ui.CommonTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.debug.ui.sourceLookupTab"/>
+ </tab>
+
+ <!-- Tests debug (CDI) tabs-->
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.mainTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%MainLaunchTab.name"
+ class="org.eclipse.cdt.launch.ui.CMainTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.argumentsTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%ArgumentsLaunchTab.name"
+ class="org.eclipse.cdt.launch.ui.CArgumentsTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.mainTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.testingTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%CTestingLaunchTab.name"
+ class="org.eclipse.cdt.testsrunner.internal.ui.launcher.CTestingTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.argumentsTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.environmentTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%EnvironmentLaunchTab.name"
+ class="org.eclipse.debug.ui.EnvironmentTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.testsrunner.testingTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.debuggerTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%DebuggerLaunchTab.name"
+ class="org.eclipse.cdt.launch.ui.ApplicationCDebuggerTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.debug.ui.environmentTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.sourceLookupTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%SourceLookupLaunchTab.name"
+ class="org.eclipse.debug.ui.sourcelookup.SourceLookupTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.cdt.cdi.launch.debuggerTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.refreshTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%RefreshLaunchTab.name"
+ class="org.eclipse.debug.ui.RefreshTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests" />
+ <placement after="org.eclipse.debug.ui.sourceLookupTab" />
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.debug.commonTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%CommonLaunchTab.name"
+ class="org.eclipse.debug.ui.CommonTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.runTests"/>
+ <placement after="org.eclipse.debug.ui.refreshTab"/>
+ </tab>
+
+ <!-- Tests debug (DSF) tabs-->
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.mainTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%MainLaunchTab.name"
+ class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CMainTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.argumentsTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%ArgumentsLaunchTab.name"
+ class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CArgumentsTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.cdt.dsf.gdb.launch.mainTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.testingTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%CTestingLaunchTab.name"
+ class="org.eclipse.cdt.testsrunner.internal.ui.launcher.CTestingTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.cdt.dsf.gdb.launch.argumentsTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.environmentTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%EnvironmentLaunchTab.name"
+ class="org.eclipse.debug.ui.EnvironmentTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.cdt.testsrunner.testingTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.debuggerTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%DebuggerLaunchTab.name"
+ class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LocalApplicationCDebuggerTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.debug.ui.environmentTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.sourceLookupTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%SourceLookupLaunchTab.name"
+ class="org.eclipse.debug.ui.sourcelookup.SourceLookupTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.cdt.dsf.gdb.launch.debuggerTab"/>
+ </tab>
+ <tab
+ id="org.eclipse.cdt.testsrunner.dsf.gdb.commonTab"
+ group="org.eclipse.cdt.testsrunner.launch.debugTestsLaunchTabGroup"
+ name="%CommonLaunchTab.name"
+ class="org.eclipse.debug.ui.CommonTab">
+ <associatedDelegate delegate="org.eclipse.cdt.testsrunner.launch.dsf.runTests"/>
+ <placement after="org.eclipse.debug.ui.sourceLookupTab"/>
+ </tab>
+
+ </extension>
+
+ <extension
+ point="org.eclipse.debug.core.processFactories">
+ <processFactory
+ class="org.eclipse.cdt.testsrunner.internal.launcher.TestingProcessFactory"
+ id="org.eclipse.cdt.testsrunner.TestingProcessFactory">
+ </processFactory>
+ </extension>
+
+</plugin>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/pom.xml b/testsrunner/org.eclipse.cdt.testsrunner/pom.xml
new file mode 100644
index 0000000..f3961df
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.eclipse.cdt</groupId>
+ <artifactId>cdt-parent</artifactId>
+ <version>8.1.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <version>7.0.0-SNAPSHOT</version>
+ <artifactId>org.eclipse.cdt.testsrunner</artifactId>
+ <packaging>eclipse-plugin</packaging>
+</project>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd b/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd
new file mode 100644
index 0000000..ca160a1
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/schema/TestsRunner.exsd
@@ -0,0 +1,178 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.cdt.testsrunner" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.cdt.testsrunner" id="TestsRunnerProvider" name="Tests Runner Provider"/>
+ </appInfo>
+ <documentation>
+ Defines an extestion point for the Tests Runner provider plug-in.
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appInfo>
+ <meta.element />
+ </appInfo>
+ </annotation>
+ <complexType>
+ <sequence minOccurs="1" maxOccurs="unbounded">
+ <element ref="runner"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="runner">
+ <complexType>
+ <sequence minOccurs="0" maxOccurs="1">
+ <element ref="features"/>
+ </sequence>
+ <attribute name="name" type="string" use="required">
+ <annotation>
+ <documentation>
+ Name of the tests runner that will be shown to user.
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="required">
+ <annotation>
+ <documentation>
+ Class implementing test runner functionality (org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider)
+ </documentation>
+ <appInfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.cdt.testsrunner.launcher.ITestsRunner"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="description" type="string">
+ <annotation>
+ <documentation>
+ Short description of the tests runner that will be shown to user
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ Internal unique name of the tests runner
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="features">
+ <complexType>
+ <attribute name="multipleTestFilter" type="boolean">
+ <annotation>
+ <documentation>
+ Should be True if Tests Runner can generate a multiple tests filter for single test module launch. In this case rerun of multiple tests or test suites will be available and a few test items may be passed to configureLaunchParameters(). It is False by default.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="testingTimeMeasurement" type="boolean">
+ <annotation>
+ <documentation>
+ Defines whether tests execution time are provided by testing framework. Otherwise turns on time measurement in Tests Runner Core. It is less accurate, but useful if testing framework does not provide time measurement.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="dataStream">
+ <annotation>
+ <documentation>
+ Defines what stream (output or error) should be used to read the data from the testing process. Output is used by default.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="error">
+ </enumeration>
+ <enumeration value="output">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ [Enter the first release in which this extension point appears.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ [Enter extension point usage example here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="apiinfo"/>
+ </appInfo>
+ <documentation>
+ [Enter API information here.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ [Enter information about supplied implementation of this extension point.]
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2011 Anton Gorenkov.
+All rights reserved. This program and the accompanying materials
+are made available under the terms of the Eclipse Public License v1.0
+which accompanies this distribution, and is available at
+http://www.eclipse.org/legal/epl-v10.html
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java
new file mode 100644
index 0000000..0e5ee47
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/TestsRunnerPlugin.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal;
+
+import java.net.URL;
+import java.util.HashSet;
+
+import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProvidersManager;
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerConstants;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchDelegate;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class TestsRunnerPlugin extends AbstractUIPlugin {
+
+ /** The plug-in ID. */
+ private static final String PLUGIN_ID = "org.eclipse.cdt.testsrunner"; //$NON-NLS-1$
+
+ /** The path to the plugin icons */
+ private static final IPath ICONS_PATH = new Path("$nl$/icons"); //$NON-NLS-1$
+
+ /** Plug-in instance. */
+ private static TestsRunnerPlugin plugin;
+
+ private TestsRunnerProvidersManager testsRunnerProvidersManager = new TestsRunnerProvidersManager();
+ private TestingSessionsManager testingSessionsManager = new TestingSessionsManager(testsRunnerProvidersManager);
+
+
+ public TestsRunnerPlugin() {
+ super();
+ plugin = this;
+ }
+
+ /**
+ * Returns the Tests Runner Plug-in instance
+ *
+ * @return the plug-in instance
+ */
+ public static TestsRunnerPlugin getDefault() {
+ return plugin;
+ }
+
+ /** Convenience method which returns the unique identifier of this plug-in. */
+ public static String getUniqueIdentifier() {
+ return PLUGIN_ID;
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+
+ /**
+ * Logs an internal error with the specified message.
+ *
+ * @param message the error message to log
+ */
+ public static void logErrorMessage(String message) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
+ }
+
+ /**
+ * Logs an internal error with the specified throwable
+ *
+ * @param e the exception to be logged
+ */
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
+ }
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+ setDefaultLaunchDelegates();
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ }
+
+ /**
+ * Access the plugin's Testing Sessions Manager instance.
+ *
+ * @return sessions manager
+ */
+ public TestingSessionsManager getTestingSessionsManager() {
+ return testingSessionsManager;
+ }
+
+ /**
+ * Access the plugin's Test Runners manager instance.
+ *
+ * @return tests runners manager
+ */
+ public TestsRunnerProvidersManager getTestsRunnerProvidersManager() {
+ return testsRunnerProvidersManager;
+ }
+
+ /**
+ * Returns the descriptor for image with <code>relativePath</code> path.
+ *
+ * @param relativePath path relative to <code>ICONS_PATH</code>
+ * @return image descriptor
+ */
+ static public ImageDescriptor getImageDescriptor(String relativePath) {
+ return getDefault().getImageDescriptorImpl(relativePath);
+ }
+
+ /**
+ * Returns the descriptor for image with <code>relativePath</code> path.
+ *
+ * @param relativePath path relative to <code>ICONS_PATH</code>
+ * @return image descriptor
+ */
+ private ImageDescriptor getImageDescriptorImpl(String relativePath) {
+ IPath path = ICONS_PATH.append(relativePath);
+ return createImageDescriptor(getDefault().getBundle(), path, true);
+ }
+
+ /**
+ * Returns the image with the specified path.
+ *
+ * @param path path
+ * @return image image
+ */
+ public static Image createAutoImage(String path) {
+ return getDefault().createAutoImageImpl(path);
+ }
+
+ /**
+ * Returns the image with the specified path.
+ *
+ * @param path path
+ * @return image image
+ */
+ private Image createAutoImageImpl(String path) {
+ Image image = getImageRegistry().get(path);
+ if (image == null) {
+ image = getImageDescriptor(path).createImage();
+ getImageRegistry().put(path, image);
+ }
+ return image;
+ }
+
+ /**
+ * Creates an image descriptor for the given path in a bundle. The path can
+ * contain variables like $NL$. If no image could be found,
+ * <code>useMissingImageDescriptor</code> decides if either the 'missing
+ * image descriptor' is returned or <code>null</code>.
+ *
+ * @param bundle a bundle
+ * @param path path in the bundle
+ * @param useMissingImageDescriptor if <code>true</code>, returns the shared
+ * image descriptor for a missing image. Otherwise, returns
+ * <code>null</code> if the image could not be found
+ * @return an {@link ImageDescriptor}, or <code>null</code> iff there's no
+ * image at the given location and <code>useMissingImageDescriptor</code> is
+ * <code>true</code>
+ */
+ private ImageDescriptor createImageDescriptor(Bundle bundle, IPath path, boolean useMissingImageDescriptor) {
+ URL url = FileLocator.find(bundle, path, null);
+ if (url != null) {
+ return ImageDescriptor.createFromURL(url);
+ }
+ if (useMissingImageDescriptor) {
+ return ImageDescriptor.getMissingImageDescriptor();
+ }
+ return null;
+ }
+
+ /**
+ * Setup the launch delegate with id <code>delegateId</code> as default for
+ * launch configuration type <code>cfgType</code> for <code>mode</code>
+ * launch mode.
+ *
+ * @param cfgType launch configuration type
+ * @param delegateId unique identifier of the launch delegate
+ * @param mode launch mode
+ */
+ private void setDefaultLaunchDelegate(ILaunchConfigurationType cfgType, String delegateId, String mode) {
+ HashSet<String> modes = new HashSet<String>();
+ modes.add(mode);
+ try {
+ if (cfgType.getPreferredDelegate(modes) == null) {
+ ILaunchDelegate[] delegates = cfgType.getDelegates(modes);
+ for (ILaunchDelegate delegate : delegates) {
+ if (delegateId.equals(delegate.getId())) {
+ cfgType.setPreferredDelegate(modes, delegate);
+ break;
+ }
+ }
+ }
+ } catch (CoreException e) {
+ log(e);
+ }
+ }
+
+ /**
+ * Sets up the default launch delegates for the Tests Runner's launch configuration type.
+ */
+ private void setDefaultLaunchDelegates() {
+ ILaunchManager launchMgr = DebugPlugin.getDefault().getLaunchManager();
+ ILaunchConfigurationType configurationType = launchMgr.getLaunchConfigurationType(ITestsRunnerConstants.LAUNCH_CONFIGURATION_TYPE_ID);
+
+ setDefaultLaunchDelegate(configurationType, ITestsRunnerConstants.PREFERRED_DEBUG_TESTS_LAUNCH_DELEGATE, ILaunchManager.DEBUG_MODE);
+ setDefaultLaunchDelegate(configurationType, ITestsRunnerConstants.PREFERRED_RUN_TESTS_LAUNCH_DELEGATE, ILaunchManager.RUN_MODE);
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java
new file mode 100644
index 0000000..c0bef98
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/CdiRunTestsLaunchDelegate.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import org.eclipse.cdt.testsrunner.launcher.BaseTestsLaunchDelegate;
+
+
+/**
+ * Launch delegate implementation that redirects its queries to CDI.
+ */
+public class CdiRunTestsLaunchDelegate extends BaseTestsLaunchDelegate {
+
+ @Override
+ public String getPreferredDelegateId() {
+ return "org.eclipse.cdt.cdi.launch.localCLaunch"; //$NON-NLS-1$
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java
new file mode 100644
index 0000000..7f68f38
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/DsfGdbRunTestsLaunchDelegate.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import org.eclipse.cdt.testsrunner.launcher.BaseTestsLaunchDelegate;
+
+
+/**
+ * Launch delegate implementation that redirects its queries to DSF.
+ */
+public class DsfGdbRunTestsLaunchDelegate extends BaseTestsLaunchDelegate {
+
+ @Override
+ public String getPreferredDelegateId() {
+ return "org.eclipse.cdt.dsf.gdb.launch.localCLaunch"; //$NON-NLS-1$
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java
new file mode 100644
index 0000000..fa08017
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ITestsLaunchConfigurationConstants.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+/**
+ * Constants used for attributes in CDT Unit Testing Support launch
+ * configurations.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ITestsLaunchConfigurationConstants {
+
+ public static final String CDT_TESTS_LAUNCH_ID = "org.eclipse.cdt.testsrunner.launch"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. The value is a string specifying
+ * tests runner string unique identifier
+ */
+ public static final String ATTR_TESTS_RUNNER = CDT_TESTS_LAUNCH_ID + ".TESTS_RUNNER"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. The value is a string list specifying
+ * tests paths to run
+ */
+ public static final String ATTR_TESTS_FILTER = CDT_TESTS_LAUNCH_ID + ".TESTS_FILTER"; //$NON-NLS-1$
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java
new file mode 100644
index 0000000..2b66e11
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import org.eclipse.osgi.util.NLS;
+
+public class LauncherMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.launcher.LauncherMessages"; //$NON-NLS-1$
+ public static String BaseTestsLaunchDelegate_invalid_tests_runner;
+ public static String BaseTestsLaunchDelegate_tests_runner_load_failed;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, LauncherMessages.class);
+ }
+
+ private LauncherMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties
new file mode 100644
index 0000000..2208efc
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/LauncherMessages.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+BaseTestsLaunchDelegate_invalid_tests_runner=Tests Runner is not specified or invalid
+BaseTestsLaunchDelegate_tests_runner_load_failed=Tests Runner cannot be instantiated
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java
new file mode 100644
index 0000000..5a99ec4
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/ProcessWrapper.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Wraps the underline process and prevent accessing to its output or error stream.
+ * This wrapping is necessary to prevent handling the test module output by Console
+ * because we want to handle it here.
+ *
+ */
+class ProcessWrapper extends Process {
+
+ /** The real underlying process. */
+ private Process wrappedProcess;
+
+ /** The flag shows whether input stream should be replaced with empty dummy. */
+ private boolean hideInputStream;
+
+ /** The flag shows whether error stream should be replaced with empty dummy. */
+ private boolean hideErrorStream;
+
+
+ /** Buffer for empty dummy stream. */
+ private byte buffer[] = new byte[0];
+
+ /** Empty dummy stream. */
+ private InputStream emptyInputStream = new ByteArrayInputStream(buffer);
+
+ /**
+ * The synchronization event: before it happens <code>waitFor()</code> will
+ * not be called on underlying process object. See also the comments in
+ * <code>waitFor()</code>.
+ */
+ private Object waitForSync = new Object();
+
+ /**
+ * Flag that shows that process output was not processed yet so the IO
+ * streams could not be closed yet.
+ */
+ private boolean streamsClosingIsAllowed = false;
+
+
+ /**
+ * The constructor
+ *
+ * @param wrappedProcess underlying process
+ * @param hideInputStream process input stream should be hidden
+ * @param hideErrorStream process error stream should be hidden
+ */
+ public ProcessWrapper(Process wrappedProcess, boolean hideInputStream, boolean hideErrorStream) {
+ this.wrappedProcess = wrappedProcess;
+ this.hideInputStream = hideInputStream;
+ this.hideErrorStream = hideErrorStream;
+ }
+
+ @Override
+ public void destroy() {
+ wrappedProcess.destroy();
+ }
+
+ @Override
+ public int exitValue() {
+ return wrappedProcess.exitValue();
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return hideErrorStream ? emptyInputStream : wrappedProcess.getErrorStream();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return hideInputStream ? emptyInputStream : wrappedProcess.getInputStream();
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return wrappedProcess.getOutputStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ // NOTE: implementation of waitFor() in Spawner will close streams after process is terminated,
+ // so we should wait with this operation until we process all stream data
+ synchronized (waitForSync) {
+ if (!streamsClosingIsAllowed) {
+ waitForSync.wait();
+ }
+ }
+ return wrappedProcess.waitFor();
+ }
+
+ /**
+ * Sets up the flag the allows IO streams closing.
+ */
+ public void allowStreamsClosing() {
+ synchronized (waitForSync) {
+ streamsClosingIsAllowed = true;
+ waitForSync.notifyAll();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java
new file mode 100644
index 0000000..ce498d5
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestingProcessFactory.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import java.io.InputStream;
+import java.util.Map;
+
+import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
+import org.eclipse.cdt.dsf.gdb.launching.GDBProcess;
+import org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess;
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.model.TestingSession;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.IProcessFactory;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.RuntimeProcess;
+
+/**
+ * Custom testing process factory allows to handle the output stream of the
+ * testing process and prevent it from output to Console.
+ */
+public class TestingProcessFactory implements IProcessFactory {
+
+ /**
+ * Runs data processing for the testing process and close IO stream when it
+ * is done.
+ */
+ private class TestingSessionRunner implements Runnable {
+
+ private TestingSession testingSession;
+ private InputStream iStream;
+ private ProcessWrapper processWrapper;
+
+ TestingSessionRunner(TestingSession testingSession, InputStream iStream, ProcessWrapper processWrapper) {
+ this.testingSession = testingSession;
+ this.iStream = iStream;
+ this.processWrapper = processWrapper;
+ }
+
+ @Override
+ public void run() {
+ try {
+ testingSession.run(iStream);
+ }
+ finally {
+ // Streams should be closed anyway to avoid testing process hang up
+ processWrapper.allowStreamsClosing();
+ }
+ }
+ }
+
+ /**
+ * Creates a wrapper for the specified process to handle its input or error
+ * stream.
+ *
+ * @param launch launch
+ * @param process process to wrap
+ * @return wrapped process
+ * @throws CoreException
+ */
+ private Process wrapProcess(ILaunch launch, Process process) throws CoreException {
+ TestingSession testingSession = TestsRunnerPlugin.getDefault().getTestingSessionsManager().newSession(launch);
+ ITestsRunnerProviderInfo testsRunnerProvider = testingSession.getTestsRunnerProviderInfo();
+ InputStream iStream =
+ testsRunnerProvider.isOutputStreamRequired() ? process.getInputStream() :
+ testsRunnerProvider.isErrorStreamRequired() ? process.getErrorStream() : null;
+ ProcessWrapper processWrapper = new ProcessWrapper(process, testsRunnerProvider.isOutputStreamRequired(), testsRunnerProvider.isErrorStreamRequired());
+ Thread t = new Thread(new TestingSessionRunner(testingSession, iStream, processWrapper));
+ t.start();
+ return processWrapper;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public IProcess newProcess(ILaunch launch, Process process, String label, Map attributes) {
+
+ try {
+ // Mimic the behavior of DSF GDBProcessFactory.
+ if (attributes != null) {
+ Object processTypeCreationAttrValue = attributes.get(IGdbDebugConstants.PROCESS_TYPE_CREATION_ATTR);
+ if (IGdbDebugConstants.GDB_PROCESS_CREATION_VALUE.equals(processTypeCreationAttrValue)) {
+ return new GDBProcess(launch, process, label, attributes);
+ }
+
+ if (IGdbDebugConstants.INFERIOR_PROCESS_CREATION_VALUE.equals(processTypeCreationAttrValue)) {
+ return new InferiorRuntimeProcess(launch, wrapProcess(launch, process), label, attributes);
+ }
+
+ // Probably, it is CDI creating a new inferior process
+ } else {
+ return new RuntimeProcess(launch, wrapProcess(launch, process), label, attributes);
+ }
+
+ } catch (CoreException e) {
+ TestsRunnerPlugin.log(e);
+ }
+
+ return null;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java
new file mode 100644
index 0000000..5f5927b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProviderInfo.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+
+/**
+ * Provides access to the information about the Tests Runner provider plug-in
+ * (id, name, description, supported features set). Also provides the access to
+ * <code>ITestsRunnerProvider</code> interface (the main interface of Tests Runner
+ * provider plug-in).
+ */
+public class TestsRunnerProviderInfo implements ITestsRunnerProviderInfo {
+
+ private static final String TESTS_RUNNER_FEATURES_ELEMENT = "features"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_FEATURE_MULTIPLE_TEST_FILTER_ATTRIBUTE = "multipleTestFilter"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_FEATURE_TESTING_TIME_MEASUREMENT_ATTRIBUTE = "testingTimeMeasurement"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_FEATURE_DATA_STREAM_ATTRIBUTE = "dataStream"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_ID_ATTRIBUTE = "id"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
+ private static final String TESTS_RUNNER_ERROR_STREAM_VALUE = "error"; //$NON-NLS-1$
+
+ /** Configuration element of the Tests Runner provider plug-ins extension point. */
+ private IConfigurationElement element;
+
+ /**
+ * The constructor.
+ *
+ * @param element configuration element of the Tests Runner provider plug-ins extension point
+ */
+ public TestsRunnerProviderInfo(IConfigurationElement element) {
+ this.element = element;
+ }
+
+ @Override
+ public String getName() {
+ return element.getAttribute(TESTS_RUNNER_NAME_ATTRIBUTE);
+ }
+
+ @Override
+ public String getId() {
+ return element.getAttribute(TESTS_RUNNER_ID_ATTRIBUTE);
+ }
+
+ @Override
+ public String getDescription() {
+ String result = element.getAttribute(TESTS_RUNNER_DESCRIPTION_ATTRIBUTE);
+ return result == null ? "" : result; //$NON-NLS-1$
+ }
+
+ /**
+ * Instantiates Tests Runner provider plug-in and return its main interface.
+ *
+ * @note Instantiated Tests Runner provider plug-in objects are not cached
+ * and are instantiated as much times as
+ * <code>instantiateTestsRunnerProvider()</code> is called.
+ *
+ * @return Tests Runner provider plug-in main interface
+ */
+ public ITestsRunnerProvider instantiateTestsRunnerProvider() {
+ try {
+ Object object = element.createExecutableExtension(TESTS_RUNNER_CLASS_ATTRIBUTE);
+ if (object instanceof ITestsRunnerProvider) {
+ return (ITestsRunnerProvider)object;
+ }
+ } catch (CoreException e) {
+ TestsRunnerPlugin.log(e);
+ }
+ return null;
+ }
+
+ /**
+ * Provides an access to the 'features' node of Tests Runner provider
+ * plug-in configuration element.
+ *
+ * @return 'features' configuration element
+ */
+ private IConfigurationElement getFeatures() {
+ IConfigurationElement[] featuresElements = element.getChildren(TESTS_RUNNER_FEATURES_ELEMENT);
+ if (featuresElements.length == 1) {
+ return featuresElements[0];
+ }
+ return null;
+ }
+
+ /**
+ * Provides an access to the value of the feature with specified name.
+ *
+ * @param featureName
+ * @return feature value or null if there is no features described or there
+ * is no feature with such name
+ */
+ private String getFeatureAttributeValue(String featureName) {
+ IConfigurationElement features = getFeatures();
+ if (features != null) {
+ return features.getAttribute(featureName);
+ }
+ return null;
+ }
+
+ /**
+ * Provides an access to the boolean value of the feature with the specified
+ * name. If the feature with such name cannot be accessed or it contains
+ * invalid boolean value, the default value will be returned.
+ *
+ * @param featureName
+ * @param defaultValue
+ * @return feature value or null if there is no features described or there
+ * is no feature with such name
+ */
+ private boolean getBooleanFeatureValue(String featureName, boolean defaultValue) {
+ String attrValue = getFeatureAttributeValue(featureName);
+ if (attrValue != null) {
+ return Boolean.parseBoolean(attrValue);
+ }
+ return defaultValue;
+ }
+
+ @Override
+ public boolean isAllowedMultipleTestFilter() {
+ return getBooleanFeatureValue(TESTS_RUNNER_FEATURE_MULTIPLE_TEST_FILTER_ATTRIBUTE, false);
+ }
+
+ /**
+ * Returns whether test execution time measurement should be performed by
+ * the Tests Runner Plug-in.
+ *
+ * @note It should be used only if testing framework does not provide
+ * execution time measurement, cause measurement by Tests Runner Plug-in is
+ * not very precise (it also takes into account output processing & internal
+ * model building time).
+ *
+ * @return whether testing time measurement should be done by Tests Runner
+ * Plug-in
+ */
+ public boolean isAllowedTestingTimeMeasurement() {
+ return getBooleanFeatureValue(TESTS_RUNNER_FEATURE_TESTING_TIME_MEASUREMENT_ATTRIBUTE, false);
+ }
+
+ @Override
+ public boolean isOutputStreamRequired() {
+ return !isErrorStreamRequired();
+ }
+
+ @Override
+ public boolean isErrorStreamRequired() {
+ String attrValue = getFeatureAttributeValue(TESTS_RUNNER_FEATURE_DATA_STREAM_ATTRIBUTE);
+ if (attrValue != null) {
+ return attrValue.equals(TESTS_RUNNER_ERROR_STREAM_VALUE);
+ }
+ return false;
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java
new file mode 100644
index 0000000..39f216a
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/launcher/TestsRunnerProvidersManager.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.launcher;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+/**
+ * Collects the data from the Tests Runner provider plug-in extension points and
+ * provides the convenient access to it.
+ */
+public class TestsRunnerProvidersManager {
+
+ /** Tests Runner Plug-ins extension point ID. */
+ private static final String TESTS_RUNNER_EXTENSION_POINT_ID = "org.eclipse.cdt.testsrunner.TestsRunner"; //$NON-NLS-1$
+
+ /** Tests Runner Plug-ins information collection. */
+ private TestsRunnerProviderInfo[] testsRunnerProviders = null;
+
+
+ /**
+ * Provides access to information about all registered Tests Runner
+ * Plug-ins.
+ *
+ * @return array of tests runner plug-ins descriptors
+ */
+ public TestsRunnerProviderInfo[] getTestsRunnersProviderInfo() {
+ if (testsRunnerProviders == null) {
+ // Initialize tests runners info
+ List<TestsRunnerProviderInfo> testsRunnerProvidersList = new ArrayList<TestsRunnerProviderInfo>();
+ for (IConfigurationElement element : Platform.getExtensionRegistry().getConfigurationElementsFor(TESTS_RUNNER_EXTENSION_POINT_ID)) {
+ testsRunnerProvidersList.add(new TestsRunnerProviderInfo(element));
+ }
+ testsRunnerProviders = testsRunnerProvidersList.toArray(new TestsRunnerProviderInfo[testsRunnerProvidersList.size()]);
+ }
+ return testsRunnerProviders;
+ }
+
+ /**
+ * Provides access to information about Tests Runner Plug-in referred in the
+ * specified launch configuration.
+ *
+ * @return tests runner plug-in descriptor
+ */
+ public TestsRunnerProviderInfo getTestsRunnerProviderInfo(ILaunchConfiguration launchConf) throws CoreException {
+ String testsRunnerId = launchConf.getAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String)null);
+ return getTestsRunnerProviderInfo(testsRunnerId);
+ }
+
+ /**
+ * Provides access to information about Tests Runner Plug-in with the
+ * specified ID.
+ *
+ * @return tests runner plug-in descriptor
+ */
+ private TestsRunnerProviderInfo getTestsRunnerProviderInfo(String testsRunnerProviderId) {
+ if (testsRunnerProviderId != null) {
+ for (TestsRunnerProviderInfo testsRunnerProvider : getTestsRunnersProviderInfo()) {
+ if (testsRunnerProvider.getId().equals(testsRunnerProviderId)) {
+ return testsRunnerProvider;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java
new file mode 100644
index 0000000..578ed7b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ITestingSessionsManagerListener.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+
+/**
+ * Testing sessions manager listener is notified of testing sessions management.
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ITestingSessionsManagerListener {
+
+ /**
+ * Notifies the listener that the specified testing session was activated.
+ *
+ * @param testingSession the activated testing session
+ */
+ void sessionActivated(ITestingSession testingSession);
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java
new file mode 100644
index 0000000..b690f1c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ModelMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.model.ModelMessages"; //$NON-NLS-1$
+ public static String TestingSession_finished_status;
+ public static String TestingSession_name_format;
+ public static String TestingSession_starting_status;
+ public static String TestingSession_stopped_status;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, ModelMessages.class);
+ }
+
+ private ModelMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties
new file mode 100644
index 0000000..c57df6a
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/ModelMessages.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+TestingSession_name_format={0} ({1})
+TestingSession_finished_status=Finished after {0} seconds
+TestingSession_starting_status=Starting...
+TestingSession_stopped_status=Testing was stopped by user
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java
new file mode 100644
index 0000000..84e9db5
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestCase.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+
+/**
+ * Represents the test case (test) of the test hierarchy.
+ */
+public class TestCase extends TestItem implements ITestCase {
+
+ /** Test case status (failed, passed, ...). */
+ private Status status;
+
+ /** Test case execution time. */
+ private int testingTime;
+
+ /**
+ * The messages that were generated by testing framework during test
+ * running.
+ */
+ private List<TestMessage> testMessages = new ArrayList<TestMessage>();
+
+
+ public TestCase(String name, TestSuite parent) {
+ super(name, parent);
+ reset();
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public int getTestingTime() {
+ return testingTime;
+ }
+
+ @Override
+ public TestMessage[] getTestMessages() {
+ return testMessages.toArray(new TestMessage[testMessages.size()]);
+ }
+
+ @Override
+ public void visit(IModelVisitor visitor) {
+ visitor.visit(this);
+ for (TestMessage message : testMessages) {
+ message.visit(visitor);
+ }
+ visitor.leave(this);
+ }
+
+ /**
+ * Resets the test case to the default state.
+ */
+ public void reset() {
+ status = Status.Skipped;
+ testingTime = 0;
+ testMessages.clear();
+ }
+
+ /**
+ * Modifies the status of the test case.
+ *
+ * @param status new test status
+ */
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ /**
+ * Modifies the execution time of the test case.
+ *
+ * @param testingTime new test execution time
+ */
+ public void setTestingTime(int testingTime) {
+ this.testingTime = testingTime;
+ }
+
+ /**
+ * Adds a new test message to the test case.
+ *
+ * @param testMessage message
+ */
+ public void addTestMessage(TestMessage testMessage) {
+ testMessages.add(testMessage);
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java
new file mode 100644
index 0000000..55c775f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestItem.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+
+/**
+ * Common implementation for the structural item of test hierarchy (test suite
+ * or test case).
+ */
+public abstract class TestItem implements ITestItem {
+
+ /** Test item has no children by default. */
+ private static final ITestItem[] NO_CHILDREN = new ITestItem[0];
+
+ /** Test item name. */
+ private final String name;
+
+ /** Item parent test suite. May be <code>null</code> for root test suite. */
+ private TestSuite parent;
+
+
+ public TestItem(String name, TestSuite parent) {
+ this.name = name;
+ this.parent = parent;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public TestSuite getParent() {
+ return parent;
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return false;
+ }
+
+ @Override
+ public ITestItem[] getChildren() {
+ return NO_CHILDREN;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java
new file mode 100644
index 0000000..afe8bfa
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestLocation.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import org.eclipse.cdt.testsrunner.model.ITestLocation;
+
+/**
+ * Represents the location of the test object.
+ */
+public class TestLocation implements ITestLocation {
+
+ /** Stores the file name in which testing object is located. */
+ private String file;
+
+ /** Stores the line number on which testing object is located. */
+ private int line;
+
+
+ public TestLocation(String file, int line) {
+ this.file = file;
+ this.line = line;
+ }
+
+ @Override
+ public String getFile() {
+ return file;
+ }
+
+ @Override
+ public int getLine() {
+ return line;
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java
new file mode 100644
index 0000000..4a5402f
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestMessage.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+
+/**
+ * Represents the message that was produced during the testing process.
+ */
+public class TestMessage implements ITestMessage {
+
+ /** Test message location. */
+ private TestLocation location;
+
+ /** Test message level */
+ private Level level;
+
+ /** Test message text */
+ private String text;
+
+
+ public TestMessage(TestLocation location, Level level, String text) {
+ this.location = location;
+ this.level = level;
+ this.text = text;
+ }
+
+ @Override
+ public TestLocation getLocation() {
+ return location;
+ }
+
+ @Override
+ public Level getLevel() {
+ return level;
+ }
+
+ @Override
+ public String getText() {
+ return text;
+ }
+
+ @Override
+ public void visit(IModelVisitor visitor) {
+ visitor.visit(this);
+ visitor.leave(this);
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java
new file mode 100644
index 0000000..0db8d5a
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestModelManager.java
@@ -0,0 +1,480 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestModelAccessor;
+import org.eclipse.cdt.testsrunner.model.ITestModelUpdater;
+import org.eclipse.cdt.testsrunner.model.ITestingSessionListener;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestItem.Status;
+import org.eclipse.cdt.testsrunner.model.ITestMessage.Level;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+/**
+ * Manages the testing model (creates, fill and update it) and notifies the
+ * listeners about updates.
+ */
+public class TestModelManager implements ITestModelUpdater, ITestModelAccessor {
+
+ /**
+ * Name of the root test suite.
+ *
+ * @note Root test suite is invisible (only its children are visible), so
+ * the name is not important.
+ */
+ public static final String ROOT_TEST_SUITE_NAME = "<root>"; //$NON-NLS-1$
+
+ /** Stack of the currently entered (and not existed) test suites. */
+ private Stack<TestSuite> testSuitesStack = new Stack<TestSuite>();
+
+ /**
+ * Currently running test case. There are no nested test cases, so the
+ * collection is not necessary.
+ */
+ private TestCase currentTestCase = null;
+
+ /**
+ * The mapping of test suite object to the index on which it was inserted to
+ * the parent.
+ *
+ * @note Test suites presence in this map means that test suite was visited
+ * during the testing process (not visited test suites are removed when
+ * testing is finished cause they are considered as renamed or removed).
+ * @note Test suite insert position is important for insertion algorithm.
+ */
+ private Map<TestItem, Integer> testSuitesIndex = new HashMap<TestItem, Integer>();
+
+ /** Listeners collection. */
+ private List<ITestingSessionListener> listeners = new ArrayList<ITestingSessionListener>();
+
+ /** Flag stores whether test execution time should be measured for the session. */
+ private boolean timeMeasurement = false;
+
+ /** Stores the test case start time or 0 there is no currently running test case. */
+ private long testCaseStartTime = 0;
+
+ /** Instance of the insertion algorithm for test suites. */
+ private TestSuiteInserter testSuiteInserter = new TestSuiteInserter();
+
+ /** Instance of the insertion algorithm for test cases. */
+ private TestCaseInserter testCaseInserter = new TestCaseInserter();
+
+
+ /**
+ * Builds current tests hierarchy from the other one (copies only necessary
+ * information).
+ */
+ private class HierarchyCopier implements IModelVisitor {
+
+ @Override
+ public void visit(ITestSuite testSuite) {
+ // Do not copy root test suite
+ if (testSuite.getParent() != null) {
+ enterTestSuite(testSuite.getName());
+ }
+ }
+
+ @Override
+ public void leave(ITestSuite testSuite) {
+ // Do not copy root test suite
+ if (testSuite.getParent() != null) {
+ exitTestSuite();
+ }
+ }
+
+ @Override
+ public void visit(ITestCase testCase) {
+ enterTestCase(testCase.getName());
+ setTestStatus(TestCase.Status.NotRun);
+ }
+
+ @Override
+ public void leave(ITestCase testCase) {
+ exitTestCase();
+ }
+
+ @Override
+ public void visit(ITestMessage testMessage) {}
+ @Override
+ public void leave(ITestMessage testMessage) {}
+ }
+
+
+ /**
+ * Utility class: generalization of insertion algorithm for test suites and
+ * test cases.
+ *
+ * <p>
+ * The algorithm tries to find the place where the new item should be
+ * inserted at. If the item with such name does not exist in the current top
+ * most test suite, it should be inserted at the current position. If it
+ * already exists (at the next or previous position) then it should be moved
+ * from there to the current one.
+ * </p>
+ *
+ * @param <E> test item type (test suite or test case)
+ */
+ private abstract class TestItemInserter<E extends TestItem> {
+
+ /**
+ * Check whether item has the required type (test suite for suites inserter and
+ * test case for cases one).
+ *
+ * @param item test item to check
+ * @return whether item has the required type
+ */
+ protected abstract boolean isRequiredTestItemType(TestItem item);
+
+ /**
+ * Creates a new item type with the specified name and parent (test
+ * suite for suites inserter and test case for cases one).
+ *
+ * @param name name of the new test item
+ * @param parent parent for the new test item
+ * @return new test item
+ */
+ protected abstract E createTestItem(String name, TestSuite parent);
+
+ /**
+ * Save new test item in the tracking structures (suite in stack, case
+ * in current variable). Additional operations (e.g. listeners
+ * notification about item entering) can be done too.
+ *
+ * @param item new test item
+ */
+ protected abstract void addNewTestItem(E item);
+
+
+ /**
+ * Returns the casted test item if it matches by name and type or
+ * <code>null</code> if it doesn't.
+ *
+ * @param item test item to check
+ * @param name test item name
+ * @return casted test item or null
+ */
+ @SuppressWarnings("unchecked")
+ private E checkTestItem(TestItem item, String name) {
+ return (isRequiredTestItemType(item) && item.getName().equals(name)) ? (E)item : null;
+ }
+
+ /**
+ * Returns the last insert index for the specified test suite. Returns 0
+ * if test suite was not inserted yet.
+ *
+ * @param testSuite test suite to look up
+ * @return insert index or 0
+ */
+ private int getLastInsertIndex(TestSuite testSuite) {
+ Integer intLastInsertIndex = testSuitesIndex.get(testSuite);
+ return intLastInsertIndex != null ? intLastInsertIndex : 0;
+ }
+
+ /**
+ * Notifies the listeners about children update of the specified test
+ * suite.
+ *
+ * @param suite updated test suite
+ */
+ private void notifyAboutChildrenUpdate(ITestSuite suite) {
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.childrenUpdate(suite);
+ }
+ }
+
+ /**
+ * Inserts the test item by the name.
+ *
+ * @param name test item name
+ */
+ public void insert(String name) {
+ TestSuite currTestSuite = testSuitesStack.peek();
+ int lastInsertIndex = getLastInsertIndex(currTestSuite);
+ List<TestItem> children = currTestSuite.getChildrenList();
+ E newTestItem = null;
+
+ // Optimization: Check whether we already pointing to the test suite with required name
+ try {
+ newTestItem = checkTestItem(children.get(lastInsertIndex), name);
+ } catch (IndexOutOfBoundsException e) {}
+ if (newTestItem != null) {
+ testSuitesIndex.put(currTestSuite, lastInsertIndex+1);
+ }
+
+ // Check whether the suite with required name was later in the hierarchy
+ if (newTestItem == null) {
+ for (int childIndex = lastInsertIndex; childIndex < children.size(); childIndex++) {
+ newTestItem = checkTestItem(children.get(childIndex), name);
+ if (newTestItem != null) {
+ testSuitesIndex.put(currTestSuite, childIndex);
+ break;
+ }
+ }
+ }
+
+ // Search in previous
+ if (newTestItem == null) {
+ for (int childIndex = 0; childIndex < lastInsertIndex; childIndex++) {
+ newTestItem = checkTestItem(children.get(childIndex), name);
+ if (newTestItem != null) {
+ children.add(lastInsertIndex, children.remove(childIndex));
+ notifyAboutChildrenUpdate(currTestSuite);
+ break;
+ }
+ }
+ }
+
+ // Add new
+ if (newTestItem == null) {
+ newTestItem = createTestItem(name, currTestSuite);
+ children.add(lastInsertIndex, newTestItem);
+ testSuitesIndex.put(currTestSuite, lastInsertIndex+1);
+ notifyAboutChildrenUpdate(currTestSuite);
+ }
+ if (!testSuitesIndex.containsKey(newTestItem)) {
+ testSuitesIndex.put(newTestItem, 0);
+ }
+ addNewTestItem(newTestItem);
+ }
+
+ }
+
+
+ /**
+ * Utility class: insertion algorithm specialization for test suites.
+ */
+ private class TestSuiteInserter extends TestItemInserter<TestSuite> {
+
+ @Override
+ protected boolean isRequiredTestItemType(TestItem item) {
+ return (item instanceof TestSuite);
+ }
+
+ @Override
+ protected TestSuite createTestItem(String name, TestSuite parent) {
+ return new TestSuite(name, parent);
+ }
+
+ @Override
+ protected void addNewTestItem(TestSuite testSuite) {
+ testSuitesStack.push(testSuite);
+
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.enterTestSuite(testSuite);
+ }
+ }
+ }
+
+
+ /**
+ * Utility class: insertion algorithm specialization for test cases.
+ */
+ private class TestCaseInserter extends TestItemInserter<TestCase> {
+
+ @Override
+ protected boolean isRequiredTestItemType(TestItem item) {
+ return (item instanceof TestCase);
+ }
+
+ @Override
+ protected TestCase createTestItem(String name, TestSuite parent) {
+ return new TestCase(name, parent);
+ }
+
+ @Override
+ protected void addNewTestItem(TestCase testCase) {
+ currentTestCase = testCase;
+ testCase.setStatus(ITestItem.Status.Skipped);
+
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.enterTestCase(testCase);
+ }
+ }
+ }
+
+
+ public TestModelManager(ITestSuite previousTestsHierarchy, boolean timeMeasurement) {
+ testSuitesStack.push(new TestSuite(ROOT_TEST_SUITE_NAME, null));
+ if (previousTestsHierarchy != null) {
+ // Copy tests hierarchy
+ this.timeMeasurement = false;
+ previousTestsHierarchy.visit(new HierarchyCopier());
+ }
+ this.timeMeasurement = timeMeasurement;
+ this.testSuitesIndex.clear();
+ }
+
+ /**
+ * Notifies the listeners that testing was started.
+ */
+ public void testingStarted() {
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.testingStarted();
+ }
+ }
+
+ /**
+ * Removes not visited test items and notifies the listeners that testing
+ * was finished.
+ */
+ public void testingFinished() {
+ // Remove all NotRun-tests and not used test suites (probably they were removed from test module)
+ getRootSuite().visit(new IModelVisitor() {
+
+ @Override
+ public void visit(ITestSuite testSuite) {
+ List<TestItem> suiteChildren = ((TestSuite)testSuite).getChildrenList();
+ for (Iterator<TestItem> it = suiteChildren.iterator(); it.hasNext();) {
+ TestItem item = it.next();
+ if ((item instanceof ITestSuite && !testSuitesIndex.containsKey(item)) ||
+ (item instanceof ITestCase && item.getStatus() == ITestItem.Status.NotRun)) {
+ it.remove();
+ }
+ }
+ }
+
+ @Override
+ public void visit(ITestMessage testMessage) {}
+ @Override
+ public void visit(ITestCase testCase) {}
+ @Override
+ public void leave(ITestSuite testSuite) {}
+ @Override
+ public void leave(ITestCase testCase) {}
+ @Override
+ public void leave(ITestMessage testMessage) {}
+ });
+ testSuitesIndex.clear();
+
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.testingFinished();
+ }
+ }
+
+ @Override
+ public void enterTestSuite(String name) {
+ testSuiteInserter.insert(name);
+ }
+
+ @Override
+ public void exitTestSuite() {
+ exitTestCase();
+ TestSuite testSuite = testSuitesStack.pop();
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.exitTestSuite(testSuite);
+ }
+ }
+
+ @Override
+ public void enterTestCase(String name) {
+ testCaseInserter.insert(name);
+ if (timeMeasurement) {
+ testCaseStartTime = System.currentTimeMillis();
+ }
+ }
+
+
+ @Override
+ public void setTestStatus(Status status) {
+ currentTestCase.setStatus(status);
+ }
+
+ @Override
+ public void setTestingTime(int testingTime) {
+ currentTestCase.setTestingTime(testingTime);
+ }
+
+ @Override
+ public void exitTestCase() {
+ if (currentTestCase != null) {
+ // Set test execution time (if time measurement is turned on)
+ if (timeMeasurement) {
+ int testingTime = (int)(System.currentTimeMillis()-testCaseStartTime);
+ currentTestCase.setTestingTime(currentTestCase.getTestingTime()+testingTime);
+ testCaseStartTime = 0;
+ }
+ TestCase testCase = currentTestCase;
+ currentTestCase = null;
+ // Notify listeners
+ for (ITestingSessionListener listener : getListenersCopy()) {
+ listener.exitTestCase(testCase);
+ }
+ }
+ }
+
+ @Override
+ public void addTestMessage(String file, int line, Level level, String text) {
+ TestLocation location = (file == null || file.isEmpty() || line <= 0) ? null : new TestLocation(file, line);
+ currentTestCase.addTestMessage(new TestMessage(location, level, text));
+ }
+
+ @Override
+ public ITestSuite currentTestSuite() {
+ return testSuitesStack.peek();
+ }
+
+
+ @Override
+ public ITestCase currentTestCase() {
+ return currentTestCase;
+ }
+
+ @Override
+ public boolean isCurrentlyRunning(ITestItem item) {
+ return (item == currentTestCase && item != null) || testSuitesStack.contains(item);
+ }
+
+ @Override
+ public TestSuite getRootSuite() {
+ return testSuitesStack.firstElement();
+ }
+
+ @Override
+ public void addChangesListener(ITestingSessionListener listener) {
+ synchronized (listeners) {
+ listeners.add(listener);
+ }
+ }
+
+ @Override
+ public void removeChangesListener(ITestingSessionListener listener) {
+ synchronized (listeners) {
+ listeners.remove(listener);
+ }
+ }
+
+ /**
+ * Copies listeners before notifying them to avoid dead-locks.
+ *
+ * @return listeners collection copy
+ */
+ private ITestingSessionListener[] getListenersCopy() {
+ synchronized (listeners) {
+ return listeners.toArray(new ITestingSessionListener[listeners.size()]);
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java
new file mode 100644
index 0000000..188f814
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestSuite.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+
+/**
+ * Represents the test suite of the tests hierarchy.
+ */
+public class TestSuite extends TestItem implements ITestSuite {
+
+ /**
+ * Stores child test suites and test cases.
+ *
+ * @note Children order is important.
+ */
+ private List<TestItem> children = new ArrayList<TestItem>();
+
+
+ public TestSuite(String name, TestSuite parent) {
+ super(name, parent);
+ }
+
+ @Override
+ public Status getStatus() {
+ Status result = Status.NotRun;
+ for (TestItem testItem : children) {
+ Status childStatus = testItem.getStatus();
+ if (result.compareTo(childStatus) < 0) {
+ result = childStatus;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int getTestingTime() {
+ int result = 0;
+ for (TestItem testItem : children) {
+ result += testItem.getTestingTime();
+ }
+ return result;
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return !children.isEmpty();
+ }
+
+ @Override
+ public TestItem[] getChildren() {
+ return children.toArray(new TestItem[children.size()]);
+ }
+
+ @Override
+ public void visit(IModelVisitor visitor) {
+ visitor.visit(this);
+ for (TestItem testItem : children) {
+ testItem.visit(visitor);
+ }
+ visitor.leave(this);
+ }
+
+ /**
+ * Returns list of children for the test suite.
+ *
+ * @return children list
+ */
+ public List<TestItem> getChildrenList() {
+ return children;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java
new file mode 100644
index 0000000..f706fa3
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSession.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import java.io.InputStream;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.Map;
+
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProvider;
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestItem.Status;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestModelAccessor;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.cdt.testsrunner.model.ITestingSessionListener;
+import org.eclipse.cdt.testsrunner.model.TestingException;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunch;
+
+/**
+ * Stores the information about tests running.
+ */
+public class TestingSession implements ITestingSession {
+
+ /** Launch object the is connected to the tests running. */
+ private ILaunch launch;
+
+ /** Information about used Tests Runner provider plug-in. */
+ private TestsRunnerProviderInfo testsRunnerProviderInfo;
+
+ /** Main interface to Tests Runner provider plug-in. */
+ private ITestsRunnerProvider testsRunnerProvider;
+
+ /**
+ * Test Model manager that is used to fill and update the model for the
+ * session.
+ */
+ private TestModelManager modelManager;
+
+ /**
+ * Total tests counter. It is -1 by default, that means that total tests
+ * count is not available.
+ *
+ * @see getTotalCounter()
+ */
+ private int totalCounter = -1;
+
+ /** Already finished tests counter. */
+ private int currentCounter = 0;
+
+ /**
+ * Test counters map by test status. They are used to quickly provide simple
+ * statistics without model scanning.
+ *
+ */
+ private Map<ITestItem.Status, Integer> statusCounters = new EnumMap<ITestItem.Status, Integer>(ITestItem.Status.class);
+
+ /**
+ * The flag stores whether the testing session contains errors at the
+ * moment.
+ *
+ * @see hasErrors()
+ */
+ private boolean hasErrors = false;
+
+ /**
+ * The flag stores whether the testing session was stopped by user.
+ *
+ * @see wasStopped()
+ */
+ private boolean wasStopped = false;
+
+ /**
+ * The flag stores whether the testing session has been finished (with or
+ * without errors).
+ */
+ private boolean finished = false;
+
+ /** Stores current status of the testing session. */
+ private String statusMessage = ModelMessages.TestingSession_starting_status;
+
+ /** Stores the time when the testing session was created. */
+ private long startTime;
+
+
+ /**
+ * Counts the number of the test cases in tests hierarchy.
+ */
+ private class TestCasesCounter implements IModelVisitor {
+
+ public int result = 0;
+
+ @Override
+ public void visit(ITestCase testCase) {
+ ++result;
+ }
+
+ @Override
+ public void visit(ITestSuite testSuite) {}
+ @Override
+ public void visit(ITestMessage testMessage) {}
+ @Override
+ public void leave(ITestSuite testSuite) {}
+ @Override
+ public void leave(ITestCase testCase) {}
+ @Override
+ public void leave(ITestMessage testMessage) {}
+ }
+
+
+ /**
+ * The constructor.
+ *
+ * @param launch connected launch object
+ * @param testsRunnerProviderInfo the information about the tests runner
+ * @param previousSession is used to determine total tests count & for tests
+ * hierarchy reusing if it is considered as similar
+ */
+ public TestingSession(ILaunch launch, TestsRunnerProviderInfo testsRunnerProviderInfo, TestingSession previousSession) {
+ this.launch = launch;
+ this.testsRunnerProviderInfo = testsRunnerProviderInfo;
+ this.testsRunnerProvider = testsRunnerProviderInfo.instantiateTestsRunnerProvider();
+ this.startTime = System.currentTimeMillis();
+ // Calculate approximate tests count by the previous similar testing session (if available)
+ if (previousSession != null) {
+ TestCasesCounter testCasesCounter = new TestCasesCounter();
+ previousSession.getModelAccessor().getRootSuite().visit(testCasesCounter);
+ totalCounter = testCasesCounter.result;
+ }
+ ITestSuite rootTestSuite = previousSession != null ? previousSession.getModelAccessor().getRootSuite() : null;
+ this.modelManager = new TestModelManager(rootTestSuite, testsRunnerProviderInfo.isAllowedTestingTimeMeasurement());
+ this.modelManager.addChangesListener(new ITestingSessionListener() {
+
+ @Override
+ public void testingStarted() {}
+
+ @Override
+ public void testingFinished() {
+ // This is necessary if totalCounter was -1 (tests count was unknown)
+ // or if tests count was estimated not accurately
+ totalCounter = currentCounter;
+ }
+
+ @Override
+ public void exitTestSuite(ITestSuite testSuite) {}
+
+ @Override
+ public void exitTestCase(ITestCase testCase) {
+ // Update testing session info (counters, flags)
+ Status testStatus = testCase.getStatus();
+ statusCounters.put(testStatus, getCount(testStatus)+1);
+ ++currentCounter;
+ if (testStatus.isError())
+ hasErrors = true;
+ }
+
+ @Override
+ public void enterTestSuite(ITestSuite testSuite) {}
+
+ @Override
+ public void enterTestCase(ITestCase testCase) {}
+
+ @Override
+ public void childrenUpdate(ITestSuite parent) {}
+ });
+ }
+
+ /**
+ * Starts the processing of the test module output.
+ *
+ * @param inputStream test module output stream
+ */
+ public void run(InputStream inputStream) {
+ modelManager.testingStarted();
+ try {
+ testsRunnerProvider.run(modelManager, inputStream);
+ // If testing session was stopped, the status is set in stop()
+ if (!wasStopped()) {
+ double testingTime = getModelAccessor().getRootSuite().getTestingTime();
+ statusMessage = MessageFormat.format(ModelMessages.TestingSession_finished_status, testingTime/1000.0);
+ }
+ } catch (TestingException e) {
+ // If testing session was stopped, the status is set in stop()
+ if (!wasStopped()) {
+ statusMessage = e.getLocalizedMessage();
+ hasErrors = true;
+ }
+ }
+ finished = true;
+ modelManager.testingFinished();
+ }
+
+ @Override
+ public int getCurrentCounter() {
+ return currentCounter;
+ }
+
+ @Override
+ public int getTotalCounter() {
+ return totalCounter;
+ }
+
+ @Override
+ public int getCount(ITestItem.Status status) {
+ Integer counterValue = statusCounters.get(status);
+ return (counterValue == null) ? 0 : counterValue;
+ }
+
+ @Override
+ public boolean hasErrors() {
+ return hasErrors;
+ }
+
+ @Override
+ public boolean wasStopped() {
+ return wasStopped;
+ }
+
+ @Override
+ public boolean isFinished() {
+ return finished;
+ }
+
+ @Override
+ public ITestModelAccessor getModelAccessor() {
+ return modelManager;
+ }
+
+ @Override
+ public ILaunch getLaunch() {
+ return launch;
+ }
+
+ @Override
+ public TestsRunnerProviderInfo getTestsRunnerProviderInfo() {
+ return testsRunnerProviderInfo;
+ }
+
+ @Override
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ @Override
+ public String getName() {
+ String launchConfName = launch.getLaunchConfiguration().getName();
+ String startTimeStr = DateFormat.getDateTimeInstance().format(new Date(startTime));
+ return MessageFormat.format(ModelMessages.TestingSession_name_format, launchConfName, startTimeStr);
+ }
+
+ @Override
+ public void stop() {
+ if (!launch.isTerminated() && launch.canTerminate()) {
+ try {
+ launch.terminate();
+ wasStopped = true;
+ statusMessage = ModelMessages.TestingSession_stopped_status;
+ } catch (DebugException e) {
+ TestsRunnerPlugin.log(e);
+ }
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java
new file mode 100644
index 0000000..66bf252
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/model/TestingSessionsManager.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.model;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProvidersManager;
+import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+/**
+ * Manages all the testing sessions (creates, activates, stores history).
+ */
+public class TestingSessionsManager {
+
+ /** Tests Runners Plug-ins Manager. */
+ private TestsRunnerProvidersManager testsRunnersManager;
+
+ /** Testing sessions history list (the first is the newest). */
+ private LinkedList<TestingSession> sessions = new LinkedList<TestingSession>();
+
+ /** Currently active testing session. */
+ private TestingSession activeSession;
+
+ /** Listeners collection. */
+ private List<ITestingSessionsManagerListener> listeners = new ArrayList<ITestingSessionsManagerListener>();
+
+ /** The size limit of the testing sessions history. */
+ private int historySizeLimit = 10;
+
+ public TestingSessionsManager(TestsRunnerProvidersManager testsRunnersManager) {
+ this.testsRunnersManager = testsRunnersManager;
+ }
+
+ /**
+ * Tries to find the last testing session for the specified launch
+ * configuration and Tests Runner provide plug-in.
+ *
+ * <p>
+ * Usually testing frameworks do not provide the information about tests
+ * hierarchy and total tests count before the testing is finished. So we try
+ * to reuse them from one the previous testing sessions that meets the
+ * requirements:
+ * <ul>
+ * <li>it should be for the same launch configuration;
+ * <li>it should be completed (finished and not stopped);
+ * <li>it should has the same tests runner;
+ * </ul>
+ * This function tries to find a such session.
+ * </p>
+ *
+ * @param launchConfiguration required launch configuration
+ * @param testsRunnerProviderInfo required Tests Runner provide plug-in
+ * @return testing session or null if not found
+ */
+ private TestingSession findActualPreviousSession(ILaunchConfiguration launchConfiguration, TestsRunnerProviderInfo testsRunnerProviderInfo) {
+ String testsRunnerName = testsRunnerProviderInfo.getName();
+ for (TestingSession session : sessions) {
+ // Find the latest testing session that matches the next requirements:
+ // - it should be for the same launch configuration (should have the same parameters)
+ // - should be already terminated (to have complete tests hierarchy structure)
+ // - should not be stopped by user (the same as terminated)
+ // - should have the same tests runner
+ if (session != null) {
+ if (launchConfiguration.equals(session.getLaunch().getLaunchConfiguration())
+ && session.isFinished()
+ && !session.wasStopped()
+ && session.getTestsRunnerProviderInfo().getName().equals(testsRunnerName)) {
+ return session;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new testing session for the specified launch.
+ *
+ * @param launch launch
+ * @return new testing session
+ */
+ public TestingSession newSession(ILaunch launch) throws CoreException {
+ TestsRunnerProviderInfo testsRunnerProviderInfo = testsRunnersManager.getTestsRunnerProviderInfo(launch.getLaunchConfiguration());
+ TestingSession previousSession = findActualPreviousSession(launch.getLaunchConfiguration(), testsRunnerProviderInfo);
+ TestingSession newTestingSession = new TestingSession(launch, testsRunnerProviderInfo, previousSession);
+ sessions.addFirst(newTestingSession);
+ setActiveSession(newTestingSession);
+ truncateHistory();
+ return newTestingSession;
+ }
+
+ /**
+ * Returns the testing sessions history (the first is the newest).
+ *
+ * @return testing sessions list
+ */
+ public List<? extends ITestingSession> getSessions() {
+ return sessions;
+ }
+
+ /**
+ * Rewrites the testing sessions history with the specified list. Truncates
+ * the history if necessary.
+ *
+ * @return testing sessions list
+ */
+ public void setSessions(List<ITestingSession> newSessions) {
+ sessions.clear();
+ for (ITestingSession newSession : newSessions) {
+ sessions.add((TestingSession) newSession);
+ }
+ truncateHistory();
+ }
+
+ /**
+ * Returns the testing sessions history size.
+ *
+ * @return history size
+ */
+ public int getSessionsCount() {
+ return sessions.size();
+ }
+
+ /**
+ * Accesses the currently active testing session.
+ *
+ * @return testing session
+ */
+ public ITestingSession getActiveSession() {
+ return activeSession;
+ }
+
+ /**
+ * Sets the new active testing session.
+ *
+ * @param newActiveSession testing session
+ */
+ public void setActiveSession(ITestingSession newActiveSession) {
+ if (activeSession != newActiveSession) {
+ activeSession = (TestingSession) newActiveSession;
+ // Notify listeners
+ for (ITestingSessionsManagerListener listener : listeners) {
+ listener.sessionActivated(activeSession);
+ }
+ }
+ }
+
+ /**
+ * Adds the given listener to this registered listeners collection.
+ * Has no effect if an identical listener is already registered.
+ *
+ * @param listener the listener to add
+ */
+ public void addListener(ITestingSessionsManagerListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes the given listener from registered listeners collection.
+ * Has no effect if the listener is not already registered.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeListener(ITestingSessionsManagerListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Returns the size limit of the testing sessions history.
+ *
+ * @return history size limit
+ */
+ public int getHistorySizeLimit() {
+ return historySizeLimit;
+ }
+
+ /**
+ * Sets the size limit of the testing sessions history.
+ *
+ * @param historySizeLimit new history size limit
+ */
+ public void setHistorySizeLimit(int historySizeLimit) {
+ this.historySizeLimit = historySizeLimit;
+ truncateHistory();
+ }
+
+ /**
+ * Truncates the history list if it is longer than size limit.
+ */
+ private void truncateHistory() {
+ // The most frequently this method will be used to remove one element, so removeAll() is unnecessary here
+ while (sessions.size() > historySizeLimit) {
+ sessions.removeLast();
+ }
+ // Handle the case when active testing session was removed from history due to truncation
+ if (!sessions.contains(activeSession)) {
+ ITestingSession newActiveSession = sessions.isEmpty() ? null : sessions.getFirst();
+ setActiveSession(newActiveSession);
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java
new file mode 100644
index 0000000..bb1d058
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/CTestingTab.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.launcher;
+
+import org.eclipse.cdt.launch.ui.CLaunchConfigurationTab;
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.launcher.ITestsLaunchConfigurationConstants;
+import org.eclipse.cdt.testsrunner.internal.launcher.TestsRunnerProviderInfo;
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+
+/**
+ * A launch configuration tab that displays and edits different testing options
+ * (e.g. Tests Runner provider plug-in).
+ * <p>
+ * This class may be instantiated. This class is not intended to be subclassed.
+ * </p>
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ */
+public class CTestingTab extends CLaunchConfigurationTab {
+
+ /**
+ * Tab identifier used for ordering of tabs added using the
+ * <code>org.eclipse.debug.ui.launchConfigurationTabs</code>
+ * extension point.
+ */
+ private static final String TAB_ID = "org.eclipse.cdt.testsrunner.testingTab"; //$NON-NLS-1$
+
+ private static final String TESTING_PROCESS_FACTORY_ID = "org.eclipse.cdt.testsrunner.TestingProcessFactory"; //$NON-NLS-1$
+
+ /** Shows the list of available Tests Runner provider plug-ins. */
+ private Combo testsRunnerProviderCombo;
+
+ /** Shows the description for the currently selected Tests Runner provider plug-in. */
+ private Label testsRunnerProviderDescriptionLabel;
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite pageComposite = new Composite(parent, SWT.NONE);
+ GridLayout pageCompositeLayout = new GridLayout(2, false);
+ pageCompositeLayout.horizontalSpacing = 40;
+ pageComposite.setLayout(pageCompositeLayout);
+
+ // Create a tests runner selector
+ new Label(pageComposite, SWT.NONE).setText(UILauncherMessages.CTestingTab_tests_runner_label);
+ testsRunnerProviderCombo = new Combo(pageComposite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ testsRunnerProviderCombo.add(UILauncherMessages.CTestingTab_tests_runner_is_not_set);
+ testsRunnerProviderCombo.setData("0", null); //$NON-NLS-1$
+
+ // Add all the tests runners
+ for (TestsRunnerProviderInfo testsRunnerProviderInfo : TestsRunnerPlugin.getDefault().getTestsRunnerProvidersManager().getTestsRunnersProviderInfo()) {
+ testsRunnerProviderCombo.setData(Integer.toString(testsRunnerProviderCombo.getItemCount()), testsRunnerProviderInfo);
+ testsRunnerProviderCombo.add(testsRunnerProviderInfo.getName());
+ }
+
+ testsRunnerProviderCombo.addModifyListener(new ModifyListener() {
+
+ @Override
+ public void modifyText(ModifyEvent e) {
+ testsRunnerProviderDescriptionLabel.setText(getCurrentTestsRunnerDescription());
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ // Create a tests runner description label
+ testsRunnerProviderDescriptionLabel = new Label(pageComposite, SWT.WRAP);
+ GridData testsRunnerProviderLabelGD = new GridData(GridData.FILL_BOTH);
+ testsRunnerProviderLabelGD.horizontalSpan = 2;
+ testsRunnerProviderLabelGD.horizontalAlignment = GridData.FILL;
+ testsRunnerProviderDescriptionLabel.setLayoutData(testsRunnerProviderLabelGD);
+
+ GridData pageCompositeGD = new GridData(GridData.FILL_BOTH);
+ pageCompositeGD.horizontalAlignment = GridData.FILL;
+ pageCompositeGD.grabExcessHorizontalSpace = true;
+ pageComposite.setLayoutData(pageCompositeGD);
+ setControl(pageComposite);
+ }
+
+ /**
+ * Returns the information for the currently selected Tests Runner provider
+ * plug-in.
+ *
+ * @return Tests Runner provide plug-in information
+ */
+ private ITestsRunnerProviderInfo getCurrentTestsRunnerProviderInfo() {
+ return getTestsRunnerProviderInfo(testsRunnerProviderCombo.getSelectionIndex());
+ }
+
+ /**
+ * Returns the information for the Tests Runner provide plug-in specified by
+ * index.
+ *
+ * @param comboIndex index in combo widget
+ * @return Tests Runner provide plug-in information
+ */
+ private ITestsRunnerProviderInfo getTestsRunnerProviderInfo(int comboIndex) {
+ return (ITestsRunnerProviderInfo)testsRunnerProviderCombo.getData(Integer.toString(comboIndex));
+ }
+
+ /**
+ * Returns the description for the currently selected Tests Runner provide
+ * plug-in.
+ *
+ * @return the description
+ */
+ private String getCurrentTestsRunnerDescription() {
+ ITestsRunnerProviderInfo testsRunnerProvider = getCurrentTestsRunnerProviderInfo();
+ if (testsRunnerProvider != null) {
+ return testsRunnerProvider.getDescription();
+ } else {
+ return UILauncherMessages.CTestingTab_no_tests_runner_label;
+ }
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+ return getCurrentTestsRunnerProviderInfo() != null;
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ config.setAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String) null);
+ config.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, TESTING_PROCESS_FACTORY_ID);
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ try {
+ String testsRunnerId = configuration.getAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, (String) null);
+ int comboIndex = 0;
+ for (int i = 1; i < testsRunnerProviderCombo.getItemCount(); i++) {
+ if (getTestsRunnerProviderInfo(i).getId().equals(testsRunnerId)) {
+ comboIndex = i;
+ break;
+ }
+ }
+ testsRunnerProviderCombo.select(comboIndex);
+
+ } catch (CoreException e) {
+ TestsRunnerPlugin.log(e);
+ }
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ ITestsRunnerProviderInfo testsRunnerProvider = getCurrentTestsRunnerProviderInfo();
+ String testsRunnerProviderId = testsRunnerProvider != null ? testsRunnerProvider.getId() : null;
+ configuration.setAttribute(ITestsLaunchConfigurationConstants.ATTR_TESTS_RUNNER, testsRunnerProviderId);
+ configuration.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, TESTING_PROCESS_FACTORY_ID);
+ }
+
+ @Override
+ public String getId() {
+ return TAB_ID;
+ }
+
+ @Override
+ public String getName() {
+ return UILauncherMessages.CTestingTab_tab_name;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ String m = super.getErrorMessage();
+ if (m == null) {
+ if (getCurrentTestsRunnerProviderInfo() == null) {
+ return UILauncherMessages.CTestingTab_no_tests_runner_error;
+ }
+ }
+ return m;
+ }
+
+ @Override
+ public Image getImage() {
+ return TestsRunnerPlugin.createAutoImage("obj16/test_notrun.gif"); //$NON-NLS-1$
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java
new file mode 100644
index 0000000..77a9d44
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/EmptyConfigurationTabGroup.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.launcher;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+
+
+/**
+ * Represents an empty tab group. Actual tabs are added via the
+ * <code>org.eclipse.debug.ui.launchConfigurationTabs</code> extension point.
+ */
+public class EmptyConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ @Override
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ setTabs(new ILaunchConfigurationTab[0]);
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java
new file mode 100644
index 0000000..8e75b59
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.launcher;
+
+import org.eclipse.osgi.util.NLS;
+
+public class UILauncherMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.launcher.UILauncherMessages"; //$NON-NLS-1$
+ public static String CTestingTab_no_tests_runner_error;
+ public static String CTestingTab_no_tests_runner_label;
+ public static String CTestingTab_tab_name;
+ public static String CTestingTab_tests_runner_is_not_set;
+ public static String CTestingTab_tests_runner_label;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, UILauncherMessages.class);
+ }
+
+ private UILauncherMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties
new file mode 100644
index 0000000..752755e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/launcher/UILauncherMessages.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+CTestingTab_no_tests_runner_error=Tests runner is not selected
+CTestingTab_no_tests_runner_label=Select a tests runner...
+CTestingTab_tab_name=C/C++ Testing
+CTestingTab_tests_runner_is_not_set=<not set>
+CTestingTab_tests_runner_label=Tests Runner
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java
new file mode 100644
index 0000000..4f3f8d9
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/CounterPanel.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import java.text.MessageFormat;
+
+
+/**
+ * Shows a simple tests count statics information (run/error/failed).
+ */
+public class CounterPanel extends Composite {
+
+ /** Testing session to show statistics for. */
+ private ITestingSession testingSession;
+
+ /** Widget showing the failed tests count. */
+ private Label failedCounterLabel;
+
+ /** Widget showing the error tests count. */
+ private Label abortedCounterLabel;
+
+ /** Widget showing the run tests count. */
+ private Label currentCounterLabel;
+
+ /**
+ * Shows whether there were skipped tests. It is used to force layout of the
+ * counter widgets after skipped tests are appeared.
+ */
+ private boolean hasSkipped;
+
+ private final Image errorIcon = TestsRunnerPlugin.createAutoImage("ovr16/failed_counter.gif"); //$NON-NLS-1$
+ private final Image failureIcon = TestsRunnerPlugin.createAutoImage("ovr16/aborted_counter.gif"); //$NON-NLS-1$
+
+
+ public CounterPanel(Composite parent, ITestingSession testingSession) {
+ super(parent, SWT.WRAP);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 9;
+ gridLayout.makeColumnsEqualWidth = false;
+ gridLayout.marginWidth = 0;
+ setLayout(gridLayout);
+
+ currentCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_run, null);
+ abortedCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_erred, errorIcon);
+ failedCounterLabel = createLabel(UIViewMessages.CounterPanel_tests_failed, failureIcon);
+ setTestingSession(testingSession);
+ }
+
+ /**
+ * Creates counter label widget.
+ *
+ * @param name widget text prefix
+ * @param image widget image or <code>null</code>
+ * @return created label
+ */
+ private Label createLabel(String name, Image image) {
+ Label label = new Label(this, SWT.NONE);
+ if (image != null) {
+ image.setBackground(label.getBackground());
+ label.setImage(image);
+ }
+ label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+
+ label = new Label(this, SWT.NONE);
+ label.setText(name);
+ label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+
+ Label value = new Label(this, SWT.READ_ONLY);
+ value.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING));
+ return value;
+ }
+
+ /**
+ * Sets the testing session to show information about.
+ *
+ * @param testingSession testing session (null is not acceptable)
+ */
+ public void setTestingSession(ITestingSession testingSession) {
+ this.testingSession = testingSession;
+ this.hasSkipped = testingSession.getCount(ITestItem.Status.Skipped) != 0;
+ updateInfoFromSession();
+ }
+
+ /**
+ * Updates the information on the panel from the currently set testing
+ * session.
+ */
+ public void updateInfoFromSession() {
+ setFailedCounter(testingSession.getCount(ITestItem.Status.Failed));
+ setAbortedCounter(testingSession.getCount(ITestItem.Status.Aborted));
+ setCurrentCounter(testingSession.getCurrentCounter(), testingSession.getCount(ITestItem.Status.Skipped));
+ redraw();
+ }
+
+ /**
+ * Sets a new value for the failed tests counter.
+ *
+ * @param newValue new counter value
+ */
+ private void setFailedCounter(int newValue) {
+ failedCounterLabel.setText(Integer.toString(newValue));
+ }
+
+ /**
+ * Sets a new value for the error tests counter.
+ *
+ * @param newValue new counter value
+ */
+ private void setAbortedCounter(int newValue) {
+ abortedCounterLabel.setText(Integer.toString(newValue));
+ }
+
+ /**
+ * Sets a new value for the run tests counter.
+ *
+ * @param currentValue new counter value
+ * @param skippedValue skipped tests counter
+ */
+ private void setCurrentCounter(int currentValue, int skippedValue) {
+ if (!hasSkipped && skippedValue != 0) {
+ layout();
+ }
+ String runString = (skippedValue == 0)
+ ? Integer.toString(currentValue)
+ : MessageFormat.format(UIViewMessages.CounterPanel_tests_skipped, currentValue, skippedValue);
+ currentCounterLabel.setText(runString);
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java
new file mode 100644
index 0000000..9787a5b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/DummyUISession.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import org.eclipse.cdt.testsrunner.launcher.ITestsRunnerProviderInfo;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestModelAccessor;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.debug.core.ILaunch;
+
+/**
+ * Represents a simple testing session which is used for UI when there is no
+ * "real" testing sessions to show (e.g. when there was no launched testing
+ * session or when all of them were cleared).
+ */
+public class DummyUISession implements ITestingSession {
+
+ @Override
+ public int getCurrentCounter() {
+ return 0;
+ }
+
+ @Override
+ public int getTotalCounter() {
+ return 0;
+ }
+
+ @Override
+ public int getCount(ITestItem.Status status) {
+ return 0;
+ }
+
+ @Override
+ public boolean hasErrors() {
+ return false;
+ }
+
+ @Override
+ public boolean wasStopped() {
+ return false;
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public ITestModelAccessor getModelAccessor() {
+ return null;
+ }
+
+ @Override
+ public ILaunch getLaunch() {
+ return null;
+ }
+
+ @Override
+ public ITestsRunnerProviderInfo getTestsRunnerProviderInfo() {
+ return null;
+ }
+
+ @Override
+ public String getStatusMessage() {
+ return ""; //$NON-NLS-1$
+ }
+
+ @Override
+ public String getName() {
+ return "<dummy>"; //$NON-NLS-1$
+ }
+
+ @Override
+ public void stop() {
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java
new file mode 100644
index 0000000..db0aa21
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/MessagesViewer.java
@@ -0,0 +1,573 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.CopySelectedMessagesAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.OpenInEditorAction;
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestLocation;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestMessage.Level;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.IOpenListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.OpenEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+
+
+/**
+ * Shows the messages for the currently selected items in tests hierarchy (test
+ * suites or test cases).
+ */
+public class MessagesViewer {
+
+ /**
+ * Enumeration of all possible message filter actions by level.
+ */
+ public enum LevelFilter {
+ Info(ISharedImages.IMG_OBJS_INFO_TSK, ITestMessage.Level.Info, ITestMessage.Level.Message),
+ Warning(ISharedImages.IMG_OBJS_WARN_TSK, ITestMessage.Level.Warning),
+ Error(ISharedImages.IMG_OBJS_ERROR_TSK, ITestMessage.Level.Error, ITestMessage.Level.FatalError, ITestMessage.Level.Exception);
+
+ private String imageId;
+ private ITestMessage.Level [] includedLevels;
+
+ LevelFilter(String imageId, ITestMessage.Level... includedLevels) {
+ this.imageId = imageId;
+ this.includedLevels = includedLevels;
+ }
+
+ /**
+ * The shared image ID corresponding to the message level filter action.
+ *
+ * @return shared image ID
+ */
+ public String getImageId() {
+ return imageId;
+ }
+
+ /**
+ * The message levels that should be shown if current message level
+ * filter action is set.
+ *
+ * @return array of message levels
+ */
+ public ITestMessage.Level [] getLevels() {
+ return includedLevels;
+ }
+
+ /**
+ * Checks whether the specified message level should be shown if current
+ * message level filter action is set.
+ *
+ * @param messageLevel message level to search
+ * @return <code>true</code> if found
+ */
+ public boolean isIncluded(ITestMessage.Level messageLevel) {
+ for (ITestMessage.Level currLevel : includedLevels) {
+ if (currLevel.equals(messageLevel)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * The content provider for the test messages viewer.
+ */
+ private class MessagesContentProvider implements IStructuredContentProvider {
+
+ /**
+ * Utility class: recursively collects all the messages of the specified
+ * test item.
+ */
+ class MessagesCollector implements IModelVisitor {
+
+ /** Collected test messages. */
+ Collection<ITestMessage> collectedTestMessages;
+
+ /**
+ * Specifies whether gathering should be done. It is used to skip
+ * the messages of the passed tests if they should not be shown.
+ */
+ boolean collect = true;
+
+ MessagesCollector(Collection<ITestMessage> testMessages) {
+ this.collectedTestMessages = testMessages;
+ }
+
+ @Override
+ public void visit(ITestMessage testMessage) {
+ if (collect) {
+ collectedTestMessages.add(testMessage);
+ }
+ }
+
+ @Override
+ public void visit(ITestCase testCase) {
+ collect = !showFailedOnly || testCase.getStatus().isError();
+ }
+
+ @Override
+ public void visit(ITestSuite testSuite) {}
+
+ @Override
+ public void leave(ITestSuite testSuite) {}
+
+ @Override
+ public void leave(ITestCase testCase) {}
+
+ @Override
+ public void leave(ITestMessage testMessage) {}
+ }
+
+ /** Test messages to show in the viewer. */
+ ITestMessage[] testMessages;
+
+ @Override
+ public void inputChanged(Viewer v, Object oldInput, Object newInput) {
+ if (newInput != null) {
+ collectMessages((ITestItem[]) newInput);
+ } else {
+ testMessages = new ITestMessage[0];
+ }
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public Object[] getElements(Object parent) {
+ return testMessages;
+ }
+
+ /**
+ * Creates a messages set with a custom comparator. It is used for the
+ * ordered messages showing.
+ *
+ * @return set to store the test messages
+ */
+ private TreeSet<ITestMessage> createMessagesSet() {
+ return new TreeSet<ITestMessage>(new Comparator<ITestMessage>() {
+
+ @Override
+ public int compare(ITestMessage message1, ITestMessage message2) {
+ // Compare messages by location
+ ITestLocation location1 = message1.getLocation();
+ ITestLocation location2 = message2.getLocation();
+
+ if (location1 != null && location2 != null) {
+ // Compare by file name
+ String file1 = location1.getFile();
+ String file2 = location2.getFile();
+ int fileResult = file1.compareTo(file2);
+ if (fileResult != 0) {
+ return fileResult;
+ } else {
+ // Compare by line number
+ int line1 = location1.getLine();
+ int line2 = location2.getLine();
+ if (line1 < line2) {
+ return -1;
+
+ } else if (line1 > line2) {
+ return 1;
+ }
+ }
+
+ } else if (location1 == null && location2 != null) {
+ return -1;
+
+ } else if (location1 != null && location2 == null) {
+ return 1;
+ }
+
+ // Compare by message text
+ String text1 = message1.getText();
+ String text2 = message2.getText();
+ return text1.compareTo(text2);
+ }
+ });
+ }
+
+ /**
+ * Creates a list to store the test messages. It is used for the
+ * unordered messages showing.
+ *
+ * @return list to store the test messages
+ */
+ private ArrayList<ITestMessage> createMessagesList() {
+ return new ArrayList<ITestMessage>();
+ }
+
+ /**
+ * Creates a collection to store the test messages depending on whether
+ * ordering is required.
+ *
+ * @return collection to store the test messages
+ */
+ private Collection<ITestMessage> createMessagesCollection() {
+ return orderingMode ? createMessagesSet() : createMessagesList();
+ }
+
+ /**
+ * Run messages collecting for the specified test items.
+ *
+ * @param testItems test items array
+ */
+ private void collectMessages(ITestItem[] testItems) {
+ Collection<ITestMessage> testMessagesCollection = createMessagesCollection();
+ for (ITestItem testItem : testItems) {
+ testItem.visit(new MessagesCollector(testMessagesCollection));
+ }
+ testMessages = testMessagesCollection.toArray(new ITestMessage[testMessagesCollection.size()]);
+ }
+ }
+
+ /**
+ * The label provider for the test messages viewer.
+ */
+ private class MessagesLabelProvider extends LabelProvider implements ITableLabelProvider {
+
+ /**
+ * Returns the full (file path) or short (file name only) file path view
+ * depending on the filter set.
+ *
+ * @param location test object location
+ * @return file path
+ */
+ private String getLocationFile(ITestLocation location) {
+ String filePath = location.getFile();
+ if (showFileNameOnly) {
+ return new File(filePath).getName();
+ } else {
+ return filePath;
+ }
+ }
+
+ @Override
+ public String getColumnText(Object obj, int index) {
+ ITestMessage message = (ITestMessage)obj;
+ ITestLocation location = message.getLocation();
+ String locationString = ""; //$NON-NLS-1$
+ if (location != null) {
+ locationString = MessageFormat.format(
+ UIViewMessages.MessagesViewer_location_format,
+ new Object[] { getLocationFile(location), location.getLine() }
+ );
+ }
+ return MessageFormat.format(UIViewMessages.MessagesViewer_message_format,
+ locationString, message.getLevel(), message.getText()
+ );
+ }
+
+ @Override
+ public Image getColumnImage(Object obj, int index) {
+ return getImage(obj);
+ }
+
+ @Override
+ public Image getImage(Object obj) {
+ Level level = ((ITestMessage)obj).getLevel();
+ String imageId = ISharedImages.IMG_OBJ_ELEMENT;
+ for (LevelFilter levelFilter : LevelFilter.values()) {
+ if (levelFilter.isIncluded(level)) {
+ imageId = levelFilter.getImageId();
+ break;
+ }
+ }
+ return PlatformUI.getWorkbench().getSharedImages().getImage(imageId);
+ }
+ }
+
+ /**
+ * Filters the required test messages by level.
+ */
+ private class MessageLevelFilter extends ViewerFilter {
+
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ return acceptedMessageLevels.contains(((ITestMessage)element).getLevel());
+ }
+ }
+
+
+ /** Main widget. */
+ private TableViewer tableViewer;
+
+ private IViewSite viewSite;
+
+ // Context menu actions
+ private OpenInEditorAction openInEditorAction;
+ private Action copyAction;
+
+ /** Specifies whether only messages for failed tests should be shown. */
+ private boolean showFailedOnly = false;
+
+ /**
+ * Specifies whether only file names should be shown (instead of full file
+ * paths).
+ */
+ private boolean showFileNameOnly = false;
+
+ /** The set of message level to show the messages with. */
+ private Set<ITestMessage.Level> acceptedMessageLevels = new HashSet<ITestMessage.Level>();
+
+ /** Specifies whether test messages ordering is on or off. */
+ private boolean orderingMode = false;
+
+
+ public MessagesViewer(Composite parent,
+ TestingSessionsManager sessionsManager, IWorkbench workbench,
+ IViewSite viewSite, Clipboard clipboard) {
+ this.viewSite = viewSite;
+ tableViewer = new TableViewer(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
+ tableViewer.setLabelProvider(new MessagesLabelProvider());
+ tableViewer.setContentProvider(new MessagesContentProvider());
+ tableViewer.addFilter(new MessageLevelFilter());
+ initContextMenu(viewSite, sessionsManager, workbench, clipboard);
+ tableViewer.addOpenListener(new IOpenListener() {
+ @Override
+ public void open(OpenEvent event) {
+ openInEditorAction.run();
+ }
+ });
+ }
+
+ /**
+ * Initializes the viewer context menu.
+ *
+ * @param viewSite view
+ * @param sessionsManager testing sessions manager
+ * @param workbench workbench
+ * @param clipboard clipboard
+ */
+ private void initContextMenu(IViewSite viewSite,
+ TestingSessionsManager sessionsManager, IWorkbench workbench,
+ Clipboard clipboard) {
+ openInEditorAction = new OpenInEditorAction(tableViewer, sessionsManager, workbench);
+ copyAction = new CopySelectedMessagesAction(tableViewer, clipboard);
+
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.addMenuListener(new IMenuListener() {
+ @Override
+ public void menuAboutToShow(IMenuManager manager) {
+ handleMenuAboutToShow(manager);
+ }
+ });
+ viewSite.registerContextMenu(menuMgr, tableViewer);
+ Menu menu = menuMgr.createContextMenu(tableViewer.getTable());
+ tableViewer.getTable().setMenu(menu);
+
+ menuMgr.add(openInEditorAction);
+ menuMgr.add(copyAction);
+ configureCopy();
+ }
+
+ /**
+ * Configures the view copy action which should be run on CTRL+C. We have to
+ * track widget focus to select the actual action because we have a few
+ * widgets that should provide copy action (at least tests hierarchy viewer
+ * and messages viewer).
+ */
+ private void configureCopy() {
+ getTableViewer().getTable().addFocusListener(new FocusListener() {
+ IAction viewCopyHandler;
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ if (viewCopyHandler != null) {
+ switchTo(viewCopyHandler);
+ }
+ }
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ switchTo(copyAction);
+ }
+
+ private void switchTo(IAction copyAction) {
+ IActionBars actionBars = viewSite.getActionBars();
+ viewCopyHandler = actionBars.getGlobalActionHandler(ActionFactory.COPY.getId());
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+ actionBars.updateActionBars();
+ }
+ });
+ }
+
+ /**
+ * Handles the context menu showing.
+ *
+ * @param manager context menu manager
+ */
+ private void handleMenuAboutToShow(IMenuManager manager) {
+ ISelection selection = tableViewer.getSelection();
+ openInEditorAction.setEnabled(!selection.isEmpty());
+ copyAction.setEnabled(!selection.isEmpty());
+ }
+
+ /**
+ * Provides access to the main widget of the messages viewer.
+ *
+ * @return main widget of the messages viewer
+ */
+ public TableViewer getTableViewer() {
+ return tableViewer;
+ }
+
+ /**
+ * Sets the test items for which the messages should be shown.
+ *
+ * @param testItems test items array
+ */
+ public void showItemsMessages(ITestItem[] testItems) {
+ tableViewer.setInput(testItems);
+ }
+
+ /**
+ * Forces the messages recollecting. It is used after message filters
+ * change.
+ */
+ private void forceRecollectMessages() {
+ // NOTE: Set input again makes content provider to recollect messages (with filters applied)
+ tableViewer.setInput(tableViewer.getInput());
+ }
+
+ /**
+ * Returns whether the messages only for the failed tests should be shown.
+ *
+ * @return filter state
+ */
+ public boolean getShowFailedOnly() {
+ return showFailedOnly;
+ }
+
+ /**
+ * Sets whether the messages only for the failed tests should be shown.
+ *
+ * @param showFailedOnly new filter state
+ */
+ public void setShowFailedOnly(boolean showFailedOnly) {
+ if (this.showFailedOnly != showFailedOnly) {
+ this.showFailedOnly = showFailedOnly;
+ forceRecollectMessages();
+ }
+ }
+
+ /**
+ * Returns whether short or long view for file paths should be shown.
+ *
+ * @return filter state
+ */
+ public boolean getShowFileNameOnly() {
+ return showFileNameOnly;
+ }
+
+ /**
+ * Sets whether short or long view for file paths should be shown.
+ *
+ * @param showFileNameOnly new filter state
+ */
+ public void setShowFileNameOnly(boolean showFileNameOnly) {
+ if (this.showFileNameOnly != showFileNameOnly) {
+ this.showFileNameOnly = showFileNameOnly;
+ forceRecollectMessages();
+ }
+ }
+
+ /**
+ * Returns whether test messages should be ordered by location.
+ *
+ * @return messages ordering state
+ */
+ public boolean getOrderingMode() {
+ return orderingMode;
+ }
+
+ /**
+ * Sets whether test messages should be ordered by location.
+ *
+ * @param orderingMode new messages ordering state
+ */
+ public void setOrderingMode(boolean orderingMode) {
+ if (this.orderingMode != orderingMode) {
+ this.orderingMode = orderingMode;
+ forceRecollectMessages();
+ }
+ }
+
+ /**
+ * Adds the filter message level filters by the message filter action level.
+ *
+ * @param levelFilter message filter action level
+ * @param refresh specifies whether viewer should be refreshed after filter
+ * update (small optimization: avoid many updates on initialization)
+ */
+ public void addLevelFilter(LevelFilter levelFilter, boolean refresh) {
+ for (ITestMessage.Level level : levelFilter.getLevels()) {
+ acceptedMessageLevels.add(level);
+ }
+ if (refresh) {
+ tableViewer.refresh();
+ }
+ }
+
+ /**
+ * Removed the filter message level filters by the message filter action
+ * level.
+ *
+ * @param levelFilter message filter action level
+ */
+ public void removeLevelFilter(LevelFilter levelFilter) {
+ for (ITestMessage.Level level : levelFilter.getLevels()) {
+ acceptedMessageLevels.remove(level);
+ }
+ tableViewer.refresh();
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java
new file mode 100644
index 0000000..dc1c004
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressBar.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A progress bar with a red/green indication for testing success or failure.
+ */
+public class ProgressBar extends Canvas {
+
+ /** Default bar width */
+ private static final int DEFAULT_WIDTH = 160;
+
+ /** Default bar height */
+ private static final int DEFAULT_HEIGHT = 18;
+
+ /** Testing session to show progress bar for. */
+ private ITestingSession testingSession;
+
+ /** Current bar width. */
+ private int colorBarWidth;
+
+ /** The bar color when everything is OK (no tests failed and no testing errors). */
+ private Color okColor;
+
+ /** The bar color when there are tests failed and or testing errors. */
+ private Color failureColor;
+
+ /** The bar color when the testing session was stopped by user. */
+ private Color stoppedColor;
+
+
+ public ProgressBar(Composite parent, ITestingSession testingSession) {
+ super(parent, SWT.NONE);
+
+ addControlListener(new ControlAdapter() {
+ @Override
+ public void controlResized(ControlEvent e) {
+ updateInfoFromSession();
+ }
+ });
+ addPaintListener(new PaintListener() {
+ @Override
+ public void paintControl(PaintEvent e) {
+ paint(e);
+ }
+ });
+
+ // Manage progress bar colors
+ Display display = parent.getDisplay();
+ failureColor = new Color(display, 159, 63, 63);
+ okColor = new Color(display, 95, 191, 95);
+ stoppedColor = new Color(display, 120, 120, 120);
+ addDisposeListener(new DisposeListener() {
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ failureColor.dispose();
+ okColor.dispose();
+ stoppedColor.dispose();
+ }
+ });
+ setTestingSession(testingSession);
+ }
+
+ /**
+ * Sets the testing session to show information about.
+ *
+ * @param testingSession testing session (null is not acceptable)
+ */
+ public void setTestingSession(ITestingSession testingSession) {
+ this.testingSession = testingSession;
+ updateInfoFromSession();
+ }
+
+ /**
+ * Updates the progress from the currently set testing session.
+ */
+ public void updateInfoFromSession() {
+ recalculateColorBarWidth();
+ redraw();
+ }
+
+ /**
+ * Sets the color of the progress bar depending on the testing session.
+ *
+ * @param gc gc
+ */
+ private void setStatusColor(GC gc) {
+ if (testingSession.wasStopped())
+ gc.setBackground(stoppedColor);
+ else if (testingSession.hasErrors())
+ gc.setBackground(failureColor);
+ else
+ gc.setBackground(okColor);
+ }
+
+ /**
+ * Calculate the width of the progress rectangle in a widget.
+ *
+ * @note If total tests count is known it is used to determine width of the
+ * progress rectangle. If it isn't the width of progress rectangle is set to
+ * the half of a widget.
+ */
+ private void recalculateColorBarWidth() {
+ Rectangle r = getClientArea();
+ int newColorBarWidth;
+ if (testingSession.getTotalCounter() > 0) {
+ newColorBarWidth = testingSession.getCurrentCounter()*(r.width-2)/testingSession.getTotalCounter();
+ } else {
+ newColorBarWidth = testingSession.getCurrentCounter() > 0 ? (r.width-2)/2 : (testingSession.isFinished() ? r.width-2 : 0);
+ }
+ colorBarWidth = Math.max(0, newColorBarWidth);
+ }
+
+ /**
+ * Draws the widget border
+ */
+ private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
+ gc.setForeground(topleft);
+ gc.drawLine(x, y, x+w-1, y);
+ gc.drawLine(x, y, x, y+h-1);
+
+ gc.setForeground(bottomright);
+ gc.drawLine(x+w, y, x+w, y+h);
+ gc.drawLine(x, y+h, x+w, y+h);
+ }
+
+ /**
+ * Handles paint event and redraws the widget if necessary.
+ *
+ * @param event paint event
+ */
+ private void paint(PaintEvent event) {
+ GC gc = event.gc;
+ Display disp = getDisplay();
+
+ Rectangle rect = getClientArea();
+ gc.fillRectangle(rect);
+ drawBevelRect(gc, rect.x, rect.y, rect.width-1, rect.height-1,
+ disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW),
+ disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
+
+ setStatusColor(gc);
+ colorBarWidth = Math.min(rect.width-2, colorBarWidth);
+ gc.fillRectangle(1, 1, colorBarWidth, rect.height-2);
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ checkWidget();
+ Point size = new Point(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ if (wHint != SWT.DEFAULT) {
+ size.x = wHint;
+ }
+ if (hHint != SWT.DEFAULT) {
+ size.y = hHint;
+ }
+ return size;
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java
new file mode 100644
index 0000000..eb8e65c
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ProgressCountPanel.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A statistics panel that compounds counter panel and red/green progress bar.
+ * Depending on orientation it may layout them vertically or horizontally.
+ */
+public class ProgressCountPanel extends Composite {
+
+ /** Child widget: counter panel. */
+ private CounterPanel counterPanel;
+
+ /** Child widget: red/green progress bar */
+ private ProgressBar progressBar;
+
+ /**
+ * Dummy session is used when there is no "real" testing sessions to show
+ * (e.g. when there was no launched testing session or when all of them were
+ * cleared).
+ */
+ private DummyUISession dummyUISession = new DummyUISession();
+
+
+ public ProgressCountPanel(Composite parent, ResultsView.Orientation currOrientation) {
+ super(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ setLayout(layout);
+ setPanelOrientation(currOrientation);
+
+ counterPanel = new CounterPanel(this, dummyUISession);
+ counterPanel.setLayoutData(
+ new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
+ progressBar = new ProgressBar(this, dummyUISession);
+ progressBar.setLayoutData(
+ new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
+
+ // Data for parent (view's) layout
+ setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
+ }
+
+ /**
+ * Sets the testing session to show information about.
+ *
+ * @param testingSession testing session or null to set default empty
+ * session
+ */
+ public void setTestingSession(ITestingSession testingSession) {
+ ITestingSession newSession = (testingSession != null) ? testingSession : dummyUISession;
+ counterPanel.setTestingSession(newSession);
+ progressBar.setTestingSession(newSession);
+ }
+
+ /**
+ * Updates the information on the panel from the currently set testing
+ * session.
+ */
+ public void updateInfoFromSession() {
+ counterPanel.updateInfoFromSession();
+ progressBar.updateInfoFromSession();
+ }
+
+ /**
+ * Sets the widget orientation.
+ *
+ * @param orientation new widget orientation (vertical or horizontal; auto
+ * is not supported)
+ */
+ public void setPanelOrientation(ResultsView.Orientation orientation) {
+ ((GridLayout)getLayout()).numColumns = (orientation == ResultsView.Orientation.Horizontal) ? 2 : 1;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java
new file mode 100644
index 0000000..50c8d94
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsPanel.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import java.util.Iterator;
+
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.internal.ui.view.MessagesViewer.LevelFilter;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.MessageLevelFilterAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.MessagesOrderingAction;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ToolBarManager;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.ViewForm;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbench;
+
+/**
+ * The main widget of testing results view. It compounds tests hierarchy and
+ * messages viewer. Depending on orientation it may layout them vertically or
+ * horizontally.
+ */
+public class ResultsPanel {
+
+ /** Parent for the child widgets (messages & tests hierarchy viewer). */
+ private SashForm sashForm;
+
+ /** Child widget: messages viewer. */
+ private MessagesViewer messagesViewer;
+
+ /** Child widget: tests hierarchy viewer. */
+ private TestsHierarchyViewer testsHierarchyViewer;
+
+ // Persistence tags
+ static final String TAG_WEIGHT0 = "weight0"; //$NON-NLS-1$
+ static final String TAG_WEIGHT1 = "weight1"; //$NON-NLS-1$
+ static final String TAG_MESSAGES_ORDERING_ACTION = "messagesOrderingAction"; //$NON-NLS-1$
+ static final String TAG_ERROR_FILTER_ACTION = "errorFilterAction"; //$NON-NLS-1$
+ static final String TAG_WARNING_FILTER_ACTION = "warningFilterAction"; //$NON-NLS-1$
+ static final String TAG_INFO_FILTER_ACTION = "infoFilterAction"; //$NON-NLS-1$
+
+ // Messages Viewer actions
+ Action messagesOrderingAction;
+ Action errorFilterAction;
+ Action warningFilterAction;
+ Action infoFilterAction;
+
+
+ public ResultsPanel(Composite parent, TestingSessionsManager sessionsManager, IWorkbench workbench, IViewSite site, Clipboard clipboard) {
+ sashForm = new SashForm(parent, SWT.VERTICAL);
+
+ // Configure tests hierarchy viewer
+ ViewForm top = new ViewForm(sashForm, SWT.NONE);
+ Composite empty = new Composite(top, SWT.NONE);
+ empty.setLayout(new Layout() {
+ @Override
+ protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
+ return new Point(1, 1); // (0, 0) does not work with super-intelligent ViewForm
+ }
+ @Override
+ protected void layout(Composite composite, boolean flushCache) {}
+ });
+ top.setTopLeft(empty); // makes ViewForm draw the horizontal separator line ...
+ testsHierarchyViewer = new TestsHierarchyViewer(top, site, clipboard);
+ top.setContent(testsHierarchyViewer.getTreeViewer().getControl());
+
+ // Configure test messages viewer
+ ViewForm bottom = new ViewForm(sashForm, SWT.NONE);
+ messagesViewer = new MessagesViewer(bottom, sessionsManager, workbench, site, clipboard);
+ Composite topLeftPanel = new Composite(bottom, SWT.NONE);
+ RowLayout topLeftPanelLayout = new RowLayout(SWT.HORIZONTAL);
+ topLeftPanelLayout.spacing = 0;
+ topLeftPanelLayout.center = true;
+ topLeftPanelLayout.marginBottom = topLeftPanelLayout.marginLeft = topLeftPanelLayout.marginRight = topLeftPanelLayout.marginTop = 0;
+ topLeftPanel.setLayout(topLeftPanelLayout);
+ ToolBar leftMessagesToolBar = new ToolBar(topLeftPanel, SWT.FLAT | SWT.WRAP);
+ ToolBarManager leftMessagesToolBarManager = new ToolBarManager(leftMessagesToolBar);
+ messagesOrderingAction = new MessagesOrderingAction(messagesViewer);
+ leftMessagesToolBarManager.add(messagesOrderingAction);
+ leftMessagesToolBarManager.update(true);
+ CLabel label = new CLabel(topLeftPanel, SWT.NONE);
+ label.setText(UIViewMessages.MessagesPanel_label);
+ bottom.setTopLeft(topLeftPanel);
+ ToolBar rightMessagesToolBar = new ToolBar(bottom, SWT.FLAT | SWT.WRAP);
+ ToolBarManager rightMessagesToolBarManager = new ToolBarManager(rightMessagesToolBar);
+ errorFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Error, true);
+ warningFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Warning, true);
+ infoFilterAction = new MessageLevelFilterAction(messagesViewer, LevelFilter.Info, false);
+ rightMessagesToolBarManager.add(errorFilterAction);
+ rightMessagesToolBarManager.add(warningFilterAction);
+ rightMessagesToolBarManager.add(infoFilterAction);
+ rightMessagesToolBarManager.update(true);
+ bottom.setTopCenter(rightMessagesToolBar);
+ bottom.setContent(messagesViewer.getTableViewer().getControl());
+
+ sashForm.setWeights(new int[]{50, 50});
+
+ testsHierarchyViewer.getTreeViewer().addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ handleTestItemSelected();
+ }
+ });
+
+ // Initialize default value
+ setShowFailedOnly(false);
+
+ // Data for parent (view's) layout
+ sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
+ }
+
+ /**
+ * Provides access to the tests hierarchy viewer.
+ *
+ * @return tests hierarchy viewer
+ */
+ public TestsHierarchyViewer getTestsHierarchyViewer() {
+ return testsHierarchyViewer;
+ }
+
+ /**
+ * Provides access to the messages viewer.
+ *
+ * @return messages viewer
+ */
+ public MessagesViewer getMessagesViewer() {
+ return messagesViewer;
+ }
+
+ /**
+ * Handles selection change in tests hierarchy viewer and updates the
+ * content of the messages viewer to show the messages for the selected
+ * items.
+ */
+ private void handleTestItemSelected() {
+ IStructuredSelection selection = (IStructuredSelection)testsHierarchyViewer.getTreeViewer().getSelection();
+ ITestItem[] testItems = new ITestItem[selection.size()];
+ int index = 0;
+ for (Iterator<?> it = selection.iterator(); it.hasNext();) {
+ testItems[index] = (ITestItem)it.next();
+ ++index;
+ }
+ messagesViewer.showItemsMessages(testItems);
+ }
+
+ /**
+ * Sets the widget orientation.
+ *
+ * @param orientation new widget orientation (vertical or horizontal; auto
+ * is not supported)
+ */
+ public void setPanelOrientation(ResultsView.Orientation orientation) {
+ sashForm.setOrientation(orientation == ResultsView.Orientation.Horizontal ? SWT.HORIZONTAL : SWT.VERTICAL);
+ }
+
+ /**
+ * Returns whether only failed tests (and messages for them) should be
+ * shown.
+ *
+ * @return filter state
+ */
+ public boolean getShowFailedOnly() {
+ return messagesViewer.getShowFailedOnly();
+ }
+
+ /**
+ * Sets whether only failed tests (and messages for them) should be shown.
+ *
+ * @param showFailedOnly new filter state
+ */
+ public void setShowFailedOnly(boolean showFailedOnly) {
+ testsHierarchyViewer.setShowFailedOnly(showFailedOnly);
+ messagesViewer.setShowFailedOnly(showFailedOnly);
+ }
+
+ /**
+ * Restores the value of the checkable action.
+ *
+ * @param memento previously saved state to restore the action value from
+ * @param key tag name that is used to restore the value
+ * @param action action to restore
+ */
+ private void restoreActionChecked(IMemento memento, String key, Action action) {
+ Boolean checked = memento.getBoolean(key);
+ if (checked != null) {
+ action.setChecked(checked);
+ action.run();
+ }
+ }
+
+ /**
+ * Restores the state of the widget.
+ *
+ * @param memento previously saved state
+ */
+ public void restoreState(IMemento memento) {
+ Integer weight0 = memento.getInteger(TAG_WEIGHT0);
+ Integer weight1 = memento.getInteger(TAG_WEIGHT1);
+ if (weight0 != null && weight1 != null) {
+ sashForm.setWeights(new int[] {weight0, weight1});
+ }
+ restoreActionChecked(memento, TAG_MESSAGES_ORDERING_ACTION, messagesOrderingAction);
+ restoreActionChecked(memento, TAG_ERROR_FILTER_ACTION, errorFilterAction);
+ restoreActionChecked(memento, TAG_WARNING_FILTER_ACTION, warningFilterAction);
+ restoreActionChecked(memento, TAG_INFO_FILTER_ACTION, infoFilterAction);
+ }
+
+ /**
+ * Saves the state of the widget.
+ *
+ * @param memento where to save the state
+ */
+ public void saveState(IMemento memento) {
+ int[] weights = sashForm.getWeights();
+ memento.putInteger(TAG_WEIGHT0, weights[0]);
+ memento.putInteger(TAG_WEIGHT1, weights[1]);
+ memento.putBoolean(TAG_MESSAGES_ORDERING_ACTION, messagesOrderingAction.isChecked());
+ memento.putBoolean(TAG_ERROR_FILTER_ACTION, errorFilterAction.isChecked());
+ memento.putBoolean(TAG_WARNING_FILTER_ACTION, warningFilterAction.isChecked());
+ memento.putBoolean(TAG_INFO_FILTER_ACTION, infoFilterAction.isChecked());
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java
new file mode 100644
index 0000000..585cf84
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/ResultsView.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.HistoryDropDownAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RerunAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ScrollLockAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFailedOnlyAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowFileNameOnlyAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowNextFailureAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowPreviousFailureAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTestsInHierarchyAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ShowTimeAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.StopAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.ToggleOrientationAction;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.IToolBarManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Represents a view part showing the testing results (count statistics,
+ * red/green bar, tests hierarchy and test messages).
+ */
+public class ResultsView extends ViewPart {
+
+ /**
+ * Represents view orientation
+ *
+ * @note <code>Auto</code> state may be not acceptable for some methods (see
+ * their comments for details).
+ */
+ public enum Orientation {
+ Horizontal,
+ Vertical,
+ Auto,
+ }
+
+ /** View parent. */
+ private Composite parent;
+
+ /** Child widget: statistics viewer. */
+ private ProgressCountPanel progressCountPanel;
+
+ /** Tests hierarchy and message viewer. */
+ private ResultsPanel resultsPanel;
+
+ /** User interface updater instance. */
+ private UIUpdater uiUpdater;
+
+ /** The reference to the testing sessions manager instance. */
+ private TestingSessionsManager sessionsManager;
+
+ /** Shows whether the results view was disposed. */
+ private boolean isDisposed = false;
+
+ // Toolbar & view menu actions
+ private Action nextAction;
+ private Action previousAction;
+ private Action rerunAction;
+ private Action stopAction;
+ private ToggleOrientationAction[] toggleOrientationActions;
+ private Action historyAction;
+ private Action showFailedOnly;
+ private Action showTestsInHierarchyAction;
+ private Action showTimeAction;
+ private Action scrollLockAction;
+ private Action showFileNameOnlyAction;
+
+ /**
+ * The current orientation preference (Horizontal, Vertical, Auto).
+ */
+ private Orientation orientation = Orientation.Auto;
+
+ /**
+ * The current view orientation (Horizontal or Vertical).
+ */
+ private Orientation currentOrientation;
+
+ /**
+ * Previously saved state. It is used to store the same state if the view
+ * was not opened.
+ */
+ private IMemento memento;
+
+ // Persistence tags
+ static final String TAG_ORIENTATION = "orientation"; //$NON-NLS-1$
+ static final String TAG_SHOW_FAILED_ONLY = "showFailedOnly"; //$NON-NLS-1$
+ static final String TAG_SHOW_TESTS_IN_HIERARCHY = "showTestsInHierarchy"; //$NON-NLS-1$
+ static final String TAG_SHOW_TIME = "showTime"; //$NON-NLS-1$
+ static final String TAG_SCROLL_LOCK = "scrollLock"; //$NON-NLS-1$
+ static final String TAG_SHOW_FILE_NAME_ONLY_ACTION = "showFileNameOnly"; //$NON-NLS-1$
+ static final String TAG_HISTORY_SIZE = "history_size"; //$NON-NLS-1$
+
+
+ @Override
+ public void createPartControl(Composite parent) {
+ sessionsManager = TestsRunnerPlugin.getDefault().getTestingSessionsManager();
+ IWorkbench workbench = TestsRunnerPlugin.getDefault().getWorkbench();
+ Clipboard clipboard = new Clipboard(parent.getDisplay());
+
+ this.parent = parent;
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ parent.setLayout(gridLayout);
+ currentOrientation = getActualOrientation();
+
+ progressCountPanel = new ProgressCountPanel(parent, currentOrientation);
+ resultsPanel = new ResultsPanel(parent, sessionsManager, workbench, getViewSite(), clipboard);
+ uiUpdater = new UIUpdater(this, resultsPanel.getTestsHierarchyViewer(), progressCountPanel, sessionsManager);
+ configureActionsBars();
+
+ parent.addControlListener(new ControlListener() {
+ @Override
+ public void controlMoved(ControlEvent e) {
+ }
+ @Override
+ public void controlResized(ControlEvent e) {
+ computeOrientation();
+ }
+ });
+
+ restoreState(memento);
+ uiUpdater.reapplyActiveSession();
+ }
+
+ @Override
+ public void setFocus() {
+ resultsPanel.getTestsHierarchyViewer().getTreeViewer().getControl().setFocus();
+ }
+
+ /**
+ * Configures the view tool bar and menu.
+ */
+ private void configureActionsBars() {
+ IActionBars actionBars = getViewSite().getActionBars();
+
+ // Create common action
+ toggleOrientationActions = new ToggleOrientationAction[] {
+ new ToggleOrientationAction(this, Orientation.Vertical),
+ new ToggleOrientationAction(this, Orientation.Horizontal),
+ new ToggleOrientationAction(this, Orientation.Auto),
+ };
+
+ nextAction = new ShowNextFailureAction(resultsPanel.getTestsHierarchyViewer());
+ nextAction.setEnabled(false);
+ actionBars.setGlobalActionHandler(ActionFactory.NEXT.getId(), nextAction);
+
+ previousAction = new ShowPreviousFailureAction(resultsPanel.getTestsHierarchyViewer());
+ previousAction.setEnabled(false);
+ actionBars.setGlobalActionHandler(ActionFactory.PREVIOUS.getId(), previousAction);
+
+ showFailedOnly = new ShowFailedOnlyAction(resultsPanel);
+ showTestsInHierarchyAction = new ShowTestsInHierarchyAction(resultsPanel.getTestsHierarchyViewer());
+ showTimeAction = new ShowTimeAction(resultsPanel.getTestsHierarchyViewer());
+ scrollLockAction = new ScrollLockAction(uiUpdater);
+ showFileNameOnlyAction = new ShowFileNameOnlyAction(resultsPanel.getMessagesViewer());
+ rerunAction = new RerunAction(sessionsManager);
+ rerunAction.setEnabled(false);
+ stopAction = new StopAction(sessionsManager);
+ stopAction.setEnabled(false);
+
+ historyAction = new HistoryDropDownAction(sessionsManager, parent.getShell());
+
+ // Configure toolbar
+ IToolBarManager toolBar = actionBars.getToolBarManager();
+ toolBar.add(nextAction);
+ toolBar.add(previousAction);
+ toolBar.add(showFailedOnly);
+ toolBar.add(scrollLockAction);
+ toolBar.add(new Separator());
+ toolBar.add(rerunAction);
+ toolBar.add(stopAction);
+ toolBar.add(historyAction);
+
+ // Configure view menu
+ IMenuManager viewMenu = actionBars.getMenuManager();
+ viewMenu.add(showTestsInHierarchyAction);
+ viewMenu.add(showTimeAction);
+ viewMenu.add(new Separator());
+ MenuManager layoutSubMenu = new MenuManager(UIViewMessages.ResultsView_layout_menu_text);
+ for (int i = 0; i < toggleOrientationActions.length; ++i) {
+ layoutSubMenu.add(toggleOrientationActions[i]);
+ }
+ viewMenu.add(layoutSubMenu);
+ viewMenu.add(new Separator());
+ viewMenu.add(showFailedOnly);
+ viewMenu.add(showFileNameOnlyAction);
+ }
+
+ @Override
+ public void dispose() {
+ isDisposed = true;
+ if (uiUpdater != null) {
+ uiUpdater.dispose();
+ }
+ }
+
+ /**
+ * Changes the view orientation
+ *
+ * @param orientation new view orientation (Horizontal, Vertical, Auto)
+ */
+ public void setOrientation(Orientation orientation) {
+ this.orientation = orientation;
+ computeOrientation();
+ }
+
+ /**
+ * Checks whether actual orientation is changed and changes orientation of
+ * the child widgets.
+ */
+ private void computeOrientation() {
+ Orientation newActualOrientation = getActualOrientation();
+ if (newActualOrientation != currentOrientation) {
+ currentOrientation = newActualOrientation;
+ progressCountPanel.setPanelOrientation(currentOrientation);
+ resultsPanel.setPanelOrientation(currentOrientation);
+ for (int i = 0; i < toggleOrientationActions.length; ++i) {
+ toggleOrientationActions[i].setChecked(orientation == toggleOrientationActions[i].getOrientation());
+ }
+ parent.layout();
+ }
+ }
+
+ /**
+ * Recalculates actual view orientation depending on the specified by user
+ * orientation value and current view size.
+ *
+ * @param orientation by user specified orientation
+ * @return actual orientation
+ */
+ private Orientation getActualOrientation() {
+ switch (orientation) {
+ case Horizontal:
+ case Vertical:
+ return orientation;
+ case Auto:
+ Point size = parent.getSize();
+ return (size.x > size.y) ? Orientation.Horizontal : Orientation.Vertical;
+ }
+ return null;
+ }
+
+ /**
+ * Updates view actions state from the active session.
+ */
+ public void updateActionsFromSession() {
+ ITestingSession session = sessionsManager.getActiveSession();
+ boolean hasErrors = session != null && session.hasErrors();
+ previousAction.setEnabled(hasErrors);
+ nextAction.setEnabled(hasErrors);
+ rerunAction.setEnabled(session != null && session.isFinished());
+ stopAction.setEnabled(session != null && !session.isFinished());
+ }
+
+ /**
+ * Changes the view caption.
+ *
+ * @param message new view caption
+ */
+ public void setCaption(String message) {
+ setContentDescription(message);
+ }
+
+ @Override
+ public void init(IViewSite site, IMemento memento) throws PartInitException {
+ super.init(site, memento);
+ this.memento = memento;
+ }
+
+ /**
+ * Restores the value of the checkable action.
+ *
+ * @param memento previously saved state to restore the action value from
+ * @param key tag name that is used to restore the value
+ * @param action action to restore
+ */
+ private void restoreActionChecked(IMemento memento, String key, Action action) {
+ Boolean checked = memento.getBoolean(key);
+ if (checked != null) {
+ action.setChecked(checked);
+ action.run();
+ }
+ }
+
+ /**
+ * Restores the state of the view.
+ *
+ * @param memento previously saved state
+ */
+ private void restoreState(IMemento memento) {
+ if (memento != null) {
+ Integer orientationIndex = memento.getInteger(TAG_ORIENTATION);
+ if (orientationIndex != null) {
+ setOrientation(Orientation.values()[orientationIndex]);
+ }
+ resultsPanel.restoreState(memento);
+ restoreActionChecked(memento, TAG_SHOW_FAILED_ONLY, showFailedOnly);
+ restoreActionChecked(memento, TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction);
+ restoreActionChecked(memento, TAG_SHOW_TIME, showTimeAction);
+ restoreActionChecked(memento, TAG_SCROLL_LOCK, scrollLockAction);
+ restoreActionChecked(memento, TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction);
+ Integer historySize = memento.getInteger(TAG_HISTORY_SIZE);
+ if (historySize != null) {
+ sessionsManager.setHistorySizeLimit(historySize);
+ }
+ }
+ }
+
+ @Override
+ public void saveState(IMemento memento) {
+ //Keep the old state;
+ if (parent == null) {
+ if (this.memento != null) {
+ memento.putMemento(this.memento);
+ }
+ return;
+ }
+
+ memento.putInteger(TAG_ORIENTATION, orientation.ordinal());
+ resultsPanel.saveState(memento);
+ memento.putBoolean(TAG_SHOW_FAILED_ONLY, showFailedOnly.isChecked());
+ memento.putBoolean(TAG_SHOW_TESTS_IN_HIERARCHY, showTestsInHierarchyAction.isChecked());
+ memento.putBoolean(TAG_SHOW_TIME, showTimeAction.isChecked());
+ memento.putBoolean(TAG_SCROLL_LOCK, scrollLockAction.isChecked());
+ memento.putBoolean(TAG_SHOW_FILE_NAME_ONLY_ACTION, showFileNameOnlyAction.isChecked());
+ memento.putInteger(TAG_HISTORY_SIZE, sessionsManager.getHistorySizeLimit());
+ }
+
+ /**
+ * Returns whether the view was disposed.
+ *
+ * @return true if the view was disposed
+ */
+ public boolean isDisposed() {
+ return isDisposed;
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java
new file mode 100644
index 0000000..5127544
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestPathUtils.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+
+/**
+ * The utilities collection to work with the test paths for items in test
+ * hierarchy.
+ */
+public class TestPathUtils {
+
+ /**
+ * The delimiter between parts of serialized test path. Should not be met in
+ * test paths names.
+ */
+ private static final String TEST_PATH_PART_DELIMITER = "\n"; //$NON-NLS-1$
+
+ /** The delimiter between parts of human readable test path. */
+ private static final String TEST_PATH_DELIMITER = "."; //$NON-NLS-1$
+
+ /**
+ * Returns the human readable path to the item in test hierarchy (e.g.
+ * MySuite.MyInnerSuite.MyTest1).
+ *
+ * @param testItem test item (test suite or test case)
+ *
+ * @return path to test item
+ */
+ public static String getTestItemPath(ITestItem testItem) {
+ StringBuilder itemPath = new StringBuilder();
+ List<ITestItem> parentItems = new ArrayList<ITestItem>();
+ while (testItem != null) {
+ parentItems.add(testItem);
+ testItem = testItem.getParent();
+ }
+ if (!parentItems.isEmpty()) {
+ for (int i = parentItems.size()-2/* exclude unnamed root test suite */; i >= 0; --i) {
+ itemPath.append(parentItems.get(i).getName());
+ if (i != 0) {
+ itemPath.append(TEST_PATH_DELIMITER);
+ }
+ }
+ }
+ return itemPath.toString();
+ }
+
+ /**
+ * Unpack the paths from the string list.
+ *
+ * @param testPaths packed test paths
+ * @return array of test paths
+ *
+ * @see packTestPaths()
+ */
+ public static String[][] unpackTestPaths(String[] testPaths) {
+ String [][] result = new String[testPaths.length][];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = testPaths[i].split(TEST_PATH_PART_DELIMITER);
+ }
+ return result;
+ }
+
+ /**
+ * Pack the paths to specified test items to string list.
+ *
+ * @param testItems test items to pack
+ * @return string list
+ *
+ * @see unpackTestPaths()
+ */
+ public static String[] packTestPaths(ITestItem[] testItems) {
+ String [] result = new String[testItems.length];
+ List<String> testPath = new ArrayList<String>();
+
+ for (int itemIdx = 0; itemIdx < testItems.length; itemIdx++) {
+ // Collect test path parts (in reverse order)
+ testPath.clear();
+ ITestItem item = testItems[itemIdx];
+ while (item != null) {
+ // Exclude root test suite
+ if (item.getParent()!= null) {
+ testPath.add(item.getName());
+ }
+ item = item.getParent();
+ }
+ // Join path parts into the only string
+ StringBuilder sb = new StringBuilder();
+ boolean needDelimiter = false;
+ for (int pathPartIdx = testPath.size()-1; pathPartIdx >= 0; pathPartIdx--) {
+ if (needDelimiter) {
+ sb.append(TEST_PATH_PART_DELIMITER);
+ } else {
+ needDelimiter = true;
+ }
+ sb.append(testPath.get(pathPartIdx));
+ }
+ result[itemIdx] = sb.toString();
+ }
+ return result;
+ }
+
+}
+
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java
new file mode 100644
index 0000000..117a7b3
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/TestsHierarchyViewer.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.cdt.internal.ui.viewsupport.ColoringLabelProvider;
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.CopySelectedTestsAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RedebugSelectedAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RelaunchSelectedAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.RerunSelectedAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.TestsHierarchyCollapseAllAction;
+import org.eclipse.cdt.testsrunner.internal.ui.view.actions.TestsHierarchyExpandAllAction;
+import org.eclipse.cdt.testsrunner.model.IModelVisitor;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestMessage;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StyledCellLabelProvider;
+import org.eclipse.jface.viewers.StyledString;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IActionBars;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.actions.ActionFactory;
+
+/**
+ * Shows the tests hierarchy in a flat or hierarchical view.
+ */
+public class TestsHierarchyViewer {
+
+ /**
+ * The content provider for the tests hierarchy viewer.
+ */
+ private class TestTreeContentProvider implements ITreeContentProvider {
+
+ /**
+ * Utility class: recursively collects all the test cases of the
+ * specified test item.
+ *
+ * It is used for flat view of tests hierarchy.
+ */
+ private class TestCasesCollector implements IModelVisitor {
+
+ public List<ITestCase> testCases = new ArrayList<ITestCase>();
+
+ @Override
+ public void visit(ITestCase testCase) {
+ testCases.add(testCase);
+ }
+
+ @Override
+ public void visit(ITestMessage testMessage) {}
+ @Override
+ public void visit(ITestSuite testSuite) {}
+ @Override
+ public void leave(ITestSuite testSuite) {}
+ @Override
+ public void leave(ITestCase testCase) {}
+ @Override
+ public void leave(ITestMessage testMessage) {}
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ return ((ITestItem) parentElement).getChildren();
+ }
+
+ @Override
+ public Object[] getElements(Object rootTestSuite) {
+ if (showTestsHierarchy) {
+ return getChildren(rootTestSuite);
+ } else {
+ TestCasesCollector testCasesCollector = new TestCasesCollector();
+ ((ITestItem)rootTestSuite).visit(testCasesCollector);
+ return testCasesCollector.testCases.toArray();
+ }
+ }
+
+ @Override
+ public Object getParent(Object object) {
+ return ((ITestItem) object).getParent();
+ }
+
+ @Override
+ public boolean hasChildren(Object object) {
+ return ((ITestItem) object).hasChildren();
+ }
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+
+ @Override
+ public void dispose() {}
+ }
+
+ /**
+ * The label provider for the tests hierarchy viewer.
+ */
+ private class TestLabelProvider extends LabelProvider implements IStyledLabelProvider {
+
+ /** Images for the test cases with the different statuses. */
+ private Map<ITestItem.Status, Image> testCaseImages = new HashMap<ITestItem.Status, Image>();
+ {
+ testCaseImages.put(ITestItem.Status.NotRun, TestsRunnerPlugin.createAutoImage("obj16/test_notrun.gif")); //$NON-NLS-1$
+ testCaseImages.put(ITestItem.Status.Skipped, TestsRunnerPlugin.createAutoImage("obj16/test_skipped.gif")); //$NON-NLS-1$
+ testCaseImages.put(ITestItem.Status.Passed, TestsRunnerPlugin.createAutoImage("obj16/test_passed.gif")); //$NON-NLS-1$
+ testCaseImages.put(ITestItem.Status.Failed, TestsRunnerPlugin.createAutoImage("obj16/test_failed.gif")); //$NON-NLS-1$
+ testCaseImages.put(ITestItem.Status.Aborted, TestsRunnerPlugin.createAutoImage("obj16/test_aborted.gif")); //$NON-NLS-1$
+ }
+
+ /** Running test case image (overrides the test case status image). */
+ private Image testCaseRunImage = TestsRunnerPlugin.createAutoImage("obj16/test_run.gif"); //$NON-NLS-1$
+
+ /** Images for the test suites with the different statuses. */
+ private Map<ITestItem.Status, Image> testSuiteImages = new HashMap<ITestItem.Status, Image>();
+ {
+ // NOTE: There is no skipped-icon for test suite, but it seems it is not a problem
+ testSuiteImages.put(ITestItem.Status.NotRun, TestsRunnerPlugin.createAutoImage("obj16/tsuite_notrun.gif")); //$NON-NLS-1$
+ testSuiteImages.put(ITestItem.Status.Skipped, TestsRunnerPlugin.createAutoImage("obj16/tsuite_notrun.gif")); //$NON-NLS-1$
+ testSuiteImages.put(ITestItem.Status.Passed, TestsRunnerPlugin.createAutoImage("obj16/tsuite_passed.gif")); //$NON-NLS-1$
+ testSuiteImages.put(ITestItem.Status.Failed, TestsRunnerPlugin.createAutoImage("obj16/tsuite_failed.gif")); //$NON-NLS-1$
+ testSuiteImages.put(ITestItem.Status.Aborted, TestsRunnerPlugin.createAutoImage("obj16/tsuite_aborted.gif")); //$NON-NLS-1$
+ }
+
+ /** Running test suite image (overrides the test suite status image). */
+ private Image testSuiteRunImage = TestsRunnerPlugin.createAutoImage("obj16/tsuite_run.gif"); //$NON-NLS-1$
+
+ /** Small optimization: the last test item cache */
+ private ITestItem lastTestItemCache = null;
+
+ /** Small optimization: test path for the last test item is cache */
+ private String lastTestItemPathCache = null;
+
+
+ @Override
+ public Image getImage(Object element) {
+ Map<ITestItem.Status, Image> imagesMap = null;
+ Image runImage = null;
+ if (element instanceof ITestCase) {
+ imagesMap = testCaseImages;
+ runImage = testCaseRunImage;
+
+ } else if (element instanceof ITestSuite) {
+ imagesMap = testSuiteImages;
+ runImage = testSuiteRunImage;
+ }
+ if (imagesMap != null) {
+ ITestItem testItem = (ITestItem)element;
+ if (testingSession.getModelAccessor().isCurrentlyRunning(testItem)) {
+ return runImage;
+ }
+ return imagesMap.get(testItem.getStatus());
+ }
+
+ return null;
+ }
+
+ @Override
+ public String getText(Object element) {
+ ITestItem testItem = (ITestItem)element;
+ StringBuilder sb = new StringBuilder();
+ sb.append(testItem.getName());
+ if (!showTestsHierarchy) {
+ appendTestItemPath(sb, testItem);
+ }
+ if (showTime) {
+ sb.append(getTestingTimeString(element));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public StyledString getStyledText(Object element) {
+ ITestItem testItem = (ITestItem)element;
+ StringBuilder labelBuf = new StringBuilder();
+ labelBuf.append(testItem.getName());
+ StyledString name = new StyledString(labelBuf.toString());
+ if (!showTestsHierarchy) {
+ appendTestItemPath(labelBuf, testItem);
+ name = StyledCellLabelProvider.styleDecoratedString(labelBuf.toString(), StyledString.QUALIFIER_STYLER, name);
+ }
+ if (showTime) {
+ String time = getTestingTimeString(element);
+ labelBuf.append(time);
+ name = StyledCellLabelProvider.styleDecoratedString(labelBuf.toString(), StyledString.COUNTER_STYLER, name);
+ }
+ return name;
+ }
+
+ /**
+ * Appends path to the parent of the specified test item. Also
+ * implements caching of the last path (cause the test item parent is
+ * often the same).
+ *
+ * @param sb string builder to append test item path to
+ * @param testItem specified test item
+ */
+ private void appendTestItemPath(StringBuilder sb, ITestItem testItem) {
+ ITestSuite testItemParent = testItem.getParent();
+ if (lastTestItemCache != testItemParent) {
+ lastTestItemCache = testItemParent;
+ lastTestItemPathCache = TestPathUtils.getTestItemPath(lastTestItemCache);
+ }
+ sb.append(MessageFormat.format(
+ UIViewMessages.TestsHierarchyViewer_test_path_format,
+ new Object[] { lastTestItemPathCache }
+ ));
+ }
+
+ /**
+ * Returns the execution time suffix for the test item.
+ *
+ * @param element test item
+ * @return execution time suffix
+ */
+ private String getTestingTimeString(Object element) {
+ return (element instanceof ITestItem)
+ ? MessageFormat.format(UIViewMessages.TestsHierarchyViewer_test_time_format, Double.toString(((ITestItem)element).getTestingTime()/1000.0))
+ : ""; //$NON-NLS-1$
+ }
+
+ }
+
+ /**
+ * Filters passed test cases and test suites.
+ */
+ private class FailedOnlyFilter extends ViewerFilter {
+
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ return ((ITestItem)element).getStatus().isError();
+ }
+ }
+
+ /** Testing session to show hierarchy of. */
+ private ITestingSession testingSession;
+
+ /** Main widget. */
+ private TreeViewer treeViewer;
+
+ /** Specifies whether test items execution time should be shown in hierarchy. */
+ private boolean showTime = true;
+
+ /** Specifies whether tests hierarchy should be shown in flat or hierarchical view. */
+ private boolean showTestsHierarchy = true;
+
+ /** Failed only tree filter instance. Created on first demand. */
+ private FailedOnlyFilter failedOnlyFilter = null;
+
+ /** System clipboard access to provide copy operations. */
+ private Clipboard clipboard;
+
+ // Context menu actions
+ private Action expandAllAction;
+ private Action collapseAllAction;
+ private Action copyAction;
+ private RelaunchSelectedAction rerunAction;
+ private RelaunchSelectedAction redebugAction;
+
+
+ public TestsHierarchyViewer(Composite parent, IViewSite viewSite, Clipboard clipboard) {
+ this.clipboard = clipboard;
+ treeViewer = new TreeViewer(parent, SWT.V_SCROLL | SWT.MULTI);
+ treeViewer.setContentProvider(new TestTreeContentProvider());
+ treeViewer.setLabelProvider(new ColoringLabelProvider(new TestLabelProvider()));
+ initContextMenu(viewSite);
+ }
+
+ /**
+ * Initializes the viewer context menu.
+ *
+ * @param viewSite view
+ */
+ private void initContextMenu(IViewSite viewSite) {
+ expandAllAction = new TestsHierarchyExpandAllAction(treeViewer);
+ collapseAllAction = new TestsHierarchyCollapseAllAction(treeViewer);
+ copyAction = new CopySelectedTestsAction(treeViewer, clipboard);
+ rerunAction = new RerunSelectedAction(testingSession, treeViewer);
+ redebugAction = new RedebugSelectedAction(testingSession, treeViewer);
+
+ MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ menuMgr.addMenuListener(new IMenuListener() {
+ @Override
+ public void menuAboutToShow(IMenuManager manager) {
+ handleMenuAboutToShow(manager);
+ }
+ });
+ viewSite.registerContextMenu(menuMgr, treeViewer);
+ Menu menu = menuMgr.createContextMenu(treeViewer.getTree());
+ treeViewer.getTree().setMenu(menu);
+
+ menuMgr.add(copyAction);
+ menuMgr.add(new Separator());
+ menuMgr.add(rerunAction);
+ menuMgr.add(redebugAction);
+ menuMgr.add(new Separator());
+ menuMgr.add(expandAllAction);
+ menuMgr.add(collapseAllAction);
+
+ IActionBars actionBars = viewSite.getActionBars();
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(), copyAction);
+ actionBars.updateActionBars();
+ }
+
+ /**
+ * Handles the context menu showing.
+ *
+ * @param manager context menu manager
+ */
+ private void handleMenuAboutToShow(IMenuManager manager) {
+ IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection();
+ boolean isRelaunchEnabledForSelection = !selection.isEmpty() &&
+ (testingSession.getTestsRunnerProviderInfo().isAllowedMultipleTestFilter() || (selection.size() == 1));
+ rerunAction.setEnabled(isRelaunchEnabledForSelection);
+ rerunAction.setTestingSession(testingSession);
+ redebugAction.setEnabled(isRelaunchEnabledForSelection);
+ redebugAction.setTestingSession(testingSession);
+ copyAction.setEnabled(!selection.isEmpty());
+
+ boolean hasAnything = treeViewer.getInput() != null;
+ expandAllAction.setEnabled(hasAnything);
+ collapseAllAction.setEnabled(hasAnything);
+ }
+
+ /**
+ * Sets the testing session to show.
+ *
+ * @param testingSession testing session or null to set default empty
+ * session
+ */
+ public void setTestingSession(ITestingSession testingSession) {
+ this.testingSession = testingSession;
+ treeViewer.setInput(testingSession != null ? testingSession.getModelAccessor().getRootSuite() : null);
+ }
+
+ /**
+ * Provides access to the main widget of the tests hierarchy viewer.
+ *
+ * @return main widget of the tests hierarchy viewer
+ */
+ public TreeViewer getTreeViewer() {
+ return treeViewer;
+ }
+
+ /**
+ * Move the selection to the next failed test case.
+ */
+ public void showNextFailure() {
+ showFailure(true);
+ }
+
+ /**
+ * Move the selection to the previous failed test case.
+ */
+ public void showPreviousFailure() {
+ showFailure(false);
+ }
+
+ /**
+ * Common implementation for movement the selection to the next or previous
+ * failed test case.
+ *
+ * @param next true if the next failed test case should be selected and false otherwise
+ */
+ private void showFailure(boolean next) {
+ IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection();
+ ITestItem selected = (ITestItem) selection.getFirstElement();
+ ITestItem failedItem;
+
+ if (selected == null) {
+ ITestItem rootSuite = (ITestItem)treeViewer.getInput();
+ // For next element we should also check its children, for previous shouldn't.
+ failedItem = findFailedImpl(rootSuite, null, next, next);
+ } else {
+ // For next element we should also check its children, for previous shouldn't.
+ failedItem = findFailedImpl(selected.getParent(), selected, next, next);
+ }
+
+ if (failedItem != null)
+ getTreeViewer().setSelection(new StructuredSelection(failedItem), true);
+ }
+
+ /**
+ * Returns the next or previous failed test case relatively to the
+ * <code>currItem</code> that should be a child of <code>parentItem</code>.
+ * If the such item was not found through the children, it steps up to the
+ * parent and continues search.
+ *
+ * @param parentItem parent test item to the current one
+ * @param currItem current item search should be started from or null if
+ * there is no any
+ * @param next true if the next failed test case should be looked for and
+ * false otherwise
+ * @param checkCurrentChild specifies whether the search should be also
+ * through the children for the current item
+ * @return found item or null
+ */
+ private ITestItem findFailedImpl(ITestItem parentItem, ITestItem currItem, boolean next, boolean checkCurrentChild) {
+ ITestItem result = findFailedChild(parentItem, currItem, next, checkCurrentChild);
+ if (result != null) {
+ return result;
+ }
+ // Nothing found at this level - try to step up
+ ITestSuite grandParentItem = parentItem.getParent();
+ if (grandParentItem != null) {
+ return findFailedImpl(grandParentItem, parentItem, next, false);
+ }
+ return null;
+ }
+
+ /**
+ * Returns the next or previous failed test case relatively to the
+ * <code>currItem</code> that should be a child of <code>parentItem</code>.
+ * Note that unlike <code>findFailedImpl()</code> this method search only
+ * through the children items.
+ *
+ * @param parentItem parent test item to the current one
+ * @param currItem current item search should be started from or null if
+ * there is no any
+ * @param next true if the next failed test case should be looked for and
+ * false otherwise
+ * @param checkCurrentChild specifies whether the search should be also
+ * through the children for the current item
+ * @return found item or null
+ */
+ private ITestItem findFailedChild(ITestItem parentItem, ITestItem currItem, boolean next, boolean checkCurrentChild) {
+ ITestItem[] children = parentItem.getChildren();
+ boolean doSearch = (currItem == null);
+ int increment = next ? 1 : -1;
+ int startIndex = next ? 0 : children.length-1;
+ int endIndex = next ? children.length : -1;
+ for (int index = startIndex; index != endIndex; index += increment) {
+ ITestItem item = children[index];
+ // Check element
+ if (doSearch) {
+ if (item instanceof ITestCase && item.getStatus().isError()) {
+ return item;
+ }
+ }
+ // If children of current element should be checked we should enable search here (if necessary)
+ if (checkCurrentChild && item == currItem) {
+ doSearch = true;
+ }
+ // Search element's children
+ if (doSearch) {
+ ITestItem result = findFailedChild(item, null, next, checkCurrentChild);
+ if (result != null) {
+ return result;
+ }
+ }
+ // If children of current element should NOT be checked we should enable search here
+ if (!checkCurrentChild && item == currItem) {
+ doSearch = true;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether test items execution time should be shown in tests
+ * hierarchy.
+ *
+ * @return true if time should be shown and false otherwise
+ */
+ public boolean showTime() {
+ return showTime;
+ }
+
+ /**
+ * Sets whether test items execution time should be shown in tests
+ * hierarchy. Updates tests hierarchy viewer if the view is changed.
+ *
+ * @param showTime true if time is shown and false otherwise
+ */
+ public void setShowTime(boolean showTime) {
+ if (this.showTime != showTime) {
+ this.showTime = showTime;
+ getTreeViewer().refresh();
+ }
+ }
+
+ /**
+ * Sets whether only failed tests should be shown.
+ *
+ * @param showFailedOnly new filter state
+ */
+ public void setShowFailedOnly(boolean showFailedOnly) {
+ // Create filter on first demand
+ if (failedOnlyFilter == null) {
+ failedOnlyFilter = new FailedOnlyFilter();
+ }
+ if (showFailedOnly) {
+ getTreeViewer().addFilter(failedOnlyFilter);
+ } else {
+ getTreeViewer().removeFilter(failedOnlyFilter);
+ }
+ }
+
+ /**
+ * Returns whether tests hierarchy should be shown in flat or hierarchical
+ * mode.
+ *
+ * @return tests hierarchy view mode
+ */
+ public boolean showTestsHierarchy() {
+ return showTestsHierarchy;
+ }
+
+ /**
+ * Sets whether tests hierarchy should be shown in flat or hierarchical
+ * mode. Updates tests hierarchy viewer if the view is changed.
+ *
+ * @param showTestsHierarchy true if tests hierarchy is shown in
+ * hierarchical mode and false otherwise
+ */
+ public void setShowTestsHierarchy(boolean showTestsHierarchy) {
+ if (this.showTestsHierarchy != showTestsHierarchy) {
+ this.showTestsHierarchy = showTestsHierarchy;
+ getTreeViewer().refresh();
+ }
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java
new file mode 100644
index 0000000..a6738e0
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIUpdater.java
@@ -0,0 +1,517 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.testsrunner.internal.model.ITestingSessionsManagerListener;
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.cdt.testsrunner.model.ITestingSessionListener;
+import org.eclipse.cdt.testsrunner.model.ITestCase;
+import org.eclipse.cdt.testsrunner.model.ITestSuite;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.progress.UIJob;
+
+/**
+ * Tracks and collects the changes in active testing session and updates the UI
+ * periodically. It allows to significantly improve the UI performance.
+ */
+public class UIUpdater {
+
+ /** Access to the results showing view. */
+ private ResultsView resultsView;
+
+ /** Access to the tests hierarchy showing widget. */
+ private TestsHierarchyViewer testsHierarchyViewer;
+
+ /** Access to the statistics showing widget. */
+ private ProgressCountPanel progressCountPanel;
+
+ /** Listener for the changes in active testing session. */
+ private ITestingSessionListener sessionListener;
+
+ /**
+ * Specifies whether tests hierarchy scrolling should be done during the
+ * testing process.
+ */
+ private boolean autoScroll = true;
+
+ /** Access to the testing sessions manager. */
+ private TestingSessionsManager sessionsManager;
+
+ /** Listener to handle active testing session change. */
+ private TestingSessionsManagerListener sessionsManagerListener;
+
+ /** Reference to the active testing session. */
+ ITestingSession testingSession;
+
+ /** Storage for the UI changes that should be done on update. */
+ UIChangesCache uiChangesCache = new UIChangesCache();
+
+ /** A job that makes an UI update periodically. */
+ UpdateUIJob updateUIJob = null;
+
+ /** Time interval over which the UI should be updated. */
+ private static final int REFRESH_INTERVAL = 200;
+
+
+ /**
+ * Storage for the UI changes that should be done on update.
+ */
+ private class UIChangesCache {
+
+ /**
+ * Specifies whether Progress Counter Panel should be updated during the
+ * next UI update.
+ */
+ private boolean needProgressCountPanelUpdate;
+
+ /**
+ * Specifies whether view actions should be updated during the next UI
+ * update.
+ */
+ private boolean needActionsUpdate;
+
+ /**
+ * A test item which path should be shown as a view caption during the
+ * next UI update.
+ */
+ private ITestItem testItemForNewViewCaption;
+
+ /**
+ * Set of tree objects on which <code>refresh()</code> should be called
+ * during the next UI update.
+ */
+ private Set<Object> treeItemsToRefresh = new HashSet<Object>();
+
+ /**
+ * Set of tree objects on which <code>update()</code> should be called
+ * during the next UI update.
+ */
+ private Set<Object> treeItemsToUpdate = new HashSet<Object>();
+
+ /** Tree object that should be revealed during the next UI update. */
+ private Object treeItemToReveal;
+
+ /** Map of tree objects that should be expanded or collapsed to their new states. */
+ private Map<Object, Boolean> treeItemsToExpand = new LinkedHashMap<Object, Boolean>();
+
+
+ UIChangesCache() {
+ resetChanges();
+ }
+
+ /**
+ * Schedules the Progress Counter Panel update during the next UI update.
+ */
+ public void scheduleProgressCountPanelUpdate() {
+ synchronized (this) {
+ needProgressCountPanelUpdate = true;
+ }
+ }
+
+ /**
+ * Schedules the view actions update during the next UI update.
+ */
+ public void scheduleActionsUpdate() {
+ synchronized (this) {
+ needActionsUpdate = true;
+ }
+ }
+
+ /**
+ * Schedules the view caption update to the path to specified test item
+ * during the next UI update.
+ *
+ * @param testItem specified test item
+ */
+ public void scheduleViewCaptionChange(ITestItem testItem) {
+ synchronized (this) {
+ testItemForNewViewCaption = testItem;
+ }
+ }
+
+ /**
+ * Schedules the <code>update()</code> call for the specified tree
+ * object during the next UI update.
+ *
+ * @param item tree object to update
+ */
+ public void scheduleTreeItemUpdate(Object item) {
+ synchronized (this) {
+ treeItemsToUpdate.add(item);
+ }
+ }
+
+ /**
+ * Schedules the revealing of the specified tree object. Overrides
+ * the previously specified tree object to reveal (if any).
+ *
+ * @param item tree object to reveal
+ */
+ public void scheduleTreeItemReveal(Object item) {
+ synchronized (this) {
+ treeItemToReveal = item;
+ }
+ }
+
+ /**
+ * Schedules the expanding or collapsing of the specified tree object.
+ * Overrides the previous state for the same tree object (if any).
+ *
+ * @param item tree object to expand or collapse
+ * @param expandedState true if the node is expanded, and false if
+ * collapsed
+ */
+ public void scheduleTreeItemExpand(Object item, boolean expandedState) {
+ synchronized (this) {
+ treeItemsToExpand.put(item, expandedState);
+ }
+ }
+
+ /**
+ * Schedules the <code>refresh()</code> call for the specified tree
+ * object during the next UI update.
+ *
+ * @param item tree object to refresh
+ */
+ public void scheduleTreeItemRefresh(Object item) {
+ synchronized (this) {
+ treeItemsToRefresh.add(item);
+ }
+ }
+
+
+ /**
+ * Apply any scheduled changes to UI.
+ */
+ public void applyChanges() {
+ synchronized (this) {
+ TreeViewer treeViewer = testsHierarchyViewer.getTreeViewer();
+ // View statistics widgets update
+ if (needProgressCountPanelUpdate) {
+ progressCountPanel.updateInfoFromSession();
+ }
+ // View actions update
+ if (needActionsUpdate) {
+ resultsView.updateActionsFromSession();
+ }
+ // View caption update
+ if (testItemForNewViewCaption != null) {
+ resultsView.setCaption(
+ MessageFormat.format(
+ UIViewMessages.UIUpdater_view_caption_format,
+ testItemForNewViewCaption.getName(),
+ TestPathUtils.getTestItemPath(testItemForNewViewCaption.getParent())
+ )
+ );
+ }
+ // Tree view update
+ if (!treeItemsToRefresh.isEmpty()) {
+ for (Object item : treeItemsToRefresh) {
+ treeViewer.refresh(item, false);
+ }
+ }
+ if (!treeItemsToUpdate.isEmpty()) {
+ treeViewer.update(treeItemsToUpdate.toArray(), null);
+ }
+ if (treeItemToReveal != null) {
+ treeViewer.reveal(treeItemToReveal);
+ }
+ if (!treeItemsToExpand.isEmpty()) {
+ for (Map.Entry<Object, Boolean> entry : treeItemsToExpand.entrySet()) {
+ treeViewer.setExpandedState(entry.getKey(), entry.getValue());
+ }
+ }
+ // All changes are applied, remove them
+ resetChangesImpl();
+ }
+ }
+
+ /**
+ * Reset all the scheduled changes to UI.
+ */
+ public void resetChanges() {
+ synchronized (this) {
+ resetChangesImpl();
+ }
+ }
+
+ /**
+ * Reset all the scheduled changes to UI. Note, this method is not
+ * synchronized so it should be used carefully
+ */
+ private void resetChangesImpl() {
+ needProgressCountPanelUpdate = false;
+ needActionsUpdate = false;
+ testItemForNewViewCaption = null;
+ treeItemsToUpdate.clear();
+ treeItemToReveal = null;
+ treeItemsToExpand.clear();
+ }
+ }
+
+
+ /**
+ * A job that makes an UI update periodically.
+ */
+ private class UpdateUIJob extends UIJob {
+
+ /** Controls whether the job should be scheduled again. */
+ private boolean isRunning = true;
+
+ public UpdateUIJob() {
+ super(UIViewMessages.UIUpdater_update_ui_job);
+ setSystem(true);
+ }
+
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (!resultsView.isDisposed()) {
+ uiChangesCache.applyChanges();
+ scheduleSelf();
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Schedule self for running after time interval.
+ */
+ public void scheduleSelf() {
+ schedule(REFRESH_INTERVAL);
+ }
+
+ /**
+ * Sets the flag that prevents planning this job again.
+ */
+ public void stop() {
+ isRunning = false;
+ }
+
+ @Override
+ public boolean shouldSchedule() {
+ return isRunning;
+ }
+
+ }
+
+
+ /**
+ * Listener for the changes in active testing session.
+ */
+ private class SessionListener implements ITestingSessionListener {
+
+ /**
+ * Common implementation for test case and test suite entering.
+ *
+ * @param testItem test case or test suite
+ */
+ private void enterTestItem(ITestItem testItem) {
+ uiChangesCache.scheduleViewCaptionChange(testItem);
+ uiChangesCache.scheduleTreeItemUpdate(testItem);
+ if (autoScroll) {
+ uiChangesCache.scheduleTreeItemReveal(testItem);
+ }
+ }
+
+ @Override
+ public void enterTestSuite(ITestSuite testSuite) {
+ enterTestItem(testSuite);
+ }
+
+ @Override
+ public void exitTestSuite(ITestSuite testSuite) {
+ uiChangesCache.scheduleTreeItemUpdate(testSuite);
+ if (autoScroll) {
+ uiChangesCache.scheduleTreeItemExpand(testSuite, false);
+ }
+ }
+
+ @Override
+ public void enterTestCase(ITestCase testCase) {
+ enterTestItem(testCase);
+ }
+
+ @Override
+ public void exitTestCase(ITestCase testCase) {
+ uiChangesCache.scheduleActionsUpdate();
+ uiChangesCache.scheduleProgressCountPanelUpdate();
+ uiChangesCache.scheduleTreeItemUpdate(testCase);
+ }
+
+ @Override
+ public void childrenUpdate(ITestSuite parent) {
+ uiChangesCache.scheduleTreeItemRefresh(parent);
+ }
+
+ @Override
+ public void testingStarted() {
+ resultsView.updateActionsFromSession();
+ Display.getDefault().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ resultsView.setCaption(testingSession.getStatusMessage());
+ progressCountPanel.updateInfoFromSession();
+ testsHierarchyViewer.getTreeViewer().refresh();
+ }
+ });
+ startUpdateUIJob();
+ }
+
+ @Override
+ public void testingFinished() {
+ stopUpdateUIJob();
+ resultsView.updateActionsFromSession();
+ Display.getDefault().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ uiChangesCache.applyChanges();
+ resultsView.setCaption(testingSession.getStatusMessage());
+ progressCountPanel.updateInfoFromSession();
+ testsHierarchyViewer.getTreeViewer().refresh();
+ testsHierarchyViewer.getTreeViewer().collapseAll();
+ testsHierarchyViewer.getTreeViewer().expandToLevel(2);
+ }
+ });
+ }
+ }
+
+
+ /**
+ * Listener to handle active testing session change.
+ */
+ private class TestingSessionsManagerListener implements ITestingSessionsManagerListener {
+
+ @Override
+ public void sessionActivated(ITestingSession newTestingSession) {
+ if (testingSession != newTestingSession) {
+ stopUpdateUIJob();
+ uiChangesCache.resetChanges();
+
+ unsubscribeFromSessionEvent();
+ testingSession = newTestingSession;
+ subscribeToSessionEvent();
+
+ resultsView.updateActionsFromSession();
+ Display.getDefault().syncExec(new Runnable() {
+
+ @Override
+ public void run() {
+ progressCountPanel.setTestingSession(testingSession);
+ testsHierarchyViewer.setTestingSession(testingSession);
+ resultsView.setCaption(testingSession != null ? testingSession.getStatusMessage() : ""); //$NON-NLS-1$
+ }
+ });
+ if (newTestingSession != null && !newTestingSession.isFinished()) {
+ startUpdateUIJob();
+ }
+ }
+ }
+ }
+
+
+ public UIUpdater(ResultsView resultsView, TestsHierarchyViewer testsHierarchyViewer, ProgressCountPanel progressCountPanel, TestingSessionsManager sessionsManager) {
+ this.resultsView = resultsView;
+ this.testsHierarchyViewer = testsHierarchyViewer;
+ this.progressCountPanel = progressCountPanel;
+ this.sessionsManager = sessionsManager;
+ sessionListener = new SessionListener();
+ sessionsManagerListener = new TestingSessionsManagerListener();
+ sessionsManager.addListener(sessionsManagerListener);
+ }
+
+ /**
+ * Returns whether tests hierarchy scrolling should be done during the
+ * testing process.
+ *
+ * @return auto scroll state
+ */
+ public boolean getAutoScroll() {
+ return autoScroll;
+ }
+
+ /**
+ * Sets whether whether tests hierarchy scrolling should be done during the
+ * testing process.
+ *
+ * @param autoScroll new filter state
+ */
+ public void setAutoScroll(boolean autoScroll) {
+ this.autoScroll = autoScroll;
+ }
+
+ /**
+ * Disposes of the UI Updater. Make the necessary clean up.
+ */
+ public void dispose() {
+ unsubscribeFromSessionEvent();
+ sessionsManager.removeListener(sessionsManagerListener);
+ }
+
+ /**
+ * Subscribes to the events of currently set testing session.
+ */
+ private void subscribeToSessionEvent() {
+ if (testingSession != null) {
+ testingSession.getModelAccessor().addChangesListener(sessionListener);
+ }
+ }
+
+ /**
+ * Unsubscribe from the events of currently set testing session.
+ */
+ private void unsubscribeFromSessionEvent() {
+ if (testingSession != null) {
+ testingSession.getModelAccessor().removeChangesListener(sessionListener);
+ }
+ }
+
+ /**
+ * Starts the UI updating job. Stops the previously running (if any).
+ */
+ private void startUpdateUIJob() {
+ stopUpdateUIJob();
+ uiChangesCache.resetChanges();
+ updateUIJob = new UpdateUIJob();
+ updateUIJob.scheduleSelf();
+ }
+
+ /**
+ * Stops the UI updating job (if any).
+ */
+ private void stopUpdateUIJob() {
+ if (updateUIJob != null) {
+ updateUIJob.stop();
+ updateUIJob = null;
+ }
+ }
+
+ /**
+ * Fakes the testing session activation and makes all necessary steps to
+ * handle it.
+ */
+ public void reapplyActiveSession() {
+ sessionsManagerListener.sessionActivated(sessionsManager.getActiveSession());
+ }
+
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java
new file mode 100644
index 0000000..9db469e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view;
+
+import org.eclipse.osgi.util.NLS;
+
+public class UIViewMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.view.UIViewMessages"; //$NON-NLS-1$
+ public static String CounterPanel_tests_erred;
+ public static String CounterPanel_tests_failed;
+ public static String CounterPanel_tests_run;
+ public static String CounterPanel_tests_skipped;
+ public static String MessagesPanel_label;
+ public static String MessagesViewer_location_format;
+ public static String MessagesViewer_message_format;
+ public static String ResultsView_layout_menu_text;
+ public static String TestsHierarchyViewer_test_path_format;
+ public static String TestsHierarchyViewer_test_time_format;
+ public static String UIUpdater_update_ui_job;
+ public static String UIUpdater_view_caption_format;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, UIViewMessages.class);
+ }
+
+ private UIViewMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties
new file mode 100644
index 0000000..f586280
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/UIViewMessages.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+CounterPanel_tests_erred=Errors:
+CounterPanel_tests_failed=Failures:
+CounterPanel_tests_run=Runs:
+CounterPanel_tests_skipped={0} ({1} ignored)
+MessagesPanel_label=Messages
+MessagesViewer_location_format={0}({1}):
+MessagesViewer_message_format={0}{1}: {2}
+ResultsView_layout_menu_text=&Layout
+TestsHierarchyViewer_test_path_format=\ - {0}
+TestsHierarchyViewer_test_time_format=\ ({0} s)
+UIUpdater_update_ui_job=Update C/C++ Tests Runner
+UIUpdater_view_caption_format={0} - {1}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java
new file mode 100644
index 0000000..1f5097b
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view.actions;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ActionsMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.testsrunner.internal.ui.view.actions.ActionsMessages"; //$NON-NLS-1$
+ public static String CopySelectedMessagesAction_text;
+ public static String CopySelectedMessagesAction_tooltip;
+ public static String CopySelectedTestsAction_text;
+ public static String CopySelectedTestsAction_tooltip;
+ public static String HistoryAction_dialog_button_remove;
+ public static String HistoryAction_dialog_button_remove_all;
+ public static String HistoryAction_dialog_limit_label;
+ public static String HistoryAction_dialog_limit_label_error;
+ public static String HistoryAction_dialog_list_title;
+ public static String HistoryAction_dialog_title;
+ public static String HistoryAction_history_item_clear_text;
+ public static String HistoryAction_history_item_show_text;
+ public static String HistoryAction_history_text;
+ public static String HistoryAction_history_tooltip;
+ public static String MessageLevelFilterAction_errors_text;
+ public static String MessageLevelFilterAction_errors_tooltip;
+ public static String MessageLevelFilterAction_infos_text;
+ public static String MessageLevelFilterAction_infos_tooltip;
+ public static String MessageLevelFilterAction_warnings_text;
+ public static String MessageLevelFilterAction_warnings_tooltip;
+ public static String MessagesOrderingAction_text;
+ public static String MessagesOrderingAction_tooltip;
+ public static String OpenInEditorAction_text;
+ public static String OpenInEditorAction_tooltip;
+ public static String RedebugSelectedAction_text;
+ public static String RedebugSelectedAction_tooltip;
+ public static String RerunAction_text;
+ public static String RerunAction_tooltip;
+ public static String RerunSelectedAction_text;
+ public static String RerunSelectedAction_tooltip;
+ public static String ScrollLockAction_name;
+ public static String ScrollLockAction_tooltip;
+ public static String ShowFailedOnlyAction_text;
+ public static String ShowFailedOnlyAction_tooltip;
+ public static String ShowFileNameOnlyAction_text;
+ public static String ShowFileNameOnlyAction_tooltip;
+ public static String ShowNextFailureAction_text;
+ public static String ShowNextFailureAction_tooltip;
+ public static String ShowPreviousFailureAction_text;
+ public static String ShowPreviousFailureAction_tooltip;
+ public static String ShowTestsInHierarchyAction_text;
+ public static String ShowTestsInHierarchyAction_tooltip;
+ public static String ShowTimeAction_text;
+ public static String ShowTimeAction_tooltip;
+ public static String StopAction_text;
+ public static String StopAction_tooltip;
+ public static String TestsHierarchyCollapseAllAction_text;
+ public static String TestsHierarchyCollapseAllAction_tooltip;
+ public static String TestsHierarchyExpandAllAction_text;
+ public static String TestsHierarchyExpandAllAction_tooltip;
+ public static String ToggleOrientationAction_automatic_text;
+ public static String ToggleOrientationAction_horizontal_text;
+ public static String ToggleOrientationAction_vertical_text;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, ActionsMessages.class);
+ }
+
+ private ActionsMessages() {
+ }
+}
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties
new file mode 100644
index 0000000..267fc50
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/ActionsMessages.properties
@@ -0,0 +1,63 @@
+###############################################################################
+# Copyright (c) 2011 Anton Gorenkov
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Anton Gorenkov - Initial implementation
+###############################################################################
+CopySelectedMessagesAction_text=&Copy
+CopySelectedMessagesAction_tooltip=Copy Selected Messages To Clipboard
+CopySelectedTestsAction_text=&Copy
+CopySelectedTestsAction_tooltip=Copy Selected Test Names To Clipboard
+HistoryAction_dialog_button_remove=&Remove
+HistoryAction_dialog_button_remove_all=Remove &All
+HistoryAction_dialog_limit_label=&Maximum count of remembered test runs:
+HistoryAction_dialog_limit_label_error=Please enter a positive integer smaller than {0}.
+HistoryAction_dialog_list_title=Select a test run:
+HistoryAction_dialog_title=Test Runs
+HistoryAction_history_item_clear_text=&Clear Terminated
+HistoryAction_history_item_show_text=History...
+HistoryAction_history_text=History
+HistoryAction_history_tooltip=Test Run History...
+MessageLevelFilterAction_errors_text=&Errors
+MessageLevelFilterAction_errors_tooltip=Show error messages
+MessageLevelFilterAction_infos_text=&Infos
+MessageLevelFilterAction_infos_tooltip=Show information messages
+MessageLevelFilterAction_warnings_text=&Warnings
+MessageLevelFilterAction_warnings_tooltip=Show warning messages
+MessagesOrderingAction_text=Messages &Ordering
+MessagesOrderingAction_tooltip=Order Messages By Location, Skip Duplicates
+OpenInEditorAction_text=&Go to File
+OpenInEditorAction_tooltip=Show File Referred By the Message
+RedebugSelectedAction_text=&Debug
+RedebugSelectedAction_tooltip=Start Debug Session For Selected Tests
+RerunAction_text=Rerun
+RerunAction_tooltip=Rerun All Tests
+RerunSelectedAction_text=&Run
+RerunSelectedAction_tooltip=Rerun Selected Tests
+ScrollLockAction_name=Scroll Lock
+ScrollLockAction_tooltip=Scroll Lock
+ShowFailedOnlyAction_text=Show &Failures Only
+ShowFailedOnlyAction_tooltip=Show &Failures Only
+ShowFileNameOnlyAction_text=Show File Names Only
+ShowFileNameOnlyAction_tooltip=Show Only File Names in Message Locations
+ShowNextFailureAction_text=Next Failure
+ShowNextFailureAction_tooltip=Next Failed Test
+ShowPreviousFailureAction_text=Previous Failure
+ShowPreviousFailureAction_tooltip=Previous Failed Test
+ShowTestsInHierarchyAction_text=Show Tests in &Hierarchy
+ShowTestsInHierarchyAction_tooltip=Show Tests in Hierarchy
+ShowTimeAction_text=Show Execution &Time
+ShowTimeAction_tooltip=Show Execution Time
+StopAction_text=Stop
+StopAction_tooltip=Stop Test Run
+TestsHierarchyCollapseAllAction_text=C&ollapse All
+TestsHierarchyCollapseAllAction_tooltip=Collapse All Nodes
+TestsHierarchyExpandAllAction_text=&Expand All
+TestsHierarchyExpandAllAction_tooltip=Expand All Nodes
+ToggleOrientationAction_automatic_text=&Automatic
+ToggleOrientationAction_horizontal_text=&Horizontal
+ToggleOrientationAction_vertical_text=&Vertical
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java
new file mode 100644
index 0000000..bcad308
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedMessagesAction.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view.actions;
+
+
+import java.util.Iterator;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.IWorkbenchCommandConstants;
+
+/**
+ * Copies the selected test messages to the clipboard.
+ */
+public class CopySelectedMessagesAction extends Action {
+
+ private Clipboard clipboard;
+ private TableViewer tableViewer;
+
+
+ public CopySelectedMessagesAction(TableViewer tableViewer, Clipboard clipboard) {
+ super(ActionsMessages.CopySelectedMessagesAction_text);
+ setToolTipText(ActionsMessages.CopySelectedMessagesAction_tooltip);
+ setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
+ this.tableViewer = tableViewer;
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public void run() {
+ ITableLabelProvider labelProvider = (ITableLabelProvider)tableViewer.getLabelProvider();
+ IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection();
+ if (!selection.isEmpty()) {
+ StringBuilder sb = new StringBuilder();
+ boolean needEOL = false;
+ for (Iterator<?> it = selection.iterator(); it.hasNext();) {
+ Object item = it.next();
+ if (needEOL) {
+ sb.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ } else {
+ needEOL = true;
+ }
+ sb.append(labelProvider.getColumnText(item, 0));
+ }
+ clipboard.setContents(
+ new String[]{ sb.toString() },
+ new Transfer[]{ TextTransfer.getInstance() });
+ }
+ }
+
+}
+
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java
new file mode 100644
index 0000000..488abcd
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/CopySelectedTestsAction.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view.actions;
+
+
+import java.util.Iterator;
+
+import org.eclipse.cdt.testsrunner.internal.ui.view.TestPathUtils;
+import org.eclipse.cdt.testsrunner.model.ITestItem;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.ui.IWorkbenchCommandConstants;
+
+/**
+ * Copies the name of the selected test items (test suites or cases) to the
+ * clipboard.
+ */
+public class CopySelectedTestsAction extends Action {
+
+ private TreeViewer treeViewer;
+ private Clipboard clipboard;
+
+
+ public CopySelectedTestsAction(TreeViewer treeViewer, Clipboard clipboard) {
+ super(ActionsMessages.CopySelectedTestsAction_text);
+ setToolTipText(ActionsMessages.CopySelectedTestsAction_tooltip);
+ setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY);
+ this.treeViewer = treeViewer;
+ this.clipboard = clipboard;
+ }
+
+ @Override
+ public void run() {
+ IStructuredSelection selection = (IStructuredSelection)treeViewer.getSelection();
+ if (!selection.isEmpty()) {
+ StringBuilder sb = new StringBuilder();
+ boolean needEOL = false;
+ for (Iterator<?> it = selection.iterator(); it.hasNext();) {
+ if (needEOL) {
+ sb.append(System.getProperty("line.separator")); //$NON-NLS-1$
+ } else {
+ needEOL = true;
+ }
+ sb.append(TestPathUtils.getTestItemPath((ITestItem)it.next()));
+ }
+ clipboard.setContents(
+ new String[]{ sb.toString() },
+ new Transfer[]{ TextTransfer.getInstance() });
+ }
+ }
+
+}
+
diff --git a/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java
new file mode 100644
index 0000000..788879e
--- /dev/null
+++ b/testsrunner/org.eclipse.cdt.testsrunner/src/org/eclipse/cdt/testsrunner/internal/ui/view/actions/HistoryDropDownAction.java
@@ -0,0 +1,448 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Anton Gorenkov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Gorenkov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.testsrunner.internal.ui.view.actions;
+
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.DialogField;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.IListAdapter;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.LayoutUtil;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.ListDialogField;
+import org.eclipse.cdt.internal.ui.wizards.dialogfields.StringDialogField;
+import org.eclipse.cdt.testsrunner.internal.TestsRunnerPlugin;
+import org.eclipse.cdt.testsrunner.internal.model.TestingSessionsManager;
+import org.eclipse.cdt.testsrunner.model.ITestingSession;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.StatusDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Shows the testing sessions history in drop down list.
+ */
+public class HistoryDropDownAction extends Action {
+
+ /**
+ * The dialog for testing sessions history management. Allows to browse,
+ * activate and remove the selected testing sessions and to set testing
+ * sessions history size limit.
+ */
+ private class HistoryListDialog extends StatusDialog {
+
+ /** Max value for the history size limit that may be set via the dialog. */
+ private static final int MAX_HISTORY_SIZE_LIMIT = 100;
+
+ /** Testing sessions history list. */
+ private ListDialogField<ITestingSession> historyList;
+
+ /** String field that allows to set testing sessions history size limit. */
+ private StringDialogField historySizeLimitField;
+
+ /** Currently set testing sessions history size limit. */
+ private int historySizeLimit;
+
+ /** The currently selected active testing session. */
+ private ITestingSession resultActiveSession;
+
+
+ /**
+ * Label provider for the dialog testing sessions list.
+ */