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());
}
}
}