using System.IO; using Exortech.NetReflector; using NMock; using NMock.Constraints; using NUnit.Framework; using ThoughtWorks.CruiseControl.Core; using ThoughtWorks.CruiseControl.Core.Tasks; using ThoughtWorks.CruiseControl.Core.Util; using ThoughtWorks.CruiseControl.Remote; namespace ThoughtWorks.CruiseControl.UnitTests.Core.Tasks { [TestFixture] public class MsDevTaskTest : ProcessExecutorTestFixtureBase { private const string MSDEV_PATH = @"C:\Program Files\Microsoft Visual Studio\Common\IDE98\Bin"; private const string WORKSPACE_FILE = @"Z:\dummy.dsw"; private const string CONFIGURATION = "DummyProject - Win32 Debug"; private MsDevTask task; private IMock mockRegistry; [SetUp] public void Setup() { mockRegistry = new DynamicMock(typeof (IRegistry)); CreateProcessExecutorMock(MSDEV_PATH); task = new MsDevTask((IRegistry) mockRegistry.MockInstance, (ProcessExecutor) mockProcessExecutor.MockInstance); } [TearDown] public void VerifyMocks() { mockRegistry.Verify(); mockProcessExecutor.Verify(); } [Test] public void ShouldLoadAllValuesFromConfiguration() { string xml = @" c:\vc6\msdev.com MyWorkspace.dsw MyProject - Win32 Debug 4 MyProject make "; MsDevTask task2 = (MsDevTask)NetReflector.Read(xml); Assert.AreEqual(@"c:\vc6\msdev.com", task2.Executable); Assert.AreEqual(@"MyWorkspace.dsw", task2.WorkspaceFile); Assert.AreEqual(@"MyProject - Win32 Debug", task2.Configuration); Assert.AreEqual(4, task2.BuildTimeoutSeconds); Assert.AreEqual(@"make", task2.BuildType); Assert.AreEqual(@"MyProject", task2.Project); } [Test] public void ShouldLoadMinimalValuesFromConfiguration() { string xml = @""; MsDevTask task2 = (MsDevTask)NetReflector.Read(xml); Assert.AreEqual(@"MyWorkspace.dsw", task2.WorkspaceFile); Assert.AreEqual(@"MyProject - Win32 Release", task2.Configuration); Assert.AreEqual(MsDevTask.DEFAULT_BUILD_TIMEOUT, task2.BuildTimeoutSeconds); Assert.AreEqual(@"make", task2.BuildType); Assert.AreEqual(@"", task2.Project); } [Test] public void ExecutableReadFromRegistryIfNotSupplied() { IMock mockRegistry2 = new DynamicMock(typeof(IRegistry)); MsDevTask task2 = new MsDevTask((IRegistry)mockRegistry2.MockInstance, (ProcessExecutor)mockProcessExecutor.MockInstance); mockRegistry2.ExpectAndReturn("GetLocalMachineSubKeyValue", MSDEV_PATH, MsDevTask.VS6_REGISTRY_PATH, MsDevTask.VS_REGISTRY_KEY); Assert.AreEqual(Path.Combine(MSDEV_PATH, @"..\..\MSDev98\Bin\") + MsDevTask.MSDEV_EXE, task2.Executable); mockRegistry2.Verify(); mockProcessExecutor.Verify(); } [Test] public void VerifyMsDevProcessInfo() { CollectingConstraint constraint = new CollectingConstraint(); ProcessResult processResult = new ProcessResult("output", "error", 0, false); mockProcessExecutor.ExpectAndReturn("Execute", processResult, new object[] { constraint, new IsAnything() }); task.Executable = MSDEV_PATH; task.WorkspaceFile = "\"MyWorkspace.dsw\""; task.Configuration = "\"MyProject - Win32 Debug\""; task.Run(IntegrationResult()); ProcessInfo info = (ProcessInfo) constraint.Parameter; Assert.AreEqual(MSDEV_PATH, info.FileName); Assert.AreEqual(DevenvTask.DEFAULT_BUILD_TIMEOUT*1000, info.TimeOut); CustomAssertion.AssertStartsWith("\"MyWorkspace.dsw\" /make \"MyProject - Win32 Debug\"", info.Arguments); } [Test] public void VerifyMsDevProcessInfoWithProjectDefined() { CollectingConstraint constraint = new CollectingConstraint(); ProcessResult processResult = new ProcessResult("output", "error", 0, false); mockProcessExecutor.ExpectAndReturn("Execute", processResult, new object[] { constraint, new IsAnything() }); task.Executable = MSDEV_PATH; task.WorkspaceFile = "\"MyWorkspace.dsw\""; task.Configuration = "\"MyProject - Win32 Debug\""; task.Project = "MyProject"; task.Run(IntegrationResult()); ProcessInfo info = (ProcessInfo)constraint.Parameter; Assert.AreEqual(MSDEV_PATH, info.FileName); Assert.AreEqual(DevenvTask.DEFAULT_BUILD_TIMEOUT * 1000, info.TimeOut); CustomAssertion.AssertStartsWith("\"MyWorkspace.dsw\" /make \"MyProject - Win32 Debug\" /project MyProject", info.Arguments); } [Test] public void ShouldSetOutputAndIntegrationStatusToSuccessOnSuccessfulBuild() { ProcessResult processResult = new ProcessResult(@"MyProject.exe - 0 error(s), 6 warning(s)", string.Empty, ProcessResult.SUCCESSFUL_EXIT_CODE, false); mockProcessExecutor.ExpectAndReturn("Execute", processResult, new object[] { new IsAnything(), new IsAnything() }); task.Executable = MSDEV_PATH; task.WorkspaceFile = WORKSPACE_FILE; task.Configuration = CONFIGURATION; IntegrationResult result = (IntegrationResult)IntegrationResult(); task.Run(result); Assert.AreEqual(IntegrationStatus.Success, result.Status); CustomAssertion.AssertMatches(@"MyProject.exe - \d+ error\(s\), \d+ warning\(s\)", result.TaskOutput); } [Test] public void ShouldSetOutputAndIntegrationStatusToFailedOnFailedBuild() { ProcessResult processResult = new ProcessResult(@"Z:\NoWorkspace.dsw could not be found and will not be loaded", string.Empty, 1, false); CollectingConstraint constraint = new CollectingConstraint(); mockProcessExecutor.ExpectAndReturn("Execute", processResult, new object[] { constraint, new IsAnything() }); task.Executable = MSDEV_PATH; task.WorkspaceFile = @"Z:\NoWorkspace.dsw"; task.Configuration = CONFIGURATION; IIntegrationResult result = Integration("myProject", "myWorkingDirectory", "myArtifactDirectory"); task.Run(result); ProcessInfo info = (ProcessInfo)constraint.Parameter; Assert.AreEqual("myWorkingDirectory", info.WorkingDirectory); Assert.AreEqual(IntegrationStatus.Failure, result.Status); CustomAssertion.AssertMatches(@"(\.|\n)*could not be found and will not be loaded", result.TaskOutput); } [Test, ExpectedException(typeof(BuilderException))] public void ShouldThrowBuilderExceptionIfProcessExecutorThrowsAnException() { mockProcessExecutor.ExpectAndThrow("Execute", new IOException(), new object[] { new IsAnything(), new IsAnything() }); task.Executable = MSDEV_PATH + ".some.extra.ext.exe"; // file should not exist task.WorkspaceFile = @"Z:\NoFile.dsw"; task.Configuration = "Debug"; task.Run(IntegrationResult()); } [Test, ExpectedException(typeof(BuilderException))] public void ShouldThrowBuilderExceptionIfProcessExecutorThrowsAnExceptionUsingUnkownProject() { mockProcessExecutor.ExpectAndThrow("Execute", new IOException(), new object[] { new IsAnything(), new IsAnything() }); task.Executable = MSDEV_PATH; task.WorkspaceFile = WORKSPACE_FILE; task.Configuration = CONFIGURATION; task.Project = "unknownproject"; task.Run(IntegrationResult()); } [Test, ExpectedException(typeof(BuilderException))] public void ShouldThrowBuilderExceptionIfProcessTimesOut() { ProcessResult processResult = new ProcessResult(string.Empty, string.Empty, ProcessResult.TIMED_OUT_EXIT_CODE, true); mockProcessExecutor.ExpectAndReturn("Execute", processResult, new object[] { new IsAnything(), new IsAnything() }); task.BuildTimeoutSeconds = 2; task.Executable = MSDEV_PATH; task.WorkspaceFile = WORKSPACE_FILE; task.Configuration = CONFIGURATION; task.Run(IntegrationResult()); } } }