Skip to content
Browse files

Making it easier to wait on CLR4 Tasks. Closes #90 and #91.

  • Loading branch information...
1 parent 869adeb commit ffd672e3edfc65accdf8fb727216d41ae5f87f92 @agross agross committed Feb 2, 2012
View
12 Machine.Specifications.sln
@@ -88,6 +88,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A3F866
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.WebDriverSupport", "Source\Machine.Specifications.WebDriverSupport\Machine.Specifications.WebDriverSupport.csproj", "{0029D44B-6E6C-4FD5-9071-EEA15A765D37}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.Clr4", "Source\Machine.Specifications.Clr4\Machine.Specifications.Clr4.csproj", "{4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Machine.Specifications.Clr4.Specs", "Source\Machine.Specifications.Clr4.Specs\Machine.Specifications.Clr4.Specs.csproj", "{8B6A3294-62DB-4838-AF2F-F107A1CC1926}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -214,6 +218,14 @@ Global
{0029D44B-6E6C-4FD5-9071-EEA15A765D37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0029D44B-6E6C-4FD5-9071-EEA15A765D37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0029D44B-6E6C-4FD5-9071-EEA15A765D37}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8B6A3294-62DB-4838-AF2F-F107A1CC1926}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8B6A3294-62DB-4838-AF2F-F107A1CC1926}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8B6A3294-62DB-4838-AF2F-F107A1CC1926}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8B6A3294-62DB-4838-AF2F-F107A1CC1926}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
View
66 Source/Machine.Specifications.Clr4.Specs/Machine.Specifications.Clr4.Specs.csproj
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8B6A3294-62DB-4838-AF2F-F107A1CC1926}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Machine.Specifications.Clr4.Specs</RootNamespace>
+ <AssemblyName>Machine.Specifications.Clr4.Specs</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Build\Debug\Tests\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\Build\Release\Tests\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedAssemblyInfo.cs">
+ <Link>Properties\SharedAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\VersionInfo.cs">
+ <Link>Properties\VersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="TaskSpecificationExtensionsSpecs.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Machine.Specifications.Clr4\Machine.Specifications.Clr4.csproj">
+ <Project>{4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}</Project>
+ <Name>Machine.Specifications.Clr4</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Machine.Specifications\Machine.Specifications.csproj">
+ <Project>{CCD02629-1262-4F78-9E9F-AC97B942D0E7}</Project>
+ <Name>Machine.Specifications</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
21 Source/Machine.Specifications.Clr4.Specs/Properties/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Machine.Specifications.Clr4.Specs")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("3a951a05-4fad-47b2-a049-1d009bd8cf78")]
View
95 Source/Machine.Specifications.Clr4.Specs/TaskSpecificationExtensionsSpecs.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Machine.Specifications.Clr4.Specs
+{
+ public static class Delayed
+ {
+ static readonly TimeSpan WaitTimeout = TimeSpan.FromMilliseconds(500);
+
+ public static Task<string> Echo(string toEcho)
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(WaitTimeout);
+
+ return toEcho;
+ });
+ }
+
+ public static Task Fail()
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(WaitTimeout);
+
+ throw new InvalidOperationException("something went wrong");
+
+ });
+ }
+
+ public static Task MultipleFails()
+ {
+ return Task.Factory.StartNew(() => Task.WaitAll(Fail(), Fail()));
+ }
+ }
+
+ [Subject(typeof(TaskSpecificationExtensions))]
+ public class when_an_async_operation_runs_without_await
+ {
+ static Task<string> Result;
+
+ Because of = () => { Result = Delayed.Echo("result"); };
+
+ It should_not_wait_for_completion =
+ () => Result.IsCompleted.ShouldBeFalse();
+ }
+
+ [Subject(typeof(TaskSpecificationExtensions))]
+ public class when_an_async_operation_runs_with_await
+ {
+ static string Result;
+
+ Because of = () => { Result = Delayed.Echo("result").Await(); };
+
+ It should_wait_for_completion =
+ () => Result.ShouldEqual("result");
+ }
+
+ [Subject(typeof(TaskSpecificationExtensions), "exception")]
+ public class when_an_async_operation_fails_without_await
+ {
+ static Exception Exception;
+
+ Because of = () => Exception = Catch.Exception(() => Delayed.Fail());
+
+ It should_not_capture_the_exception =
+ () => Exception.ShouldBeNull();
+ }
+
+ [Subject(typeof(TaskSpecificationExtensions), "exception")]
+ public class when_a_single_async_operation_fails_with_await
+ {
+ static Exception Exception;
+
+ Because of = () => Exception = Catch.Exception(() => Delayed.Fail().Await());
+
+ It should_capture_the_first_exception =
+ () => Exception.ShouldBeOfType<InvalidOperationException>();
+ }
+
+ [Subject(typeof(TaskSpecificationExtensions), "exception")]
+ public class when_multiple_async_operations_fail_with_await
+ {
+ static Exception Exception;
+
+ Because of = () => Exception = Catch.Exception(() => Delayed.MultipleFails().Await());
+
+ It should_capture_the_aggregate_exception =
+ () => Exception.ShouldBeOfType<AggregateException>();
+
+ It should_capture_all_inner_exceptions =
+ () => ((AggregateException) Exception).InnerExceptions.Count.ShouldEqual(2);
+ }
+}
View
39 Source/Machine.Specifications.Clr4/AwaitResult.cs
@@ -0,0 +1,39 @@
+using System.Threading.Tasks;
+
+namespace Machine.Specifications
+{
+ public class AwaitResult
+ {
+ readonly Task _task;
+
+ public AwaitResult(Task task)
+ {
+ _task = task;
+ }
+
+ public Task AsTask
+ {
+ get { return _task; }
+ }
+ }
+
+ public class AwaitResult<T>
+ {
+ readonly Task<T> _task;
+
+ public AwaitResult(Task<T> task)
+ {
+ _task = task;
+ }
+
+ public Task<T> AsTask
+ {
+ get { return _task; }
+ }
+
+ public static implicit operator T(AwaitResult<T> m)
+ {
+ return m._task.Result;
+ }
+ }
+}
View
57 Source/Machine.Specifications.Clr4/Machine.Specifications.Clr4.csproj
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Machine.Specifications</RootNamespace>
+ <AssemblyName>Machine.Specifications.Clr4</AssemblyName>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="Microsoft.CSharp" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedAssemblyInfo.cs">
+ <Link>Properties\SharedAssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\VersionInfo.cs">
+ <Link>Properties\VersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="AwaitResult.cs" />
+ <Compile Include="TaskSpecificationExtensions.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
View
18 Source/Machine.Specifications.Clr4/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Machine.Specifications.Clr4")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f501eefc-0b39-4082-928a-2bc3fa4d4338")]
View
45 Source/Machine.Specifications.Clr4/TaskSpecificationExtensions.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Machine.Specifications
+{
+ public static class TaskSpecificationExtensions
+ {
+ public static AwaitResult<T> Await<T>(this Task<T> task)
+ {
+ try
+ {
+ task.Wait();
+ }
+ catch (AggregateException ex)
+ {
+ if (ex.InnerExceptions.Count == 1)
+ {
+ throw ex.InnerExceptions.First();
+ }
+ throw;
+ }
+
+ return new AwaitResult<T>(task);
+ }
+
+ public static AwaitResult Await(this Task task)
+ {
+ try
+ {
+ task.Wait();
+ }
+ catch (AggregateException ex)
+ {
+ if (ex.InnerExceptions.Count == 1)
+ {
+ throw ex.InnerExceptions.First();
+ }
+ throw;
+ }
+
+ return new AwaitResult(task);
+ }
+ }
+}
View
31 Source/Machine.Specifications.Example.Clr4/AsyncSpecs.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Machine.Specifications.Example.Clr4
+{
+ public class AsyncWorker
+ {
+ public Task<string> DoWorkAsync()
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(TimeSpan.FromMilliseconds(500));
+ return "done";
+ });
+ }
+ }
+
+ class when_using_tasks_to_do_async_work
+ {
+ static AsyncWorker Worker;
+ static string Result;
+
+ Establish context = () => { Worker = new AsyncWorker(); };
+
+ Because of = () => { Result = Worker.DoWorkAsync().Await(); };
+
+ It should_wait_for_the_async_work_to_complete =
+ () => Result.ShouldEqual("done");
+ }
+}
View
0 ....Specifications.Example.Clr4/Clr4Specs.cs → ...ations.Example.Clr4/ExpandoObjectSpecs.cs
File renamed without changes.
View
7 Source/Machine.Specifications.Example.Clr4/Machine.Specifications.Example.Clr4.csproj
@@ -46,10 +46,15 @@
<Compile Include="..\VersionInfo.cs">
<Link>Properties\VersionInfo.cs</Link>
</Compile>
- <Compile Include="Clr4Specs.cs" />
+ <Compile Include="AsyncSpecs.cs" />
+ <Compile Include="ExpandoObjectSpecs.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\Machine.Specifications.Clr4\Machine.Specifications.Clr4.csproj">
+ <Project>{4F5B8F3D-21FE-46AE-9D45-4E1ED891F4DF}</Project>
+ <Name>Machine.Specifications.Clr4</Name>
+ </ProjectReference>
<ProjectReference Include="..\Machine.Specifications\Machine.Specifications.csproj">
<Project>{CCD02629-1262-4F78-9E9F-AC97B942D0E7}</Project>
<Name>Machine.Specifications</Name>
View
6 rakefile.rb
@@ -148,11 +148,11 @@ def build (msbuild_options, config)
task :run do
puts 'Running Specs...'
- specs = FileList.new("#{configatron.out_dir}/Tests/*.Specs.dll").to_a
+ specs = FileList.new("#{configatron.out_dir}/Tests/*.Specs.dll").exclude(/Clr4/)
sh "#{configatron.out_dir}/mspec.exe", "--html", "Specs/#{configatron.project}.Specs.html", "-x", "example", *(configatron.mspec_options + specs)
- specs = ["#{configatron.out_dir}/Tests/Machine.Specifications.Example.Clr4.dll"]
- sh "#{configatron.out_dir}/mspec-clr4.exe", "-x", "example", *(configatron.mspec_options + specs)
+ specs = FileList.new("#{configatron.out_dir}/Tests/*Clr4*.dll")
+ sh "#{configatron.out_dir}/mspec-clr4.exe", *(configatron.mspec_options + specs)
puts "Wrote specs to Specs/#{configatron.project}.Specs.html, run 'rake specs:view' to see them"
end

0 comments on commit ffd672e

Please sign in to comment.
Something went wrong with that request. Please try again.