Index: project/core/core.csproj
===================================================================
--- project/core/core.csproj (revision 3352)
+++ project/core/core.csproj (working copy)
@@ -649,6 +649,7 @@
Code
+
Code
@@ -688,6 +689,7 @@
Code
+
Code
Index: project/core/IntegrationResult.cs
===================================================================
--- project/core/IntegrationResult.cs (revision 3352)
+++ project/core/IntegrationResult.cs (working copy)
@@ -245,7 +245,10 @@
public void AddTaskResult(ITaskResult result)
{
- taskResults.Add(result);
+ lock (taskResults.SyncRoot)
+ {
+ taskResults.Add(result);
+ }
if (! (Failed || Status == IntegrationStatus.Exception)) Status = result.Succeeded() ? IntegrationStatus.Success : IntegrationStatus.Failure;
}
@@ -388,4 +391,4 @@
return string.Format("Project: {0}, Status: {1}, Label: {2}, StartTime: {3}", ProjectName, Status, Label, StartTime);
}
}
-}
\ No newline at end of file
+}
Index: project/core/tasks/ParallelTask.cs
===================================================================
--- project/core/tasks/ParallelTask.cs (revision 0)
+++ project/core/tasks/ParallelTask.cs (revision 0)
@@ -0,0 +1,45 @@
+using System.Collections;
+using System.IO;
+using System.Threading;
+using Exortech.NetReflector;
+using ThoughtWorks.CruiseControl.Core.Util;
+
+namespace ThoughtWorks.CruiseControl.Core.Tasks
+{
+ [ReflectorType("parallel")]
+ public class ParallelTask : ITask
+ {
+ private ITask[] tasks = new ITask[] { new NullTask() };
+
+
+ [ReflectorArray("tasks", Required = false)]
+ public ITask[] Tasks
+ {
+ get { return tasks; }
+ set { tasks = value; }
+ }
+
+ public void Run(IIntegrationResult result)
+ {
+ Thread[] threads = new Thread[tasks.Length];
+ for(int i = 0; i < threads.Length; i++)
+ {
+ object[] objs = { tasks[i], result };
+ threads[i] = new Thread((ParameterizedThreadStart)ThreadStub);
+ threads[i].Start(objs);
+ }
+ foreach (Thread t in threads)
+ {
+ t.Join();
+ }
+ }
+
+ public void ThreadStub(object o)
+ {
+ object[] objs = (object[])o;
+ ITask task = (ITask)objs[0];
+ IIntegrationResult res = (IIntegrationResult)objs[1];
+ task.Run(res);
+ }
+ }
+}
Index: project/core/tasks/SerialTask.cs
===================================================================
--- project/core/tasks/SerialTask.cs (revision 0)
+++ project/core/tasks/SerialTask.cs (revision 0)
@@ -0,0 +1,28 @@
+using System.Collections;
+using System.IO;
+using Exortech.NetReflector;
+using ThoughtWorks.CruiseControl.Core.Util;
+
+namespace ThoughtWorks.CruiseControl.Core.Tasks
+{
+ [ReflectorType("serial")]
+ public class SerialTask : ITask
+ {
+ private ITask[] tasks = new ITask[] { new NullTask() };
+
+ [ReflectorArray("tasks", Required = false)]
+ public ITask[] Tasks
+ {
+ get { return tasks; }
+ set { tasks = value; }
+ }
+
+ public void Run(IIntegrationResult result)
+ {
+ foreach (ITask task in tasks)
+ {
+ task.Run(result);
+ }
+ }
+ }
+}
Index: project/UnitTests/Core/Tasks/ParallelTaskTest.cs
===================================================================
--- project/UnitTests/Core/Tasks/ParallelTaskTest.cs (revision 0)
+++ project/UnitTests/Core/Tasks/ParallelTaskTest.cs (revision 0)
@@ -0,0 +1,62 @@
+using NUnit.Framework;
+using Exortech.NetReflector;
+using ThoughtWorks.CruiseControl.Core;
+using ThoughtWorks.CruiseControl.Core.Tasks;
+using ThoughtWorks.CruiseControl.Core.Util;
+
+namespace ThoughtWorks.CruiseControl.UnitTests.Core.Tasks
+{
+ [TestFixture]
+ public class ParallelTaskTest
+ {
+ private ParallelTask task;
+
+ [SetUp]
+ public void Setup()
+ {
+ task = new ParallelTask();
+ }
+
+ [Test]
+ public void CanRunOneNullTask()
+ {
+ IntegrationResult result = new IntegrationResult();
+ task.Tasks = new ITask[1];
+ task.Tasks[0] = new NullTask();
+ task.Run(result);
+ Assert.IsTrue(result.Succeeded);
+ }
+
+ [Test]
+ public void CanRunTwoNullTasks()
+ {
+ IntegrationResult result = new IntegrationResult();
+ task.Tasks = new ITask[2];
+ task.Tasks[0] = new NullTask();
+ task.Tasks[1] = new NullTask();
+ task.Run(result);
+ Assert.IsTrue(result.Succeeded);
+ }
+
+ [Test]
+ public void PopulateFromReflector()
+ {
+ string xml = @"
+
+
+
+ mybatchfile.bat
+ C:\
+ myarg1 myarg2
+ 123
+
+
+
+ ";
+
+ task = (ParallelTask)NetReflector.Read(xml);
+ Assert.IsInstanceOfType(typeof(ExecutableTask), task.Tasks[0]);
+ Assert.IsInstanceOfType(typeof(NullTask), task.Tasks[1]);
+ }
+ }
+}
Index: project/UnitTests/Core/Tasks/SerialTaskTest.cs
===================================================================
--- project/UnitTests/Core/Tasks/SerialTaskTest.cs (revision 0)
+++ project/UnitTests/Core/Tasks/SerialTaskTest.cs (revision 0)
@@ -0,0 +1,62 @@
+using NUnit.Framework;
+using Exortech.NetReflector;
+using ThoughtWorks.CruiseControl.Core;
+using ThoughtWorks.CruiseControl.Core.Tasks;
+using ThoughtWorks.CruiseControl.Core.Util;
+
+namespace ThoughtWorks.CruiseControl.UnitTests.Core.Tasks
+{
+ [TestFixture]
+ public class SerialTaskTest
+ {
+ private SerialTask task;
+
+ [SetUp]
+ public void Setup()
+ {
+ task = new SerialTask();
+ }
+
+ [Test]
+ public void CanRunOneNullTask()
+ {
+ IntegrationResult result = new IntegrationResult();
+ task.Tasks = new ITask[1];
+ task.Tasks[0] = new NullTask();
+ task.Run(result);
+ Assert.IsTrue(result.Succeeded);
+ }
+
+ [Test]
+ public void CanRunTwoNullTasks()
+ {
+ IntegrationResult result = new IntegrationResult();
+ task.Tasks = new ITask[2];
+ task.Tasks[0] = new NullTask();
+ task.Tasks[1] = new NullTask();
+ task.Run(result);
+ Assert.IsTrue(result.Succeeded);
+ }
+
+ [Test]
+ public void PopulateFromReflector()
+ {
+ string xml = @"
+
+
+
+ mybatchfile.bat
+ C:\
+ myarg1 myarg2
+ 123
+
+
+
+ ";
+
+ task = (SerialTask)NetReflector.Read(xml);
+ Assert.IsInstanceOfType(typeof(ExecutableTask), task.Tasks[0]);
+ Assert.IsInstanceOfType(typeof(NullTask), task.Tasks[1]);
+ }
+ }
+}
Index: project/UnitTests/UnitTests.csproj
===================================================================
--- project/UnitTests/UnitTests.csproj (revision 3352)
+++ project/UnitTests/UnitTests.csproj (working copy)
@@ -673,6 +673,7 @@
Code
+
Code
@@ -715,6 +716,7 @@
Code
+
Code