├── .editorconfig
├── .gitattributes
├── .gitignore
├── Automation.StorageEmulator.sln
├── LICENSE.txt
├── NuGet.config
├── README.md
├── appveyor.yml
├── build.cmd
├── src
└── Core
│ ├── AzureStorageEmulatorAutomation.cs
│ ├── Core.csproj
│ └── ProcessHelper.cs
└── tests
└── Core.Tests
├── AzureStorageEmulatorAutomationTests.cs
├── Core.Tests.csproj
├── StopAzureStorageEmulatorFixture.cs
└── TestHelper.cs
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 | # Get the Visual Studio extension: http://visualstudiogallery.msdn.microsoft.com/c8bccfe2-650c-4b42-bc5c-845e21f96328
3 |
4 | # Top-most EditorConfig file
5 | root = true
6 |
7 | # Unix-style newlines with a newline ending every file
8 | [*]
9 | insert_final_newline = true
10 |
11 | [*.bat]
12 | end_of_line = crlf
13 |
14 | [*.cmd]
15 | end_of_line = crlf
16 |
17 | [*.cs]
18 | indent_style = space
19 | indent_size = 4
20 |
21 | # Visual Studio will trim newlines from the end of a file
22 | [*.csproj]
23 | end_of_line = crlf
24 | insert_final_newline = false
25 |
26 | [*.sln]
27 | end_of_line = crlf
28 | insert_final_newline = false
29 |
30 | [*.sql]
31 | end_of_line = crlf
32 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
3 | *.bat text=auto eol=crlf
4 | *.cmd text=auto eol=crlf
5 | *.config text=auto
6 | *.cs text=auto diff=csharp
7 | *.cshtml text=auto
8 | *.css text=auto
9 | *.htm text=auto
10 | *.html text=auto
11 | *.js text=auto
12 | *.msbuild text=auto
13 | *.resx text=auto
14 | *.props text=auto
15 | *.pubxml text=auto
16 | *.ruleset text=auto
17 | *.StyleCop text=auto
18 | *.sql text=auto eol=crlf
19 | *.svg text=auto
20 | *.txt text=auto
21 | *.xml text=auto
22 | *.targets text=auto
23 |
24 | *.proj text=auto merge=union
25 | *.csproj text=auto merge=union eol=crlf
26 | *.vbproj text=auto merge=union eol=crlf
27 | *.fsproj text=auto merge=union eol=crlf
28 | *.dbproj text=auto merge=union eol=crlf
29 | *.sln text=auto merge=union eol=crlf
30 |
31 | *.jpg binary
32 | *.png binary
33 | *.gif binary
34 | *.ico binary
35 | *.otf binary
36 | *.eot binary
37 | *.ttf binary
38 | *.woff binary
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and files generated by
2 | ## popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 | .vs/
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | x64/
16 | bld/
17 | [Bb]in/
18 | [Oo]bj/
19 | App_Data/
20 | artifacts/
21 |
22 | # Roslyn cache directories
23 | *.ide/
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 |
29 | #NUNIT
30 | *.VisualState.xml
31 | TestResult.xml
32 |
33 | # Build Results of an ATL Project
34 | [Dd]ebugPS/
35 | [Rr]eleasePS/
36 | dlldata.c
37 |
38 | *_i.c
39 | *_p.c
40 | *_i.h
41 | *.ilk
42 | *.meta
43 | *.obj
44 | *.pch
45 | *.pdb
46 | *.pgc
47 | *.pgd
48 | *.rsp
49 | *.sbr
50 | *.tlb
51 | *.tli
52 | *.tlh
53 | *.tmp
54 | *.tmp_proj
55 | *.log
56 | *.vspscc
57 | *.vssscc
58 | .builds
59 | *.pidb
60 | *.svclog
61 | *.scc
62 | *.exe
63 | *.dll
64 | *.pdb
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 |
133 | # NuGet Packages
134 | .nuget/
135 | packages/*
136 | *.nupkg
137 |
138 | # Windows Azure Build Output
139 | csx/
140 | *.build.csdef
141 |
142 | # Windows Store app package directory
143 | AppPackages/
144 |
145 | # Others
146 | sql/
147 | *.Cache
148 | ClientBin/
149 | [Ss]tyle[Cc]op.*
150 | ~$*
151 | *~
152 | *.dbmdl
153 | *.dbproj.schemaview
154 | *.pfx
155 | *.publishsettings
156 | node_modules/
157 |
158 | # RIA/Silverlight projects
159 | Generated_Code/
160 |
161 | # Backup & report files from converting an old project file
162 | # to a newer Visual Studio version. Backup files are not needed,
163 | # because we have git ;-)
164 | _UpgradeReport_Files/
165 | Backup*/
166 | UpgradeLog*.XML
167 | UpgradeLog*.htm
168 |
169 | # SQL Server files
170 | *.mdf
171 | *.ldf
172 |
173 | # Business Intelligence projects
174 | *.rdl.data
175 | *.bim.layout
176 | *.bim_*.settings
177 |
178 | # Microsoft Fakes
179 | FakesAssemblies/
180 |
181 | # NCrunch
182 | _NCrunch_*
183 | .*crunch*.local.xml
184 | *.ncrunchsolution
185 | *.ncrunchproject
186 |
--------------------------------------------------------------------------------
/Automation.StorageEmulator.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 15
3 | VisualStudioVersion = 15.0.28010.2046
4 | MinimumVisualStudioVersion = 10.0.40219.1
5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C552E461-996F-4741-B1C8-52F01A698D91}"
6 | EndProject
7 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "src\Core\Core.csproj", "{B7C6D934-CE8C-434E-8778-7BA96C2F56F8}"
8 | EndProject
9 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Tests", "tests\Core.Tests\Core.Tests.csproj", "{37AF5A2D-467B-4FA2-AFBE-53AB652737FA}"
10 | EndProject
11 | Global
12 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
13 | Debug|Any CPU = Debug|Any CPU
14 | Release|Any CPU = Release|Any CPU
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {B7C6D934-CE8C-434E-8778-7BA96C2F56F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {B7C6D934-CE8C-434E-8778-7BA96C2F56F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {B7C6D934-CE8C-434E-8778-7BA96C2F56F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {B7C6D934-CE8C-434E-8778-7BA96C2F56F8}.Release|Any CPU.Build.0 = Release|Any CPU
21 | {37AF5A2D-467B-4FA2-AFBE-53AB652737FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {37AF5A2D-467B-4FA2-AFBE-53AB652737FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {37AF5A2D-467B-4FA2-AFBE-53AB652737FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {37AF5A2D-467B-4FA2-AFBE-53AB652737FA}.Release|Any CPU.Build.0 = Release|Any CPU
25 | EndGlobalSection
26 | GlobalSection(SolutionProperties) = preSolution
27 | HideSolutionNode = FALSE
28 | EndGlobalSection
29 | GlobalSection(NestedProjects) = preSolution
30 | {37AF5A2D-467B-4FA2-AFBE-53AB652737FA} = {C552E461-996F-4741-B1C8-52F01A698D91}
31 | EndGlobalSection
32 | GlobalSection(ExtensibilityGlobals) = postSolution
33 | SolutionGuid = {BB641CA7-132B-42E4-A209-62CF5E380C0B}
34 | EndGlobalSection
35 | EndGlobal
36 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ritter Insurance Marketing, LLC
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.
22 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Automation : Windows Azure Storage Emulator
2 |
3 | This library enables programmatic control of the Windows Azure Storage Emulator from .NET. This can be useful during integration testing, or anytime you need to work with the Windows Azure Storage Emulator from .NET code.
4 |
5 | 
6 | 
7 |
8 | ## Prerequisites
9 |
10 | - .NET Framework 4.5.2 or .Net Standard 2.0
11 | - Windows Azure Storage Emulator installed
12 | - It's been tested with Windows Azure Storage Emulator 4.1.0.0 locally by @kendaleiv and the build passes with Windows Azure Storage Emulator 3.3.0.0 on a build agent -- it may work with other versions, or, it may not.
13 |
14 | ## Installation
15 |
16 | Install the [RimDev.Automation.StorageEmulator](https://www.nuget.org/packages/RimDev.Automation.StorageEmulator/) package from NuGet:
17 |
18 | ```
19 | PM> Install-Package RimDev.Automation.StorageEmulator
20 | ```
21 |
22 | ## Quick Start (C#)
23 |
24 | To start the Windows Azure Storage Emulator:
25 |
26 | ```csharp
27 | new AzureStorageEmulatorAutomation().Start();
28 | ```
29 |
30 | You can also do some other things, like:
31 |
32 | ```csharp
33 | var automation = new AzureStorageEmulatorAutomation();
34 |
35 | automation.Start();
36 |
37 | AzureStorageEmulatorAutomation.IsEmulatorRunning(); // should be true
38 |
39 | automation.ClearAll();
40 |
41 | // Or, clear only certain things:
42 | automation.ClearBlobs();
43 | automation.ClearTables();
44 | automation.ClearQueues();
45 |
46 | automation.Stop();
47 |
48 | AzureStorageEmulatorAutomation.IsEmulatorRunning(); // should be false
49 | ```
50 | `AzureStorageEmulatorAutomation` implements `IDisposable`. The `Dispose` method will only stop the Windows Azure Storage Emulator if it was started by the `AzureStorageEmulatorAutomation` instance. We're nice and don't close it if it was opened by a different instance (or, a user opening it manually on their machine).
51 |
52 | An example `IDispoable` implementation might look like:
53 |
54 | ```csharp
55 | using (var automation = new AzureStorageEmulatorAutomation())
56 | {
57 | automation.Start();
58 |
59 | // Work with the running Azure Storage Emulator here.
60 | }
61 |
62 | // Outside the scope of the using, if the Azure Storage Emulator was
63 | // started by `automation.Start();` above, then it should be shut down.
64 | // If it was already running, it should remain running.
65 | ```
66 |
67 | In certain scenarios the Storage Emulator might not be initialized yet, for example running tests on a hosted build agent.
68 | In those cases, `Start` might time-out and you will encounter this error in your log:
69 |
70 | ```log
71 | No available SQL Instance was found.
72 | One or more initialization actions have failed. Resolve these errors before attempting to run the storage emulator again.
73 | Error: The storage emulator needs to be initialized. Please run the 'init' command.
74 | ```
75 |
76 | In that case, make sure you call `Init` once before calling `Start`:
77 |
78 | ```csharp
79 | automation.Init();
80 | automation.Start();
81 | ```
82 |
83 | ## Thanks
84 |
85 | Thanks to [Ritter IM](http://ritterim.com) for supporting OSS.
86 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image: Visual Studio 2017
2 |
3 | cache:
4 | - packages -> **\packages.config
5 |
6 | install:
7 | - ps: md -force .nuget >$null 2>&1
8 | - ps: "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile '.nuget/nuget.exe'"
9 |
10 | configuration: Release
11 |
12 | build_script:
13 | - ./build.cmd /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
14 |
15 | test: off
16 |
17 | artifacts:
18 | - path: ./msbuild.log
19 | - path: ./artifacts/*.nupkg
20 |
21 | deploy:
22 | - provider: Environment
23 | name: NuGet
24 | on:
25 | branch: master
26 |
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @echo Off
2 | pushd %~dp0
3 | setlocal enabledelayedexpansion
4 |
5 | rmdir /s /q "artifacts"
6 |
7 | :Build
8 | echo.
9 | echo *** STARTING BUILD ***
10 | echo.
11 |
12 | dotnet build src/core/core.csproj --configuration Release
13 | if %ERRORLEVEL% neq 0 goto :BuildFail
14 |
15 | echo.
16 | echo *** BUILD SUCCEEDED ***
17 | echo.
18 |
19 | echo.
20 | echo *** STARTING TESTS ***
21 | echo.
22 |
23 | dotnet test tests/core.tests/core.tests.csproj --configuration Release
24 | if %ERRORLEVEL% neq 0 goto :TestFail
25 |
26 | echo.
27 | echo *** TESTS SUCCEEDED ***
28 | echo.
29 |
30 | echo.
31 | echo *** STARTING PACK ***
32 | echo.
33 |
34 | dotnet pack src/core/core.csproj --configuration Release --no-build --output ../../artifacts
35 | if %ERRORLEVEL% neq 0 goto :PackFail
36 |
37 | echo.
38 | echo *** PACK SUCCEEDED ***
39 | echo.
40 | goto End
41 |
42 | :BuildFail
43 | echo.
44 | echo *** BUILD FAILED ***
45 | goto End
46 |
47 | :TestFail
48 | echo.
49 | echo *** TEST FAILED ***
50 | goto End
51 |
52 | :PackFail
53 | echo.
54 | echo *** PACK FAILED ***
55 | goto End
56 |
57 | :End
58 | echo.
59 | popd
60 | exit /B %ERRORLEVEL%
61 |
--------------------------------------------------------------------------------
/src/Core/AzureStorageEmulatorAutomation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace RimDev.Automation.StorageEmulator
5 | {
6 | public class AzureStorageEmulatorAutomation : IDisposable
7 | {
8 | public bool StartedByAutomation { get; private set; }
9 |
10 | public void Dispose()
11 | {
12 | if (StartedByAutomation)
13 | {
14 | Stop();
15 | }
16 | }
17 |
18 | ///
19 | /// Do one-time initialization needed by the emulator.
20 | /// Use this before if you find error "The storage emulator needs to be initialized. Please run the 'init' command."
21 | ///
22 | public void Init()
23 | {
24 | if (!IsEmulatorRunning())
25 | {
26 | RunWithParameter("init");
27 | }
28 | }
29 |
30 | public void Start()
31 | {
32 | if (!IsEmulatorRunning())
33 | {
34 | RunWithParameter("start");
35 | StartedByAutomation = true;
36 | }
37 | }
38 |
39 | public void Stop()
40 | {
41 | RunWithParameter("stop");
42 | }
43 |
44 | public void ClearAll()
45 | {
46 | RunWithParameter("clear all");
47 | }
48 |
49 | public void ClearBlobs()
50 | {
51 | RunWithParameter("clear blob");
52 | }
53 |
54 | public void ClearTables()
55 | {
56 | RunWithParameter("clear table");
57 | }
58 |
59 | public void ClearQueues()
60 | {
61 | RunWithParameter("clear queue");
62 | }
63 |
64 | public static bool IsEmulatorRunning()
65 | {
66 | var path = GetPathToStorageEmulatorExecutable();
67 |
68 | var output = ProcessHelper.RunAndGetStandardOutputAsString(path, "status");
69 |
70 | if (output.Contains("IsRunning: True"))
71 | {
72 | return true;
73 | }
74 | else if (output.Contains("IsRunning: False"))
75 | {
76 | return false;
77 | }
78 |
79 | throw new ApplicationException("Unable to determine if Azure Storage Emulator is running.");
80 | }
81 |
82 | private static void RunWithParameter(string parameter)
83 | {
84 | var path = GetPathToStorageEmulatorExecutable();
85 |
86 | ProcessHelper.RunAndGetStandardOutputAsString(path, parameter);
87 | }
88 |
89 | private static string AzureSdkDirectory
90 | {
91 | get
92 | {
93 | var programFilesX86 = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
94 | var path = Path.Combine(programFilesX86, @"Microsoft SDKs\Azure");
95 |
96 | return path;
97 | }
98 | }
99 |
100 | private static string GetPathToStorageEmulatorExecutable()
101 | {
102 | var paths = new[]
103 | {
104 | Path.Combine(AzureSdkDirectory, @"Storage Emulator\AzureStorageEmulator.exe"),
105 | Path.Combine(AzureSdkDirectory, @"Storage Emulator\WAStorageEmulator.exe")
106 | };
107 |
108 | foreach (var path in paths)
109 | {
110 | if (File.Exists(path))
111 | {
112 | return path;
113 | }
114 | }
115 |
116 | throw new FileNotFoundException(
117 | "Unable to locate Azure storage emulator at any of the expected paths.",
118 | string.Join(", ", paths));
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/Core/Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0;net452
5 |
6 |
7 |
8 | RimDev.Automation.StorageEmulator
9 | RimDev.Automation.StorageEmulator
10 | RimDev.Automation.StorageEmulator
11 | Programatically control Azure Storage Emulator.
12 | Ritter Insurance Marketing
13 | https://raw.githubusercontent.com/ritterim/automation-storage-emulator/master/LICENSE.txt
14 | https://github.com/ritterim/automation-storage-emulator
15 | azure storage emulator automation
16 |
17 |
18 |
19 | 0.3.1
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/Core/ProcessHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace RimDev.Automation.StorageEmulator
4 | {
5 | public class ProcessHelper
6 | {
7 | public static string RunAndGetStandardOutputAsString(string path, string parameter)
8 | {
9 | var process = new Process
10 | {
11 | StartInfo = new ProcessStartInfo(path, parameter)
12 | {
13 | CreateNoWindow = true,
14 | RedirectStandardOutput = true,
15 | UseShellExecute = false,
16 | WindowStyle = ProcessWindowStyle.Hidden
17 | }
18 | };
19 |
20 | process.Start();
21 |
22 | var sr = process.StandardOutput;
23 | var output = sr.ReadToEnd();
24 |
25 | process.WaitForExit();
26 |
27 | return output;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/Core.Tests/AzureStorageEmulatorAutomationTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Xunit;
4 |
5 | namespace RimDev.Automation.StorageEmulator.Tests
6 | {
7 | public class AzureStorageEmulatorAutomationTests : IClassFixture
8 | {
9 | private readonly AzureStorageEmulatorAutomation storageEm;
10 |
11 | public AzureStorageEmulatorAutomationTests()
12 | {
13 | storageEm = new AzureStorageEmulatorAutomation();
14 | }
15 |
16 | [Fact]
17 | public void Dispose_ClosesStorageEmulatorIfStartedByAutomation()
18 | {
19 | new AzureStorageEmulatorAutomation().Stop();
20 |
21 | storageEm.Start();
22 |
23 | storageEm.Dispose();
24 |
25 | TestHelper.VerifyAzureStorageEmulatorIsNotRunning();
26 | }
27 |
28 | [Fact]
29 | public async Task Dispose_DoesNotCloseStorageEmulatorIfNotStartedByAutomation()
30 | {
31 | // Use a different instance of automation
32 | new AzureStorageEmulatorAutomation().Start();
33 |
34 | Assert.False(storageEm.StartedByAutomation, "StartedByAutomation should be false before calling dispose");
35 |
36 | storageEm.Dispose();
37 |
38 | await TestHelper.VerifyAzureStorageEmulatorIsRunningAsync();
39 | }
40 |
41 | [Fact]
42 | public async Task Start_StartsStorageEmulator()
43 | {
44 | new AzureStorageEmulatorAutomation().Stop();
45 |
46 | storageEm.Start();
47 |
48 | await TestHelper.VerifyAzureStorageEmulatorIsRunningAsync();
49 | }
50 |
51 | [Fact]
52 | public async Task Start_DoesNotThrowIfRanTwice()
53 | {
54 | storageEm.Start();
55 |
56 | await TestHelper.VerifyAzureStorageEmulatorIsRunningAsync();
57 |
58 | storageEm.Start();
59 |
60 | await TestHelper.VerifyAzureStorageEmulatorIsRunningAsync();
61 | }
62 |
63 | [Fact]
64 | public async Task Init_DoesNotClearBlobs()
65 | {
66 | const string testBlobContainer = "testcontainer";
67 | const string testTableName = "testtable";
68 | const string testQueueName = "testqueue";
69 |
70 | new AzureStorageEmulatorAutomation().Start();
71 |
72 | await TestHelper.AddTestBlobToContainerAsync(testBlobContainer);
73 | await TestHelper.AddTestRowToTableAsync(testTableName);
74 | await TestHelper.AddTestQueueItemToAsync(testQueueName);
75 |
76 | async Task BlobContainerContainsTestBlob() => await TestHelper.BlobContainerExistsAndContainsTestBlobAsync(testBlobContainer);
77 | async Task TableContainsTestRow() => await TestHelper.TableExistsAndContainsTestRowAsync(testTableName);
78 | async Task QueueContainsTestMessage() => await TestHelper.QueueExistsAndContainsTestMessageAsync(testQueueName);
79 |
80 | Assert.True(await BlobContainerContainsTestBlob());
81 | Assert.True(await TableContainsTestRow());
82 | Assert.True(await QueueContainsTestMessage());
83 |
84 | storageEm.Init();
85 | storageEm.Start();
86 |
87 | Assert.True(await BlobContainerContainsTestBlob());
88 | Assert.True(await TableContainsTestRow());
89 | Assert.True(await QueueContainsTestMessage());
90 |
91 | storageEm.ClearAll();
92 | }
93 |
94 | [Fact]
95 | public async Task Stop_StopsStorageEmulatorIfStartedByAutomation()
96 | {
97 | new AzureStorageEmulatorAutomation().Stop();
98 |
99 | storageEm.Start();
100 |
101 | await TestHelper.VerifyAzureStorageEmulatorIsRunningAsync();
102 |
103 | storageEm.Stop();
104 |
105 | TestHelper.VerifyAzureStorageEmulatorIsNotRunning();
106 | }
107 |
108 | [Fact]
109 | public void Stop_StopsStorageEmulatorIfNotStartedByAutomation()
110 | {
111 | // Use a different instance of automation
112 | new AzureStorageEmulatorAutomation().Start();
113 |
114 | storageEm.Stop();
115 |
116 | TestHelper.VerifyAzureStorageEmulatorIsNotRunning();
117 | }
118 |
119 | [Fact]
120 | public async Task ClearAll_RemovesAllData()
121 | {
122 | const string testBlobContainer = "testcontainer";
123 | const string testTableName = "testtable";
124 | const string testQueueName = "testqueue";
125 |
126 | storageEm.Start();
127 |
128 | await TestHelper.AddTestBlobToContainerAsync(testBlobContainer);
129 | await TestHelper.AddTestRowToTableAsync(testTableName);
130 | await TestHelper.AddTestQueueItemToAsync(testQueueName);
131 |
132 | async Task BlobContainerContainsTestBlob() => await TestHelper.BlobContainerExistsAndContainsTestBlobAsync(testBlobContainer);
133 | async Task TableContainsTestRow() => await TestHelper.TableExistsAndContainsTestRowAsync(testTableName);
134 | async Task QueueContainsTestMessage() => await TestHelper.QueueExistsAndContainsTestMessageAsync(testQueueName);
135 |
136 | Assert.True(await BlobContainerContainsTestBlob());
137 | Assert.True(await TableContainsTestRow());
138 | Assert.True(await QueueContainsTestMessage());
139 |
140 | storageEm.ClearAll();
141 |
142 | Assert.False(await BlobContainerContainsTestBlob());
143 | Assert.False(await TableContainsTestRow());
144 | Assert.False(await QueueContainsTestMessage());
145 | }
146 |
147 | [Fact]
148 | public async Task ClearBlobs_RemovesBlobData()
149 | {
150 | const string testBlobContainer = "testcontainer";
151 |
152 | storageEm.Start();
153 |
154 | await TestHelper.AddTestBlobToContainerAsync(testBlobContainer);
155 |
156 | async Task BlobContainerContainsTestBlob() => await TestHelper.BlobContainerExistsAndContainsTestBlobAsync(testBlobContainer);
157 |
158 | Assert.True(await BlobContainerContainsTestBlob());
159 |
160 | storageEm.ClearBlobs();
161 |
162 | Assert.False(await BlobContainerContainsTestBlob());
163 | }
164 |
165 | [Fact]
166 | public async Task ClearTables_RemovesTableData()
167 | {
168 | const string testTableName = "testtable";
169 |
170 | storageEm.Start();
171 |
172 | await TestHelper.AddTestRowToTableAsync(testTableName);
173 |
174 | async Task TableContainsTestRow() => await TestHelper.TableExistsAndContainsTestRowAsync(testTableName);
175 |
176 | Assert.True(await TableContainsTestRow());
177 |
178 | storageEm.ClearTables();
179 |
180 | Assert.False(await TableContainsTestRow());
181 | }
182 |
183 | [Fact]
184 | public async Task ClearQueues_RemovesQueueData()
185 | {
186 | const string testQueueName = "testqueue";
187 |
188 | storageEm.Start();
189 |
190 | await TestHelper.AddTestQueueItemToAsync(testQueueName);
191 |
192 | async Task QueueContainsTestMessage() => await TestHelper.QueueExistsAndContainsTestMessageAsync(testQueueName);
193 |
194 | Assert.True(await QueueContainsTestMessage());
195 |
196 | storageEm.ClearQueues();
197 |
198 | Assert.False(await QueueContainsTestMessage());
199 | }
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/tests/Core.Tests/Core.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net452;netcoreapp2.1
5 | RimDev.Automation.StorageEmulator.Tests
6 | RimDev.Automation.StorageEmulator.Tests
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | all
15 | runtime; build; native; contentfiles; analyzers
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tests/Core.Tests/StopAzureStorageEmulatorFixture.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace RimDev.Automation.StorageEmulator.Tests
4 | {
5 | public class StopAzureStorageEmulatorFixture : IDisposable
6 | {
7 | public StopAzureStorageEmulatorFixture()
8 | {
9 | var automation = new AzureStorageEmulatorAutomation();
10 |
11 | automation.Stop();
12 |
13 | TestHelper.VerifyAzureStorageEmulatorIsNotRunning();
14 | }
15 |
16 | public void Dispose()
17 | {
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tests/Core.Tests/TestHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.WindowsAzure.Storage;
2 | using Microsoft.WindowsAzure.Storage.Blob;
3 | using Microsoft.WindowsAzure.Storage.Queue;
4 | using Microsoft.WindowsAzure.Storage.Table;
5 | using System;
6 | using System.Threading.Tasks;
7 |
8 | namespace RimDev.Automation.StorageEmulator.Tests
9 | {
10 | public class TestHelper
11 | {
12 | private const string TestBlobName = "TestBlob";
13 | private const string TestQueueMessage = "test-queue-message";
14 |
15 | private static readonly CloudStorageAccount StorageAccount =
16 | CloudStorageAccount.DevelopmentStorageAccount;
17 |
18 | public static async Task VerifyAzureStorageEmulatorIsRunningAsync()
19 | {
20 | var tableName = "test" + Guid.NewGuid().ToString().Replace("-", "");
21 | var cloudTable = GetCloudTable(tableName);
22 |
23 | var tableExists = await cloudTable.ExistsAsync();
24 | if (tableExists)
25 | {
26 | throw new ApplicationException("Table unexpectedly exists.");
27 | }
28 | }
29 |
30 | public static void VerifyAzureStorageEmulatorIsNotRunning()
31 | {
32 | var isRunning = AzureStorageEmulatorAutomation.IsEmulatorRunning();
33 |
34 | if (isRunning)
35 | {
36 | throw new ApplicationException("The Azure Storage Emulator is running.");
37 | }
38 | }
39 |
40 | public static async Task AddTestRowToTableAsync(string tableName)
41 | {
42 | var cloudTable = GetCloudTable(tableName);
43 | await cloudTable.CreateIfNotExistsAsync();
44 |
45 | var testTableEntity = new TestTableEntity
46 | {
47 | PartitionKey = Guid.NewGuid().ToString(),
48 | RowKey = Guid.NewGuid().ToString(),
49 | TestProperty = "test"
50 | };
51 |
52 | await cloudTable.ExecuteAsync(TableOperation.Insert(testTableEntity));
53 | }
54 |
55 | public static async Task AddTestBlobToContainerAsync(string blobContainer)
56 | {
57 | var cloudBlobContainer = GetCloudBlobContainer(blobContainer);
58 | await cloudBlobContainer.CreateIfNotExistsAsync();
59 |
60 | var blockBlob = cloudBlobContainer.GetBlockBlobReference(TestBlobName);
61 |
62 | await blockBlob.UploadTextAsync("test");
63 | }
64 |
65 | public static async Task AddTestQueueItemToAsync(string queueName)
66 | {
67 | var cloudQueue = GetCloudQueue(queueName);
68 | await cloudQueue.CreateIfNotExistsAsync();
69 |
70 | var cloudQueueMessage = new CloudQueueMessage(TestQueueMessage);
71 |
72 | await cloudQueue.AddMessageAsync(cloudQueueMessage);
73 | }
74 |
75 | public static async Task BlobContainerExistsAndContainsTestBlobAsync(string blobContainer)
76 | {
77 | var cloudBlobContainer = GetCloudBlobContainer(blobContainer);
78 |
79 | if (!await cloudBlobContainer.ExistsAsync())
80 | {
81 | return false;
82 | }
83 |
84 | var cloudBlob = await cloudBlobContainer.GetBlobReferenceFromServerAsync(TestBlobName);
85 | return await cloudBlob.ExistsAsync();
86 | }
87 |
88 | public static async Task TableExistsAndContainsTestRowAsync(string tableName)
89 | {
90 | var cloudTable = GetCloudTable(tableName);
91 |
92 | if (!await cloudTable.ExistsAsync())
93 | {
94 | return false;
95 | }
96 |
97 | var results = (await cloudTable.ExecuteQuerySegmentedAsync(new TableQuery(), new TableContinuationToken())).Results;
98 |
99 | if (results?.Count > 1 )
100 | {
101 | throw new ApplicationException(string.Format(
102 | "count of test rows was {0}.",
103 | results?.Count));
104 | }
105 |
106 | return results?.Count == 1;
107 | }
108 |
109 | public static async Task QueueExistsAndContainsTestMessageAsync(string queueName)
110 | {
111 | var cloudQueue = GetCloudQueue(queueName);
112 |
113 | if (!await cloudQueue.ExistsAsync())
114 | {
115 | return false;
116 | }
117 |
118 | var queueMessage = await cloudQueue.PeekMessageAsync();
119 |
120 | if (queueMessage != null && queueMessage.AsString == TestQueueMessage)
121 | {
122 | return true;
123 | }
124 |
125 | return false;
126 | }
127 |
128 | private static CloudTable GetCloudTable(string tableName)
129 | {
130 | var tableClient = StorageAccount.CreateCloudTableClient();
131 |
132 | var table = tableClient.GetTableReference(tableName);
133 | return table;
134 | }
135 |
136 | private static CloudBlobContainer GetCloudBlobContainer(string containerName)
137 | {
138 | var blobClient = StorageAccount.CreateCloudBlobClient();
139 |
140 | var blobContainer = blobClient.GetContainerReference(containerName);
141 | return blobContainer;
142 | }
143 |
144 | private static CloudQueue GetCloudQueue(string queueName)
145 | {
146 | var queueClient = StorageAccount.CreateCloudQueueClient();
147 |
148 | var cloudQueue = queueClient.GetQueueReference(queueName);
149 | return cloudQueue;
150 | }
151 |
152 | private class TestTableEntity : TableEntity
153 | {
154 | public string TestProperty { get; set; }
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------