├── .gitattributes ├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── LICENSE.txt ├── WebAPIContrib.Formatting.ProtoBuf.sln ├── build.bat ├── readme.md ├── src └── WebApiContrib.Formatting.ProtoBuf │ ├── Properties │ └── AssemblyInfo.cs │ ├── ProtoBufFormatter.cs │ ├── WebApiContrib.Formatting.ProtoBuf.csproj │ ├── WebApiContrib.Formatting.ProtoBuf.nuspec │ └── packages.config ├── test └── WebApiContrib.Formatting.ProtoBuf.Test │ ├── EvilItem.cs │ ├── Item.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── ProtoBufFormatterTest.cs │ ├── WebApiContrib.Formatting.ProtoBuf.Test.csproj │ └── packages.config └── tools ├── nunit └── SimpleSummary.xslt └── psake ├── default.ps1 ├── psake.bat └── psake.psm1 /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text diff=csharp 17 | *.vb text 18 | *.c text 19 | *.cpp text 20 | *.cxx text 21 | *.h text 22 | *.hxx text 23 | *.py text 24 | *.rb text 25 | *.java text 26 | *.html text 27 | *.htm text 28 | *.css text 29 | *.scss text 30 | *.sass text 31 | *.less text 32 | *.js text 33 | *.lisp text 34 | *.clj text 35 | *.sql text 36 | *.php text 37 | *.lua text 38 | *.m text 39 | *.asm text 40 | *.erl text 41 | *.fs text 42 | *.fsx text 43 | *.hs text 44 | 45 | *.csproj text merge=union 46 | *.vbproj text merge=union 47 | *.fsproj text merge=union 48 | *.dbproj text merge=union 49 | *.sln text eol=crlf merge=union -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | [Bb]in 23 | [Dd]ebug*/ 24 | *.lib 25 | *.sbr 26 | obj/ 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* 30 | build/ 31 | deploy/ 32 | docs/ 33 | nuget/ 34 | packages/ 35 | *.nupkg 36 | -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebApiContrib/WebApiContrib.Formatting.ProtoBuf/7f24399e55761f6778a228722e2b1b314559cea0/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 6 | $(NuGetToolsPath)\nuget.exe 7 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 8 | $([System.IO.Path]::Combine($(SolutionDir), "packages")) 9 | $(TargetDir.Trim('\\')) 10 | 11 | 12 | "" 13 | 14 | 15 | false 16 | 17 | 18 | false 19 | 20 | 21 | "$(NuGetExePath)" install "$(PackagesConfig)" -source $(PackageSources) -o "$(PackagesDir)" 22 | "$(NuGetExePath)" pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols 23 | 24 | 25 | 26 | RestorePackages; 27 | $(BuildDependsOn); 28 | 29 | 30 | 31 | 32 | $(BuildDependsOn); 33 | BuildPackage; 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 51 | 52 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2012 Pedro Reys, Chris Missal, Headspring and other contributors 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /WebAPIContrib.Formatting.ProtoBuf.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{4C93B8FC-96F9-47BA-9380-753847F03E1C}" 7 | ProjectSection(SolutionItems) = preProject 8 | .nuget\NuGet.exe = .nuget\NuGet.exe 9 | .nuget\NuGet.targets = .nuget\NuGet.targets 10 | EndProjectSection 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApiContrib.Formatting.ProtoBuf", "src\WebApiContrib.Formatting.ProtoBuf\WebApiContrib.Formatting.ProtoBuf.csproj", "{2537E1C1-0212-4595-9F73-C0DEAE31BD62}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApiContrib.Formatting.ProtoBuf.Test", "test\WebApiContrib.Formatting.ProtoBuf.Test\WebApiContrib.Formatting.ProtoBuf.Test.csproj", "{29D92544-1A02-4042-9C3B-BDF6DA0325F0}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {2537E1C1-0212-4595-9F73-C0DEAE31BD62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {2537E1C1-0212-4595-9F73-C0DEAE31BD62}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {2537E1C1-0212-4595-9F73-C0DEAE31BD62}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {2537E1C1-0212-4595-9F73-C0DEAE31BD62}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {29D92544-1A02-4042-9C3B-BDF6DA0325F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {29D92544-1A02-4042-9C3B-BDF6DA0325F0}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {29D92544-1A02-4042-9C3B-BDF6DA0325F0}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {29D92544-1A02-4042-9C3B-BDF6DA0325F0}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.0\lib\NET35 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | echo off 2 | .\tools\psake\psake.bat %* -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | WebAPIContrib 2 | ============= 3 | 4 | Community Contributions for ASP.NET Web API 5 | 6 | http://webapicontrib.github.com/ -------------------------------------------------------------------------------- /src/WebApiContrib.Formatting.ProtoBuf/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebApiContrib.Formatting.ProtoBuf")] 9 | [assembly: AssemblyDescription("Description")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebApiContrib.Formatting.ProtoBuf")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d4d79666-983a-472d-b811-b0126601c3ca")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | [assembly: AssemblyVersion("0.9.5")] 33 | [assembly: AssemblyFileVersion("0.9.5")] 34 | -------------------------------------------------------------------------------- /src/WebApiContrib.Formatting.ProtoBuf/ProtoBufFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Net.Http.Formatting; 7 | using System.Net.Http.Headers; 8 | using System.Reflection; 9 | using System.Threading.Tasks; 10 | using ProtoBuf; 11 | using ProtoBuf.Meta; 12 | 13 | namespace WebApiContrib.Formatting 14 | { 15 | public class ProtoBufFormatter : MediaTypeFormatter 16 | { 17 | private static readonly MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/x-protobuf"); 18 | private static Lazy model = new Lazy(CreateTypeModel); 19 | 20 | public static RuntimeTypeModel Model 21 | { 22 | get { return model.Value; } 23 | } 24 | 25 | public ProtoBufFormatter() 26 | { 27 | SupportedMediaTypes.Add(mediaType); 28 | } 29 | 30 | public static MediaTypeHeaderValue DefaultMediaType 31 | { 32 | get { return mediaType; } 33 | } 34 | 35 | public override bool CanReadType(Type type) 36 | { 37 | return CanReadTypeCore(type); 38 | } 39 | 40 | public override bool CanWriteType(Type type) 41 | { 42 | return CanReadTypeCore(type); 43 | } 44 | 45 | public override Task ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger) 46 | { 47 | var tcs = new TaskCompletionSource(); 48 | 49 | try 50 | { 51 | object result = Model.Deserialize(stream, null, type); 52 | tcs.SetResult(result); 53 | } 54 | catch (Exception ex) 55 | { 56 | tcs.SetException(ex); 57 | } 58 | 59 | return tcs.Task; 60 | } 61 | 62 | public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) 63 | { 64 | var tcs = new TaskCompletionSource(); 65 | 66 | try 67 | { 68 | Model.Serialize(stream, value); 69 | tcs.SetResult(null); 70 | } 71 | catch (Exception ex) 72 | { 73 | tcs.SetException(ex); 74 | } 75 | 76 | return tcs.Task; 77 | } 78 | 79 | private static RuntimeTypeModel CreateTypeModel() 80 | { 81 | var typeModel = RuntimeTypeModel.Create(); 82 | typeModel.UseImplicitZeroDefaults = false; 83 | return typeModel; 84 | } 85 | 86 | private static bool CanReadTypeCore(Type type) 87 | { 88 | return type.GetCustomAttributes(typeof(ProtoContractAttribute)).Any(); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/WebApiContrib.Formatting.ProtoBuf/WebApiContrib.Formatting.ProtoBuf.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {2537E1C1-0212-4595-9F73-C0DEAE31BD62} 9 | Library 10 | Properties 11 | WebApiContrib.Formatting 12 | WebApiContrib.Formatting.ProtoBuf 13 | v4.6.1 14 | 512 15 | true 16 | ..\..\ 17 | 18 | 19 | 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | false 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | false 37 | 38 | 39 | 40 | ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 41 | 42 | 43 | ..\..\packages\protobuf-net.3.0.29\lib\net461\protobuf-net.dll 44 | 45 | 46 | ..\..\packages\protobuf-net.Core.3.0.29\lib\net461\protobuf-net.Core.dll 47 | 48 | 49 | 50 | ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll 51 | 52 | 53 | ..\..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll 54 | 55 | 56 | 57 | 58 | 59 | ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll 60 | 61 | 62 | 63 | ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll 64 | 65 | 66 | 67 | ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll 68 | 69 | 70 | ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll 71 | 72 | 73 | 74 | ..\..\packages\System.ServiceModel.Primitives.4.7.0\lib\net461\System.ServiceModel.Primitives.dll 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | Designer 85 | 86 | 87 | 88 | 89 | 90 | 97 | -------------------------------------------------------------------------------- /src/WebApiContrib.Formatting.ProtoBuf/WebApiContrib.Formatting.ProtoBuf.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | WebApiContrib Contributors 8 | ChrisMissal pedroreys panesofglass alexzeitler darrelmiller 9 | false 10 | $description$ 11 | https://github.com/WebApiContrib/WebApiContrib.Formatting.ProtoBuf 12 | https://raw.github.com/WebApiContrib/WebApiContrib.Formatting.ProtoBuf/master/LICENSE.txt 13 | Copyright © WebApiContrib 2012 - 2013 14 | webapi webapicontrib protobuf 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/WebApiContrib.Formatting.ProtoBuf/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/EvilItem.cs: -------------------------------------------------------------------------------- 1 | namespace WebApiContrib.Formatting.ProtoBuf.Test 2 | { 3 | public class EvilItem 4 | { 5 | 6 | public int Id { get; set; } 7 | 8 | public string Name { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/Item.cs: -------------------------------------------------------------------------------- 1 | using ProtoBuf; 2 | 3 | namespace WebApiContrib.Formatting.ProtoBuf.Test 4 | { 5 | [ProtoContract] 6 | public class Item 7 | { 8 | [ProtoMember(1)] 9 | public int Id { get; set; } 10 | [ProtoMember(2)] 11 | public string Name { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebApiContrib.Formatting.ProtoBuf.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WebApiContrib.Formatting.ProtoBuf.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("3d12ff72-351e-4adb-9168-c0c165e01617")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/ProtoBufFormatterTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Net.Http.Formatting; 6 | using Moq; 7 | using Xunit; 8 | 9 | namespace WebApiContrib.Formatting.ProtoBuf.Test 10 | { 11 | public class ProtoBufFormatterTest 12 | { 13 | [Fact] 14 | public void WhenInvokedContentShouldNotThrow() 15 | { 16 | var item = new Item { Id = 1, Name = "Filip" }; 17 | Assert.DoesNotThrow(() => new ObjectContent(item, new ProtoBufFormatter())); 18 | } 19 | 20 | [Fact] 21 | public void WhenInvokedWithUnsupportedTypeContentShouldEmpty() 22 | { 23 | var item = new EvilItem { Id = 1, Name = "Filip" }; 24 | Assert.Throws(() => new ObjectContent(item, new ProtoBufFormatter())); 25 | } 26 | 27 | [Fact] 28 | public void WhenInvokedContentHeadersShouldBeSetCorrectly() 29 | { 30 | var item = new Item { Id = 1, Name = "Filip" }; 31 | var content = new ObjectContent(item, new ProtoBufFormatter()); 32 | 33 | Assert.Equal("application/x-protobuf", content.Headers.ContentType.MediaType); 34 | } 35 | 36 | [Fact] 37 | public async void WhenUsedToDeserializeShouldCreateCorrectObject() 38 | { 39 | var formatter = new ProtoBufFormatter(); 40 | var item = new Item { Id = 1, Name = "Filip" }; 41 | var content = new ObjectContent(item, formatter); 42 | 43 | var deserializedItem = await content.ReadAsAsync(new[] { formatter }); 44 | Assert.Same(item, deserializedItem); 45 | } 46 | 47 | [Fact] 48 | public void WhenCallingCanReadShouldNotBeAbleToReadTypesItDoesNotUnderstand() 49 | { 50 | var formatter = new ProtoBufFormatter(); 51 | var canRead = formatter.CanReadType(typeof(EvilItem)); 52 | Assert.False(canRead); 53 | } 54 | 55 | [Fact] 56 | public void WhenCallingCanWriteShouldNotBeAbleToWriteTypesItDoesNotUnderstand() 57 | { 58 | var formatter = new ProtoBufFormatter(); 59 | var canWrite = formatter.CanWriteType(typeof(EvilItem)); 60 | Assert.False(canWrite); 61 | } 62 | 63 | [Fact] 64 | public void WhenCallingCanReadShouldBeAbleToReadTypesItUnderstands() 65 | { 66 | var formatter = new ProtoBufFormatter(); 67 | var canRead = formatter.CanReadType(typeof(Item)); 68 | Assert.True(canRead); 69 | } 70 | 71 | [Fact] 72 | public void WhenCallingCanWriteShouldBeAbleToWriteTypesItUnderstands() 73 | { 74 | var formatter = new ProtoBufFormatter(); 75 | var canWrite = formatter.CanWriteType(typeof(Item)); 76 | Assert.True(canWrite); 77 | } 78 | 79 | [Fact] 80 | public async void WhenWritingToStreamShouldSuccessfullyComplete() 81 | { 82 | var formatter = new ProtoBufFormatter(); 83 | var item = new Item { Id = 1, Name = "Filip" }; 84 | 85 | var ms = new MemoryStream(); 86 | await formatter.WriteToStreamAsync(typeof(Item), item, ms, new ByteArrayContent(new byte[0]), 87 | new Mock().Object); 88 | 89 | var deserialized = ProtoBufFormatter.Model.Deserialize(ms, null, typeof(Item)); 90 | 91 | Assert.Same(deserialized, item); 92 | } 93 | 94 | [Fact] 95 | public async void WhenReadingFromStreamShouldSuccessfullyComplete() 96 | { 97 | var formatter = new ProtoBufFormatter(); 98 | var item = new Item { Id = 1, Name = "Filip" }; 99 | 100 | var ms = new MemoryStream(); 101 | ProtoBufFormatter.Model.Serialize(ms, item); 102 | 103 | var deserialized = await formatter.ReadFromStreamAsync(typeof(Item), ms, new ByteArrayContent(new byte[0]), 104 | new Mock().Object); 105 | 106 | Assert.Same(deserialized as Item, item); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/WebApiContrib.Formatting.ProtoBuf.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {29D92544-1A02-4042-9C3B-BDF6DA0325F0} 8 | Library 9 | Properties 10 | WebApiContrib.Formatting.ProtoBuf.Test 11 | WebApiContrib.Formatting.ProtoBuf.Test 12 | v4.6.1 13 | 512 14 | ..\..\ 15 | true 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\..\packages\Moq.4.2.1312.1622\lib\net40\Moq.dll 38 | 39 | 40 | ..\..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll 41 | 42 | 43 | ..\..\packages\protobuf-net.3.0.29\lib\net461\protobuf-net.dll 44 | 45 | 46 | ..\..\packages\protobuf-net.Core.3.0.29\lib\net461\protobuf-net.Core.dll 47 | 48 | 49 | 50 | ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll 51 | 52 | 53 | ..\..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll 54 | 55 | 56 | 57 | 58 | 59 | ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll 60 | 61 | 62 | 63 | ..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll 64 | 65 | 66 | 67 | ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll 68 | 69 | 70 | ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll 71 | 72 | 73 | 74 | ..\..\packages\System.ServiceModel.Primitives.4.7.0\lib\net461\System.ServiceModel.Primitives.dll 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | ..\..\packages\xunit.1.9.2\lib\net20\xunit.dll 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | {2537e1c1-0212-4595-9f73-c0deae31bd62} 98 | WebApiContrib.Formatting.ProtoBuf 99 | 100 | 101 | 102 | 103 | 110 | -------------------------------------------------------------------------------- /test/WebApiContrib.Formatting.ProtoBuf.Test/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tools/nunit/SimpleSummary.xslt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Tests run: 11 | 12 | , Errors: 13 | 14 | , Failures: 15 | 16 | , Not run: 17 | 18 | , Time: 19 | 20 | seconds 21 | 22 | 23 | 24 | 25 | 26 | Failures: 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Tests not run: 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ) 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /tools/psake/default.ps1: -------------------------------------------------------------------------------- 1 | Properties { 2 | $base_dir = resolve-path .\..\..\ 3 | $packages_dir = "$base_dir\packages" 4 | $build_artifacts_dir = "$base_dir\build" 5 | $solution_name = "$base_dir\WebApiContrib.Formatting.ProtoBuf.sln" 6 | $test_dll = "$build_artifacts_dir\WebApiContrib.Formatting.ProtoBuf.Tests.dll" 7 | $nunit_runner = "$packages_dir\NUnit.Runners.2.6.0.12051\tools" 8 | $nunit_build_destination = "$build_artifacts_dir\tools\nunit" 9 | $nunitConsole = "$nunit_build_destination\nunit-console.exe" 10 | $nuget_exe = "$base_dir\.nuget\Nuget.exe" 11 | } 12 | 13 | Task Default -Depends BuildWebApiContrib, NuGetBuild #, PrepareForTest, RunUnitTests 14 | 15 | Task BuildWebApiContrib -Depends Clean, Build 16 | 17 | Task Clean { 18 | Exec { msbuild $solution_name /v:Quiet /t:Clean /p:Configuration=Release } 19 | } 20 | 21 | Task Build -depends Clean { 22 | Exec { msbuild $solution_name /v:Quiet /t:Build /p:Configuration=Release /p:OutDir=$build_artifacts_dir\ } 23 | } 24 | 25 | Task NuGetBuild -depends Clean { 26 | & $nuget_exe pack "$base_dir/src/WebApiContrib.Formatting.ProtoBuf/WebApiContrib.Formatting.ProtoBuf.csproj" -Build -OutputDirectory $build_artifacts_dir -Verbose -Properties Configuration=Release 27 | } 28 | 29 | Task PrepareForTest { 30 | $tools_folder = "$build_artifacts_dir\tools" 31 | if (Test-Path $tools_folder) { 32 | Remove-Item $tools_folder -Force -Recurse 33 | } 34 | Copy-Item "$nunit_runner\*" $nunit_build_destination 35 | Copy-Item "$nunit_runner\lib\*" "$nunit_build_destination\lib" 36 | } 37 | 38 | Task RunUnitTests -depends PrepareForTest, Build { 39 | $test_result = "$build_artifacts_dir\UnitTestsResult.xml" 40 | 41 | & "$nunitConsole" "$test_dll" /nologo /nodots "/xml=$test_result" 42 | 43 | if ($lastexitcode -gt 0) 44 | { 45 | throw "{0} unit tests failed. See {1} for a simple summary." -f $lastexitcode, $test_result 46 | } 47 | if ($lastexitcode -lt 0) 48 | { 49 | throw "unit test run was terminated by a fatal error. See {0} for a simple summary." -f $test_result 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tools/psake/psake.bat: -------------------------------------------------------------------------------- 1 | powershell.exe -NoProfile -ExecutionPolicy unrestricted -Command "& {Import-Module '.\tools\psake\psake.psm1'; invoke-psake .\tools\psake\default.ps1 %1 -parameters @{"version"="'%2'";"appPrefix"="'%3'";"filePath"="'%4'"}; if ($lastexitcode -ne 0) {write-host "ERROR: $lastexitcode" -fore RED; exit $lastexitcode} }" -------------------------------------------------------------------------------- /tools/psake/psake.psm1: -------------------------------------------------------------------------------- 1 | # psake 2 | # Copyright (c) 2010 James Kovacs 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # The above copyright notice and this permission notice shall be included in 11 | # all copies or substantial portions of the Software. 12 | # 13 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | # THE SOFTWARE. 20 | 21 | #Requires -Version 2.0 22 | 23 | #-- Public Module Functions --# 24 | 25 | # .ExternalHelp psake.psm1-help.xml 26 | function Invoke-Task 27 | { 28 | [CmdletBinding()] 29 | param( 30 | [Parameter(Position=0,Mandatory=1)] [string]$taskName 31 | ) 32 | 33 | Assert $taskName ($msgs.error_invalid_task_name) 34 | 35 | $taskKey = $taskName.ToLower() 36 | 37 | if ($currentContext.aliases.Contains($taskKey)) { 38 | $taskName = $currentContext.aliases.$taskKey.Name 39 | $taskKey = $taskName.ToLower() 40 | } 41 | 42 | $currentContext = $psake.context.Peek() 43 | 44 | Assert ($currentContext.tasks.Contains($taskKey)) ($msgs.error_task_name_does_not_exist -f $taskName) 45 | 46 | if ($currentContext.executedTasks.Contains($taskKey)) { return } 47 | 48 | Assert (!$currentContext.callStack.Contains($taskKey)) ($msgs.error_circular_reference -f $taskName) 49 | 50 | $currentContext.callStack.Push($taskKey) 51 | 52 | $task = $currentContext.tasks.$taskKey 53 | 54 | $precondition_is_valid = & $task.Precondition 55 | 56 | if (!$precondition_is_valid) { 57 | Write-ColoredOutput ($msgs.precondition_was_false -f $taskName) -foregroundcolor Cyan 58 | } else { 59 | if ($taskKey -ne 'default') { 60 | 61 | if ($task.PreAction -or $task.PostAction) { 62 | Assert ($task.Action -ne $null) ($msgs.error_missing_action_parameter -f $taskName) 63 | } 64 | 65 | if ($task.Action) { 66 | try { 67 | foreach($childTask in $task.DependsOn) { 68 | Invoke-Task $childTask 69 | } 70 | 71 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() 72 | $currentContext.currentTaskName = $taskName 73 | 74 | & $currentContext.taskSetupScriptBlock 75 | 76 | if ($task.PreAction) { 77 | & $task.PreAction 78 | } 79 | 80 | if ($currentContext.config.taskNameFormat -is [ScriptBlock]) { 81 | & $currentContext.config.taskNameFormat $taskName 82 | } else { 83 | Write-ColoredOutput ($currentContext.config.taskNameFormat -f $taskName) -foregroundcolor Cyan 84 | } 85 | 86 | foreach ($variable in $task.requiredVariables) { 87 | Assert ((test-path "variable:$variable") -and ((get-variable $variable).Value -ne $null)) ($msgs.required_variable_not_set -f $variable, $taskName) 88 | } 89 | 90 | & $task.Action 91 | 92 | if ($task.PostAction) { 93 | & $task.PostAction 94 | } 95 | 96 | & $currentContext.taskTearDownScriptBlock 97 | $task.Duration = $stopwatch.Elapsed 98 | } catch { 99 | if ($task.ContinueOnError) { 100 | "-"*70 101 | Write-ColoredOutput ($msgs.continue_on_error -f $taskName,$_) -foregroundcolor Yellow 102 | "-"*70 103 | $task.Duration = $stopwatch.Elapsed 104 | } else { 105 | throw $_ 106 | } 107 | } 108 | } else { 109 | # no action was specified but we still execute all the dependencies 110 | foreach($childTask in $task.DependsOn) { 111 | Invoke-Task $childTask 112 | } 113 | } 114 | } else { 115 | foreach($childTask in $task.DependsOn) { 116 | Invoke-Task $childTask 117 | } 118 | } 119 | 120 | Assert (& $task.Postcondition) ($msgs.postcondition_failed -f $taskName) 121 | } 122 | 123 | $poppedTaskKey = $currentContext.callStack.Pop() 124 | Assert ($poppedTaskKey -eq $taskKey) ($msgs.error_corrupt_callstack -f $taskKey,$poppedTaskKey) 125 | 126 | $currentContext.executedTasks.Push($taskKey) 127 | } 128 | 129 | # .ExternalHelp psake.psm1-help.xml 130 | function Exec 131 | { 132 | [CmdletBinding()] 133 | param( 134 | [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd, 135 | [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd) 136 | ) 137 | & $cmd 138 | if ($lastexitcode -ne 0) { 139 | throw ("Exec: " + $errorMessage) 140 | } 141 | } 142 | 143 | # .ExternalHelp psake.psm1-help.xml 144 | function Assert 145 | { 146 | [CmdletBinding()] 147 | param( 148 | [Parameter(Position=0,Mandatory=1)]$conditionToCheck, 149 | [Parameter(Position=1,Mandatory=1)]$failureMessage 150 | ) 151 | if (!$conditionToCheck) { 152 | throw ("Assert: " + $failureMessage) 153 | } 154 | } 155 | 156 | # .ExternalHelp psake.psm1-help.xml 157 | function Task 158 | { 159 | [CmdletBinding()] 160 | param( 161 | [Parameter(Position=0,Mandatory=1)][string]$name = $null, 162 | [Parameter(Position=1,Mandatory=0)][scriptblock]$action = $null, 163 | [Parameter(Position=2,Mandatory=0)][scriptblock]$preaction = $null, 164 | [Parameter(Position=3,Mandatory=0)][scriptblock]$postaction = $null, 165 | [Parameter(Position=4,Mandatory=0)][scriptblock]$precondition = {$true}, 166 | [Parameter(Position=5,Mandatory=0)][scriptblock]$postcondition = {$true}, 167 | [Parameter(Position=6,Mandatory=0)][switch]$continueOnError = $false, 168 | [Parameter(Position=7,Mandatory=0)][string[]]$depends = @(), 169 | [Parameter(Position=8,Mandatory=0)][string[]]$requiredVariables = @(), 170 | [Parameter(Position=9,Mandatory=0)][string]$description = $null, 171 | [Parameter(Position=10,Mandatory=0)][string]$alias = $null 172 | ) 173 | if ($name -eq 'default') { 174 | Assert (!$action) ($msgs.error_default_task_cannot_have_action) 175 | } 176 | 177 | $newTask = @{ 178 | Name = $name 179 | DependsOn = $depends 180 | PreAction = $preaction 181 | Action = $action 182 | PostAction = $postaction 183 | Precondition = $precondition 184 | Postcondition = $postcondition 185 | ContinueOnError = $continueOnError 186 | Description = $description 187 | Duration = [System.TimeSpan]::Zero 188 | RequiredVariables = $requiredVariables 189 | Alias = $alias 190 | } 191 | 192 | $taskKey = $name.ToLower() 193 | 194 | $currentContext = $psake.context.Peek() 195 | 196 | Assert (!$currentContext.tasks.ContainsKey($taskKey)) ($msgs.error_duplicate_task_name -f $name) 197 | 198 | $currentContext.tasks.$taskKey = $newTask 199 | 200 | if($alias) 201 | { 202 | $aliasKey = $alias.ToLower() 203 | 204 | Assert (!$currentContext.aliases.ContainsKey($aliasKey)) ($msgs.error_duplicate_alias_name -f $alias) 205 | 206 | $currentContext.aliases.$aliasKey = $newTask 207 | } 208 | } 209 | 210 | # .ExternalHelp psake.psm1-help.xml 211 | function Properties { 212 | [CmdletBinding()] 213 | param( 214 | [Parameter(Position=0,Mandatory=1)][scriptblock]$properties 215 | ) 216 | $psake.context.Peek().properties += $properties 217 | } 218 | 219 | # .ExternalHelp psake.psm1-help.xml 220 | function Include { 221 | [CmdletBinding()] 222 | param( 223 | [Parameter(Position=0,Mandatory=1)][string]$fileNamePathToInclude 224 | ) 225 | Assert (test-path $fileNamePathToInclude -pathType Leaf) ($msgs.error_invalid_include_path -f $fileNamePathToInclude) 226 | $psake.context.Peek().includes.Enqueue((Resolve-Path $fileNamePathToInclude)); 227 | } 228 | 229 | # .ExternalHelp psake.psm1-help.xml 230 | function FormatTaskName { 231 | [CmdletBinding()] 232 | param( 233 | [Parameter(Position=0,Mandatory=1)]$format 234 | ) 235 | $psake.context.Peek().config.taskNameFormat = $format 236 | } 237 | 238 | # .ExternalHelp psake.psm1-help.xml 239 | function TaskSetup { 240 | [CmdletBinding()] 241 | param( 242 | [Parameter(Position=0,Mandatory=1)][scriptblock]$setup 243 | ) 244 | $psake.context.Peek().taskSetupScriptBlock = $setup 245 | } 246 | 247 | # .ExternalHelp psake.psm1-help.xml 248 | function TaskTearDown { 249 | [CmdletBinding()] 250 | param( 251 | [Parameter(Position=0,Mandatory=1)][scriptblock]$teardown 252 | ) 253 | $psake.context.Peek().taskTearDownScriptBlock = $teardown 254 | } 255 | 256 | # .ExternalHelp psake.psm1-help.xml 257 | function Framework { 258 | [CmdletBinding()] 259 | param( 260 | [Parameter(Position=0,Mandatory=1)][string]$framework 261 | ) 262 | $psake.context.Peek().config.framework = $framework 263 | } 264 | 265 | # .ExternalHelp psake.psm1-help.xml 266 | function Invoke-psake { 267 | [CmdletBinding()] 268 | param( 269 | [Parameter(Position = 0, Mandatory = 0)][string] $buildFile, 270 | [Parameter(Position = 1, Mandatory = 0)][string[]] $taskList = @(), 271 | [Parameter(Position = 2, Mandatory = 0)][string] $framework, 272 | [Parameter(Position = 3, Mandatory = 0)][switch] $docs = $false, 273 | [Parameter(Position = 4, Mandatory = 0)][hashtable] $parameters = @{}, 274 | [Parameter(Position = 5, Mandatory = 0)][hashtable] $properties = @{}, 275 | [Parameter(Position = 6, Mandatory = 0)][switch] $nologo = $false 276 | ) 277 | try { 278 | if (-not $nologo) { 279 | "psake version {0}`nCopyright (c) 2010 James Kovacs`n" -f $psake.version 280 | } 281 | 282 | # If the default.ps1 file exists and the given "buildfile" isn 't found assume that the given 283 | # $buildFile is actually the target Tasks to execute in the default.ps1 script. 284 | if ($buildFile -and !(test-path $buildFile -pathType Leaf) -and (test-path $psake.config_default.buildFileName -pathType Leaf)) { 285 | $taskList = $buildFile.Split(', ') 286 | $buildFile = $psake.config_default.buildFileName 287 | } 288 | 289 | # Execute the build file to set up the tasks and defaults 290 | Assert (test-path $buildFile -pathType Leaf) ($msgs.error_build_file_not_found -f $buildFile) 291 | 292 | $psake.build_script_file = get-item $buildFile 293 | $psake.build_script_dir = $psake.build_script_file.DirectoryName 294 | $psake.build_success = $false 295 | 296 | $psake.context.push(@{ 297 | "taskSetupScriptBlock" = {}; 298 | "taskTearDownScriptBlock" = {}; 299 | "executedTasks" = new-object System.Collections.Stack; 300 | "callStack" = new-object System.Collections.Stack; 301 | "originalEnvPath" = $env:path; 302 | "originalDirectory" = get-location; 303 | "originalErrorActionPreference" = $global:ErrorActionPreference; 304 | "tasks" = @{}; 305 | "aliases" = @{}; 306 | "properties" = @(); 307 | "includes" = new-object System.Collections.Queue; 308 | "config" = Create-ConfigurationForNewContext $buildFile $framework 309 | }) 310 | 311 | Load-Configuration $psake.build_script_dir 312 | 313 | Load-Modules 314 | 315 | $stopwatch = [System.Diagnostics.Stopwatch]::StartNew() 316 | 317 | set-location $psake.build_script_dir 318 | 319 | $frameworkOldValue = $framework 320 | . $psake.build_script_file.FullName 321 | 322 | $currentContext = $psake.context.Peek() 323 | 324 | if ($framework -ne $frameworkOldValue) { 325 | write-coloredoutput $msgs.warning_deprecated_framework_variable -foregroundcolor Yellow 326 | $currentContext.config.framework = $framework 327 | } 328 | 329 | if ($docs) { 330 | Write-Documentation 331 | Cleanup-Environment 332 | return 333 | } 334 | 335 | Configure-BuildEnvironment 336 | 337 | while ($currentContext.includes.Count -gt 0) { 338 | $includeFilename = $currentContext.includes.Dequeue() 339 | . $includeFilename 340 | } 341 | 342 | foreach ($key in $parameters.keys) { 343 | if (test-path "variable:\$key") { 344 | set-item -path "variable:\$key" -value $parameters.$key | out-null 345 | } else { 346 | new-item -path "variable:\$key" -value $parameters.$key | out-null 347 | } 348 | } 349 | 350 | # The initial dot (.) indicates that variables initialized/modified in the propertyBlock are available in the parent scope. 351 | foreach ($propertyBlock in $currentContext.properties) { 352 | . $propertyBlock 353 | } 354 | 355 | foreach ($key in $properties.keys) { 356 | if (test-path "variable:\$key") { 357 | set-item -path "variable:\$key" -value $properties.$key | out-null 358 | } 359 | } 360 | 361 | # Execute the list of tasks or the default task 362 | if ($taskList) { 363 | foreach ($task in $taskList) { 364 | invoke-task $task 365 | } 366 | } elseif ($currentContext.tasks.default) { 367 | invoke-task default 368 | } else { 369 | throw $msgs.error_no_default_task 370 | } 371 | 372 | Write-ColoredOutput ("`n" + $msgs.build_success + "`n") -foregroundcolor Green 373 | 374 | Write-TaskTimeSummary $stopwatch.Elapsed 375 | 376 | $psake.build_success = $true 377 | } catch { 378 | $currentConfig = Get-CurrentConfigurationOrDefault 379 | if ($currentConfig.verboseError) { 380 | $error_message = "{0}: An Error Occurred. See Error Details Below: `n" -f (Get-Date) 381 | $error_message += ("-" * 70) + "`n" 382 | $error_message += Resolve-Error $_ 383 | $error_message += ("-" * 70) + "`n" 384 | $error_message += "Script Variables" + "`n" 385 | $error_message += ("-" * 70) + "`n" 386 | $error_message += get-variable -scope script | format-table | out-string 387 | } else { 388 | # ($_ | Out-String) gets error messages with source information included. 389 | $error_message = "{0}: An Error Occurred: `n{1}" -f (Get-Date), ($_ | Out-String) 390 | } 391 | 392 | $psake.build_success = $false 393 | 394 | if (!$psake.run_by_psake_build_tester) { 395 | # if we are running in a nested scope (i.e. running a psake script from a psake script) then we need to re-throw the exception 396 | # so that the parent script will fail otherwise the parent script will report a successful build 397 | $inNestedScope = ($psake.context.count -gt 1) 398 | if ( $inNestedScope ) { 399 | throw $_ 400 | } else { 401 | Write-ColoredOutput $error_message -foregroundcolor Red 402 | } 403 | 404 | } 405 | } finally { 406 | Cleanup-Environment 407 | } 408 | } 409 | 410 | #-- Private Module Functions --# 411 | function Write-ColoredOutput { 412 | param( 413 | [string] $message, 414 | [System.ConsoleColor] $foregroundcolor 415 | ) 416 | 417 | $currentConfig = Get-CurrentConfigurationOrDefault 418 | if ($currentConfig.coloredOutput -eq $true) { 419 | if (($Host.UI -ne $null) -and ($Host.UI.RawUI -ne $null)) { 420 | $previousColor = $Host.UI.RawUI.ForegroundColor 421 | $Host.UI.RawUI.ForegroundColor = $foregroundcolor 422 | } 423 | } 424 | 425 | $message 426 | 427 | if ($previousColor -ne $null) { 428 | $Host.UI.RawUI.ForegroundColor = $previousColor 429 | } 430 | } 431 | 432 | function Load-Modules { 433 | $currentConfig = $psake.context.peek().config 434 | if ($currentConfig.modules) { 435 | $currentConfig.modules | foreach { 436 | resolve-path $_ | foreach { 437 | "Loading module: $_" 438 | $module = import-module $_ -passthru 439 | if (!$module) { 440 | throw ($msgs.error_loading_module -f $_.Name) 441 | } 442 | } 443 | } 444 | "" 445 | } 446 | } 447 | 448 | function Load-Configuration { 449 | param( 450 | [string] $configdir = $PSScriptRoot 451 | ) 452 | 453 | $psakeConfigFilePath = (join-path $configdir "psake-config.ps1") 454 | 455 | if (test-path $psakeConfigFilePath -pathType Leaf) { 456 | try { 457 | $config = Get-CurrentConfigurationOrDefault 458 | . $psakeConfigFilePath 459 | } catch { 460 | throw "Error Loading Configuration from psake-config.ps1: " + $_ 461 | } 462 | } 463 | } 464 | 465 | function Get-CurrentConfigurationOrDefault() { 466 | if ($psake.context.count -gt 0) { 467 | return $psake.context.peek().config 468 | } else { 469 | return $psake.config_default 470 | } 471 | } 472 | 473 | function Create-ConfigurationForNewContext { 474 | param( 475 | [string] $buildFile, 476 | [string] $framework 477 | ) 478 | 479 | $previousConfig = Get-CurrentConfigurationOrDefault 480 | 481 | $config = new-object psobject -property @{ 482 | buildFileName = $previousConfig.buildFileName; 483 | framework = $previousConfig.framework; 484 | taskNameFormat = $previousConfig.taskNameFormat; 485 | verboseError = $previousConfig.verboseError; 486 | coloredOutput = $previousConfig.coloredOutput; 487 | modules = $previousConfig.modules 488 | } 489 | 490 | if ($framework) { 491 | $config.framework = $framework; 492 | } 493 | 494 | if ($buildFile) { 495 | $config.buildFileName = $buildFile; 496 | } 497 | 498 | return $config 499 | } 500 | 501 | function Configure-BuildEnvironment { 502 | $framework = $psake.context.peek().config.framework 503 | if ($framework.Length -ne 3 -and $framework.Length -ne 6) { 504 | throw ($msgs.error_invalid_framework -f $framework) 505 | } 506 | $versionPart = $framework.Substring(0, 3) 507 | $bitnessPart = $framework.Substring(3) 508 | $versions = $null 509 | switch ($versionPart) { 510 | '1.0' { 511 | $versions = @('v1.0.3705') 512 | } 513 | '1.1' { 514 | $versions = @('v1.1.4322') 515 | } 516 | '2.0' { 517 | $versions = @('v2.0.50727') 518 | } 519 | '3.0' { 520 | $versions = @('v2.0.50727') 521 | } 522 | '3.5' { 523 | $versions = @('v3.5', 'v2.0.50727') 524 | } 525 | '4.0' { 526 | $versions = @('v4.0.30319') 527 | } 528 | default { 529 | throw ($msgs.error_unknown_framework -f $versionPart, $framework) 530 | } 531 | } 532 | 533 | $bitness = 'Framework' 534 | if ($versionPart -ne '1.0' -and $versionPart -ne '1.1') { 535 | switch ($bitnessPart) { 536 | 'x86' { 537 | $bitness = 'Framework' 538 | } 539 | 'x64' { 540 | $bitness = 'Framework64' 541 | } 542 | { [string]::IsNullOrEmpty($_) } { 543 | $ptrSize = [System.IntPtr]::Size 544 | switch ($ptrSize) { 545 | 4 { 546 | $bitness = 'Framework' 547 | } 548 | 8 { 549 | $bitness = 'Framework64' 550 | } 551 | default { 552 | throw ($msgs.error_unknown_pointersize -f $ptrSize) 553 | } 554 | } 555 | } 556 | default { 557 | throw ($msgs.error_unknown_bitnesspart -f $bitnessPart, $framework) 558 | } 559 | } 560 | } 561 | $frameworkDirs = $versions | foreach { "$env:windir\Microsoft.NET\$bitness\$_\" } 562 | 563 | $frameworkDirs | foreach { Assert (test-path $_ -pathType Container) ($msgs.error_no_framework_install_dir_found -f $_)} 564 | 565 | $env:path = ($frameworkDirs -join ";") + ";$env:path" 566 | # if any error occurs in a PS function then "stop" processing immediately 567 | # this does not effect any external programs that return a non-zero exit code 568 | $global:ErrorActionPreference = "Stop" 569 | } 570 | 571 | function Cleanup-Environment { 572 | if ($psake.context.Count -gt 0) { 573 | $currentContext = $psake.context.Peek() 574 | $env:path = $currentContext.originalEnvPath 575 | Set-Location $currentContext.originalDirectory 576 | $global:ErrorActionPreference = $currentContext.originalErrorActionPreference 577 | [void] $psake.context.Pop() 578 | } 579 | } 580 | 581 | # borrowed from Jeffrey Snover http://blogs.msdn.com/powershell/archive/2006/12/07/resolve-error.aspx 582 | function Resolve-Error($ErrorRecord = $Error[0]) { 583 | $error_message = "`nErrorRecord:{0}ErrorRecord.InvocationInfo:{1}Exception:{2}" 584 | $formatted_errorRecord = $ErrorRecord | format-list * -force | out-string 585 | $formatted_invocationInfo = $ErrorRecord.InvocationInfo | format-list * -force | out-string 586 | $formatted_exception = "" 587 | $Exception = $ErrorRecord.Exception 588 | for ($i = 0; $Exception; $i++, ($Exception = $Exception.InnerException)) { 589 | $formatted_exception += ("$i" * 70) + "`n" 590 | $formatted_exception += $Exception | format-list * -force | out-string 591 | $formatted_exception += "`n" 592 | } 593 | 594 | return $error_message -f $formatted_errorRecord, $formatted_invocationInfo, $formatted_exception 595 | } 596 | 597 | function Write-Documentation { 598 | $currentContext = $psake.context.Peek() 599 | 600 | if ($currentContext.tasks.default) { 601 | $defaultTaskDependencies = $currentContext.tasks.default.DependsOn 602 | } else { 603 | $defaultTaskDependencies = @() 604 | } 605 | 606 | $currentContext.tasks.Keys | foreach-object { 607 | if ($_ -eq "default") { 608 | return 609 | } 610 | 611 | $task = $currentContext.tasks.$_ 612 | new-object PSObject -property @{ 613 | Name = $task.Name; 614 | Description = $task.Description; 615 | "Depends On" = $task.DependsOn -join ", " 616 | Default = if ($defaultTaskDependencies -contains $task.Name) { $true } 617 | } 618 | } | sort 'Name' | format-table -autoSize -property Name,Description,"Depends On",Default 619 | } 620 | 621 | function Write-TaskTimeSummary($invokePsakeDuration) { 622 | "-" * 70 623 | "Build Time Report" 624 | "-" * 70 625 | $list = @() 626 | $currentContext = $psake.context.Peek() 627 | while ($currentContext.executedTasks.Count -gt 0) { 628 | $taskKey = $currentContext.executedTasks.Pop() 629 | $task = $currentContext.tasks.$taskKey 630 | if ($taskKey -eq "default") { 631 | continue 632 | } 633 | $list += new-object PSObject -property @{ 634 | Name = $task.Name; 635 | Duration = $task.Duration 636 | } 637 | } 638 | [Array]::Reverse($list) 639 | $list += new-object PSObject -property @{ 640 | Name = "Total:"; 641 | Duration = $invokePsakeDuration 642 | } 643 | # using "out-string | where-object" to filter out the blank line that format-table prepends 644 | $list | format-table -autoSize -property Name,Duration | out-string -stream | where-object { $_ } 645 | } 646 | 647 | DATA msgs { 648 | convertfrom-stringdata @' 649 | error_invalid_task_name = Task name should not be null or empty string. 650 | error_task_name_does_not_exist = Task {0} does not exist. 651 | error_circular_reference = Circular reference found for task {0}. 652 | error_missing_action_parameter = Action parameter must be specified when using PreAction or PostAction parameters for task {0}. 653 | error_corrupt_callstack = Call stack was corrupt. Expected {0}, but got {1}. 654 | error_invalid_framework = Invalid .NET Framework version, {0} specified. 655 | error_unknown_framework = Unknown .NET Framework version, {0} specified in {1}. 656 | error_unknown_pointersize = Unknown pointer size ({0}) returned from System.IntPtr. 657 | error_unknown_bitnesspart = Unknown .NET Framework bitness, {0}, specified in {1}. 658 | error_no_framework_install_dir_found = No .NET Framework installation directory found at {0}. 659 | error_bad_command = Error executing command {0}. 660 | error_default_task_cannot_have_action = 'default' task cannot specify an action. 661 | error_duplicate_task_name = Task {0} has already been defined. 662 | error_duplicate_alias_name = Alias {0} has already been defined. 663 | error_invalid_include_path = Unable to include {0}. File not found. 664 | error_build_file_not_found = Could not find the build file {0}. 665 | error_no_default_task = 'default' task required. 666 | error_loading_module = Error loading module {0}. 667 | warning_deprecated_framework_variable = Warning: Using global variable $framework to set .NET framework version used is deprecated. Instead use Framework function or configuration file psake-config.ps1. 668 | required_variable_not_set = Variable {0} must be set to run task {1}. 669 | postcondition_failed = Postcondition failed for task {0}. 670 | precondition_was_false = Precondition was false, not executing task {0}. 671 | continue_on_error = Error in task {0}. {1} 672 | build_success = Build Succeeded! 673 | '@ 674 | } 675 | 676 | import-localizeddata -bindingvariable msgs -erroraction silentlycontinue 677 | 678 | $script:psake = @{} 679 | $psake.version = "4.1.0" # contains the current version of psake 680 | $psake.context = new-object system.collections.stack # holds onto the current state of all variables 681 | $psake.run_by_psake_build_tester = $false # indicates that build is being run by psake-BuildTester 682 | $psake.config_default = new-object psobject -property @{ 683 | buildFileName = "default.ps1"; 684 | framework = "4.0"; 685 | taskNameFormat = "Executing {0}"; 686 | verboseError = $false; 687 | coloredOutput = $true; 688 | modules = $null; 689 | } # contains default configuration, can be overriden in psake-config.ps1 in directory with psake.psm1 or in directory with current build script 690 | 691 | $psake.build_success = $false # indicates that the current build was successful 692 | $psake.build_script_file = $null # contains a System.IO.FileInfo for the current build script 693 | $psake.build_script_dir = "" # contains a string with fully-qualified path to current build script 694 | 695 | Load-Configuration 696 | 697 | export-modulemember -function invoke-psake, invoke-task, task, properties, include, formattaskname, tasksetup, taskteardown, framework, assert, exec -variable psake --------------------------------------------------------------------------------