├── .gitignore ├── LICENSE ├── README.md ├── bin ├── application │ └── linux └── pnunit │ ├── agent │ ├── agent.conf │ ├── agent.log.conf │ ├── launcher │ ├── launcher.log.conf │ ├── linuxtest.conf │ ├── mactest.conf │ └── wintest.conf ├── img ├── gui-testing-in-action-linux.gif ├── gui-testing-in-action-macos.gif ├── gui-testing-in-action-windows.gif ├── multiplatform-gui.png └── windows-application.png ├── lib ├── log4net │ └── log4net.dll ├── mono │ └── Mono.Posix.dll ├── nunit │ ├── nunit.core.dll │ ├── nunit.core.interfaces.dll │ ├── nunit.framework.dll │ └── nunit.util.dll └── pnunit │ ├── agent │ ├── AgentConfig.cs │ ├── App.ico │ ├── AssemblyPreload.cs │ ├── ConfigureRemoting.cs │ ├── OSProcessKillerCmd.cs │ ├── PNUnitAgent.cs │ ├── PlatformIdentifier.cs │ ├── ProcessInfo.cs │ ├── ProcessPool.cs │ ├── Shell.cs │ ├── TestConsoleAccess.cs │ ├── agent.conf │ ├── agent.cs │ └── agent.csproj │ ├── guitest │ └── GuiTestRunner.cs │ ├── launcher │ ├── App.ico │ ├── Barrier.cs │ ├── CliArgsReader.cs │ ├── Configurator.cs │ ├── Launcher.cs │ ├── LauncherArgs.cs │ ├── LauncherStatus.cs │ ├── LogWriter.cs │ ├── MessageQueue.cs │ ├── NUnitResultCollector.cs │ ├── PNUnitService.cs │ ├── Program.cs │ ├── Runner.cs │ ├── TestConf.cs │ ├── TestsRun.cs │ ├── automation │ │ ├── LauncherService.cs │ │ └── PNUnitAutomatedLauncher.cs │ ├── filereport │ │ ├── StatusReport.cs │ │ └── TestLogReport.cs │ ├── launcher.csproj │ ├── launcherautomation │ │ ├── FileReportConstants.cs │ │ ├── ILauncher.cs │ │ ├── TestRange.cs │ │ ├── TestSuiteLoggerParams.cs │ │ └── launcherautomation.csproj │ ├── test.conf │ └── testlogger │ │ ├── TestSuiteEntry.cs │ │ └── TestSuiteLogger.cs │ ├── pnunit.framework │ ├── Interfaces.cs │ ├── PNUnitServices.cs │ ├── ProcessNameSetter.cs │ └── pnunit.framework.csproj │ ├── pnunit.sln │ ├── pnunittestrunner │ ├── InitServices.cs │ ├── NUnitTestRunner.cs │ ├── PNUnitTestRunner.cs │ ├── Program.cs │ ├── TestInfoReader.cs │ └── pnunittestrunner.csproj │ └── testloggerinterface │ ├── ITestLogger.cs │ ├── TestLoggerClient.cs │ └── testloggerinterface.csproj └── src ├── application ├── gui │ ├── linux │ │ ├── ApplicationWindow.cs │ │ ├── ErrorDialog.cs │ │ ├── ExceptionsHandler.cs │ │ ├── GtkGuiMessage.cs │ │ ├── ProcessNameSetter.cs │ │ ├── Program.cs │ │ ├── WindowHandler.cs │ │ ├── linux.csproj │ │ ├── linux.sln │ │ ├── testing │ │ │ ├── TestHelper.cs │ │ │ ├── TesteableApplicationWindow.cs │ │ │ └── TesteableErrorDialog.cs │ │ ├── threading │ │ │ └── GtkApplicationTimer.cs │ │ └── ui │ │ │ ├── AlignmentBuilder.cs │ │ │ ├── BaseDialog.cs │ │ │ ├── CellContentRenderer.cs │ │ │ ├── ControlBuilder.cs │ │ │ ├── ControlPacker.cs │ │ │ ├── GtkListView.cs │ │ │ ├── Keyboard.cs │ │ │ ├── Mouse.cs │ │ │ ├── ProgressControls.cs │ │ │ └── TreeBuilder.cs │ ├── macos │ │ ├── AppDelegate.cs │ │ ├── ApplicationWindow.cs │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── AppIcon-128.png │ │ │ │ ├── AppIcon-128@2x.png │ │ │ │ ├── AppIcon-16.png │ │ │ │ ├── AppIcon-16@2x.png │ │ │ │ ├── AppIcon-256.png │ │ │ │ ├── AppIcon-256@2x.png │ │ │ │ ├── AppIcon-32.png │ │ │ │ ├── AppIcon-32@2x.png │ │ │ │ ├── AppIcon-512.png │ │ │ │ ├── AppIcon-512@2x.png │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Entitlements.plist │ │ ├── ExceptionsHandler.cs │ │ ├── Info.plist │ │ ├── MacOsGuiMessage.cs │ │ ├── Main.cs │ │ ├── Main.storyboard │ │ ├── RemotingHack.cs │ │ ├── ViewController.cs │ │ ├── ViewController.designer.cs │ │ ├── WindowHandler.cs │ │ ├── macos.csproj │ │ ├── macos.sln │ │ ├── testing │ │ │ ├── TestHelper.cs │ │ │ ├── TesteableApplicationWindow.cs │ │ │ └── TesteableErrorDialog.cs │ │ ├── threading │ │ │ └── MacApplicationTimer.cs │ │ └── ui │ │ │ ├── NSBuilder.cs │ │ │ ├── NSColors.cs │ │ │ ├── NSViewPacker.cs │ │ │ └── ProgressControls.cs │ └── windows │ │ ├── App.config │ │ ├── ApplicationWindow.cs │ │ ├── ErrorDialog.cs │ │ ├── ExceptionsHandler.cs │ │ ├── Program.cs │ │ ├── WindowHandler.cs │ │ ├── WindowsGuiMessage.cs │ │ ├── testing │ │ ├── TestHelper.cs │ │ ├── TesteableApplicationWindow.cs │ │ └── TesteableErrorDialog.cs │ │ ├── threading │ │ └── WinApplicationTimer.cs │ │ ├── ui │ │ ├── ControlBuilder.cs │ │ ├── ControlPacker.cs │ │ └── ProgressControls.cs │ │ ├── windows.csproj │ │ └── windows.sln └── lib │ ├── ApplicationArgs.cs │ ├── ApplicationOperations.cs │ ├── IGuiMessage.cs │ ├── Localization.cs │ ├── interfaces │ ├── IApplicationWindow.cs │ └── IProgressControls.cs │ ├── lib.csproj │ └── threading │ ├── ApplicationThread.cs │ └── ApplicationThreadWaiter.cs └── testing ├── guitest ├── ApplicationWindowTests.cs ├── OSVersionName.cs ├── PlatformUtils.cs ├── TestOperations.cs ├── WaitingAssert.cs └── guitest.csproj └── guitestinterfaces ├── GuiTesteableServices.cs ├── ITesteableApplicationWindow.cs ├── ITesteableErrorDialog.cs └── guitestinterfaces.csproj /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Códice Software S.L. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/application/linux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 3 | 4 | mono $DIR/linux.exe "$@" 5 | -------------------------------------------------------------------------------- /bin/pnunit/agent: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 3 | 4 | mono $DIR/agent.exe "$@" 5 | -------------------------------------------------------------------------------- /bin/pnunit/agent.conf: -------------------------------------------------------------------------------- 1 | 2 | 8080 3 | . 4 | 5 | -------------------------------------------------------------------------------- /bin/pnunit/agent.log.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /bin/pnunit/launcher: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 3 | 4 | mono $DIR/launcher.exe "$@" 5 | -------------------------------------------------------------------------------- /bin/pnunit/launcher.log.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /bin/pnunit/linuxtest.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | BasicApplicationWindowTest 11 | 12 | 13 | linux:BasicApplicationWindowTest 14 | guitest.dll 15 | linux:GuiTest.ApplicationWindowTests.BasicApplicationWindowTest 16 | $host:$port 17 | 18 | ..\application 19 | --testing 20 | 21 | 22 | 23 | 24 | 25 | 26 | AddExistingElementTest 27 | 28 | 29 | linux:AddExistingElementTest 30 | guitest.dll 31 | linux:GuiTest.ApplicationWindowTests.AddExistingElementTest 32 | $host:$port 33 | 34 | ..\application 35 | --testing 36 | 37 | 38 | 39 | 40 | 41 | 42 | RemoveUnexistingElementTest 43 | 44 | 45 | linux:RemoveUnexistingElementTest 46 | guitest.dll 47 | linux:GuiTest.ApplicationWindowTests.RemoveUnexistingElementTest 48 | $host:$port 49 | 50 | ..\application 51 | --testing 52 | 53 | 54 | 55 | 56 | 57 | 58 | ThisTestWillFailAtTheEndTest 59 | 60 | 61 | linux:ThisTestWillFailAtTheEndTest 62 | guitest.dll 63 | linux:GuiTest.ApplicationWindowTests.ThisTestWillFailAtTheEndTest 64 | $host:$port 65 | 66 | ..\application 67 | --testing 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /bin/pnunit/mactest.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | BasicApplicationWindowTest 11 | 12 | 13 | mac:BasicApplicationWindowTest 14 | guitest.dll 15 | mac:GuiTest.ApplicationWindowTests.BasicApplicationWindowTest 16 | $host:$port 17 | 18 | ..\application 19 | --testing 20 | 21 | 22 | 23 | 24 | 25 | 26 | AddExistingElementTest 27 | 28 | 29 | mac:AddExistingElementTest 30 | guitest.dll 31 | mac:GuiTest.ApplicationWindowTests.AddExistingElementTest 32 | $host:$port 33 | 34 | ..\application 35 | --testing 36 | 37 | 38 | 39 | 40 | 41 | 42 | RemoveUnexistingElementTest 43 | 44 | 45 | mac:RemoveUnexistingElementTest 46 | guitest.dll 47 | mac:GuiTest.ApplicationWindowTests.RemoveUnexistingElementTest 48 | $host:$port 49 | 50 | ..\application 51 | --testing 52 | 53 | 54 | 55 | 56 | 57 | 58 | ThisTestWillFailAtTheEndTest 59 | 60 | 61 | mac:ThisTestWillFailAtTheEndTest 62 | guitest.dll 63 | mac:GuiTest.ApplicationWindowTests.ThisTestWillFailAtTheEndTest 64 | $host:$port 65 | 66 | ..\application 67 | --testing 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /bin/pnunit/wintest.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | BasicApplicationWindowTest 11 | 12 | 13 | windows:BasicApplicationWindowTest 14 | guitest.dll 15 | windows:GuiTest.ApplicationWindowTests.BasicApplicationWindowTest 16 | $host:$port 17 | 18 | ..\application 19 | --testing 20 | 21 | 22 | 23 | 24 | 25 | 26 | AddExistingElementTest 27 | 28 | 29 | windows:AddExistingElementTest 30 | guitest.dll 31 | windows:GuiTest.ApplicationWindowTests.AddExistingElementTest 32 | $host:$port 33 | 34 | ..\application 35 | --testing 36 | 37 | 38 | 39 | 40 | 41 | 42 | RemoveUnexistingElementTest 43 | 44 | 45 | windows:RemoveUnexistingElementTest 46 | guitest.dll 47 | windows:GuiTest.ApplicationWindowTests.RemoveUnexistingElementTest 48 | $host:$port 49 | 50 | ..\application 51 | --testing 52 | 53 | 54 | 55 | 56 | 57 | 58 | ThisTestWillFailAtTheEndTest 59 | 60 | 61 | windows:ThisTestWillFailAtTheEndTest 62 | guitest.dll 63 | windows:GuiTest.ApplicationWindowTests.ThisTestWillFailAtTheEndTest 64 | $host:$port 65 | 66 | ..\application 67 | --testing 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /img/gui-testing-in-action-linux.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/img/gui-testing-in-action-linux.gif -------------------------------------------------------------------------------- /img/gui-testing-in-action-macos.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/img/gui-testing-in-action-macos.gif -------------------------------------------------------------------------------- /img/gui-testing-in-action-windows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/img/gui-testing-in-action-windows.gif -------------------------------------------------------------------------------- /img/multiplatform-gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/img/multiplatform-gui.png -------------------------------------------------------------------------------- /img/windows-application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/img/windows-application.png -------------------------------------------------------------------------------- /lib/log4net/log4net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/log4net/log4net.dll -------------------------------------------------------------------------------- /lib/mono/Mono.Posix.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/mono/Mono.Posix.dll -------------------------------------------------------------------------------- /lib/nunit/nunit.core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/nunit/nunit.core.dll -------------------------------------------------------------------------------- /lib/nunit/nunit.core.interfaces.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/nunit/nunit.core.interfaces.dll -------------------------------------------------------------------------------- /lib/nunit/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/nunit/nunit.framework.dll -------------------------------------------------------------------------------- /lib/nunit/nunit.util.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/nunit/nunit.util.dll -------------------------------------------------------------------------------- /lib/pnunit/agent/AgentConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Xml.Serialization; 4 | 5 | 6 | namespace PNUnit.Agent 7 | { 8 | [Serializable] 9 | public class AgentConfig 10 | { 11 | public int Port; 12 | public string PathToAssemblies; 13 | public bool NoTimeout; 14 | } 15 | 16 | public class AgentConfigLoader 17 | { 18 | public static AgentConfig LoadFromFile(string file) 19 | { 20 | using (FileStream reader = new FileStream(file, FileMode.Open, FileAccess.Read)) 21 | { 22 | XmlSerializer ser= new XmlSerializer(typeof(AgentConfig)); 23 | return (AgentConfig) ser.Deserialize(reader); 24 | } 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /lib/pnunit/agent/App.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/pnunit/agent/App.ico -------------------------------------------------------------------------------- /lib/pnunit/agent/AssemblyPreload.cs: -------------------------------------------------------------------------------- 1 | namespace PNUnit.Agent 2 | { 3 | public static class AssemblyPreload 4 | { 5 | public const string PRELOADED_ASSEMBLY = "cmtest.dll"; 6 | 7 | public const string PRELOADED_PROCESS_FILE_PREFIX = "pnunit_"; 8 | 9 | public static bool CanUsePreload(string assembly) 10 | { 11 | return assembly == PRELOADED_ASSEMBLY; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/pnunit/agent/ConfigureRemoting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections; 4 | using System.Runtime.Remoting; 5 | using System.Runtime.Remoting.Channels; 6 | using System.Runtime.Remoting.Channels.Tcp; 7 | using System.Runtime.Serialization.Formatters; 8 | 9 | using log4net; 10 | 11 | namespace PNUnit.Agent 12 | { 13 | class ConfigureRemoting 14 | { 15 | internal static void Configure(int port) 16 | { 17 | mLog.InfoFormat("Registering channel"); 18 | 19 | if (File.Exists("agent.remoting.conf")) 20 | { 21 | mLog.Info("Using agent.remoting.conf"); 22 | RemotingConfiguration.Configure("agent.remoting.conf", false); 23 | return; 24 | } 25 | 26 | // init remoting 27 | BinaryClientFormatterSinkProvider clientProvider = 28 | new BinaryClientFormatterSinkProvider(); 29 | BinaryServerFormatterSinkProvider serverProvider = 30 | new BinaryServerFormatterSinkProvider(); 31 | serverProvider.TypeFilterLevel = 32 | System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; 33 | 34 | IDictionary props = new Hashtable(); 35 | props["port"] = port; 36 | string s = System.Guid.NewGuid().ToString(); 37 | props["name"] = s; 38 | props["typeFilterLevel"] = TypeFilterLevel.Full; 39 | try 40 | { 41 | TcpChannel chan = new TcpChannel( 42 | props, clientProvider, serverProvider); 43 | 44 | mLog.InfoFormat("Registering channel on port {0}", port); 45 | ChannelServices.RegisterChannel(chan, false); 46 | //RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.Off; 47 | } 48 | catch (Exception e) 49 | { 50 | mLog.InfoFormat("Can't register channel.\n{0}", e.Message); 51 | Console.WriteLine("Can't register channel.\n{0}", e.Message); 52 | throw; 53 | } 54 | } 55 | 56 | static readonly ILog mLog = LogManager.GetLogger("ConfigureRemoting"); 57 | } 58 | } -------------------------------------------------------------------------------- /lib/pnunit/agent/OSProcessKillerCmd.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Diagnostics; 3 | 4 | using log4net; 5 | 6 | namespace Codice.Test 7 | { 8 | public static class OSProcessKillerCmd 9 | { 10 | public static void KillProcessTree(string pid) 11 | { 12 | if (PlatformIdentifier.IsWindows()) 13 | { 14 | KillProcessForcedWindows(pid, true); 15 | return; 16 | } 17 | 18 | KillProcessTreeUnix(pid); 19 | } 20 | 21 | public static void KillProcess(string pid) 22 | { 23 | if (PlatformIdentifier.IsWindows()) 24 | { 25 | KillProcessForcedWindows(pid, false); 26 | return; 27 | } 28 | 29 | KillProcessForcedUnix(pid); 30 | } 31 | 32 | static void KillProcessForcedWindows(string pid, bool bHasToKillProcessTree) 33 | { 34 | string processName = "taskkill"; 35 | string killTreeArg = bHasToKillProcessTree ? "/T" : string.Empty; 36 | 37 | string args = string.Format("/F {0} /PID {1}", killTreeArg, pid); 38 | 39 | mLog.DebugFormat("executing [{0} {1}]", processName, args); 40 | 41 | using (Process taskKill = new Process()) 42 | { 43 | taskKill.StartInfo.FileName = processName; 44 | taskKill.StartInfo.Arguments = args; 45 | taskKill.StartInfo.CreateNoWindow = true; 46 | taskKill.StartInfo.UseShellExecute = false; 47 | taskKill.Start(); 48 | taskKill.WaitForExit(PROCESS_MAX_WAIT_EXIT_MILLIS); 49 | } 50 | } 51 | 52 | static void KillProcessTreeUnix(string pid) 53 | { 54 | List pids = new List(); 55 | GetChildProcesses(pid, pids); 56 | 57 | string args = string.Join(" ", pids.ToArray()); 58 | KillProcessForcedUnix(args); 59 | } 60 | 61 | static void KillProcessForcedUnix(string pidsArg) 62 | { 63 | mLog.DebugFormat("executing [{0} {1}]", "kill -9", pidsArg); 64 | 65 | using (Process kill = Process.Start("kill", "-9 " + pidsArg)) 66 | { 67 | kill.WaitForExit(PROCESS_MAX_WAIT_EXIT_MILLIS); 68 | } 69 | } 70 | 71 | static void GetChildProcesses(string requestedPid, List outChildPids) 72 | { 73 | outChildPids.Add(requestedPid); 74 | 75 | foreach (string childPid in ProcessInfo.UnixGetChildrenPids(requestedPid)) 76 | GetChildProcesses(childPid, outChildPids); 77 | } 78 | 79 | const int PROCESS_MAX_WAIT_EXIT_MILLIS = 2000; 80 | 81 | static readonly ILog mLog = LogManager.GetLogger("ProcessKiller"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/pnunit/agent/PlatformIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Codice.Test 4 | { 5 | public class PlatformIdentifier 6 | { 7 | private static bool bIsWindowsInitialized = false; 8 | private static bool bIsWindows = false; 9 | public static bool IsWindows() 10 | { 11 | if( !bIsWindowsInitialized ) 12 | { 13 | switch (Environment.OSVersion.Platform) 14 | { 15 | case PlatformID.Win32Windows: 16 | case PlatformID.Win32NT: 17 | bIsWindows = true; 18 | break; 19 | } 20 | bIsWindowsInitialized = true; 21 | } 22 | return bIsWindows; 23 | } 24 | 25 | private static bool bIsMacInitialized = false; 26 | private static bool bIsMac = false; 27 | public static bool IsMac() 28 | { 29 | if (!bIsMacInitialized) 30 | { 31 | if (!IsWindows()) 32 | { 33 | // The first versions of the framework (1.0 and 1.1) 34 | // didn't include any PlatformID value for Unix, 35 | // so Mono used the value 128. The newer framework 2.0 36 | // added Unix to the PlatformID enum but, 37 | // sadly, with a different value: 4 and newer versions of 38 | // .NET distinguished between Unix and MacOS X, 39 | // introducing yet another value 6 for MacOS X. 40 | 41 | System.Version v = Environment.Version; 42 | int p = (int) Environment.OSVersion.Platform; 43 | 44 | if( (v.Major >= 3 && v.Minor >= 5) || 45 | (IsRunningUnderMono() && v.Major >= 2 && v.Minor >= 2)) 46 | { 47 | //MacOs X exist in the enumeration 48 | bIsMac = p == 6; 49 | } 50 | else 51 | { 52 | if ((p == 4) || (p == 128)) 53 | { 54 | int major = Environment.OSVersion.Version.Major; 55 | //18.x.x macOS 10.14.x Mojave 56 | //17.x.x macOS 10.13.x High Sierra 57 | //16.x.x macOS 10.12.x Sierra 58 | //15.x.x OS X 10.11.x El Capitan 59 | //14.x.x OS X 10.10.x Yosemite 60 | //13.x.x OS X 10.9.x Mavericks 61 | //12.x.x OS X 10.8.x Mountain Lion 62 | //11.x.x OS X 10.7.x Lion 63 | //10.x.x OS X 10.6.x Snow Leopard 64 | //9.x.x OS X 10.5.x Leopard 65 | //8.x.x OS X 10.4.x Tiger 66 | // DAVE: this is not very nice, as it may conflict 67 | // on other OS like solaris or aix. 68 | bIsMac = major >= 8; 69 | } 70 | } 71 | } 72 | 73 | bIsMacInitialized = true; 74 | } 75 | 76 | return bIsMac; 77 | } 78 | 79 | 80 | private static bool IsRunningUnderMono() 81 | { 82 | Type t = Type.GetType("Mono.Runtime"); 83 | 84 | return (t != null); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/pnunit/agent/TestConsoleAccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | using PNUnit.Framework; 5 | 6 | namespace PNUnit.Agent 7 | { 8 | public class TestLogInfo : MarshalByRefObject, ITestLogInfo 9 | { 10 | public string OSVersion = string.Empty; 11 | public string BackendType = string.Empty; 12 | 13 | public void SetOSVersion(string s) 14 | { 15 | OSVersion = s; 16 | } 17 | 18 | public void SetBackendType(string s) 19 | { 20 | BackendType = s; 21 | } 22 | } 23 | 24 | public class TestConsoleAccess : MarshalByRefObject, ITestConsoleAccess 25 | { 26 | public TestConsoleAccess(string outputFile) 27 | { 28 | mOutputFilePath = outputFile; 29 | } 30 | 31 | public void WriteLine(string s) 32 | { 33 | if (mStoreOutputEnabled) 34 | AppendOutputTest(s); 35 | 36 | if(mConsoleEnabled) 37 | Console.WriteLine(s); 38 | } 39 | 40 | public void Write(char[] buf) 41 | { 42 | if (mStoreOutputEnabled) 43 | AppendOutputTest(buf); 44 | 45 | if (mConsoleEnabled) 46 | Console.Write(buf); 47 | } 48 | 49 | public void Clear() 50 | { 51 | using (StreamWriter sw = new StreamWriter(mOutputFilePath, false)) 52 | { 53 | sw.WriteLine(); 54 | } 55 | } 56 | 57 | public override object InitializeLifetimeService() 58 | { 59 | return null; 60 | } 61 | 62 | internal static void EnableConsole() 63 | { 64 | mConsoleEnabled = true; 65 | } 66 | 67 | internal static void DisableConsole() 68 | { 69 | mConsoleEnabled = false; 70 | } 71 | 72 | internal static void EnableStoreOutput() 73 | { 74 | mStoreOutputEnabled = true; 75 | } 76 | 77 | internal static void DisableStoreOutput() 78 | { 79 | mStoreOutputEnabled = false; 80 | } 81 | 82 | private void AppendOutputTest(string text) 83 | { 84 | using (StreamWriter sw = new StreamWriter(mOutputFilePath, true)) 85 | { 86 | sw.WriteLine(text); 87 | } 88 | } 89 | 90 | private void AppendOutputTest(char[] buf) 91 | { 92 | using (StreamWriter sw = new StreamWriter(mOutputFilePath, true)) 93 | { 94 | sw.WriteLine(buf); 95 | } 96 | } 97 | 98 | string mOutputFilePath; 99 | static bool mConsoleEnabled = true; 100 | static bool mStoreOutputEnabled = true; 101 | } 102 | } -------------------------------------------------------------------------------- /lib/pnunit/agent/agent.conf: -------------------------------------------------------------------------------- 1 | 2 | 8080 3 | . 4 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/App.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/lib/pnunit/launcher/App.ico -------------------------------------------------------------------------------- /lib/pnunit/launcher/Barrier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace PNUnit.Launcher 5 | { 6 | public class Barrier 7 | { 8 | public int mCount; 9 | public int mMaxCount; 10 | private Object mLock = new Object(); 11 | private string mName; 12 | 13 | private static int MAX_WAIT_TIME = 600 * 1000; //milliseconds - 10 minutes 14 | public static void SetMaxWaitTime(int seconds) 15 | { 16 | MAX_WAIT_TIME = seconds * 1000; 17 | } 18 | 19 | public Barrier(string name, int maxCount) 20 | { 21 | mCount = 0; 22 | mName = name; 23 | mMaxCount = maxCount; 24 | } 25 | 26 | public void Enter() 27 | { 28 | lock( mLock ) 29 | { 30 | ++mCount; 31 | if( mCount == mMaxCount ) 32 | { 33 | Monitor.PulseAll(mLock); 34 | } 35 | else if( mCount < mMaxCount ) 36 | { 37 | if (!Monitor.Wait(mLock, MAX_WAIT_TIME)) 38 | { 39 | Console.WriteLine("Barrier {0} abandoned due to timeout!!!", 40 | mName); 41 | } 42 | } 43 | else 44 | { 45 | //nothing to do, entering in a barrier already used 46 | } 47 | } 48 | } 49 | 50 | public void Abandon() 51 | { 52 | lock( mLock ) 53 | { 54 | --mMaxCount; 55 | if( mCount >= mMaxCount ) 56 | { 57 | mCount = 0; 58 | Monitor.PulseAll(mLock); 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/Configurator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.IO; 4 | using System.Runtime.Remoting.Channels; 5 | using System.Runtime.Remoting.Channels.Tcp; 6 | using System.Runtime.Serialization.Formatters; 7 | using System.Reflection; 8 | 9 | using log4net; 10 | using log4net.Config; 11 | 12 | namespace PNUnit.Launcher 13 | { 14 | internal class Configurator 15 | { 16 | internal static bool ConfigureRemoting(int port, string ipToBind) 17 | { 18 | BinaryClientFormatterSinkProvider clientProvider = null; 19 | BinaryServerFormatterSinkProvider serverProvider = 20 | new BinaryServerFormatterSinkProvider(); 21 | serverProvider.TypeFilterLevel = 22 | System.Runtime.Serialization.Formatters.TypeFilterLevel.Full; 23 | 24 | IDictionary props = new Hashtable(); 25 | props["port"] = port; 26 | props["typeFilterLevel"] = TypeFilterLevel.Full; 27 | 28 | if (!string.IsNullOrEmpty(ipToBind)) 29 | { 30 | mLog.InfoFormat("Binding the ip to {0}", ipToBind); 31 | props["bindTo"] = ipToBind; 32 | } 33 | 34 | try 35 | { 36 | TcpChannel chan = new TcpChannel( 37 | props, clientProvider, serverProvider); 38 | 39 | mLog.DebugFormat("Registering channel on port {0}", port); 40 | ChannelServices.RegisterChannel(chan, false); 41 | return true; 42 | } 43 | catch (Exception e) 44 | { 45 | mLog.InfoFormat("Can't register channel.\n{0}", e.Message); 46 | return false; 47 | } 48 | } 49 | 50 | internal static void ConfigureLogging( 51 | bool bIsAutomatedLauncher, string customLogOutputPath) 52 | { 53 | string logConfFileName = "launcher.log.conf"; 54 | 55 | if (bIsAutomatedLauncher) 56 | logConfFileName = "automated" + logConfFileName; 57 | 58 | if (!File.Exists(logConfFileName)) 59 | { 60 | logConfFileName = GetConfigFilePath(logConfFileName); 61 | } 62 | 63 | // the following property must be declared in the "file" tag in .log.conf appenders: 64 | // "%property{LogFolder}" 65 | log4net.GlobalContext.Properties["LogFolder"] = customLogOutputPath; 66 | 67 | XmlConfigurator.Configure(new FileInfo(logConfFileName)); 68 | } 69 | 70 | static string GetConfigFilePath(string fileName) 71 | { 72 | return Path.Combine(GetAppPath(), fileName); 73 | } 74 | 75 | static string GetAppPath() 76 | { 77 | return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 78 | } 79 | 80 | static readonly ILog mLog = LogManager.GetLogger("launcher"); 81 | } 82 | } -------------------------------------------------------------------------------- /lib/pnunit/launcher/LauncherArgs.cs: -------------------------------------------------------------------------------- 1 | namespace PNUnit.Launcher 2 | { 3 | internal class LauncherArgs 4 | { 5 | internal string ConfigFile; 6 | internal string ResultLogFile; 7 | internal string ErrorLogFile; 8 | internal string ResultFile = null; 9 | internal string FailedConfigFile = null; 10 | internal int RetryOnFailure = 0; 11 | internal int MaxRetry = DEFAULT_TEST_RETRY; 12 | internal bool ShellMode = false; 13 | internal TestRange TestRange = null; 14 | internal int TestsTimeout = 0; 15 | internal string ListTestsFile; 16 | internal string UseFileReport; 17 | 18 | const int DEFAULT_TEST_RETRY = 3; 19 | } 20 | } -------------------------------------------------------------------------------- /lib/pnunit/launcher/LauncherStatus.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace PNUnit.Launcher 4 | { 5 | internal class LauncherStatus 6 | { 7 | internal int TestCount; 8 | internal int TestToExecuteCount; 9 | internal int CurrentTest; 10 | internal int ExecutedTests; 11 | internal string CurrentTestName; 12 | internal string WarningMsg; 13 | 14 | internal LauncherStatus(int testCount, int testToExecuteCount) 15 | { 16 | TestCount = testCount; 17 | TestToExecuteCount = testToExecuteCount; 18 | } 19 | 20 | internal void SetCurrentTestName(string testName) 21 | { 22 | CurrentTestName = testName; 23 | } 24 | 25 | internal void SetWarningMessage(string warningMessage) 26 | { 27 | WarningMsg = warningMessage; 28 | } 29 | 30 | internal List GetRepeatedTests() 31 | { 32 | lock (this) 33 | { 34 | return new List(mRepeatedTests); 35 | } 36 | } 37 | 38 | internal List GetFailedTests() 39 | { 40 | lock (this) 41 | { 42 | return new List(mFailedTests); 43 | } 44 | } 45 | 46 | internal List GetIgnoredTests() 47 | { 48 | lock (this) 49 | { 50 | return new List(mIgnoredTests); 51 | } 52 | } 53 | 54 | internal void Increment() 55 | { 56 | ++CurrentTest; 57 | } 58 | 59 | internal void IncrementExecuted() 60 | { 61 | ++ExecutedTests; 62 | } 63 | 64 | internal void AddFailed(string failed) 65 | { 66 | lock (this) 67 | { 68 | if (mFailedTests.Contains(failed)) 69 | return; 70 | 71 | mFailedTests.Add(failed); 72 | } 73 | } 74 | 75 | internal void AddIgnored(string ignored) 76 | { 77 | lock (this) 78 | { 79 | if (mIgnoredTests.Contains(ignored)) 80 | return; 81 | 82 | mIgnoredTests.Add(ignored); 83 | } 84 | } 85 | 86 | internal void AddRepeated(string repeated) 87 | { 88 | lock (this) 89 | { 90 | if (mRepeatedTests.Contains(repeated)) 91 | return; 92 | 93 | mRepeatedTests.Add(repeated); 94 | } 95 | } 96 | 97 | internal void UpdateProgress( 98 | int runTestsCount, int totalTestCount, 99 | List failed, List ignored) 100 | { 101 | lock (this) 102 | { 103 | CurrentTest = runTestsCount; 104 | ExecutedTests = runTestsCount; 105 | TestCount = totalTestCount; 106 | TestToExecuteCount = totalTestCount; 107 | mFailedTests = failed; 108 | mIgnoredTests = ignored; 109 | } 110 | } 111 | 112 | List mRepeatedTests = new List(); 113 | List mFailedTests = new List(); 114 | List mIgnoredTests = new List(); 115 | } 116 | } -------------------------------------------------------------------------------- /lib/pnunit/launcher/NUnitResultCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | using NUnit.Core; 5 | using NUnit.Util; 6 | 7 | 8 | namespace PNUnit.Launcher 9 | { 10 | class NUnitResultCollector 11 | { 12 | private ArrayList mResultList = new ArrayList(); 13 | 14 | internal void AddResults(TestResult[] results) 15 | { 16 | mResultList.AddRange(results); 17 | } 18 | 19 | internal void SaveResults(string fileName) 20 | { 21 | TestResult all = new TestResult(new TestName()); 22 | 23 | foreach (TestResult r in mResultList) all.AddResult(r); 24 | 25 | new XmlResultWriter(fileName).SaveTestResult(all); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/TestsRun.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using NUnit.Core; 6 | 7 | using PNUnit.Framework; 8 | 9 | namespace PNUnit.Launcher 10 | { 11 | internal class TestsRun 12 | { 13 | internal bool PendingTestsToFinish() 14 | { 15 | lock (mResultLock) 16 | { 17 | return (mLaunchedTests > 0) && (mResults.Count < mLaunchedTests); 18 | } 19 | } 20 | 21 | internal bool IsTestExecuted(string name) 22 | { 23 | lock (mResultLock) 24 | { 25 | return mExecutedTests.Contains(name); 26 | } 27 | } 28 | 29 | internal TestResult[] GetTestResults() 30 | { 31 | lock (mResultLock) 32 | { 33 | TestResult[] result = new TestResult[mResults.Count]; 34 | int i = 0; 35 | foreach (TestResult res in mResults) 36 | result[i++] = res; 37 | 38 | return result; 39 | } 40 | } 41 | 42 | internal void IncrementTestsLaunched() 43 | { 44 | lock (mResultLock) 45 | { 46 | ++mLaunchedTests; 47 | } 48 | } 49 | 50 | internal void DecrementTestsLaunched() 51 | { 52 | lock (mResultLock) 53 | { 54 | --mLaunchedTests; 55 | } 56 | } 57 | 58 | internal int LaunchedCount 59 | { 60 | get 61 | { 62 | lock (mResultLock) 63 | { 64 | return mLaunchedTests; 65 | } 66 | } 67 | } 68 | 69 | internal void AddExecutedTest(string testName) 70 | { 71 | lock (mResultLock) 72 | { 73 | mExecutedTests.Add(testName); 74 | } 75 | } 76 | 77 | internal void AddTestResult(PNUnitTestResult testResult) 78 | { 79 | lock (mResultLock) 80 | { 81 | mResults.Add(testResult); 82 | } 83 | } 84 | 85 | internal bool AllTestsFinished() 86 | { 87 | lock (mResultLock) 88 | { 89 | return mResults.Count == mLaunchedTests; 90 | } 91 | } 92 | 93 | internal int TestsResultsCount 94 | { 95 | get 96 | { 97 | lock (mResultLock) 98 | { 99 | return mResults.Count; 100 | } 101 | } 102 | } 103 | 104 | Object mResultLock = new Object(); 105 | int mLaunchedTests = 0; 106 | List mExecutedTests = new List(); 107 | List mResults = new List(); 108 | } 109 | } -------------------------------------------------------------------------------- /lib/pnunit/launcher/automation/LauncherService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | using log4net; 6 | 7 | namespace PNUnit.Launcher.Automation 8 | { 9 | class LauncherService: MarshalByRefObject, ILauncher 10 | { 11 | public LauncherService(string ipToBind, int port) 12 | { 13 | mListenAddress = string.Format("{0}:{1}", ipToBind, port); 14 | } 15 | 16 | // live forever 17 | public override object InitializeLifetimeService() 18 | { 19 | return null; 20 | } 21 | 22 | public string RunTest( 23 | string testFile, 24 | List testsToRun, 25 | string resultLogFile, 26 | string errorLogFile, 27 | string failedConfFile, 28 | int numRetriesOnFailure, 29 | TestSuiteLoggerParams loggerParams, 30 | TestRange testRange, 31 | List cliArgs, 32 | int testTimeout) 33 | { 34 | mLog.InfoFormat("Request to run tests on file [{0}]", testFile); 35 | 36 | if (mAutomatedLauncher != null) 37 | { 38 | string msg = "Can't launch another test suite because a test suite is currently running"; 39 | mLog.Error(msg); 40 | return msg; 41 | } 42 | 43 | mAutomatedLauncher = new PNUnitAutomatedLauncher(mListenAddress); 44 | 45 | return mAutomatedLauncher.RunTest( 46 | testFile, 47 | testsToRun, 48 | resultLogFile, 49 | errorLogFile, 50 | failedConfFile, 51 | numRetriesOnFailure, 52 | loggerParams, 53 | testRange, 54 | cliArgs == null ? null : cliArgs.ToArray(), 55 | testTimeout); 56 | } 57 | 58 | public AutomatedLauncherStatus GetStatus() 59 | { 60 | mLog.DebugFormat("GetStatus invoked"); 61 | 62 | if (mAutomatedLauncher == null) 63 | { 64 | return new AutomatedLauncherStatus(); 65 | } 66 | 67 | return mAutomatedLauncher.GetStatus(); 68 | } 69 | 70 | public void Exit() 71 | { 72 | CanExit = true; 73 | } 74 | 75 | public bool CanExit = false; 76 | 77 | string mListenAddress; 78 | 79 | PNUnitAutomatedLauncher mAutomatedLauncher = null; 80 | 81 | static readonly ILog mLog = LogManager.GetLogger("AutomatedLauncher"); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/filereport/StatusReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | using log4net; 6 | 7 | using PNUnit.Launcher.Automation; 8 | 9 | namespace PNUnit.Launcher.FileReport 10 | { 11 | internal static class StatusReport 12 | { 13 | internal static void Write( 14 | string file, LauncherStatus status, bool bFinished) 15 | { 16 | string content = GetContent(status, bFinished); 17 | 18 | int retries = 0; 19 | while (true) 20 | { 21 | try 22 | { 23 | File.WriteAllText(file, content); 24 | return; 25 | } 26 | catch(Exception e) 27 | { 28 | mLog.Info("The status file cannot be written. Error: " + e.Message); 29 | if (retries++ > 10) 30 | return; 31 | 32 | System.Threading.Thread.Sleep(500); 33 | continue; 34 | } 35 | } 36 | } 37 | 38 | static string GetContent(LauncherStatus status, bool bFinished) 39 | { 40 | return string.Join(FileReportConstants.FIELD_SEPARATOR, new string[] { 41 | status.TestCount.ToString(), 42 | status.TestToExecuteCount.ToString(), 43 | status.CurrentTestName, 44 | status.CurrentTest.ToString(), 45 | status.ExecutedTests.ToString(), 46 | string.Join(FileReportConstants.LIST_SEPARATOR, status.GetRepeatedTests().ToArray()), 47 | string.Join(FileReportConstants.LIST_SEPARATOR, status.GetFailedTests().ToArray()), 48 | string.Join(FileReportConstants.LIST_SEPARATOR, status.GetIgnoredTests().ToArray()), 49 | status.WarningMsg, 50 | bFinished.ToString()}); 51 | } 52 | 53 | static readonly ILog mLog = LogManager.GetLogger("launcher"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/filereport/TestLogReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace PNUnit.Launcher.FileReport 7 | { 8 | internal static class TestLogReport 9 | { 10 | internal static void LogTest( 11 | string file, 12 | TestSuiteEntry.Data entry, 13 | string testName, 14 | bool isRepeated) 15 | { 16 | string contents = string.Join(FileReportConstants.TEST_FIELD_SEPARATOR, new string[] { 17 | testName, 18 | entry.BackendType, 19 | entry.ClientConfig, 20 | entry.ServerConfig, 21 | entry.ExecTime.ToString(), 22 | entry.Status, 23 | entry.Log, 24 | isRepeated.ToString()}); 25 | 26 | File.AppendAllText(file, contents + FileReportConstants.TEST_SEPARATOR); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/launcherautomation/FileReportConstants.cs: -------------------------------------------------------------------------------- 1 | namespace PNUnit.Launcher.FileReport 2 | { 3 | public class FileReportConstants 4 | { 5 | public const string FIELD_SEPARATOR = "@#@"; 6 | public const string LIST_SEPARATOR = "#$#"; 7 | 8 | public const string TEST_FIELD_SEPARATOR = ".@#@."; 9 | public const string TEST_SEPARATOR = "#$@%@$#\n"; 10 | 11 | public const string LOG_FILE_EXTENSION = ".log"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/launcherautomation/ILauncher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Collections.Generic; 5 | 6 | using System.Security.Permissions; 7 | using System.Runtime.Serialization; 8 | using System.Runtime.Serialization.Formatters.Binary; 9 | 10 | namespace PNUnit.Launcher.Automation 11 | { 12 | public interface ILauncher 13 | { 14 | string RunTest( 15 | string testFile, 16 | List testsToRun, 17 | string resultLogFile, 18 | string errorLogFile, 19 | string failedConfFile, 20 | int numRetriesOnFailure, 21 | TestSuiteLoggerParams loggerParams, 22 | TestRange testRange, 23 | List cliArgs, 24 | int testTimeout); 25 | 26 | AutomatedLauncherStatus GetStatus(); 27 | 28 | void Exit(); 29 | } 30 | 31 | [Serializable] 32 | public class AutomatedLauncherStatus 33 | { 34 | public int TestCount; 35 | public int TestToExecuteCount; 36 | public int CurrentTest; 37 | public int ExecutedTests; 38 | public string CurrentTestName = string.Empty; 39 | public List RepeatedTests = new List(); 40 | public List FailedTests = new List(); 41 | public List IgnoredTests = new List(); 42 | public bool Finished = false; 43 | public string WarningMsg = string.Empty; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/launcherautomation/TestRange.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace PNUnit.Launcher 4 | { 5 | [Serializable] 6 | public class TestRange 7 | { 8 | public int StartTest = 0; 9 | public int EndTest = 0; 10 | 11 | public static TestRange FromString(string range) 12 | { 13 | if (string.IsNullOrEmpty(range)) 14 | return null; 15 | 16 | // format 0-15 or 80- 17 | string[] parts = range.Split('-'); 18 | 19 | if (parts.Length < 1) 20 | return null; 21 | 22 | int ini; 23 | 24 | if (!int.TryParse(parts[0], out ini)) 25 | return null; 26 | 27 | if (parts[1] == string.Empty || 28 | parts[1].Equals("LAST", StringComparison.InvariantCultureIgnoreCase)) 29 | return new TestRange(ini, LAST); 30 | 31 | int end; 32 | 33 | if (!int.TryParse(parts[1], out end)) 34 | return null; 35 | 36 | return new TestRange(ini, end); 37 | } 38 | 39 | public TestRange(int ini, int end) 40 | { 41 | SetTestRange(ini, end); 42 | } 43 | 44 | public void SetTestRange(int ini, int end) 45 | { 46 | StartTest = ini; 47 | EndTest = end; 48 | } 49 | 50 | public void ResetTestRange() 51 | { 52 | SetTestRange(0, 0); 53 | } 54 | 55 | public override string ToString() 56 | { 57 | string end = (EndTest == LAST) ? "LAST" : string.Format("{0}", EndTest); 58 | return string.Format("{0}-{1}", StartTest, end); 59 | } 60 | 61 | public const int LAST = int.MaxValue; 62 | } 63 | } -------------------------------------------------------------------------------- /lib/pnunit/launcher/launcherautomation/TestSuiteLoggerParams.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PNUnit.Launcher 6 | { 7 | [Serializable] 8 | public class TestSuiteLoggerParams 9 | { 10 | public TestSuiteLoggerParams( 11 | string buildType, 12 | string buildName, 13 | int cset, 14 | string buildComment, 15 | string suiteType, 16 | string suiteName, 17 | string host, 18 | string vmachine, 19 | bool bLogSuccess) 20 | { 21 | mbInitialized = true; 22 | 23 | mBuildType = buildType; 24 | mBuildName = buildName; 25 | mCset = cset; 26 | mBuildComment = buildComment; 27 | mSuiteType = suiteType; 28 | mSuiteName = suiteName; 29 | mHost = host; 30 | mVMachine = vmachine; 31 | mbLogSuccess = bLogSuccess; 32 | } 33 | 34 | public TestSuiteLoggerParams() 35 | { 36 | mbInitialized = false; 37 | } 38 | 39 | public bool IsInitialized() 40 | { 41 | return mbInitialized; 42 | } 43 | 44 | public string BuildType { get { return mBuildType; } } 45 | public string BuildName { get { return mBuildName; } } 46 | public int Cset { get { return mCset; } } 47 | public string Comment { get { return mBuildComment; } } 48 | public string SuiteType { get { return mSuiteType; } } 49 | public string SuiteName { get { return mSuiteName; } } 50 | public string Host { get { return mHost; } } 51 | public string VMachine { get { return mVMachine; } } 52 | public bool LogSuccessfulTests { get { return mbLogSuccess; } } 53 | 54 | string mBuildType; 55 | string mBuildName; 56 | int mCset; 57 | string mBuildComment; 58 | string mSuiteType; 59 | string mSuiteName; 60 | string mHost; 61 | string mVMachine; 62 | bool mbLogSuccess; 63 | bool mbInitialized; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/launcherautomation/launcherautomation.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | bin\x86\Debug\ 6 | DEBUG;TRACE 7 | full 8 | x86 9 | prompt 10 | false 11 | 12 | 13 | bin\x86\Release\ 14 | TRACE 15 | true 16 | pdbonly 17 | x86 18 | prompt 19 | false 20 | false 21 | 22 | 23 | 24 | Debug 25 | AnyCPU 26 | {50BB6499-3821-4786-B9AD-9DDADB1A14FA} 27 | Library 28 | Properties 29 | launcherautomation 30 | launcherautomation 31 | v2.0 32 | 512 33 | 34 | PlasticSCM 35 | PlasticSCM 36 | PlasticSCM 37 | Plastic SCM Source Control Service:{774e58ba-f1b9-40a7-b676-834fa2c220fe} 38 | 39 | 40 | true 41 | full 42 | false 43 | ..\..\..\..\bin\pnunit\ 44 | DEBUG;TRACE 45 | prompt 46 | 4 47 | 48 | 49 | pdbonly 50 | true 51 | bin\Release\ 52 | TRACE 53 | prompt 54 | 4 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/test.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | First test group 5 | 6 | 7 | Test name 8 | Test assembly 9 | Fully qualified test name 10 | host:port 11 | 12 | fill me up! 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/testlogger/TestSuiteEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | using NUnit.Core; 5 | 6 | using PNUnit.Framework; 7 | 8 | namespace PNUnit.Launcher 9 | { 10 | internal static class TestSuiteEntry 11 | { 12 | internal class Data 13 | { 14 | internal string ServerConfig = string.Empty; 15 | internal string BackendType = string.Empty; 16 | internal string ClientConfig = string.Empty; 17 | internal int ExecTime = 0; 18 | internal string Status = FAILURE_STATUS; 19 | internal string Log = string.Empty; 20 | } 21 | 22 | internal static Data Calculate( 23 | TestResult[] testResults, bool bLogSuccessful) 24 | { 25 | Data result = new Data(); 26 | 27 | foreach (PNUnitTestResult tr in testResults) 28 | { 29 | if (string.IsNullOrEmpty(tr.BackendType)) 30 | { 31 | //: client test 32 | result.ClientConfig = tr.OSVersion; 33 | result.ExecTime = (int)Math.Round(tr.Time); 34 | result.Status = tr.ResultState.ToString(); 35 | 36 | if (tr.Killed) 37 | result.Status = KILLED_STATUS; 38 | 39 | if (bLogSuccessful || tr.ResultState != ResultState.Success) 40 | { 41 | result.Log += CollectOutput(tr); 42 | result.Log = result.Log.Replace("'", "''").Replace("\"", "''"); 43 | } 44 | } 45 | else 46 | { 47 | //: server test 48 | result.ServerConfig = tr.OSVersion; 49 | result.BackendType = tr.BackendType; 50 | } 51 | 52 | if (tr.ResultState != ResultState.Success && 53 | tr.ResultState != ResultState.Ignored) 54 | { 55 | result.Log += "---------------------------"; 56 | result.Log += "ERROR: " + tr.Message; 57 | result.Log += "---------------------------"; 58 | } 59 | } 60 | return result; 61 | } 62 | 63 | static string CollectOutput(PNUnitTestResult tr) 64 | { 65 | StringBuilder sb = new StringBuilder(); 66 | sb.Append(tr.Output); 67 | 68 | if (tr.Results != null && tr.Results.Count > 0) 69 | foreach (TestResult child in tr.Results) 70 | DoCollectOutput(child, sb); 71 | 72 | return sb.ToString(); 73 | } 74 | 75 | static void DoCollectOutput(TestResult res, StringBuilder sb) 76 | { 77 | if (res.Results != null && res.Results.Count > 0)//skip non-leaf nodes 78 | { 79 | foreach (TestResult child in res.Results) 80 | DoCollectOutput(child, sb); 81 | 82 | return; 83 | } 84 | 85 | sb.AppendLine(); 86 | 87 | sb.AppendFormat( 88 | "Test: {0}\n Result: {1,-14} Assert Count: {2,-2} Time: {3,5}", 89 | res.FullName, 90 | GetExecutionResult(res), 91 | res.AssertCount, 92 | res.Time); 93 | 94 | sb.AppendLine(); 95 | 96 | if (!res.IsSuccess) 97 | { 98 | sb.AppendLine("Message: " + res.Message); 99 | sb.AppendLine("Stack Trace: "); 100 | sb.AppendLine(res.StackTrace); 101 | } 102 | } 103 | 104 | static string GetExecutionResult(TestResult res) 105 | { 106 | if (res.IsSuccess) return "SUCCESS"; 107 | if (res.IsFailure) return "FAILURE"; 108 | if (!res.Executed) return "NOT EXECUTED"; 109 | return "UNKNOWN"; 110 | } 111 | 112 | const string FAILURE_STATUS = "Failure"; 113 | const string KILLED_STATUS = "Killed"; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/pnunit/launcher/testlogger/TestSuiteLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using NUnit.Core; 4 | using log4net; 5 | 6 | using TestLogger; 7 | 8 | namespace PNUnit.Launcher 9 | { 10 | internal class TestSuiteLogger 11 | { 12 | internal TestSuiteLoggerParams SuiteParams { get { return mTestSuiteLoggerParams; } } 13 | 14 | internal TestSuiteLogger(TestSuiteLoggerParams testSuiteLoggerParams) 15 | { 16 | mTestSuiteLoggerParams = testSuiteLoggerParams; 17 | } 18 | 19 | internal void SaveBuild() 20 | { 21 | TestLoggerClient client = new TestLoggerClient(); 22 | try 23 | { 24 | mBuildId = client.SaveBuild( 25 | mTestSuiteLoggerParams.BuildType, 26 | mTestSuiteLoggerParams.BuildName, 27 | mTestSuiteLoggerParams.Cset.ToString(), 28 | mTestSuiteLoggerParams.Comment); 29 | } 30 | catch (Exception e) 31 | { 32 | log.Error("ERROR LOGGING TEST STATS IN DATABASE: " + e.Message); 33 | } 34 | } 35 | 36 | internal void CreateSuite() 37 | { 38 | TestLoggerClient client = new TestLoggerClient(); 39 | try 40 | { 41 | mSuiteRunId = client.SaveSuiteRun( 42 | mBuildId, 43 | mTestSuiteLoggerParams.SuiteType, 44 | mTestSuiteLoggerParams.SuiteName, 45 | mTestSuiteLoggerParams.Host, 46 | mTestSuiteLoggerParams.VMachine); 47 | } 48 | catch (Exception e) 49 | { 50 | log.Error("ERROR LOGGING TEST STATS IN DATABASE: " + e.Message); 51 | } 52 | } 53 | 54 | internal void LogTestRunResults( 55 | TestResult[] testResults, string suiteType, string testName, bool isRepeated) 56 | { 57 | TestSuiteEntry.Data entry = TestSuiteEntry.Calculate( 58 | testResults, mTestSuiteLoggerParams.LogSuccessfulTests); 59 | 60 | TestLoggerClient client = new TestLoggerClient(); 61 | try 62 | { 63 | client.SaveTestRun( 64 | mBuildId, 65 | mSuiteRunId, 66 | suiteType, 67 | testName, 68 | entry.ClientConfig, 69 | entry.ServerConfig, 70 | entry.BackendType, 71 | entry.ExecTime, 72 | entry.Status, 73 | entry.Log, 74 | isRepeated); 75 | } 76 | catch (Exception e) 77 | { 78 | log.Error("ERROR LOGGING TEST STATS IN DATABASE: " + e.Message); 79 | } 80 | } 81 | 82 | readonly ILog log = LogManager.GetLogger("launcher"); 83 | Guid mBuildId; 84 | 85 | TestSuiteLoggerParams mTestSuiteLoggerParams; 86 | Guid mSuiteRunId; 87 | } 88 | } -------------------------------------------------------------------------------- /lib/pnunit/pnunit.framework/ProcessNameSetter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | public class ProcessNameSetter 6 | { 7 | [DllImport("libc")] // Linux 8 | private static extern int prctl(int option, byte[] arg2, IntPtr arg3, 9 | IntPtr arg4, IntPtr arg5); 10 | 11 | [DllImport("libc")] // BSD 12 | private static extern void setproctitle(byte[] fmt, byte[] str_arg); 13 | 14 | public static void SetProcessName(string name) 15 | { 16 | if (IsWindows()) 17 | return; 18 | 19 | try 20 | { 21 | if (prctl(15 /* PR_SET_NAME */, Encoding.ASCII.GetBytes(name + "\0"), 22 | IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0) 23 | { 24 | Console.WriteLine("Error setting process name"); 25 | } 26 | } 27 | catch (EntryPointNotFoundException) 28 | { 29 | try 30 | { 31 | setproctitle(Encoding.ASCII.GetBytes("%s\0"), 32 | Encoding.ASCII.GetBytes(name + "\0")); 33 | } 34 | catch (Exception e) 35 | { 36 | Console.WriteLine(e.Message); 37 | } 38 | } 39 | } 40 | 41 | private static bool IsWindows() 42 | { 43 | switch (Environment.OSVersion.Platform) 44 | { 45 | case PlatformID.Win32Windows: 46 | case PlatformID.Win32NT: 47 | case PlatformID.Win32S: 48 | return true; 49 | default: 50 | return false; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/pnunit/pnunittestrunner/InitServices.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Util; 3 | 4 | namespace PNUnitTestRunner 5 | { 6 | public class InitServices 7 | { 8 | public static void InitNUnitServices() 9 | { 10 | // initialize NUnit services 11 | // Add Standard Services to ServiceManager 12 | ServiceManager.Services.AddService(new SettingsService()); 13 | ServiceManager.Services.AddService(new DomainManager()); 14 | ServiceManager.Services.AddService(new ProjectService()); 15 | 16 | // initialize NUnit services 17 | // Add Standard Services to ServiceManager 18 | ServiceManager.Services.AddService(new SettingsService()); 19 | ServiceManager.Services.AddService(new DomainManager()); 20 | ServiceManager.Services.AddService(new ProjectService()); 21 | 22 | NUnit.Core.CoreExtensions.Host.InitializeService(); 23 | 24 | // Initialize Services 25 | ServiceManager.Services.InitializeServices(); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /lib/pnunit/pnunittestrunner/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | 5 | using log4net; 6 | using log4net.Config; 7 | 8 | using PNUnit.Framework; 9 | 10 | namespace PNUnitTestRunner 11 | { 12 | class Program 13 | { 14 | static void Main(string[] args) 15 | { 16 | ConfigureLogging(); 17 | 18 | // usage: pnunitinfofile agentconfigfile path to assemblies 19 | if (args.Length != 2) 20 | { 21 | Console.WriteLine("Wrong number of parameters; exiting ..."); 22 | Environment.Exit(1); 23 | } 24 | 25 | if (args[0] == "preload") 26 | { 27 | RunPreload(args[1]); 28 | return; 29 | } 30 | 31 | InitServices.InitNUnitServices(); 32 | 33 | RunOnce(args[0], args[1]); 34 | } 35 | 36 | static void RunOnce(string testInfoFile, string pathToAssemblies) 37 | { 38 | PNUnitTestInfo info = TestInfoReader.ReadTestInfo(testInfoFile); 39 | 40 | if (info == null) 41 | { 42 | Console.WriteLine("Cannot execute tests without information; exiting ..."); 43 | Environment.Exit(1); 44 | } 45 | 46 | ProcessNameSetter.SetProcessName(info.TestName); 47 | 48 | IPNUnitServices services = 49 | PNUnitServices.GetPNunitServicesProxy(info.PNUnitServicesServer); 50 | 51 | if (info.TestName.StartsWith("run-nunit")) 52 | { 53 | new NUnitTestRunner(info, pathToAssemblies).Run(services); 54 | return; 55 | } 56 | 57 | new PNUnitTestRunner(pathToAssemblies).Run(info, services, null); 58 | } 59 | 60 | static void RunPreload(string pathToAssemblies) 61 | { 62 | mLog.Debug("Preload started. Path To assemblies:" + pathToAssemblies); 63 | InitServices.InitNUnitServices(); 64 | 65 | PNUnitTestRunner runner = new PNUnitTestRunner(pathToAssemblies); 66 | runner.Preload(); 67 | 68 | int pidOfThisExpectedByAgent = Codice.Test.PlatformIdentifier.IsWindows() ? 69 | System.Diagnostics.Process.GetCurrentProcess().Id : 70 | Mono.Unix.UnixEnvironment.GetParentProcessId(); 71 | 72 | string testInfoFile = Path.Combine( 73 | Path.GetTempPath(), 74 | PNUnit.Agent.AssemblyPreload.PRELOADED_PROCESS_FILE_PREFIX + pidOfThisExpectedByAgent.ToString()); 75 | 76 | int count = 0; 77 | while(!File.Exists(testInfoFile)) 78 | { 79 | System.Threading.Thread.Sleep(150); 80 | mLog.DebugFormat("Waiting for testinfo file to be created...: {0}", testInfoFile); 81 | 82 | count++; 83 | 84 | if (count >= 6000) //wait 1,5 minutes for test arrival 85 | { 86 | mLog.Fatal("Tired of waiting: Cannot execute tests without information; exiting ..."); 87 | Environment.Exit(1); 88 | } 89 | 90 | } 91 | 92 | mLog.DebugFormat("Preload read {0} from file", testInfoFile); 93 | 94 | PNUnitTestInfo info = TestInfoReader.ReadTestInfo(testInfoFile); 95 | 96 | if (info == null) 97 | { 98 | mLog.Fatal("Cannot execute tests without information; exiting ..."); 99 | Environment.Exit(1); 100 | } 101 | 102 | ProcessNameSetter.SetProcessName(info.TestName); 103 | 104 | IPNUnitServices services = 105 | PNUnitServices.GetPNunitServicesProxy(info.PNUnitServicesServer); 106 | 107 | runner.Run(info, services, null); 108 | } 109 | 110 | static void ConfigureLogging() 111 | { 112 | string log4netpath = Path.Combine( 113 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 114 | "pnunittestrunner.log.conf"); 115 | 116 | XmlConfigurator.Configure(new FileInfo(log4netpath)); 117 | } 118 | 119 | static readonly ILog mLog = LogManager.GetLogger("Program"); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /lib/pnunit/pnunittestrunner/TestInfoReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PNUnit.Framework; 3 | using System.IO; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | using System.Runtime.Serialization.Formatters; 6 | using log4net; 7 | 8 | namespace PNUnitTestRunner 9 | { 10 | public class TestInfoReader 11 | { 12 | public static PNUnitTestInfo ReadTestInfo(string testInfoPath) 13 | { 14 | int ini = Environment.TickCount; 15 | PNUnitTestInfo result = null; 16 | 17 | try 18 | { 19 | using (FileStream fs = new FileStream(testInfoPath, FileMode.Open, FileAccess.Read)) 20 | { 21 | BinaryFormatter bf = new BinaryFormatter(); 22 | bf.AssemblyFormat = FormatterAssemblyStyle.Simple; 23 | result = (PNUnitTestInfo)bf.Deserialize(fs); 24 | 25 | return result; 26 | } 27 | } 28 | catch (Exception e) 29 | { 30 | mLog.ErrorFormat("Something wrong happened when reading the agent info: " + e.Message); 31 | return null; 32 | } 33 | finally 34 | { 35 | TryDelete(testInfoPath); 36 | mLog.DebugFormat( 37 | "Read test info file {0} {1} ms", 38 | testInfoPath, Environment.TickCount - ini); 39 | } 40 | } 41 | 42 | static void TryDelete(string testInfoPath) 43 | { 44 | try 45 | { 46 | File.Delete(testInfoPath); 47 | } 48 | catch (Exception e) 49 | { 50 | mLog.WarnFormat("Could not delete testInfoFile {0} {1}", testInfoPath, e.Message); 51 | mLog.Debug(e.StackTrace); 52 | } 53 | } 54 | 55 | static readonly ILog mLog = LogManager.GetLogger("PNUnitTestRunner"); 56 | } 57 | } -------------------------------------------------------------------------------- /lib/pnunit/pnunittestrunner/pnunittestrunner.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {06A6D68A-82A2-4CC2-8388-3DC6A43310BF} 9 | Exe 10 | Properties 11 | pnunittestrunner 12 | pnunittestrunner 13 | v4.5 14 | 15 | 16 | 512 17 | PlasticSCM 18 | PlasticSCM 19 | PlasticSCM 20 | Plastic SCM Source Control Service:{774e58ba-f1b9-40a7-b676-834fa2c220fe} 21 | 22 | 23 | AnyCPU 24 | true 25 | full 26 | false 27 | ..\..\..\bin\pnunit\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | x86 34 | pdbonly 35 | true 36 | bin\Release\ 37 | TRACE 38 | prompt 39 | 4 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ..\..\log4net\log4net.dll 51 | 52 | 53 | False 54 | ..\..\..\02nervathirdparty\mono\Mono.Posix.dll 55 | 56 | 57 | ..\..\nunit\nunit.core.dll 58 | 59 | 60 | ..\..\nunit\nunit.core.interfaces.dll 61 | 62 | 63 | ..\..\nunit\nunit.util.dll 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | {621C27DA-CC29-4663-9FE4-BF5A67970C18} 72 | agent 73 | 74 | 75 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68} 76 | pnunit.framework 77 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | -------------------------------------------------------------------------------- /lib/pnunit/testloggerinterface/ITestLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TestLogger 4 | { 5 | public interface ITestLogger 6 | { 7 | bool CheckConnection(); 8 | 9 | Guid SaveBuild( 10 | string type, 11 | string name, 12 | string changeset, 13 | string comment); 14 | 15 | Guid SaveSuiteRun( 16 | Guid buildId, 17 | string type, 18 | string name, 19 | string host, 20 | string vmachine); 21 | 22 | void SaveTestRun( 23 | Guid buildId, 24 | Guid suiteRunId, 25 | string suiteType, 26 | string testName, 27 | string clientConfig, 28 | string serverConfig, 29 | string backendType, 30 | int executionTimeSecs, 31 | string status, 32 | string log, 33 | bool isRepeated); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/pnunit/testloggerinterface/TestLoggerClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | 5 | using log4net; 6 | 7 | namespace TestLogger 8 | { 9 | public class TestLoggerClient 10 | { 11 | public TestLoggerClient() 12 | { 13 | mServerLoggerUrl = LoadLoggerServerUrl(); 14 | } 15 | 16 | public TestLoggerClient(string serverLoggerUrl) 17 | { 18 | mServerLoggerUrl = serverLoggerUrl; 19 | } 20 | 21 | public bool CheckConnection() 22 | { 23 | ITestLogger logger = (ITestLogger) 24 | Activator.GetObject(typeof(ITestLogger), mServerLoggerUrl); 25 | return logger.CheckConnection(); 26 | } 27 | 28 | public Guid SaveBuild(string type, string name, string changeset, string comment) 29 | { 30 | ITestLogger logger = (ITestLogger) 31 | Activator.GetObject(typeof(ITestLogger), mServerLoggerUrl); 32 | return logger.SaveBuild(type, name, changeset, comment); 33 | } 34 | 35 | public Guid SaveSuiteRun( 36 | Guid buildId, 37 | string type, 38 | string name, 39 | string host, 40 | string vmachine) 41 | { 42 | ITestLogger logger = (ITestLogger) 43 | Activator.GetObject(typeof(ITestLogger), mServerLoggerUrl); 44 | return logger.SaveSuiteRun(buildId, type, name, host, vmachine); 45 | } 46 | 47 | public void SaveTestRun( 48 | Guid buildId, 49 | Guid suiteRunId, 50 | string suiteType, 51 | string testName, 52 | string clientConfig, 53 | string serverConfig, 54 | string backendType, 55 | int executionTimeSecs, 56 | string status, 57 | string log, 58 | bool isRepeated) 59 | { 60 | ITestLogger logger = (ITestLogger) 61 | Activator.GetObject(typeof(ITestLogger), mServerLoggerUrl); 62 | logger.SaveTestRun( 63 | buildId, 64 | suiteRunId, 65 | suiteType, 66 | testName, 67 | clientConfig, 68 | serverConfig, 69 | backendType, 70 | executionTimeSecs, 71 | status, 72 | log, 73 | isRepeated); 74 | } 75 | 76 | private string LoadLoggerServerUrl() 77 | { 78 | string serverLoggerConfPath = 79 | Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 80 | TEST_LOGGER_SERVER_CONF_FILE); 81 | try 82 | { 83 | using (StreamReader sr = new StreamReader(serverLoggerConfPath)) 84 | { 85 | return sr.ReadToEnd().Trim(); 86 | } 87 | } 88 | catch (Exception) 89 | { 90 | return "tcp://192.168.1.78:9999/TestLogger"; 91 | } 92 | } 93 | 94 | private string mServerLoggerUrl = string.Empty; 95 | private const string TEST_LOGGER_SERVER_CONF_FILE = "testloggerserver.conf"; 96 | private readonly ILog log = LogManager.GetLogger("launcher"); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/pnunit/testloggerinterface/testloggerinterface.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {17A8659A-7BBE-45F5-85DD-A931953775A2} 9 | Library 10 | Properties 11 | testloggerinterface 12 | testloggerinterface 13 | v2.0 14 | 512 15 | 16 | PlasticSCM 17 | PlasticSCM 18 | PlasticSCM 19 | Plastic SCM Source Control Service:{774e58ba-f1b9-40a7-b676-834fa2c220fe} 20 | 21 | 22 | true 23 | full 24 | false 25 | ..\..\..\bin\pnunit\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | ..\..\log4net\log4net.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /src/application/gui/linux/ErrorDialog.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | 3 | using Codice.Examples.GuiTesting.Lib; 4 | using Codice.Examples.GuiTesting.Linux.UI; 5 | 6 | namespace Codice.Examples.GuiTesting.Linux 7 | { 8 | internal class ErrorDialog : BaseDialog 9 | { 10 | internal Button OkButton { get { return mOkButton; } } 11 | internal Label MessageLabel { get { return mMessageLabel; } } 12 | 13 | internal ErrorDialog(string title, string message, Window parent) 14 | : base(title, parent) 15 | { 16 | BuildComponents(message); 17 | SetSizeRequest(DIALOG_WIDTH, DIALOG_HEIGHT); 18 | } 19 | 20 | void BuildComponents(string message) 21 | { 22 | HBox messageBox = new HBox(); 23 | 24 | mMessageLabel = ControlBuilder.CreateExplanationLabel(message); 25 | Image messageImage = Image.NewFromIconName( 26 | "dialog-error", IconSize.Dialog); 27 | 28 | ControlPacker.Add(messageBox, messageImage); 29 | ControlPacker.Fill( 30 | messageBox, 31 | AlignmentBuilder.LeftPadding( 32 | mMessageLabel, AlignmentBuilder.SMALL_PADDING)); 33 | 34 | AddComponents( 35 | AlignmentBuilder.TopBottomPadding( 36 | messageBox, AlignmentBuilder.SMALL_PADDING)); 37 | 38 | mOkButton = CreateOkButton( 39 | Localization.GetText(Localization.Name.Ok)); 40 | 41 | DefaultResponse = (ResponseType)GetResponseForWidget(mOkButton); 42 | } 43 | 44 | Button mOkButton; 45 | Label mMessageLabel; 46 | 47 | const int DIALOG_WIDTH = 360; 48 | const int DIALOG_HEIGHT = 160; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/application/gui/linux/ExceptionsHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using log4net; 4 | 5 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 6 | 7 | namespace Codice.Examples.GuiTesting.Linux 8 | { 9 | internal static class ExceptionsHandler 10 | { 11 | internal static void SetExceptionHandlers(bool isTestingMode) 12 | { 13 | if (isTestingMode) 14 | { 15 | SetTestingExceptionHandlers(); 16 | return; 17 | } 18 | 19 | SetStandardExceptionHandlers(); 20 | } 21 | 22 | static void SetStandardExceptionHandlers() 23 | { 24 | AppDomain.CurrentDomain.UnhandledException += HandleTestingUnhandledException; 25 | GLib.ExceptionManager.UnhandledException += HandleUnhandledGlibTestingException; 26 | } 27 | 28 | static void SetTestingExceptionHandlers() 29 | { 30 | // We don't want to eat up the exception during testing like nothing 31 | // happens, but we still want to save it in order to display it 32 | // as the cause of the failed test. 33 | AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; 34 | GLib.ExceptionManager.UnhandledException += HandleUnhandledGlibException; 35 | } 36 | 37 | static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs e) 38 | { 39 | // Here you'd usually log the exception, send telemetry events... 40 | Exception ex = e.ExceptionObject as Exception; 41 | if (ex == null) 42 | return; 43 | 44 | Console.Error.WriteLine(ex.Message); 45 | Console.Error.WriteLine(ex.StackTrace); 46 | } 47 | 48 | static void HandleUnhandledGlibException(GLib.UnhandledExceptionArgs e) 49 | { 50 | // Here you'd usually log the exception, send telemetry events... 51 | mLog.ErrorFormat("The runtime is terminating [{0}]", e.IsTerminating); 52 | e.ExitApplication = false; 53 | 54 | Exception ex = e.ExceptionObject as Exception; 55 | if (ex == null) 56 | return; 57 | 58 | Console.Error.WriteLine(ex.Message); 59 | Console.Error.WriteLine(ex.StackTrace); 60 | } 61 | 62 | static void HandleTestingUnhandledException(object sender, UnhandledExceptionEventArgs e) 63 | { 64 | HandleTestingException(e.ExceptionObject as Exception); 65 | } 66 | 67 | static void HandleUnhandledGlibTestingException(GLib.UnhandledExceptionArgs e) 68 | { 69 | HandleTestingException(e.ExceptionObject as Exception); 70 | 71 | mLog.ErrorFormat("The runtime is terminating [{0}]", e.IsTerminating); 72 | e.ExitApplication = false; 73 | } 74 | 75 | static void HandleTestingException(Exception ex) 76 | { 77 | GuiTesteableServices.UnhandledException = ex; 78 | } 79 | 80 | static readonly ILog mLog = LogManager.GetLogger("ExceptionsHandler"); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/application/gui/linux/GtkGuiMessage.cs: -------------------------------------------------------------------------------- 1 | using Codice.Examples.GuiTesting.Lib.Interfaces; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux 4 | { 5 | internal class GtkGuiMessage : GuiMessage.IGuiMessage 6 | { 7 | void GuiMessage.IGuiMessage.ShowError(string title, string message) 8 | { 9 | ErrorDialog dialog = new ErrorDialog( 10 | title, message, WindowHandler.ApplicationWindow); 11 | 12 | WindowHandler.SetActiveDialogForTesting(dialog); 13 | 14 | try 15 | { 16 | dialog.RunModal(); 17 | } 18 | finally 19 | { 20 | WindowHandler.RemoveDialogForTesting(dialog); 21 | dialog.Dispose(); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/application/gui/linux/ProcessNameSetter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | using log4net; 6 | 7 | namespace Codice.Examples.GuiTesting.Linux 8 | { 9 | internal class ProcessNameSetter 10 | { 11 | [DllImport("libc")] // Linux 12 | static extern int prctl( 13 | int option, byte[] arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5); 14 | 15 | [DllImport("libc")] // BSD 16 | static extern int setproctitle(byte[] fmt, byte[] str_arg); 17 | 18 | internal static void SetProcessName(string name) 19 | { 20 | if (IsWindows()) 21 | return; 22 | 23 | try 24 | { 25 | if (PrctlSetName(name) != 0) 26 | mLog.Debug("Error setting process name"); 27 | } 28 | catch (EntryPointNotFoundException) 29 | { 30 | try 31 | { 32 | setproctitle( 33 | Encoding.ASCII.GetBytes("%s\0"), 34 | Encoding.ASCII.GetBytes(name + "\0")); 35 | } 36 | catch (Exception ex) 37 | { 38 | mLog.DebugFormat( 39 | "Couldn't change process name: {0}", ex.Message); 40 | } 41 | } 42 | } 43 | 44 | static int PrctlSetName(string name) 45 | { 46 | return prctl( 47 | (int)OPTION.PR_SET_NAME, 48 | Encoding.ASCII.GetBytes(name + "\0"), 49 | IntPtr.Zero, 50 | IntPtr.Zero, 51 | IntPtr.Zero); 52 | } 53 | 54 | enum OPTION 55 | { 56 | PR_SET_NAME = 15 57 | } 58 | 59 | private static bool IsWindows() 60 | { 61 | switch (Environment.OSVersion.Platform) 62 | { 63 | case PlatformID.Win32Windows: 64 | case PlatformID.Win32NT: 65 | case PlatformID.Win32S: 66 | return true; 67 | default: 68 | return false; 69 | } 70 | } 71 | 72 | static readonly ILog mLog = LogManager.GetLogger("ProcessNameSetter"); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/application/gui/linux/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using Gtk; 5 | 6 | using GuiTest; 7 | 8 | using Codice.Examples.GuiTesting.Lib; 9 | using Codice.Examples.GuiTesting.Lib.Interfaces; 10 | using Codice.Examples.GuiTesting.Lib.Threading; 11 | using Codice.Examples.GuiTesting.Linux.Threading; 12 | 13 | namespace Codice.Examples.GuiTesting.Linux 14 | { 15 | static class Program 16 | { 17 | [STAThread] 18 | static void Main(string[] args) 19 | { 20 | try 21 | { 22 | ApplicationArgs appArgs = ApplicationArgs.Parse(args); 23 | 24 | ExceptionsHandler.SetExceptionHandlers(appArgs.IsTestingMode); 25 | 26 | ProcessNameSetter.SetProcessName("linux"); 27 | 28 | ThreadWaiterBuilder.Initialize(new GtkApplicationTimerBuilder()); 29 | 30 | GuiMessage.Initialize(new GtkGuiMessage()); 31 | 32 | if (appArgs.IsTestingMode) 33 | InstallTestAssembliesResolver(appArgs.PathToAssemblies); 34 | 35 | // Tip: you could launch different windows depending on the 36 | // argument flags. 37 | Application.Init(); 38 | WindowHandler.LaunchApplicationWindow(); 39 | 40 | if (appArgs.IsTestingMode) 41 | WindowHandler.LaunchTest(appArgs.TestInfoFile, appArgs.PathToAssemblies); 42 | 43 | Application.Run(); 44 | } 45 | catch (Exception ex) 46 | { 47 | // You would track the exception here 48 | Console.Error.WriteLine($"{ex.GetType()}: {ex.Message}"); 49 | Console.Error.WriteLine(ex.StackTrace); 50 | 51 | ExitCode = 1; 52 | Application.Quit(); 53 | } 54 | finally 55 | { 56 | // You would dispose everything you need here. 57 | Environment.Exit(ExitCode); 58 | } 59 | } 60 | 61 | static void InstallTestAssembliesResolver(string pathToAssemblies) 62 | { 63 | List assemblies = new List(); 64 | assemblies.Add("nunit.core.dll"); 65 | assemblies.Add("nunit.core.interfaces.dll"); 66 | assemblies.Add("nunit.util.dll"); 67 | assemblies.Add("pnunit.framework.dll"); 68 | 69 | assemblies.Add("guitestinterfaces.dll"); 70 | assemblies.Add("guitest.dll"); 71 | 72 | GuiTestRunner.GuiTestAssemblyResolver.InstallAssemblyResolver( 73 | pathToAssemblies, assemblies); 74 | } 75 | 76 | static int ExitCode = 0; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/application/gui/linux/WindowHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Threading; 5 | 6 | using Gtk; 7 | 8 | using log4net; 9 | using log4net.Config; 10 | using log4net.Repository; 11 | 12 | using GuiTest; 13 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 14 | using Codice.Examples.GuiTesting.Lib; 15 | using Codice.Examples.GuiTesting.Linux.Testing; 16 | 17 | namespace Codice.Examples.GuiTesting.Linux 18 | { 19 | internal static class WindowHandler 20 | { 21 | internal static Window ApplicationWindow 22 | { 23 | get { return mApplicationWindow; } 24 | } 25 | 26 | internal static void LaunchApplicationWindow() 27 | { 28 | ApplicationOperations operations = new ApplicationOperations(); 29 | mApplicationWindow = new ApplicationWindow(operations); 30 | mApplicationWindow.WindowPosition = WindowPosition.Center; 31 | mApplicationWindow.ShowAll(); 32 | } 33 | 34 | internal static void UnregisterApplicationWindow() 35 | { 36 | mApplicationWindow.Dispose(); 37 | mApplicationWindow = null; 38 | 39 | TerminateApplication(); 40 | } 41 | 42 | internal static void SetActiveDialogForTesting(Dialog dialog) 43 | { 44 | if (!mbIsTestRun) 45 | return; 46 | 47 | mActiveDialog = dialog; 48 | } 49 | 50 | internal static void RemoveDialogForTesting(Dialog dialog) 51 | { 52 | if (!mbIsTestRun) 53 | return; 54 | 55 | if (mActiveDialog == dialog) 56 | mActiveDialog = null; 57 | } 58 | 59 | internal static Dialog GetActiveDialog() 60 | { 61 | return mActiveDialog; 62 | } 63 | 64 | internal static void LaunchTest(string testInfoFile, string pathToAssemblies) 65 | { 66 | mbIsTestRun = true; 67 | 68 | ConfigureTestLogging(); 69 | InitTesteableServices(); 70 | 71 | GuiTestRunner testRunner = new GuiTestRunner( 72 | testInfoFile, pathToAssemblies, new GuiFinalizer(), null); 73 | 74 | ThreadPool.QueueUserWorkItem(new WaitCallback(testRunner.Run)); 75 | } 76 | 77 | static void ConfigureTestLogging() 78 | { 79 | try 80 | { 81 | string log4netPath = Path.Combine( 82 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 83 | "pnunittestrunner.log.conf"); 84 | 85 | XmlConfigurator.Configure(mLogRepository, new FileInfo(log4netPath)); 86 | } 87 | catch { } // Log config failed, nothing else to do! 88 | } 89 | 90 | static void InitTesteableServices() 91 | { 92 | TesteableApplicationWindow testeableWindow = 93 | new TesteableApplicationWindow(mApplicationWindow); 94 | 95 | GuiTesteableServices.Init(testeableWindow); 96 | } 97 | 98 | static void TerminateApplication() 99 | { 100 | if (mbIsTestRun) 101 | return; 102 | 103 | Application.Quit(); 104 | } 105 | 106 | static ApplicationWindow mApplicationWindow; 107 | static Dialog mActiveDialog; 108 | static bool mbIsTestRun = false; 109 | 110 | static readonly ILoggerRepository mLogRepository = 111 | LogManager.CreateRepository("log4net-rep"); 112 | 113 | class GuiFinalizer : GuiTestRunner.IGuiFinalizer 114 | { 115 | void GuiTestRunner.IGuiFinalizer.Finalize(int exitCode) 116 | { 117 | Environment.Exit(exitCode); 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/application/gui/linux/linux.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2046 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "linux", "linux.csproj", "{353B26F1-B1C1-4731-ADF8-87B40A763F19}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lib", "..\..\lib\lib.csproj", "{A1079FA8-882B-40D6-A289-3A13767CABDD}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{0182C75F-FE4F-4A0F-B938-083A868BFA6B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitest", "..\..\..\testing\guitest\guitest.csproj", "{9EE461F0-5FCA-4631-8335-73E1A0AF2861}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitestinterfaces", "..\..\..\testing\guitestinterfaces\guitestinterfaces.csproj", "{D775E82D-4045-4E11-AE85-4402CA0AD054}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pnunit.framework", "..\..\..\..\lib\pnunit\pnunit.framework\pnunit.framework.csproj", "{5261ABA1-98E6-4603-A4F0-59CAC307AC68}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | NAnt|Any CPU = NAnt|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 28 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.NAnt|Any CPU.Build.0 = Release|Any CPU 29 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {353B26F1-B1C1-4731-ADF8-87B40A763F19}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 34 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.Build.0 = Release|Any CPU 35 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 40 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.Build.0 = Release|Any CPU 41 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 46 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.Build.0 = Release|Any CPU 47 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 50 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|Any CPU.Build.0 = Debug|Any CPU 51 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.ActiveCfg = NAnt|Any CPU 52 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.Build.0 = NAnt|Any CPU 53 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|Any CPU.Build.0 = Release|Any CPU 55 | EndGlobalSection 56 | GlobalSection(SolutionProperties) = preSolution 57 | HideSolutionNode = FALSE 58 | EndGlobalSection 59 | GlobalSection(NestedProjects) = preSolution 60 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861} = {0182C75F-FE4F-4A0F-B938-083A868BFA6B} 61 | {D775E82D-4045-4E11-AE85-4402CA0AD054} = {0182C75F-FE4F-4A0F-B938-083A868BFA6B} 62 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68} = {0182C75F-FE4F-4A0F-B938-083A868BFA6B} 63 | EndGlobalSection 64 | GlobalSection(ExtensibilityGlobals) = postSolution 65 | SolutionGuid = {FD1A3758-F68F-4C01-9C40-EE45432517B1} 66 | EndGlobalSection 67 | EndGlobal 68 | -------------------------------------------------------------------------------- /src/application/gui/linux/testing/TesteableApplicationWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 4 | 5 | namespace Codice.Examples.GuiTesting.Linux.Testing 6 | { 7 | internal class TesteableApplicationWindow : ITesteableApplicationWindow 8 | { 9 | internal TesteableApplicationWindow(ApplicationWindow window) 10 | { 11 | mWindow = window; 12 | } 13 | 14 | void ITesteableApplicationWindow.ChangeText(string text) 15 | { 16 | TestHelper.SetText(mWindow.TextEntry, text); 17 | } 18 | 19 | string ITesteableApplicationWindow.GetText() 20 | { 21 | return TestHelper.GetText(mWindow.TextEntry); 22 | } 23 | 24 | void ITesteableApplicationWindow.ClickAddButton() 25 | { 26 | TestHelper.ClickButton(mWindow.AddButton); 27 | } 28 | 29 | void ITesteableApplicationWindow.ClickRemoveButton() 30 | { 31 | TestHelper.ClickButton(mWindow.RemoveButton); 32 | } 33 | 34 | bool ITesteableApplicationWindow.AreButtonsEnabled() 35 | { 36 | return TestHelper.IsSensitive(mWindow.AddButton) 37 | && TestHelper.IsSensitive(mWindow.RemoveButton); 38 | } 39 | 40 | string ITesteableApplicationWindow.GetItemInListAt(int index) 41 | { 42 | return TestHelper.GetItemAt(mWindow.ListView, index); 43 | } 44 | 45 | int ITesteableApplicationWindow.GetItemsInListCount() 46 | { 47 | return TestHelper.GetItemCount(mWindow.ListView); 48 | } 49 | 50 | string ITesteableApplicationWindow.GetProgressMessage() 51 | { 52 | if (mWindow.ProgressControls.HasError) 53 | return string.Empty; 54 | 55 | return TestHelper.GetText(mWindow.ProgressControls.ProgressLabel); 56 | } 57 | 58 | string ITesteableApplicationWindow.GetErrorMessage() 59 | { 60 | if (!mWindow.ProgressControls.HasError) 61 | return string.Empty; 62 | 63 | return TestHelper.GetText(mWindow.ProgressControls.ProgressLabel); 64 | } 65 | 66 | ITesteableErrorDialog ITesteableApplicationWindow.GetErrorDialog() 67 | { 68 | if (WindowHandler.GetActiveDialog() == null) 69 | return null; 70 | 71 | ErrorDialog errorDialog = WindowHandler.GetActiveDialog() as ErrorDialog; 72 | if (errorDialog == null) 73 | return null; 74 | 75 | return new TesteableErrorDialog(errorDialog); 76 | } 77 | 78 | readonly ApplicationWindow mWindow; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/application/gui/linux/testing/TesteableErrorDialog.cs: -------------------------------------------------------------------------------- 1 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.Testing 4 | { 5 | internal class TesteableErrorDialog : ITesteableErrorDialog 6 | { 7 | internal TesteableErrorDialog(ErrorDialog errorDialog) 8 | { 9 | mDialog = errorDialog; 10 | } 11 | 12 | void ITesteableErrorDialog.ClickOkButton() 13 | { 14 | TestHelper.ClickDialogButton(mDialog.OkButton); 15 | } 16 | 17 | string ITesteableErrorDialog.GetTitle() 18 | { 19 | return TestHelper.GetTitle(mDialog); 20 | } 21 | 22 | string ITesteableErrorDialog.GetMessage() 23 | { 24 | return TestHelper.GetText(mDialog.MessageLabel); 25 | } 26 | 27 | readonly ErrorDialog mDialog; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/application/gui/linux/threading/GtkApplicationTimer.cs: -------------------------------------------------------------------------------- 1 | using Codice.Examples.GuiTesting.Lib.Threading; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.Threading 4 | { 5 | internal class GtkApplicationTimerBuilder : IApplicationTimerBuilder 6 | { 7 | public IApplicationTimer Get( 8 | bool bModalMode, 9 | ThreadWaiter.TimerTick timerTickDelegate) 10 | { 11 | return new GtkApplicationTimer(DEFAULT_TIMER_INTERVAL, timerTickDelegate); 12 | } 13 | 14 | public IApplicationTimer Get( 15 | bool bModalMode, 16 | int timerInterval, 17 | ThreadWaiter.TimerTick timerTickDelegate) 18 | { 19 | return new GtkApplicationTimer((uint)timerInterval, timerTickDelegate); 20 | } 21 | 22 | const int DEFAULT_TIMER_INTERVAL = 500; 23 | } 24 | 25 | internal class GtkApplicationTimer : IApplicationTimer 26 | { 27 | internal GtkApplicationTimer( 28 | uint timerInterval, ThreadWaiter.TimerTick timerTickDelegate) 29 | { 30 | mTimerInterval = timerInterval; 31 | mTimerTickDelegate = timerTickDelegate; 32 | } 33 | 34 | public void Start() 35 | { 36 | mTimeoutId = GLib.Timeout.Add( 37 | mTimerInterval, new GLib.TimeoutHandler(OnTimerTick)); 38 | } 39 | 40 | public void Stop() 41 | { 42 | if (mTimeoutId == 0) 43 | return; 44 | 45 | GLib.Source.Remove(mTimeoutId); 46 | mTimeoutId = 0; 47 | } 48 | 49 | bool OnTimerTick() 50 | { 51 | mTimerTickDelegate(); 52 | 53 | return true; 54 | } 55 | 56 | uint mTimeoutId; 57 | 58 | readonly uint mTimerInterval; 59 | ThreadWaiter.TimerTick mTimerTickDelegate; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/AlignmentBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using Gtk; 8 | 9 | namespace Codice.Examples.GuiTesting.Linux.UI 10 | { 11 | internal static class AlignmentBuilder 12 | { 13 | internal const int SMALL_PADDING = 5; 14 | 15 | internal static void SetLeftAlignment(Label label) 16 | { 17 | label.SetAlignment(0, (float)0.5); 18 | } 19 | 20 | internal static void SetRightAlignment(Label label) 21 | { 22 | label.SetAlignment(1, (float)0.5); 23 | } 24 | 25 | internal static Alignment LeftPadding(Widget widget, uint leftPadding) 26 | { 27 | return Padding(widget, 0, 0, leftPadding, 0); 28 | } 29 | 30 | internal static Alignment RightPadding(Widget widget, uint rightPadding) 31 | { 32 | return Padding(widget, 0, 0, 0, rightPadding); 33 | } 34 | 35 | internal static Alignment LeftRightPadding(Widget widget, uint leftRightPadding) 36 | { 37 | return Padding(widget, 0, 0, leftRightPadding, leftRightPadding); 38 | } 39 | 40 | internal static Alignment TopBottomPadding(Widget widget, uint topBottomPadding) 41 | { 42 | return Padding(widget, topBottomPadding, topBottomPadding, 0, 0); 43 | } 44 | 45 | internal static Alignment RightAlignment(Widget widget) 46 | { 47 | Alignment result = new Alignment(1, 0, 0, 0); 48 | result.Add(widget); 49 | 50 | return result; 51 | } 52 | 53 | static Alignment Padding( 54 | Widget widget, 55 | uint topPadding, 56 | uint bottomPadding, 57 | uint leftPadding, 58 | uint rightPadding) 59 | { 60 | Alignment result = new Alignment(1, 1, 1, 1); 61 | result.TopPadding = topPadding; 62 | result.BottomPadding = bottomPadding; 63 | result.LeftPadding = leftPadding; 64 | result.RightPadding = rightPadding; 65 | result.Add(widget); 66 | 67 | return result; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/BaseDialog.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal class BaseDialog : Dialog 6 | { 7 | internal BaseDialog(string title, Window parent) : base(title, parent, DialogFlags.Modal) 8 | { 9 | SetPosition(WindowPosition.CenterOnParent); 10 | BorderWidth = 10; 11 | Resizable = false; 12 | HasSeparator = true; 13 | } 14 | 15 | public override void Dispose() 16 | { 17 | Destroy(); 18 | base.Dispose(); 19 | } 20 | 21 | internal void AddComponents(params Widget[] widgets) 22 | { 23 | foreach (Widget widget in widgets) 24 | ControlPacker.Add(VBox, widget); 25 | 26 | ShowAll(); 27 | } 28 | 29 | internal Button CreateOkButton(string buttonText) 30 | { 31 | return (Button)AddButton(buttonText, ResponseType.Ok); 32 | } 33 | 34 | internal ResponseType RunModal() 35 | { 36 | WindowHandler.SetActiveDialogForTesting(this); 37 | 38 | ResponseType responseType; 39 | while ((responseType = (ResponseType)Run()) == ResponseType.None) { } 40 | 41 | return responseType; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/CellContentRenderer.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | using Pango; 3 | 4 | namespace Codice.Examples.GuiTesting.Linux.UI 5 | { 6 | internal static class CellContentRenderer 7 | { 8 | internal static void RenderText(CellRenderer cell, string text) 9 | { 10 | CellRendererText textCell = cell as CellRendererText; 11 | textCell.FontDesc.Weight = Weight.Normal; 12 | textCell.Text = text; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/ControlBuilder.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal static class ControlBuilder 6 | { 7 | internal static Button CreateButton(string text) 8 | { 9 | Button result = new Button(text); 10 | result.Relief = ReliefStyle.Normal; 11 | result.SetSizeRequest(DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT); 12 | 13 | return result; 14 | } 15 | 16 | internal static Entry CreateEntry() 17 | { 18 | return new Entry(); 19 | } 20 | 21 | internal static Label CreateExplanationLabel(string text) 22 | { 23 | Label result = CreateLabel(); 24 | result.Name = text; 25 | result.LabelProp = Mono.Unix.Catalog.GetString(text); 26 | result.Justify = Justification.Left; 27 | result.LineWrapMode = Pango.WrapMode.Word; 28 | result.LineWrap = true; 29 | result.SizeAllocated += (sender, args) => 30 | { 31 | Label label = sender as Label; 32 | label.SetSizeRequest(args.Allocation.Width - 1, -1); 33 | }; 34 | return result; 35 | } 36 | 37 | internal static Label CreateLabel(string text) 38 | { 39 | Label result = CreateLabel(); 40 | result.Name = text; 41 | result.LabelProp = Mono.Unix.Catalog.GetString(text); 42 | return result; 43 | } 44 | 45 | internal static Label CreateSelectableLabel() 46 | { 47 | Label result = CreateLabel(); 48 | result.Selectable = true; 49 | return result; 50 | } 51 | 52 | internal static Label CreateLabel() 53 | { 54 | Label result = new Label(); 55 | result.SetPadding(5, 0); 56 | return result; 57 | } 58 | 59 | internal static Widget CreateEmptyArea() 60 | { 61 | return new HBox(true, 0); 62 | } 63 | 64 | const int DEFAULT_BUTTON_WIDTH = 100; 65 | const int DEFAULT_BUTTON_HEIGHT = 34; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/ControlPacker.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal static class ControlPacker 6 | { 7 | internal static void Add(Box box, Widget widget, uint padding = 0) 8 | { 9 | box.PackStart(widget, false, false, padding); 10 | } 11 | 12 | internal static void Fill(Box box, Widget widget, uint padding = 0) 13 | { 14 | box.PackStart(widget, true, true, padding); 15 | } 16 | 17 | internal static void PackActionButtons(HBox box, uint padding, params Widget[] buttons) 18 | { 19 | HBox buttonsBox = new HBox(); 20 | 21 | Add(buttonsBox, buttons[0]); 22 | for (int i = 1; i < buttons.Length; i++) 23 | Add(buttonsBox, AlignmentBuilder.LeftPadding(buttons[i], padding)); 24 | 25 | Fill(box, ControlBuilder.CreateEmptyArea()); 26 | Add(box, buttonsBox); 27 | } 28 | 29 | internal static void PackProgressLabel(HBox box, Label progressLabel) 30 | { 31 | box.HeightRequest = PROGRESS_PANEL_HEIGHT; 32 | AlignmentBuilder.SetLeftAlignment(progressLabel); 33 | Fill(box, progressLabel); 34 | } 35 | 36 | const int PROGRESS_PANEL_HEIGHT = 22; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/GtkListView.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal class GtkListView 6 | { 7 | internal delegate Gtk.TreePath FindRowFunc(Gtk.TreeModel model, T value); 8 | 9 | internal readonly Gtk.TreeView View; 10 | 11 | internal bool HeadersVisible 12 | { 13 | get { return View.HeadersVisible; } 14 | set { View.HeadersVisible = value; } 15 | } 16 | 17 | internal GtkListView( 18 | List columns, 19 | Dictionary sortFunctionsByColumn, 20 | Gtk.TreeModelFilterVisibleFunc visibleFunc) 21 | { 22 | View = TreeBuilder.CreateTreeView(); 23 | mSortFunctionByColumn = sortFunctionsByColumn; 24 | mVisibleFunc = visibleFunc; 25 | 26 | foreach (Gtk.TreeViewColumn column in columns) 27 | View.AppendColumn(column); 28 | } 29 | 30 | internal void Fill(List values) 31 | { 32 | if (values == null) 33 | return; 34 | 35 | Gtk.ListStore listStore = new Gtk.ListStore(typeof(T)); 36 | 37 | values.ForEach((val) => listStore.AppendValues(val)); 38 | 39 | mModelFilter = new Gtk.TreeModelFilter(listStore, null); 40 | mModelFilter.VisibleFunc = mVisibleFunc; 41 | 42 | mModelSort = new Gtk.TreeModelSort(mModelFilter); 43 | SetSortFunctions(mModelSort, mSortFunctionByColumn); 44 | 45 | if (View.Model != null) 46 | (View.Model as Gtk.TreeModelSort).Dispose(); 47 | 48 | View.Model = mModelSort; 49 | } 50 | 51 | internal List GetSelected() 52 | { 53 | List result = new List(); 54 | 55 | if (View.Selection.CountSelectedRows() == 0) 56 | return result; 57 | 58 | foreach (Gtk.TreePath path in View.Selection.GetSelectedRows()) 59 | result.Add(GetObjectFromTreePath(mModelSort, path)); 60 | 61 | return result; 62 | } 63 | 64 | static T GetObjectFromTreePath(Gtk.TreeModelSort modelSort, Gtk.TreePath path) 65 | { 66 | Gtk.TreeIter iter; 67 | modelSort.GetIter(out iter, path); 68 | return GetObjectFromTreeIter(modelSort, iter); 69 | } 70 | 71 | static T GetObjectFromTreeIter(Gtk.TreeModel model, Gtk.TreeIter iter) 72 | { 73 | return (T)model.GetValue(iter, 0); 74 | } 75 | 76 | static void SetSortFunctions( 77 | Gtk.TreeModelSort treeModelSort, 78 | Dictionary sortFunctions) 79 | { 80 | foreach (int sortColumnId in sortFunctions.Keys) 81 | treeModelSort.SetSortFunc(sortColumnId, sortFunctions[sortColumnId]); 82 | } 83 | 84 | Gtk.TreeModelFilter mModelFilter; 85 | Gtk.TreeModelSort mModelSort; 86 | 87 | readonly Dictionary mSortFunctionByColumn; 88 | readonly Gtk.TreeModelFilterVisibleFunc mVisibleFunc; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/Keyboard.cs: -------------------------------------------------------------------------------- 1 | using Gdk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal static class Keyboard 6 | { 7 | internal static bool IsEnterPressed(EventKey eventKey) 8 | { 9 | Key key = eventKey.Key; 10 | 11 | return key == Key.Return 12 | || key == Key.ISO_Enter 13 | || key == Key.Key_3270_Enter 14 | || key == Key.KP_Enter; 15 | } 16 | 17 | internal static bool IsSpacePressed(EventKey eventKey) 18 | { 19 | Key key = eventKey.Key; 20 | 21 | return key == Key.space 22 | || key == Key.KP_Space; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/Mouse.cs: -------------------------------------------------------------------------------- 1 | using Gdk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal static class Mouse 6 | { 7 | internal static bool IsRightMouseButtonPressed(EventButton eventButton) 8 | { 9 | return eventButton.Button == RIGTH_MOUSE_BUTTON; 10 | } 11 | 12 | const int RIGTH_MOUSE_BUTTON = 3; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/ProgressControls.cs: -------------------------------------------------------------------------------- 1 | using Gdk; 2 | using Gtk; 3 | 4 | using Codice.Examples.GuiTesting.Lib.Interfaces; 5 | 6 | namespace Codice.Examples.GuiTesting.Linux.UI 7 | { 8 | internal class ProgressControls : IProgressControls 9 | { 10 | public bool HasError { get { return mbHasError; } } 11 | public Label ProgressLabel { get { return mProgressLabel; } } 12 | 13 | internal ProgressControls(Label progressLabel, Widget[] widgets) 14 | { 15 | mProgressLabel = progressLabel; 16 | mWidgets = widgets; 17 | } 18 | 19 | void IProgressControls.HideProgress() 20 | { 21 | mProgressLabel.Visible = false; 22 | 23 | EnableWidgets(mWidgets); 24 | 25 | if (mbFocusedWidget != null) 26 | mbFocusedWidget.GrabFocus(); 27 | } 28 | 29 | void IProgressControls.ShowError(string message) 30 | { 31 | mbHasError = true; 32 | 33 | mProgressLabel.ModifyFg(StateType.Normal, COLOR_RED); 34 | mProgressLabel.Text = message; 35 | mProgressLabel.Visible = true; 36 | } 37 | 38 | void IProgressControls.ShowProgress(string message) 39 | { 40 | mbHasError = false; 41 | 42 | mProgressLabel.ModifyFg(StateType.Normal, COLOR_BLACK); 43 | mProgressLabel.Text = message; 44 | mProgressLabel.Visible = true; 45 | 46 | mbFocusedWidget = GetFocusedWidget(mWidgets); 47 | 48 | DisableWidgets(mWidgets); 49 | } 50 | 51 | static void DisableWidgets(Widget[] widgets) 52 | { 53 | foreach (Widget widget in widgets) 54 | widget.Sensitive = false; 55 | } 56 | 57 | static void EnableWidgets(Widget[] widgets) 58 | { 59 | foreach (Widget widget in widgets) 60 | widget.Sensitive = true; 61 | } 62 | 63 | static Widget GetFocusedWidget(Widget[] widgets) 64 | { 65 | foreach (Widget widget in widgets) 66 | { 67 | if (widget.HasFocus) 68 | return widget; 69 | } 70 | 71 | return null; 72 | } 73 | 74 | Widget mbFocusedWidget; 75 | bool mbHasError; 76 | 77 | readonly Label mProgressLabel; 78 | readonly Widget[] mWidgets; 79 | 80 | static readonly Color COLOR_RED = new Color(255, 0, 0); 81 | static readonly Color COLOR_BLACK = new Color(0, 0, 0); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/application/gui/linux/ui/TreeBuilder.cs: -------------------------------------------------------------------------------- 1 | using Gtk; 2 | 3 | namespace Codice.Examples.GuiTesting.Linux.UI 4 | { 5 | internal static class TreeBuilder 6 | { 7 | internal static TreeView CreateTreeView() 8 | { 9 | TreeView result = new TreeView(); 10 | result.FixedHeightMode = true; 11 | result.ButtonPressEvent += TreeView_ProtectButtonPressMultipleSelection; 12 | result.KeyPressEvent += TreeView_ProtectActivateMultipleSelection; 13 | 14 | return result; 15 | } 16 | 17 | internal static TreeViewColumn CreateColumn( 18 | string label, 19 | int fixedWidth, 20 | TreeCellDataFunc renderFunc) 21 | { 22 | TreeViewColumn result = new TreeViewColumn() 23 | { 24 | Title = label, 25 | Sizing = TreeViewColumnSizing.Fixed, 26 | FixedWidth = fixedWidth, 27 | Resizable = true, 28 | Reorderable = false, 29 | SortIndicator = false 30 | }; 31 | 32 | CellRendererText cell = new CellRendererText(); 33 | result.PackStart(cell, true); 34 | result.SetCellDataFunc(cell, renderFunc); 35 | 36 | return result; 37 | } 38 | 39 | [GLib.ConnectBefore] 40 | static void TreeView_ProtectButtonPressMultipleSelection( 41 | object sender, ButtonPressEventArgs e) 42 | { 43 | TreeView treeView = sender as TreeView; 44 | 45 | if (!Mouse.IsRightMouseButtonPressed(e.Event)) 46 | { 47 | e.RetVal = false; 48 | return; 49 | } 50 | 51 | TreePath treePath; 52 | treeView.GetPathAtPos((int)e.Event.X, (int)e.Event.Y, out treePath); 53 | 54 | foreach (TreePath selectedRow in treeView.Selection.GetSelectedRows()) 55 | { 56 | if (selectedRow.Equals(treePath)) 57 | { 58 | e.RetVal = true; 59 | return; 60 | } 61 | } 62 | 63 | e.RetVal = false; 64 | } 65 | 66 | [GLib.ConnectBefore] 67 | static void TreeView_ProtectActivateMultipleSelection( 68 | object sender, KeyPressEventArgs args) 69 | { 70 | TreeView treeView = sender as TreeView; 71 | 72 | if (Keyboard.IsEnterPressed(args.Event) 73 | || Keyboard.IsSpacePressed(args.Event)) 74 | { 75 | treeView.ActivateRow(null, null); 76 | args.RetVal = true; 77 | return; 78 | } 79 | 80 | args.RetVal = false; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/application/gui/macos/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using AppKit; 5 | using Foundation; 6 | 7 | using GuiTest; 8 | 9 | using Codice.Examples.GuiTesting.Lib; 10 | using Codice.Examples.GuiTesting.Lib.Threading; 11 | using Codice.Examples.GuiTesting.MacOS.threading; 12 | using Codice.Examples.GuiTesting.Lib.Interfaces; 13 | 14 | namespace Codice.Examples.GuiTesting.MacOS 15 | { 16 | [Register("AppDelegate")] 17 | public class AppDelegate : NSApplicationDelegate 18 | { 19 | public override bool ApplicationShouldTerminateAfterLastWindowClosed(NSApplication sender) 20 | { 21 | return !GetApplicationArgs().IsTestingMode; 22 | } 23 | 24 | public override void DidFinishLaunching(NSNotification notification) 25 | { 26 | ApplicationArgs appArgs = GetApplicationArgs(); 27 | 28 | ExceptionsHandler.SetExceptionHandlers(appArgs.IsTestingMode); 29 | 30 | ThreadWaiterBuilder.Initialize(new MacApplicationTimerBuilder()); 31 | 32 | WindowHandler.Initialize(this); 33 | GuiMessage.Initialize(new MacOsGuiMessage()); 34 | 35 | NSApplication.SharedApplication.ActivateIgnoringOtherApps(true); 36 | 37 | if (appArgs.IsTestingMode) 38 | InstallTestAssembliesResolver(appArgs.PathToAssemblies); 39 | 40 | // Tip: you could launch different windows depending on the 41 | // argument flags. 42 | WindowHandler.LaunchApplicationWindow(); 43 | 44 | if (appArgs.IsTestingMode) 45 | { 46 | RemotingHack.ApplyRemotingConfigurationWorkaround(); 47 | WindowHandler.LaunchTest(appArgs.TestInfoFile, appArgs.PathToAssemblies); 48 | } 49 | } 50 | 51 | static void InstallTestAssembliesResolver(string pathToAssemblies) 52 | { 53 | List assemblies = new List(); 54 | assemblies.Add("nunit.core.dll"); 55 | assemblies.Add("nunit.core.interfaces.dll"); 56 | assemblies.Add("nunit.util.dll"); 57 | assemblies.Add("pnunit.framework.dll"); 58 | 59 | assemblies.Add("guitestinterfaces.dll"); 60 | assemblies.Add("guitest.dll"); 61 | 62 | GuiTestRunner.GuiTestAssemblyResolver.InstallAssemblyResolver( 63 | pathToAssemblies, assemblies); 64 | } 65 | 66 | ApplicationArgs GetApplicationArgs() 67 | { 68 | string[] args = NSProcessInfo.ProcessInfo.Arguments; 69 | 70 | // NSProcessInfo.ProcessInfo.Arguments contains the executable 71 | // path. Just remove it. 72 | string[] result = new string[args.Length - 1]; 73 | Array.Copy(args, 1, result, 0, args.Length - 1); 74 | 75 | return ApplicationArgs.Parse(result); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PlasticSCM/GuiTestSharp/0a146b273dd8ad4301508862bb25acce65456728/src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "AppIcon-16.png", 5 | "size": "16x16", 6 | "scale": "1x", 7 | "idiom": "mac" 8 | }, 9 | { 10 | "filename": "AppIcon-16@2x.png", 11 | "size": "16x16", 12 | "scale": "2x", 13 | "idiom": "mac" 14 | }, 15 | { 16 | "filename": "AppIcon-32.png", 17 | "size": "32x32", 18 | "scale": "1x", 19 | "idiom": "mac" 20 | }, 21 | { 22 | "filename": "AppIcon-32@2x.png", 23 | "size": "32x32", 24 | "scale": "2x", 25 | "idiom": "mac" 26 | }, 27 | { 28 | "filename": "AppIcon-128.png", 29 | "size": "128x128", 30 | "scale": "1x", 31 | "idiom": "mac" 32 | }, 33 | { 34 | "filename": "AppIcon-128@2x.png", 35 | "size": "128x128", 36 | "scale": "2x", 37 | "idiom": "mac" 38 | }, 39 | { 40 | "filename": "AppIcon-256.png", 41 | "size": "256x256", 42 | "scale": "1x", 43 | "idiom": "mac" 44 | }, 45 | { 46 | "filename": "AppIcon-256@2x.png", 47 | "size": "256x256", 48 | "scale": "2x", 49 | "idiom": "mac" 50 | }, 51 | { 52 | "filename": "AppIcon-512.png", 53 | "size": "512x512", 54 | "scale": "1x", 55 | "idiom": "mac" 56 | }, 57 | { 58 | "filename": "AppIcon-512@2x.png", 59 | "size": "512x512", 60 | "scale": "2x", 61 | "idiom": "mac" 62 | } 63 | ], 64 | "info": { 65 | "version": 1, 66 | "author": "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /src/application/gui/macos/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /src/application/gui/macos/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/application/gui/macos/ExceptionsHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 4 | 5 | namespace Codice.Examples.GuiTesting.MacOS 6 | { 7 | internal class ExceptionsHandler 8 | { 9 | internal static void SetExceptionHandlers(bool isTestingMode) 10 | { 11 | if (isTestingMode) 12 | { 13 | SetTestingExceptionHandlers(); 14 | return; 15 | } 16 | 17 | SetStandardExceptionHandlers(); 18 | } 19 | 20 | static void SetStandardExceptionHandlers() 21 | { 22 | AppDomain.CurrentDomain.UnhandledException += HandleUndhandledException; 23 | } 24 | 25 | static void SetTestingExceptionHandlers() 26 | { 27 | AppDomain.CurrentDomain.UnhandledException += HandleTestingUnhandledException; 28 | } 29 | 30 | static void HandleUndhandledException( 31 | object sender, UnhandledExceptionEventArgs e) 32 | { 33 | // Here you'd usually log the exception, send telemetry events... 34 | } 35 | 36 | static void HandleTestingUnhandledException( 37 | object sender, UnhandledExceptionEventArgs e) 38 | { 39 | // We don't want to eat up the exception during testing like nothing 40 | // happens, but we still want to save it in order to display it 41 | // as the cause of the failed test. 42 | GuiTesteableServices.UnhandledException = (Exception)e.ExceptionObject; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/application/gui/macos/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | macos 7 | CFBundleIdentifier 8 | com.codicesoftware.guitesting.macos 9 | CFBundleShortVersionString 10 | 1.0 11 | CFBundleVersion 12 | 1 13 | LSMinimumSystemVersion 14 | 10.7 15 | CFBundleDevelopmentRegion 16 | en 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundlePackageType 20 | APPL 21 | NSPrincipalClass 22 | NSApplication 23 | XSAppIconAssets 24 | Assets.xcassets/AppIcon.appiconset 25 | MonoBundleExecutable 26 | macos.exe 27 | CFBundleExecutable 28 | macos 29 | CFBundleDisplayName 30 | GUI Testing example 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/application/gui/macos/MacOsGuiMessage.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | using Codice.Examples.GuiTesting.Lib; 4 | using Codice.Examples.GuiTesting.Lib.Interfaces; 5 | 6 | namespace Codice.Examples.GuiTesting.MacOS 7 | { 8 | public class MacOsGuiMessage : GuiMessage.IGuiMessage 9 | { 10 | void GuiMessage.IGuiMessage.ShowError(string title, string message) 11 | { 12 | NSAlert alert = new NSAlert(); 13 | alert.MessageText = title; 14 | alert.InformativeText = message; 15 | alert.Icon = NSImage.ImageNamed(NSImageName.Caution); 16 | alert.AlertStyle = NSAlertStyle.Warning; 17 | 18 | NSButton closeButton = alert.AddButton( 19 | Localization.GetText(Localization.Name.Ok)); 20 | closeButton.KeyEquivalent = ESC_KEY_EQUIVALENT; 21 | 22 | WindowHandler.SetActiveDialogForTesting(alert); 23 | 24 | alert.RunModal(); 25 | 26 | WindowHandler.RemoveDialogForTesting(alert); 27 | } 28 | 29 | internal static readonly string ESC_KEY_EQUIVALENT = 30 | ((char)0x001B).ToString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/application/gui/macos/Main.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | namespace Codice.Examples.GuiTesting.MacOS 4 | { 5 | static class MainClass 6 | { 7 | static void Main(string[] args) 8 | { 9 | NSApplication.Init(); 10 | 11 | // You only need this hack if you removed your MainMenu.xib class, 12 | // which is in charge of pointing out which is your Application's 13 | // delegate. 14 | NSApplication.SharedApplication.Delegate = new AppDelegate(); 15 | 16 | NSApplication.Main(args); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/application/gui/macos/RemotingHack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Runtime.Remoting; 4 | using System.Reflection; 5 | 6 | namespace Codice.Examples.GuiTesting.MacOS 7 | { 8 | internal static class RemotingHack 9 | { 10 | internal static void ApplyRemotingConfigurationWorkaround() 11 | { 12 | new MonoBug44707_Workaround().HackMonoBug_44707(); 13 | } 14 | 15 | class MonoBug44707_Workaround 16 | { 17 | // Bug #44707 18 | // RemotingConfiguration.Configure() throws RemotingException because 19 | // it cannot load 'machine.config' 20 | // https://bugzilla.xamarin.com/show_bug.cgi?id=44707 21 | internal void HackMonoBug_44707() 22 | { 23 | string machineConfigPath = Path.Combine( 24 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 25 | "machine.config"); 26 | 27 | MethodInfo readConfigMethod = 28 | typeof(RemotingConfiguration).GetMethod( 29 | "ReadConfigFile", 30 | BindingFlags.NonPublic | BindingFlags.Static); 31 | CheckValidReadConfigFileMethod(readConfigMethod); 32 | 33 | readConfigMethod.Invoke(this, new[] { machineConfigPath }); 34 | 35 | FieldInfo defaultReadField = 36 | typeof(RemotingConfiguration).GetField( 37 | "defaultConfigRead", 38 | BindingFlags.NonPublic | BindingFlags.Static); 39 | CheckValidDefaultConfigReadField(defaultReadField); 40 | 41 | defaultReadField.SetValue(this, true); 42 | } 43 | 44 | static void CheckValidReadConfigFileMethod(MethodInfo mi) 45 | { 46 | if (mi != null) 47 | return; 48 | 49 | throw new InvalidOperationException( 50 | "RemotingHack failed - ReadConfigFile method not found " + 51 | "in RemotingConfiguration class."); 52 | } 53 | 54 | static void CheckValidDefaultConfigReadField(FieldInfo fi) 55 | { 56 | if (fi != null) 57 | return; 58 | 59 | throw new InvalidOperationException( 60 | "RemotingHack failed - 'defaulConfigRead' field not found " + 61 | "in RemotingConfiguration class."); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/application/gui/macos/ViewController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using AppKit; 4 | using Foundation; 5 | 6 | namespace macos 7 | { 8 | public partial class ViewController : NSViewController 9 | { 10 | public ViewController(IntPtr handle) : base(handle) 11 | { 12 | } 13 | 14 | public override void ViewDidLoad() 15 | { 16 | base.ViewDidLoad(); 17 | 18 | // Do any additional setup after loading the view. 19 | } 20 | 21 | public override NSObject RepresentedObject 22 | { 23 | get 24 | { 25 | return base.RepresentedObject; 26 | } 27 | set 28 | { 29 | base.RepresentedObject = value; 30 | // Update the view, if already loaded. 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/application/gui/macos/ViewController.designer.cs: -------------------------------------------------------------------------------- 1 | // WARNING 2 | // 3 | // This file has been generated automatically by Xamarin Studio to store outlets and 4 | // actions made in the UI designer. If it is removed, they will be lost. 5 | // Manual changes to this file may not be handled correctly. 6 | // 7 | using Foundation; 8 | 9 | namespace macos 10 | { 11 | [Register("ViewController")] 12 | partial class ViewController 13 | { 14 | void ReleaseDesignerOutlets() 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/application/gui/macos/WindowHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | using System.Threading; 6 | 7 | using AppKit; 8 | using Foundation; 9 | 10 | using log4net; 11 | using log4net.Config; 12 | using log4net.Repository; 13 | 14 | using GuiTest; 15 | 16 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 17 | using Codice.Examples.GuiTesting.Lib; 18 | using Codice.Examples.GuiTesting.MacOS.Testing; 19 | 20 | namespace Codice.Examples.GuiTesting.MacOS 21 | { 22 | internal static class WindowHandler 23 | { 24 | internal static NSWindow ApplicationWindow 25 | { 26 | get { return mApplicationWindow; } 27 | } 28 | 29 | internal static void Initialize(NSObject application) 30 | { 31 | mApplication = application; 32 | } 33 | 34 | internal static void LaunchApplicationWindow() 35 | { 36 | ApplicationOperations operations = new ApplicationOperations(); 37 | mApplicationWindow = new ApplicationWindow(operations); 38 | mApplicationWindow.ReleasedWhenClosed = true; 39 | mApplicationWindow.MakeKeyAndOrderFront(mApplication); 40 | } 41 | 42 | internal static void UnregisterApplicationWindow() 43 | { 44 | mApplicationWindow = null; 45 | } 46 | 47 | internal static void SetActiveDialogForTesting(NSObject dialog) 48 | { 49 | if (!mbIsTestRun) 50 | return; 51 | 52 | mActiveDialog = dialog; 53 | } 54 | 55 | internal static void RemoveDialogForTesting(NSObject dialog) 56 | { 57 | if (!mbIsTestRun) 58 | return; 59 | 60 | if (mActiveDialog == dialog) 61 | mActiveDialog = null; 62 | } 63 | 64 | internal static NSObject GetActiveDialog() 65 | { 66 | return mActiveDialog; 67 | } 68 | 69 | internal static void LaunchTest(string testInfoFile, string pathToAssemblies) 70 | { 71 | mbIsTestRun = true; 72 | 73 | ConfigureTestLogging(); 74 | InitTesteableServices(); 75 | 76 | GuiTestRunner testRunner = new GuiTestRunner( 77 | testInfoFile, pathToAssemblies, new GuiFinalizer(), null); 78 | 79 | ThreadPool.QueueUserWorkItem(new WaitCallback(testRunner.Run)); 80 | } 81 | 82 | static void ConfigureTestLogging() 83 | { 84 | try 85 | { 86 | string log4netPath = Path.Combine( 87 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 88 | "pnunittestrunner.log.conf"); 89 | 90 | XmlConfigurator.Configure(new FileInfo(log4netPath)); 91 | } 92 | catch { } 93 | } 94 | 95 | static void InitTesteableServices() 96 | { 97 | TesteableApplicationWindow testeableWindow = 98 | new TesteableApplicationWindow(mApplicationWindow); 99 | 100 | GuiTesteableServices.Init(testeableWindow); 101 | } 102 | 103 | static NSObject mApplication; 104 | 105 | static ApplicationWindow mApplicationWindow; 106 | static NSObject mActiveDialog; 107 | static bool mbIsTestRun = false; 108 | 109 | class GuiFinalizer : GuiTestRunner.IGuiFinalizer 110 | { 111 | void GuiTestRunner.IGuiFinalizer.Finalize(int exitCode) 112 | { 113 | // Environmnet.Exit is unable to terminate unmanaged threads 114 | // launched by the native Cocoa framework. We don't use any 115 | // in this example application, but you could face crashes 116 | // if you decide to rely on Environment.Exit to set an exit code. 117 | Exit(exitCode); 118 | } 119 | 120 | [DllImport("__Internal", EntryPoint = "exit")] 121 | static extern void Exit(int exitCode); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/application/gui/macos/macos.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "macos", "macos.csproj", "{6D9C8C74-3091-4963-BD5B-BF71A8611E01}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{423E90A2-ACD1-4793-B302-C97C10DF4AD7}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitest", "..\..\..\testing\guitest\guitest.csproj", "{9EE461F0-5FCA-4631-8335-73E1A0AF2861}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pnunit.framework", "..\..\..\..\lib\pnunit\pnunit.framework\pnunit.framework.csproj", "{5261ABA1-98E6-4603-A4F0-59CAC307AC68}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitestinterfaces", "..\..\..\testing\guitestinterfaces\guitestinterfaces.csproj", "{D775E82D-4045-4E11-AE85-4402CA0AD054}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lib", "..\..\lib\lib.csproj", "{A1079FA8-882B-40D6-A289-3A13767CABDD}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|x86 = Debug|x86 19 | Release|x86 = Release|x86 20 | NAnt|Any CPU = NAnt|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.Debug|x86.ActiveCfg = Debug|x86 24 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.Debug|x86.Build.0 = Debug|x86 25 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.Release|x86.ActiveCfg = Release|x86 26 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.Release|x86.Build.0 = Release|x86 27 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.NAnt|Any CPU.ActiveCfg = Debug|x86 28 | {6D9C8C74-3091-4963-BD5B-BF71A8611E01}.NAnt|Any CPU.Build.0 = Debug|x86 29 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|x86.ActiveCfg = Debug|Any CPU 30 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|x86.Build.0 = Debug|Any CPU 31 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|x86.ActiveCfg = Release|Any CPU 32 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|x86.Build.0 = Release|Any CPU 33 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.ActiveCfg = Debug|Any CPU 34 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.Build.0 = Debug|Any CPU 35 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|x86.ActiveCfg = Debug|Any CPU 36 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|x86.Build.0 = Debug|Any CPU 37 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|x86.ActiveCfg = Release|Any CPU 38 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|x86.Build.0 = Release|Any CPU 39 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.ActiveCfg = NAnt|Any CPU 40 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.Build.0 = NAnt|Any CPU 41 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|x86.ActiveCfg = Debug|Any CPU 42 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|x86.Build.0 = Debug|Any CPU 43 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|x86.ActiveCfg = Release|Any CPU 44 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|x86.Build.0 = Release|Any CPU 45 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.ActiveCfg = Debug|Any CPU 46 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.Build.0 = Debug|Any CPU 47 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|x86.ActiveCfg = Debug|Any CPU 48 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|x86.Build.0 = Debug|Any CPU 49 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|x86.ActiveCfg = Release|Any CPU 50 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|x86.Build.0 = Release|Any CPU 51 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.ActiveCfg = Debug|Any CPU 52 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.Build.0 = Debug|Any CPU 53 | EndGlobalSection 54 | GlobalSection(NestedProjects) = preSolution 55 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861} = {423E90A2-ACD1-4793-B302-C97C10DF4AD7} 56 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68} = {423E90A2-ACD1-4793-B302-C97C10DF4AD7} 57 | {D775E82D-4045-4E11-AE85-4402CA0AD054} = {423E90A2-ACD1-4793-B302-C97C10DF4AD7} 58 | EndGlobalSection 59 | GlobalSection(MonoDevelopProperties) = preSolution 60 | outputpath = ../../../../bin/application 61 | EndGlobalSection 62 | EndGlobal 63 | -------------------------------------------------------------------------------- /src/application/gui/macos/testing/TesteableApplicationWindow.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 4 | 5 | namespace Codice.Examples.GuiTesting.MacOS.Testing 6 | { 7 | internal class TesteableApplicationWindow : ITesteableApplicationWindow 8 | { 9 | public TesteableApplicationWindow(ApplicationWindow window) 10 | { 11 | mWindow = window; 12 | mHelper = new TestHelper(); 13 | } 14 | 15 | void ITesteableApplicationWindow.ClickAddButton() 16 | { 17 | mHelper.ClickButton(mWindow.AddButton); 18 | } 19 | 20 | void ITesteableApplicationWindow.ClickRemoveButton() 21 | { 22 | mHelper.ClickButton(mWindow.RemoveButton); 23 | } 24 | 25 | bool ITesteableApplicationWindow.AreButtonsEnabled() 26 | { 27 | return mHelper.IsEnabled(mWindow.AddButton) 28 | && mHelper.IsEnabled(mWindow.RemoveButton); 29 | } 30 | 31 | void ITesteableApplicationWindow.ChangeText(string text) 32 | { 33 | mHelper.SetText(mWindow.TextField, text); 34 | } 35 | 36 | string ITesteableApplicationWindow.GetText() 37 | { 38 | return mHelper.GetText(mWindow.TextField); 39 | } 40 | 41 | int ITesteableApplicationWindow.GetItemsInListCount() 42 | { 43 | return mHelper.GetItemCount(mWindow.TableView); 44 | } 45 | 46 | string ITesteableApplicationWindow.GetItemInListAt(int index) 47 | { 48 | return mHelper.GetItemAt(mWindow.TableView, "Text", index); 49 | } 50 | 51 | string ITesteableApplicationWindow.GetProgressMessage() 52 | { 53 | if (mWindow.ProgressControls.HasError) 54 | return string.Empty; 55 | 56 | return mHelper.GetText(mWindow.ProgressControls.ProgressTextField); 57 | } 58 | 59 | string ITesteableApplicationWindow.GetErrorMessage() 60 | { 61 | if (!mWindow.ProgressControls.HasError) 62 | return string.Empty; 63 | 64 | return mHelper.GetText(mWindow.ProgressControls.ProgressTextField); 65 | } 66 | 67 | ITesteableErrorDialog ITesteableApplicationWindow.GetErrorDialog() 68 | { 69 | if (WindowHandler.GetActiveDialog() == null) 70 | return null; 71 | 72 | NSAlert errorDialog = WindowHandler.GetActiveDialog() as NSAlert; 73 | if (errorDialog == null) 74 | return null; 75 | 76 | return new TesteableErrorDialog(errorDialog); 77 | } 78 | 79 | readonly ApplicationWindow mWindow; 80 | readonly TestHelper mHelper; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/application/gui/macos/testing/TesteableErrorDialog.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 4 | using Codice.Examples.GuiTesting.Lib; 5 | 6 | namespace Codice.Examples.GuiTesting.MacOS.Testing 7 | { 8 | internal class TesteableErrorDialog : ITesteableErrorDialog 9 | { 10 | internal TesteableErrorDialog(NSAlert alert) 11 | { 12 | mAlert = alert; 13 | mHelper = new TestHelper(); 14 | } 15 | 16 | void ITesteableErrorDialog.ClickOkButton() 17 | { 18 | mHelper.ClickDialogButton( 19 | mHelper.GetButton( 20 | mAlert, 21 | Localization.GetText(Localization.Name.Ok))); 22 | } 23 | 24 | string ITesteableErrorDialog.GetTitle() 25 | { 26 | return mHelper.GetAlertTitle(mAlert); 27 | } 28 | 29 | string ITesteableErrorDialog.GetMessage() 30 | { 31 | return mHelper.GetAlertMessage(mAlert); 32 | } 33 | 34 | readonly NSAlert mAlert; 35 | readonly TestHelper mHelper; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/application/gui/macos/threading/MacApplicationTimer.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | 3 | using Codice.Examples.GuiTesting.Lib.Threading; 4 | 5 | namespace Codice.Examples.GuiTesting.MacOS.threading 6 | { 7 | public class MacApplicationTimerBuilder : IApplicationTimerBuilder 8 | { 9 | IApplicationTimer IApplicationTimerBuilder.Get( 10 | bool bModalMode, ThreadWaiter.TimerTick timerTickDelegate) 11 | { 12 | return new MacApplicationTimer(DEFAULT_TIMER_INTERVAL, timerTickDelegate); 13 | } 14 | 15 | const double DEFAULT_TIMER_INTERVAL = 0.0001; 16 | } 17 | 18 | public class MacApplicationTimer : IApplicationTimer 19 | { 20 | internal MacApplicationTimer( 21 | double timerInterval, ThreadWaiter.TimerTick timerTickDelegate) 22 | { 23 | mTimerInterval = timerInterval; 24 | mTimerTickDelegate = timerTickDelegate; 25 | } 26 | 27 | void IApplicationTimer.Start() 28 | { 29 | mTimer = NSTimer.CreateRepeatingScheduledTimer( 30 | mTimerInterval, OnTimerTick); 31 | NSRunLoop.Current.AddTimer(mTimer, NSRunLoopMode.EventTracking); 32 | } 33 | 34 | void IApplicationTimer.Stop() 35 | { 36 | if (mTimer == null) 37 | return; 38 | 39 | mTimer.Invalidate(); 40 | mTimer = null; 41 | } 42 | 43 | void OnTimerTick(NSTimer timer) 44 | { 45 | mTimerTickDelegate(); 46 | } 47 | 48 | readonly double mTimerInterval; 49 | readonly ThreadWaiter.TimerTick mTimerTickDelegate; 50 | 51 | NSTimer mTimer; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/application/gui/macos/ui/NSColors.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | namespace Codice.Examples.GuiTesting.MacOS.UI 4 | { 5 | internal static class NSColors 6 | { 7 | internal static readonly NSColor NotificationText = GetColorFromRgb(0, 103, 149); 8 | internal static readonly NSColor ErrorText = GetColorFromRgb(198, 38, 53); 9 | 10 | internal static NSColor GetColorFromRgb(int r, int g, int b) 11 | { 12 | return NSColor.FromCalibratedRgba( 13 | r / 255.0f, g / 255.0f, b / 255.0f, 1.0f); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/application/gui/macos/ui/NSViewPacker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | using AppKit; 4 | using Foundation; 5 | 6 | namespace Codice.Examples.GuiTesting.MacOS.UI 7 | { 8 | internal static class NSViewPacker 9 | { 10 | internal static void PackViews( 11 | NSView parent, string[] constraints, NSDictionary views) 12 | { 13 | foreach (NSView view in views.Values) 14 | { 15 | view.TranslatesAutoresizingMaskIntoConstraints = false; 16 | parent.AddSubview(view); 17 | } 18 | 19 | parent.AddConstraints(BuildConstraints(constraints, views)); 20 | } 21 | 22 | internal static void Fill(NSView parent, NSView child) 23 | { 24 | PackViews( 25 | parent, 26 | new string[] 27 | { 28 | "H:|[child]|", 29 | "V:|[child]|" 30 | }, 31 | new NSDictionary("child", child)); 32 | } 33 | 34 | static NSLayoutConstraint[] BuildConstraints( 35 | string[] constraints, NSDictionary views) 36 | { 37 | List result = new List(); 38 | 39 | foreach (string format in constraints) 40 | result.AddRange(NSLayoutConstraint.FromVisualFormat(format, 0, null, views)); 41 | 42 | return result.ToArray(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/application/gui/macos/ui/ProgressControls.cs: -------------------------------------------------------------------------------- 1 | using AppKit; 2 | 3 | using Codice.Examples.GuiTesting.Lib.Interfaces; 4 | 5 | namespace Codice.Examples.GuiTesting.MacOS.UI 6 | { 7 | internal class ProgressControls : IProgressControls 8 | { 9 | public bool HasError { get { return mbHasError; } } 10 | public NSTextField ProgressTextField { get { return mProgressTextField; } } 11 | 12 | internal ProgressControls( 13 | NSWindow window, NSTextField progressTextField, NSView[] views) 14 | { 15 | mWindow = window; 16 | mProgressTextField = progressTextField; 17 | mViews = views; 18 | } 19 | 20 | void IProgressControls.ShowProgress(string message) 21 | { 22 | mbHasError = false; 23 | 24 | mProgressTextField.TextColor = NSColors.NotificationText; 25 | mProgressTextField.StringValue = message; 26 | mProgressTextField.Hidden = false; 27 | 28 | mResponder = NSViewArray.GetFirstResponder(mWindow, mViews); 29 | 30 | NSViewArray.Disable(mViews); 31 | } 32 | 33 | void IProgressControls.HideProgress() 34 | { 35 | mProgressTextField.Hidden = true; 36 | 37 | NSViewArray.Enable(mViews); 38 | 39 | if (mResponder != null) 40 | mWindow.MakeFirstResponder(mResponder); 41 | } 42 | 43 | void IProgressControls.ShowError(string message) 44 | { 45 | mbHasError = true; 46 | 47 | mProgressTextField.TextColor = NSColors.ErrorText; 48 | mProgressTextField.StringValue = message; 49 | mProgressTextField.Hidden = false; 50 | } 51 | 52 | NSResponder mResponder; 53 | bool mbHasError = false; 54 | 55 | readonly NSWindow mWindow; 56 | readonly NSTextField mProgressTextField; 57 | readonly NSView[] mViews; 58 | 59 | static class NSViewArray 60 | { 61 | internal static void Enable(NSView[] views) 62 | { 63 | SetEnablement(views, true); 64 | } 65 | 66 | internal static void Disable(NSView[] views) 67 | { 68 | SetEnablement(views, false); 69 | } 70 | 71 | internal static NSView GetFirstResponder(NSWindow window, NSView[] views) 72 | { 73 | if (views == null) 74 | return null; 75 | 76 | foreach (NSView view in views) 77 | { 78 | if (window.FirstResponder == view) 79 | return view; 80 | } 81 | 82 | return null; 83 | } 84 | 85 | static void SetEnablement(NSView[] views, bool enabled) 86 | { 87 | if (views == null) 88 | return; 89 | 90 | foreach (NSView view in views) 91 | { 92 | if (view == null) 93 | continue; 94 | 95 | NSControl control = view as NSControl; 96 | if (control != null) 97 | { 98 | control.Enabled = enabled; 99 | continue; 100 | } 101 | 102 | NSTextView textView = view as NSTextView; 103 | if (textView != null) 104 | { 105 | textView.Selectable = enabled; 106 | textView.Editable = enabled; 107 | 108 | textView.TextColor = enabled 109 | ? NSColor.ControlText 110 | : NSColor.DisabledControlText; 111 | } 112 | } 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/application/gui/windows/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/application/gui/windows/ErrorDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | using Codice.Examples.GuiTesting.Lib; 6 | using Codice.Examples.GuiTesting.Windows.UI; 7 | 8 | namespace Codice.Examples.GuiTesting.Windows 9 | { 10 | internal class ErrorDialog : Form 11 | { 12 | internal Button OkButton { get { return mOkButton; } } 13 | internal Label MessageLabel { get { return mMessageLabel; } } 14 | 15 | internal ErrorDialog(string title, string message) 16 | { 17 | BuildComponents(); 18 | 19 | Text = title; 20 | mMessageLabel.Text = message; 21 | } 22 | 23 | protected override void Dispose(bool disposing) 24 | { 25 | if (disposing) 26 | mOkButton.Click -= OkButton_Click; 27 | 28 | base.Dispose(disposing); 29 | } 30 | 31 | void OkButton_Click(object sender, EventArgs e) 32 | { 33 | DialogResult = DialogResult.OK; 34 | Close(); 35 | } 36 | 37 | void BuildComponents() 38 | { 39 | Width = DIALOG_WIDTH; 40 | Height = DIALOG_HEIGHT; 41 | FormBorderStyle = FormBorderStyle.FixedDialog; 42 | MinimizeBox = false; 43 | MaximizeBox = false; 44 | 45 | SuspendLayout(); 46 | try 47 | { 48 | ControlPacker.AddControl( 49 | this, ControlBuilder.CreateVerticalPadding(DockStyle.Top)); 50 | ControlPacker.AddControl(this, BuildMessagePanel()); 51 | ControlPacker.AddControl( 52 | this, ControlBuilder.CreateVerticalPadding(DockStyle.Top)); 53 | ControlPacker.AddControl(this, BuildButtonPanel()); 54 | ControlPacker.AddControl( 55 | this, ControlBuilder.CreateVerticalPadding(DockStyle.Bottom)); 56 | } 57 | finally 58 | { 59 | ResumeLayout(); 60 | } 61 | } 62 | 63 | Panel BuildMessagePanel() 64 | { 65 | Panel result = ControlBuilder.CreatePanel(DockStyle.Top); 66 | result.Height = 70; 67 | 68 | PictureBox errorPictureBox = ControlBuilder.CreatePictureBox( 69 | SystemIcons.Error.ToBitmap(), DockStyle.Left); 70 | mMessageLabel = ControlBuilder.CreateLabel(string.Empty, DockStyle.Fill); 71 | mMessageLabel.AutoSize = false; 72 | 73 | ControlPacker.AddControl( 74 | result, ControlBuilder.CreateHorizontalPadding(DockStyle.Left)); 75 | ControlPacker.AddControl(result, errorPictureBox); 76 | ControlPacker.AddControl( 77 | result, ControlBuilder.CreateHorizontalPadding(DockStyle.Left)); 78 | ControlPacker.AddControl(result, mMessageLabel); 79 | ControlPacker.AddControl( 80 | result, ControlBuilder.CreateHorizontalPadding(DockStyle.Right)); 81 | 82 | return result; 83 | } 84 | 85 | Panel BuildButtonPanel() 86 | { 87 | Panel result = ControlBuilder.CreatePanel( 88 | ControlBuilder.DefaultControlHeight, DockStyle.Top); 89 | 90 | mOkButton = ControlBuilder.CreateButton( 91 | Localization.GetText(Localization.Name.Ok), DockStyle.Right); 92 | 93 | mOkButton.Click += OkButton_Click; 94 | CancelButton = mOkButton; 95 | 96 | ControlPacker.AddControl(result, mOkButton); 97 | ControlPacker.AddControl( 98 | result, ControlBuilder.CreateHorizontalPadding(DockStyle.Right)); 99 | 100 | return result; 101 | } 102 | 103 | Label mMessageLabel; 104 | Button mOkButton; 105 | 106 | const int DIALOG_WIDTH = 310; 107 | const int DIALOG_HEIGHT = 155; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/application/gui/windows/ExceptionsHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Windows.Forms; 4 | 5 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 6 | 7 | namespace Codice.Examples.GuiTesting.Windows 8 | { 9 | internal static class ExceptionsHandler 10 | { 11 | internal static void SetExceptionHandlers(bool isTestingMode) 12 | { 13 | if (isTestingMode) 14 | { 15 | SetTestingExceptionHandlers(); 16 | return; 17 | } 18 | 19 | SetStandardExceptionHandlers(); 20 | } 21 | 22 | static void SetStandardExceptionHandlers() 23 | { 24 | Application.ThreadException += HandleThreadException; 25 | AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; 26 | } 27 | 28 | static void SetTestingExceptionHandlers() 29 | { 30 | // We don't want to eat up the exception during testing like nothing 31 | // happens, but we still want to save it in order to display it 32 | // as the cause of the failed test. 33 | Application.ThreadException += HandleTestingThreadException; 34 | AppDomain.CurrentDomain.UnhandledException += HandleTestingUnhandledException; 35 | } 36 | 37 | static void HandleThreadException(object sender, ThreadExceptionEventArgs e) 38 | { 39 | // Here you'd usually log the exception, send telemetry events... 40 | } 41 | 42 | static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs e) 43 | { 44 | // Here you'd usually log the exception, send telemetry events... 45 | } 46 | 47 | static void HandleTestingThreadException(object sender, ThreadExceptionEventArgs e) 48 | { 49 | HandleTestingException(e.Exception); 50 | } 51 | 52 | static void HandleTestingUnhandledException(object sender, UnhandledExceptionEventArgs e) 53 | { 54 | HandleTestingException((Exception)e.ExceptionObject); 55 | } 56 | 57 | static void HandleTestingException(Exception ex) 58 | { 59 | GuiTesteableServices.UnhandledException = ex; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/application/gui/windows/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | 5 | using GuiTest; 6 | 7 | using Codice.Examples.GuiTesting.Lib; 8 | using Codice.Examples.GuiTesting.Lib.Threading; 9 | using Codice.Examples.GuiTesting.Windows.Threading; 10 | using Codice.Examples.GuiTesting.Lib.Interfaces; 11 | 12 | namespace Codice.Examples.GuiTesting.Windows 13 | { 14 | static class Program 15 | { 16 | [STAThread] 17 | static void Main(string[] args) 18 | { 19 | try 20 | { 21 | ApplicationArgs appArgs = ApplicationArgs.Parse(args); 22 | 23 | ExceptionsHandler.SetExceptionHandlers(appArgs.IsTestingMode); 24 | 25 | ThreadWaiterBuilder.Initialize(new WinPlasticTimerBuilder()); 26 | 27 | GuiMessage.Initialize(new WindowsGuiMessage()); 28 | 29 | Application.EnableVisualStyles(); 30 | Application.SetCompatibleTextRenderingDefault(false); 31 | 32 | if (appArgs.IsTestingMode) 33 | InstallTestAssembliesResolver(appArgs.PathToAssemblies); 34 | 35 | // Tip: you could launch different windows depending on the 36 | // argument flags. 37 | WindowHandler.LaunchApplicationWindow(); 38 | 39 | if (appArgs.IsTestingMode) 40 | WindowHandler.LaunchTest(appArgs.TestInfoFile, appArgs.PathToAssemblies); 41 | 42 | Application.Run(); 43 | } 44 | catch 45 | { 46 | // You would track the exception here. 47 | ExitCode = 1; 48 | Application.Exit(); 49 | } 50 | finally 51 | { 52 | // You would dispose everything you need here. 53 | Environment.Exit(ExitCode); 54 | } 55 | } 56 | 57 | static void InstallTestAssembliesResolver(string pathToAssemblies) 58 | { 59 | List assemblies = new List(); 60 | assemblies.Add("nunit.core.dll"); 61 | assemblies.Add("nunit.core.interfaces.dll"); 62 | assemblies.Add("nunit.util.dll"); 63 | assemblies.Add("pnunit.framework.dll"); 64 | 65 | assemblies.Add("guitestinterfaces.dll"); 66 | assemblies.Add("guitest.dll"); 67 | 68 | GuiTestRunner.GuiTestAssemblyResolver.InstallAssemblyResolver( 69 | pathToAssemblies, assemblies); 70 | } 71 | 72 | static int ExitCode = 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/application/gui/windows/WindowHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Threading; 5 | using System.Windows.Forms; 6 | 7 | using log4net; 8 | using log4net.Config; 9 | using log4net.Repository; 10 | 11 | using GuiTest; 12 | 13 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 14 | using Codice.Examples.GuiTesting.Lib; 15 | using Codice.Examples.GuiTesting.Windows.Testing; 16 | 17 | namespace Codice.Examples.GuiTesting.Windows 18 | { 19 | internal static class WindowHandler 20 | { 21 | internal static IWin32Window ApplicationWindow 22 | { 23 | get { return mApplicationWindow; } 24 | } 25 | 26 | internal static void LaunchApplicationWindow() 27 | { 28 | ApplicationOperations operations = new ApplicationOperations(); 29 | mApplicationWindow = new ApplicationWindow(operations); 30 | mApplicationWindow.StartPosition = FormStartPosition.CenterScreen; 31 | mApplicationWindow.Show(); 32 | } 33 | 34 | internal static void UnregisterApplicationWindow() 35 | { 36 | mApplicationWindow.Dispose(); 37 | mApplicationWindow = null; 38 | 39 | TerminateApplication(); 40 | } 41 | 42 | internal static void SetActiveDialogForTesting(Form dialog) 43 | { 44 | if (!mbIsTestRun) 45 | return; 46 | 47 | mActiveDialog = dialog; 48 | } 49 | 50 | internal static void RemoveDialogForTesting(Form dialog) 51 | { 52 | if (!mbIsTestRun) 53 | return; 54 | 55 | if (mActiveDialog == dialog) 56 | mActiveDialog = null; 57 | } 58 | 59 | internal static Form GetActiveDialog() 60 | { 61 | if (mActiveDialog == null) 62 | return null; 63 | 64 | // Although by this point the Form is created, it might not be 65 | // visible yet, so it's handle is not created. 66 | // If the handle is not created, all Invoke and BeginInvoke calls 67 | // will fail, so we'll have to wait. 68 | while (!mActiveDialog.IsHandleCreated) { } 69 | 70 | return mActiveDialog; 71 | } 72 | 73 | internal static void LaunchTest(string testInfoFile, string pathToAssemblies) 74 | { 75 | mbIsTestRun = true; 76 | 77 | ConfigureTestLogging(); 78 | InitTesteableServices(); 79 | 80 | GuiTestRunner testRunner = new GuiTestRunner( 81 | testInfoFile, pathToAssemblies, new GuiFinalizer(), null); 82 | 83 | ThreadPool.QueueUserWorkItem(new WaitCallback(testRunner.Run)); 84 | } 85 | 86 | static void ConfigureTestLogging() 87 | { 88 | try 89 | { 90 | string log4netPath = Path.Combine( 91 | Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 92 | "pnunittestrunner.log.conf"); 93 | 94 | XmlConfigurator.Configure(mLogRepository, new FileInfo(log4netPath)); 95 | } 96 | catch { } // Log config failed, nothing else to do! 97 | } 98 | 99 | static void InitTesteableServices() 100 | { 101 | TesteableApplicationWindow testeableWindow = 102 | new TesteableApplicationWindow(mApplicationWindow); 103 | 104 | GuiTesteableServices.Init(testeableWindow); 105 | } 106 | 107 | static void TerminateApplication() 108 | { 109 | if (mbIsTestRun) 110 | return; 111 | 112 | Application.Exit(); 113 | } 114 | 115 | static ApplicationWindow mApplicationWindow; 116 | static Form mActiveDialog; 117 | static bool mbIsTestRun = false; 118 | 119 | static readonly ILoggerRepository mLogRepository = 120 | LogManager.CreateRepository("log4net-rep"); 121 | 122 | class GuiFinalizer : GuiTestRunner.IGuiFinalizer 123 | { 124 | void GuiTestRunner.IGuiFinalizer.Finalize(int exitCode) 125 | { 126 | Environment.Exit(exitCode); 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/application/gui/windows/WindowsGuiMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | using Codice.Examples.GuiTesting.Lib.Interfaces; 4 | 5 | namespace Codice.Examples.GuiTesting.Windows 6 | { 7 | internal class WindowsGuiMessage : GuiMessage.IGuiMessage 8 | { 9 | void GuiMessage.IGuiMessage.ShowError(string title, string message) 10 | { 11 | Form dialog = new ErrorDialog(title, message); 12 | dialog.StartPosition = FormStartPosition.CenterParent; 13 | 14 | WindowHandler.SetActiveDialogForTesting(dialog); 15 | 16 | try 17 | { 18 | dialog.ShowDialog(WindowHandler.ApplicationWindow); 19 | } 20 | finally 21 | { 22 | WindowHandler.RemoveDialogForTesting(dialog); 23 | dialog.Dispose(); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/application/gui/windows/testing/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace Codice.Examples.GuiTesting.Windows.Testing 4 | { 5 | internal class TestHelper 6 | { 7 | internal TestHelper(Control control) 8 | { 9 | mControl = control; 10 | } 11 | 12 | internal string GetText(Control control) 13 | { 14 | string result = string.Empty; 15 | mControl.Invoke((MethodInvoker)delegate 16 | { 17 | result = control.Text; 18 | }); 19 | 20 | return result; 21 | } 22 | 23 | internal void SetText(Control control, string text) 24 | { 25 | mControl.Invoke((MethodInvoker)delegate 26 | { 27 | control.Text = text; 28 | }); 29 | } 30 | 31 | internal void ClickButton(Button button) 32 | { 33 | mControl.Invoke((MethodInvoker)delegate 34 | { 35 | button.PerformClick(); 36 | }); 37 | } 38 | 39 | internal void ClickDialogResultButton(Button button) 40 | { 41 | mControl.Invoke((MethodInvoker)delegate 42 | { 43 | button.PerformClick(); 44 | }); 45 | 46 | while (!mControl.IsDisposed) { } 47 | } 48 | 49 | internal bool IsEnabled(Control control) 50 | { 51 | bool result = false; 52 | mControl.Invoke((MethodInvoker)delegate 53 | { 54 | result = control.Enabled; 55 | }); 56 | 57 | return result; 58 | } 59 | 60 | internal int GetItemCount(ListBox listBox) 61 | { 62 | int result = -1; 63 | mControl.Invoke((MethodInvoker)delegate 64 | { 65 | result = listBox.Items.Count; 66 | }); 67 | 68 | return result; 69 | } 70 | 71 | internal object GetItemAt(ListBox listBox, int index) 72 | { 73 | object result = null; 74 | mControl.Invoke((MethodInvoker)delegate 75 | { 76 | result = listBox.Items[index]; 77 | }); 78 | 79 | return result; 80 | } 81 | 82 | readonly Control mControl; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/application/gui/windows/testing/TesteableApplicationWindow.cs: -------------------------------------------------------------------------------- 1 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 2 | 3 | namespace Codice.Examples.GuiTesting.Windows.Testing 4 | { 5 | internal class TesteableApplicationWindow : ITesteableApplicationWindow 6 | { 7 | internal TesteableApplicationWindow(ApplicationWindow window) 8 | { 9 | mWindow = window; 10 | mHelper = new TestHelper(mWindow); 11 | } 12 | 13 | void ITesteableApplicationWindow.ChangeText(string text) 14 | { 15 | mHelper.SetText(mWindow.TextBox, text); 16 | } 17 | 18 | string ITesteableApplicationWindow.GetText() 19 | { 20 | return mHelper.GetText(mWindow.TextBox); 21 | } 22 | 23 | void ITesteableApplicationWindow.ClickAddButton() 24 | { 25 | mHelper.ClickButton(mWindow.AddButton); 26 | } 27 | 28 | void ITesteableApplicationWindow.ClickRemoveButton() 29 | { 30 | mHelper.ClickButton(mWindow.RemoveButton); 31 | } 32 | 33 | bool ITesteableApplicationWindow.AreButtonsEnabled() 34 | { 35 | return mHelper.IsEnabled(mWindow.AddButton) 36 | && mHelper.IsEnabled(mWindow.RemoveButton); 37 | } 38 | 39 | string ITesteableApplicationWindow.GetItemInListAt(int index) 40 | { 41 | return mHelper.GetItemAt(mWindow.ListBox, index).ToString(); 42 | } 43 | 44 | int ITesteableApplicationWindow.GetItemsInListCount() 45 | { 46 | return mHelper.GetItemCount(mWindow.ListBox); 47 | } 48 | 49 | string ITesteableApplicationWindow.GetProgressMessage() 50 | { 51 | if (mWindow.ProgressControls.HasError) 52 | return string.Empty; 53 | 54 | return mHelper.GetText(mWindow.ProgressControls.ProgressLabel); 55 | } 56 | 57 | string ITesteableApplicationWindow.GetErrorMessage() 58 | { 59 | if (!mWindow.ProgressControls.HasError) 60 | return string.Empty; 61 | 62 | return mHelper.GetText(mWindow.ProgressControls.ProgressLabel); 63 | } 64 | 65 | ITesteableErrorDialog ITesteableApplicationWindow.GetErrorDialog() 66 | { 67 | if (WindowHandler.GetActiveDialog() == null) 68 | return null; 69 | 70 | ErrorDialog errorDialog = WindowHandler.GetActiveDialog() as ErrorDialog; 71 | if (errorDialog == null) 72 | return null; 73 | 74 | return new TesteableErrorDialog(errorDialog); 75 | } 76 | 77 | readonly ApplicationWindow mWindow; 78 | readonly TestHelper mHelper; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/application/gui/windows/testing/TesteableErrorDialog.cs: -------------------------------------------------------------------------------- 1 | using Codice.Examples.GuiTesting.GuiTestInterfaces; 2 | using Codice.Examples.GuiTesting.Windows.Testing; 3 | 4 | namespace Codice.Examples.GuiTesting.Windows.Testing 5 | { 6 | internal class TesteableErrorDialog : ITesteableErrorDialog 7 | { 8 | internal TesteableErrorDialog(ErrorDialog dialog) 9 | { 10 | mErrorDialog = dialog; 11 | mHelper = new TestHelper(mErrorDialog); 12 | } 13 | 14 | void ITesteableErrorDialog.ClickOkButton() 15 | { 16 | mHelper.ClickDialogResultButton(mErrorDialog.OkButton); 17 | } 18 | 19 | string ITesteableErrorDialog.GetTitle() 20 | { 21 | return mHelper.GetText(mErrorDialog); 22 | } 23 | 24 | string ITesteableErrorDialog.GetMessage() 25 | { 26 | return mHelper.GetText(mErrorDialog.MessageLabel); 27 | } 28 | 29 | readonly ErrorDialog mErrorDialog; 30 | readonly TestHelper mHelper; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/application/gui/windows/threading/WinApplicationTimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | using Codice.Examples.GuiTesting.Lib.Threading; 5 | 6 | namespace Codice.Examples.GuiTesting.Windows.Threading 7 | { 8 | public class WinPlasticTimerBuilder : IApplicationTimerBuilder 9 | { 10 | IApplicationTimer IApplicationTimerBuilder.Get( 11 | bool bModalMode, ThreadWaiter.TimerTick timerTickDelegate) 12 | { 13 | return new WinPlasticTimer(DEFAULT_TIMER_INTERVAL, timerTickDelegate); 14 | } 15 | 16 | const int DEFAULT_TIMER_INTERVAL = 100; 17 | } 18 | 19 | public class WinPlasticTimer : IApplicationTimer 20 | { 21 | public WinPlasticTimer(int timerInterval, ThreadWaiter.TimerTick timerTickDelegate) 22 | { 23 | mTimerInterval = timerInterval; 24 | mTimerTickDelegate = timerTickDelegate; 25 | } 26 | 27 | public void Start() 28 | { 29 | mTimer = new Timer(); 30 | mTimer.Interval = mTimerInterval; 31 | mTimer.Tick += OnTimerTick; 32 | 33 | mTimer.Start(); 34 | } 35 | 36 | public void Stop() 37 | { 38 | mTimer.Stop(); 39 | mTimer.Tick -= OnTimerTick; 40 | mTimer.Dispose(); 41 | } 42 | 43 | void OnTimerTick(object sender, EventArgs e) 44 | { 45 | mTimerTickDelegate(); 46 | } 47 | 48 | Timer mTimer; 49 | 50 | readonly int mTimerInterval; 51 | readonly ThreadWaiter.TimerTick mTimerTickDelegate; 52 | } 53 | } -------------------------------------------------------------------------------- /src/application/gui/windows/ui/ControlBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | namespace Codice.Examples.GuiTesting.Windows.UI 5 | { 6 | internal static class ControlBuilder 7 | { 8 | internal const int DefaultControlHeight = 23; 9 | 10 | internal const int DefaultHorizontalPaddingWidth = 6; 11 | internal const int DefaultVerticalPaddingHeight = 8; 12 | 13 | internal static Control CreateVerticalPadding(DockStyle dock) 14 | { 15 | Panel result = CreatePanel(dock); 16 | result.Height = DefaultVerticalPaddingHeight; 17 | 18 | return result; 19 | } 20 | 21 | internal static Control CreateHorizontalPadding(DockStyle dock) 22 | { 23 | Panel result = CreatePanel(dock); 24 | result.Width = DefaultHorizontalPaddingWidth; 25 | 26 | return result; 27 | } 28 | 29 | internal static Panel CreatePanel(int height, DockStyle dock) 30 | { 31 | Panel result = CreatePanel(dock); 32 | result.Height = height; 33 | 34 | return result; 35 | } 36 | 37 | internal static Panel CreatePanel(DockStyle dock) 38 | { 39 | Panel result = new Panel(); 40 | result.Dock = dock; 41 | 42 | return result; 43 | } 44 | 45 | internal static Label CreateLabel(string text, DockStyle dock) 46 | { 47 | Label result = new Label(); 48 | result.Text = text; 49 | result.Dock = dock; 50 | result.AutoSize = true; 51 | 52 | return result; 53 | } 54 | 55 | internal static TextBox CreateTextbox(DockStyle dock) 56 | { 57 | TextBox result = new TextBox(); 58 | result.Dock = dock; 59 | 60 | return result; 61 | } 62 | 63 | internal static Button CreateButton(string text, DockStyle dock) 64 | { 65 | Button result = new Button(); 66 | result.Text = text; 67 | result.Dock = dock; 68 | 69 | return result; 70 | } 71 | 72 | internal static ListBox CreateListBox(DockStyle dock) 73 | { 74 | ListBox result = new ListBox(); 75 | result.Dock = dock; 76 | 77 | return result; 78 | } 79 | 80 | internal static PictureBox CreatePictureBox(Image image, DockStyle dock) 81 | { 82 | PictureBox result = new PictureBox(); 83 | result.Image = image; 84 | result.Width = image.Width; 85 | result.Height = image.Height; 86 | result.Dock = dock; 87 | 88 | return result; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/application/gui/windows/ui/ControlPacker.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace Codice.Examples.GuiTesting.Windows.UI 4 | { 5 | internal static class ControlPacker 6 | { 7 | internal static void AddControl(Control parent, Control child) 8 | { 9 | parent.Controls.Add(child); 10 | if (child.Dock == DockStyle.Left || child.Dock == DockStyle.Top || 11 | child.Dock == DockStyle.Fill || child.Dock == DockStyle.None) 12 | { 13 | child.BringToFront(); 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/application/gui/windows/ui/ProgressControls.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | using Codice.Examples.GuiTesting.Lib.Interfaces; 5 | 6 | namespace Codice.Examples.GuiTesting.Windows.UI 7 | { 8 | internal class ProgressControls : IProgressControls 9 | { 10 | public bool HasError { get { return mbHasError; } } 11 | public Label ProgressLabel { get { return mProgressLabel; } } 12 | 13 | internal ProgressControls(Label progressLabel, Control[] controls) 14 | { 15 | mProgressLabel = progressLabel; 16 | mControls = controls; 17 | } 18 | 19 | void IProgressControls.ShowProgress(string message) 20 | { 21 | mbHasError = false; 22 | 23 | mProgressLabel.ForeColor = Color.Black; 24 | mProgressLabel.Text = message; 25 | mProgressLabel.Show(); 26 | 27 | mFocusedControl = GetFocusedControl(mControls); 28 | 29 | DisableControls(mControls); 30 | } 31 | 32 | void IProgressControls.HideProgress() 33 | { 34 | mProgressLabel.Hide(); 35 | 36 | EnableControls(mControls); 37 | 38 | if (mFocusedControl != null) 39 | mFocusedControl.Focus(); 40 | } 41 | 42 | void IProgressControls.ShowError(string message) 43 | { 44 | mbHasError = true; 45 | 46 | mProgressLabel.ForeColor = Color.Red; 47 | mProgressLabel.Text = message; 48 | mProgressLabel.Show(); 49 | } 50 | 51 | static void EnableControls(Control[] controls) 52 | { 53 | foreach (Control control in controls) 54 | control.Enabled = true; 55 | } 56 | 57 | static void DisableControls(Control[] controls) 58 | { 59 | foreach (Control control in controls) 60 | control.Enabled = false; 61 | } 62 | 63 | static Control GetFocusedControl(Control[] controls) 64 | { 65 | foreach (Control control in controls) 66 | { 67 | if (control.Focused) 68 | return control; 69 | } 70 | 71 | return null; 72 | } 73 | 74 | Control mFocusedControl; 75 | bool mbHasError; 76 | 77 | readonly Label mProgressLabel; 78 | readonly Control[] mControls; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/application/gui/windows/windows.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "windows", "windows.csproj", "{20C1F257-2ADF-4E38-AE86-F167E284AF99}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "lib", "..\..\lib\lib.csproj", "{A1079FA8-882B-40D6-A289-3A13767CABDD}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "testing", "testing", "{2EBF8C53-4C4F-464D-9D79-45FACDA7DC87}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitestinterfaces", "..\..\..\testing\guitestinterfaces\guitestinterfaces.csproj", "{D775E82D-4045-4E11-AE85-4402CA0AD054}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pnunit.framework", "..\..\..\..\lib\pnunit\pnunit.framework\pnunit.framework.csproj", "{5261ABA1-98E6-4603-A4F0-59CAC307AC68}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "guitest", "..\..\..\testing\guitest\guitest.csproj", "{9EE461F0-5FCA-4631-8335-73E1A0AF2861}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | NAnt|Any CPU = NAnt|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 28 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.NAnt|Any CPU.Build.0 = Release|Any CPU 29 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {20C1F257-2ADF-4E38-AE86-F167E284AF99}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 34 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.NAnt|Any CPU.Build.0 = Release|Any CPU 35 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {A1079FA8-882B-40D6-A289-3A13767CABDD}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 40 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.NAnt|Any CPU.Build.0 = Release|Any CPU 41 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {D775E82D-4045-4E11-AE85-4402CA0AD054}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.ActiveCfg = NAnt|Any CPU 46 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.NAnt|Any CPU.Build.0 = NAnt|Any CPU 47 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 50 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Debug|Any CPU.Build.0 = Debug|Any CPU 51 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.ActiveCfg = Release|Any CPU 52 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.NAnt|Any CPU.Build.0 = Release|Any CPU 53 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861}.Release|Any CPU.Build.0 = Release|Any CPU 55 | EndGlobalSection 56 | GlobalSection(SolutionProperties) = preSolution 57 | HideSolutionNode = FALSE 58 | EndGlobalSection 59 | GlobalSection(NestedProjects) = preSolution 60 | {D775E82D-4045-4E11-AE85-4402CA0AD054} = {2EBF8C53-4C4F-464D-9D79-45FACDA7DC87} 61 | {5261ABA1-98E6-4603-A4F0-59CAC307AC68} = {2EBF8C53-4C4F-464D-9D79-45FACDA7DC87} 62 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861} = {2EBF8C53-4C4F-464D-9D79-45FACDA7DC87} 63 | EndGlobalSection 64 | GlobalSection(ExtensibilityGlobals) = postSolution 65 | SolutionGuid = {82C11AC5-A331-451E-9EE5-81E58F2E8E93} 66 | EndGlobalSection 67 | EndGlobal 68 | -------------------------------------------------------------------------------- /src/application/lib/ApplicationArgs.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace Codice.Examples.GuiTesting.Lib 4 | { 5 | public class ApplicationArgs 6 | { 7 | public readonly bool IsTestingMode; 8 | public readonly string TestInfoFile; 9 | public readonly string PathToAssemblies; 10 | 11 | ApplicationArgs( 12 | bool isTestingMode, 13 | string testInfoFile, 14 | string pathToAssemblies) 15 | { 16 | IsTestingMode = isTestingMode; 17 | TestInfoFile = testInfoFile; 18 | PathToAssemblies = pathToAssemblies; 19 | } 20 | 21 | public static ApplicationArgs Parse(string[] args) 22 | { 23 | if (args.Length < 3 24 | || args[0] != TESTING_FLAG 25 | || !File.Exists(args[1]) 26 | || !Directory.Exists(args[2])) 27 | { 28 | return new ApplicationArgs(false, string.Empty, string.Empty); 29 | } 30 | 31 | return new ApplicationArgs(true, args[1], args[2]); 32 | } 33 | 34 | const string TESTING_FLAG = "--testing"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/application/lib/IGuiMessage.cs: -------------------------------------------------------------------------------- 1 | namespace Codice.Examples.GuiTesting.Lib.Interfaces 2 | { 3 | public class GuiMessage 4 | { 5 | public interface IGuiMessage 6 | { 7 | void ShowError(string title, string message); 8 | } 9 | 10 | public static void Initialize(IGuiMessage guiMessage) 11 | { 12 | mGuiMessage = guiMessage; 13 | } 14 | 15 | public static void ShowError(string title, string message) 16 | { 17 | mGuiMessage.ShowError(title, message); 18 | } 19 | 20 | static IGuiMessage mGuiMessage; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/application/lib/Localization.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Codice.Examples.GuiTesting.Lib 4 | { 5 | public class Localization 6 | { 7 | public enum Name 8 | { 9 | ApplicationName, 10 | Ok, 11 | AddButton, 12 | RemoveButton, 13 | TextInputLabel, 14 | AddingElementProgressText, 15 | RemovingElementProgressText, 16 | ElementCantBeEmptyErrorMessage, 17 | ErrorTitle, 18 | ElementNotInTheListErrorMessage, 19 | ElementInTheListErrorMessage 20 | } 21 | 22 | Localization() 23 | { 24 | mTexts = new Dictionary(); 25 | mTexts.Add(Name.ApplicationName, "GUI Testing example"); 26 | mTexts.Add(Name.Ok, "OK"); 27 | mTexts.Add(Name.AddButton, "Add"); 28 | mTexts.Add(Name.RemoveButton, "Remove"); 29 | mTexts.Add(Name.TextInputLabel, "Text: "); 30 | mTexts.Add(Name.AddingElementProgressText, "Adding element {0}..."); 31 | mTexts.Add(Name.RemovingElementProgressText, "Removing element {0}..."); 32 | mTexts.Add(Name.ElementCantBeEmptyErrorMessage, "The element can't be empty!"); 33 | mTexts.Add(Name.ErrorTitle, "Error"); 34 | mTexts.Add(Name.ElementNotInTheListErrorMessage, "The element {0} is not in the list, and thus it can't be removed!"); 35 | mTexts.Add(Name.ElementInTheListErrorMessage, "The element {0} is already in the list, and thus it can't be added!"); 36 | } 37 | 38 | public static string GetText(Name name) 39 | { 40 | return GetInstance().TryGetString(name); 41 | } 42 | 43 | public static string GetText(Name name, params object[] args) 44 | { 45 | string result = GetInstance().TryGetString(name); 46 | 47 | return (result == UNLOCALIZED) 48 | ? UNLOCALIZED 49 | : string.Format(result, args); 50 | } 51 | 52 | static Localization GetInstance() 53 | { 54 | if (mInstance == null) 55 | mInstance = new Localization(); 56 | 57 | return mInstance; 58 | } 59 | 60 | string TryGetString(Name name) 61 | { 62 | if (!mTexts.ContainsKey(name)) 63 | return "UNLOCALIZED"; 64 | 65 | return mTexts[name]; 66 | } 67 | 68 | static Localization mInstance; 69 | 70 | readonly Dictionary mTexts; 71 | 72 | const string UNLOCALIZED = "UNLOCALIZED"; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/application/lib/interfaces/IApplicationWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Codice.Examples.GuiTesting.Lib.Interfaces 4 | { 5 | public interface IApplicationWindow 6 | { 7 | void UpdateItems(List items); 8 | void ClearInput(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/application/lib/interfaces/IProgressControls.cs: -------------------------------------------------------------------------------- 1 | namespace Codice.Examples.GuiTesting.Lib.Interfaces 2 | { 3 | public interface IProgressControls 4 | { 5 | bool HasError { get; } 6 | 7 | void ShowProgress(string message); 8 | void HideProgress(); 9 | 10 | void ShowError(string message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/application/lib/lib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {A1079FA8-882B-40D6-A289-3A13767CABDD} 8 | Library 9 | Properties 10 | Codice.Examples.GuiTesting.Lib 11 | lib 12 | v4.5 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\..\..\bin\application\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/application/lib/threading/ApplicationThread.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Codice.Examples.GuiTesting.Lib.Threading 5 | { 6 | public class ApplicationThread 7 | { 8 | public bool IsRunning { get { lock (mLock) { return mbIsRunning; } } } 9 | public Exception Exception { get { lock (mLock) { return mException; } } } 10 | 11 | public delegate void Operation(); 12 | 13 | public ApplicationThread(Operation performOperationDelegate) 14 | { 15 | SetRunning(true); 16 | mPerformOperationDelegate = performOperationDelegate; 17 | } 18 | 19 | public void Execute() 20 | { 21 | ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadWork)); 22 | } 23 | 24 | void ThreadWork(object state) 25 | { 26 | SetException(null); 27 | 28 | try 29 | { 30 | mPerformOperationDelegate(); 31 | } 32 | catch (Exception ex) 33 | { 34 | SetException( 35 | ex.InnerException == null 36 | ? ex 37 | : ex.InnerException); 38 | } 39 | finally 40 | { 41 | SetRunning(false); 42 | } 43 | } 44 | 45 | void SetRunning(bool bIsRunning) 46 | { 47 | lock (mLock) 48 | { 49 | mbIsRunning = bIsRunning; 50 | } 51 | } 52 | 53 | void SetException(Exception exception) 54 | { 55 | lock (mLock) 56 | { 57 | mException = exception; 58 | } 59 | } 60 | 61 | Operation mPerformOperationDelegate; 62 | 63 | bool mbIsRunning; 64 | Exception mException; 65 | object mLock = new object(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/application/lib/threading/ApplicationThreadWaiter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Codice.Examples.GuiTesting.Lib.Threading 4 | { 5 | public interface IApplicationTimerBuilder 6 | { 7 | IApplicationTimer Get( 8 | bool bModalMode, 9 | ThreadWaiter.TimerTick timerTickDelegate); 10 | } 11 | 12 | public interface IApplicationTimer 13 | { 14 | void Start(); 15 | void Stop(); 16 | } 17 | 18 | public interface IThreadWaiterBuilder 19 | { 20 | IThreadWaiter GetWaiter(); 21 | IThreadWaiter GetModalWaiter(); 22 | } 23 | 24 | public interface IThreadWaiter 25 | { 26 | Exception Exception { get; } 27 | 28 | void Execute( 29 | ApplicationThread.Operation threadOperationDelegate, 30 | ApplicationThread.Operation afterOperationDelegate); 31 | 32 | void Cancel(); 33 | } 34 | 35 | public static class ThreadWaiter 36 | { 37 | public delegate void TimerTick(); 38 | 39 | public static void Initialize(IThreadWaiterBuilder threadWaiterBuilder) 40 | { 41 | mThreadWaiterBuilder = threadWaiterBuilder; 42 | } 43 | 44 | public static IThreadWaiter GetWaiter() 45 | { 46 | return mThreadWaiterBuilder.GetWaiter(); 47 | } 48 | 49 | public static IThreadWaiter GetModalWaiter() 50 | { 51 | return mThreadWaiterBuilder.GetModalWaiter(); 52 | } 53 | 54 | public static void Reset() 55 | { 56 | mThreadWaiterBuilder = new ThreadWaiterBuilder(); 57 | } 58 | 59 | static IThreadWaiterBuilder mThreadWaiterBuilder = new ThreadWaiterBuilder(); 60 | } 61 | 62 | public class ThreadWaiterBuilder : IThreadWaiterBuilder 63 | { 64 | public static void Initialize(IApplicationTimerBuilder timerBuilder) 65 | { 66 | mPlasticTimerBuilder = timerBuilder; 67 | } 68 | 69 | IThreadWaiter IThreadWaiterBuilder.GetWaiter() 70 | { 71 | return new PlasticThreadWaiter(mPlasticTimerBuilder, false); 72 | } 73 | 74 | IThreadWaiter IThreadWaiterBuilder.GetModalWaiter() 75 | { 76 | return new PlasticThreadWaiter(mPlasticTimerBuilder, true); 77 | } 78 | 79 | static IApplicationTimerBuilder mPlasticTimerBuilder; 80 | } 81 | 82 | public class PlasticThreadWaiter : IThreadWaiter 83 | { 84 | public Exception Exception { get { return mThreadOperation.Exception; } } 85 | 86 | internal PlasticThreadWaiter( 87 | IApplicationTimerBuilder timerBuilder, bool bModalMode) 88 | { 89 | mPlasticTimer = timerBuilder.Get(bModalMode, OnTimerTick); 90 | } 91 | 92 | public void Execute( 93 | ApplicationThread.Operation threadOperationDelegate, 94 | ApplicationThread.Operation afterOperationDelegate) 95 | { 96 | mThreadOperation = new ApplicationThread(threadOperationDelegate); 97 | mAfterOperationDelegate = afterOperationDelegate; 98 | 99 | mPlasticTimer.Start(); 100 | 101 | mThreadOperation.Execute(); 102 | } 103 | 104 | public void Cancel() 105 | { 106 | mbCancelled = true; 107 | } 108 | 109 | void OnTimerTick() 110 | { 111 | if (mThreadOperation.IsRunning) 112 | return; 113 | 114 | mPlasticTimer.Stop(); 115 | 116 | if (mbCancelled) 117 | return; 118 | 119 | mAfterOperationDelegate(); 120 | } 121 | 122 | bool mbCancelled = false; 123 | 124 | IApplicationTimer mPlasticTimer; 125 | ApplicationThread mThreadOperation; 126 | ApplicationThread.Operation mAfterOperationDelegate; 127 | } 128 | } -------------------------------------------------------------------------------- /src/testing/guitest/PlatformUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace GuiTest 5 | { 6 | public static class PlatformUtils 7 | { 8 | public enum Platform 9 | { 10 | Unknown, 11 | Windows, 12 | MacOS, 13 | Linux 14 | } 15 | 16 | public static Platform CurrentPlatform 17 | { 18 | get 19 | { 20 | if (mCurrentPlatform != Platform.Unknown) 21 | return mCurrentPlatform; 22 | 23 | mCurrentPlatform = GetCurrentPlatform(); 24 | return mCurrentPlatform; 25 | } 26 | } 27 | 28 | static Platform GetCurrentPlatform() 29 | { 30 | switch (Environment.OSVersion.Platform) 31 | { 32 | case PlatformID.MacOSX: 33 | return Platform.MacOS; 34 | 35 | case PlatformID.Unix: 36 | return AreMacOSDirectoriesPresent() 37 | ? Platform.MacOS 38 | : Platform.Linux; 39 | 40 | default: 41 | return Platform.Windows; 42 | } 43 | } 44 | 45 | static bool AreMacOSDirectoriesPresent() 46 | { 47 | return Directory.Exists("/Applications") 48 | && Directory.Exists("/System") 49 | && Directory.Exists("/Users") 50 | && Directory.Exists("/Volumes"); 51 | } 52 | 53 | static Platform mCurrentPlatform = Platform.Unknown; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/testing/guitest/guitest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9EE461F0-5FCA-4631-8335-73E1A0AF2861} 8 | Library 9 | Properties 10 | guitest 11 | guitest 12 | v4.5.1 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\..\..\bin\pnunit\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | ..\..\..\lib\log4net\log4net.dll 36 | 37 | 38 | False 39 | ..\..\..\lib\mono\Mono.Posix.dll 40 | 41 | 42 | ..\..\..\lib\nunit\nunit.core.dll 43 | 44 | 45 | ..\..\..\lib\nunit\nunit.core.interfaces.dll 46 | 47 | 48 | ..\..\..\lib\nunit\nunit.framework.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {5261aba1-98e6-4603-a4f0-59cac307ac68} 64 | pnunit.framework 65 | 66 | 67 | {d775e82d-4045-4e11-ae85-4402ca0ad054} 68 | guitestinterfaces 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/testing/guitestinterfaces/GuiTesteableServices.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Codice.Examples.GuiTesting.GuiTestInterfaces 4 | { 5 | public class GuiTesteableServices 6 | { 7 | public static Exception UnhandledException 8 | { 9 | get { lock (mInstance) return mInstance.mUnhandledException; } 10 | set { lock (mInstance) mInstance.mUnhandledException = value; } 11 | } 12 | 13 | public static void Init(ITesteableApplicationWindow window) 14 | { 15 | if (mInstance == null) 16 | mInstance = new GuiTesteableServices(); 17 | 18 | mInstance.mTesteableApplicationWindow = window; 19 | } 20 | 21 | public static ITesteableApplicationWindow GetApplicationWindow() 22 | { 23 | return mInstance.mTesteableApplicationWindow; 24 | } 25 | 26 | Exception mUnhandledException; 27 | static GuiTesteableServices mInstance; 28 | 29 | ITesteableApplicationWindow mTesteableApplicationWindow; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/testing/guitestinterfaces/ITesteableApplicationWindow.cs: -------------------------------------------------------------------------------- 1 | namespace Codice.Examples.GuiTesting.GuiTestInterfaces 2 | { 3 | public interface ITesteableApplicationWindow 4 | { 5 | void ClickAddButton(); 6 | void ClickRemoveButton(); 7 | 8 | bool AreButtonsEnabled(); 9 | 10 | void ChangeText(string text); 11 | string GetText(); 12 | 13 | int GetItemsInListCount(); 14 | string GetItemInListAt(int index); 15 | 16 | string GetProgressMessage(); 17 | string GetErrorMessage(); 18 | 19 | ITesteableErrorDialog GetErrorDialog(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/testing/guitestinterfaces/ITesteableErrorDialog.cs: -------------------------------------------------------------------------------- 1 | namespace Codice.Examples.GuiTesting.GuiTestInterfaces 2 | { 3 | public interface ITesteableErrorDialog 4 | { 5 | void ClickOkButton(); 6 | 7 | string GetTitle(); 8 | string GetMessage(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/testing/guitestinterfaces/guitestinterfaces.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D775E82D-4045-4E11-AE85-4402CA0AD054} 8 | Library 9 | Properties 10 | Codice.Examples.GuiTesting.GuiTestInterfaces 11 | guitestinterfaces 12 | v4.5 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\..\..\bin\pnunit\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | --------------------------------------------------------------------------------