├── .gitattributes
├── .gitignore
├── AnyOS.AnyCPU.Debug-Test-Archive-List.txt
├── BuildToolsVersion.txt
├── CONTRIBUTING.md
├── Documentation
└── design
│ └── dumpling
│ ├── events.md
│ ├── images
│ └── drawing1.png
│ ├── index_mvp.md
│ ├── rest.md
│ └── state-and-storage.md
├── DotnetCLIVersion.txt
├── LICENSE
├── README.md
├── build.cmd
├── build.proj
├── build_test.cmd
├── dir.props
├── dir.targets
├── dir.traversal.targets
├── init-tools.cmd
├── mono.targets
├── netci.groovy
├── override.targets
├── publishexe.targets
├── roslyn.xplat.targets
├── src
├── .nuget
│ └── packages.Windows_NT.config
├── BuildValues.props
├── NuGet.Config
├── dir.props
├── dir.targets
├── dirs.proj
├── reliability.sln
├── stress.codegen.nuspec
├── stress.codegen
│ ├── ExecutionFileGenerator.cs
│ ├── GenerateStressSuiteTask.cs
│ ├── HelixToFProjectFileGenerator.cs
│ ├── ITestDiscoverer.cs
│ ├── LoadSuiteConfig.cs
│ ├── LoadSuiteGenerator.cs
│ ├── LoadTestConfig.cs
│ ├── LoadTestInfo.cs
│ ├── LoadTestProjectFileGenerator.cs
│ ├── LoadTestProjectJsonFileGenerator.cs
│ ├── LoadTestSourceFileGenerator.cs
│ ├── MergeAllProjectJsonsTask.cs
│ ├── ProgramSourceFileGenerator.cs
│ ├── ProjectJsonDependencyInfo.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SourceFileInfo.cs
│ ├── StandAloneTestDiscoverer.cs
│ ├── TestAssemblyLoader.cs
│ ├── ToFProjectFileGenerator.cs
│ ├── UnitTestInfo.cs
│ ├── UnitTestSelector.cs
│ ├── XUnitTestDiscoverer.cs
│ ├── app.config
│ ├── packages.config
│ ├── resources
│ │ ├── Resources.Designer.cs
│ │ ├── Resources.resx
│ │ └── runstress.sh
│ ├── stress.codegen.csproj
│ └── utils
│ │ ├── FileUtils.cs
│ │ ├── Output.cs
│ │ └── RetryExtensions.cs
├── stress.execution.nuspec
├── stress.execution
│ ├── ActionUnitTest.cs
│ ├── AsyncWorkerStrategy.cs
│ ├── DedicatedThreadWorkerStrategy.cs
│ ├── ExecutionEngine.cs
│ ├── FairTestPattern.cs
│ ├── ILoadPattern.cs
│ ├── ITestPattern.cs
│ ├── IUnitTestEnumerator.cs
│ ├── IWorkerStrategy.cs
│ ├── LoadAttribute.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── RandomTestPattern.cs
│ ├── SelfDestruct.cs
│ ├── StaticLoadPattern.cs
│ ├── StepLoadPattern.cs
│ ├── StressTestShim.cs
│ ├── TestExecutionLog.cs
│ ├── UnitTest.cs
│ ├── UnitTestEnumerator.cs
│ ├── XunitTestAssemblyEnumerator.cs
│ ├── XunitTestClassEnumerator.cs
│ ├── XunitUnitTest.cs
│ ├── app.config
│ ├── project.json
│ └── stress.execution.csproj
├── stress.run
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── project.json
│ ├── stress.run.csproj
│ └── stress.run.xproj
├── stress.samples
│ ├── App.config
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── SimpleSample.cs
│ ├── packages.config
│ └── stress.samples.csproj
├── stress.tests
│ ├── ArrayTests.cs
│ ├── JaggedArray.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── StressTestsAssemblyTestEnumerator.cs
│ ├── project.json
│ └── stress.tests.csproj
└── stress
│ ├── App.config
│ ├── CmdArgProcessing.cs
│ ├── Program.cs
│ ├── Properties
│ └── AssemblyInfo.cs
│ ├── StressEssentials.ps1
│ ├── packages.config
│ └── stress.csproj
├── test
├── README.md
├── buildgen.proj
├── buildgenerated.proj
├── dir.props
├── dir.targets
├── genstress.proj
└── suiteconfig
│ ├── 16hr.suite.json
│ ├── 1hr.suite.json
│ ├── 2hr.suite.json
│ ├── 4hr.suite.json
│ ├── 8hr.suite.json
│ ├── daily.suite.json
│ └── smoketest.suite.json
└── toolbox
└── list_build_ids
├── DumpCore.sln
├── DumpCore.vcxproj
├── example.py
├── list_build_ids.cpp
├── python_binding.cpp
└── setup.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | # Declare files that will always have CRLF line endings on checkout.
7 | *.sh text eol=lf
8 |
9 | ###############################################################################
10 | # Set default behavior for command prompt diff.
11 | #
12 | # This is need for earlier builds of msysgit that does not have it on by
13 | # default for csharp files.
14 | # Note: This is only used by command line
15 | ###############################################################################
16 | #*.cs diff=csharp
17 |
18 | ###############################################################################
19 | # Set the merge driver for project and solution files
20 | #
21 | # Merging from the command prompt will add diff markers to the files if there
22 | # are conflicts (Merging from VS is not affected by the settings below, in VS
23 | # the diff markers are never inserted). Diff markers may cause the following
24 | # file extensions to fail to load in VS. An alternative would be to treat
25 | # these files as binary and thus will always conflict and require user
26 | # intervention with every merge. To do so, just uncomment the entries below
27 | ###############################################################################
28 | #*.sln merge=binary
29 | #*.csproj merge=binary
30 | #*.vbproj merge=binary
31 | #*.vcxproj merge=binary
32 | #*.vcproj merge=binary
33 | #*.dbproj merge=binary
34 | #*.fsproj merge=binary
35 | #*.lsproj merge=binary
36 | #*.wixproj merge=binary
37 | #*.modelproj merge=binary
38 | #*.sqlproj merge=binary
39 | #*.wwaproj merge=binary
40 |
41 | ###############################################################################
42 | # behavior for image files
43 | #
44 | # image files are treated as binary by default.
45 | ###############################################################################
46 | #*.jpg binary
47 | #*.png binary
48 | #*.gif binary
49 |
50 | ###############################################################################
51 | # diff behavior for common document formats
52 | #
53 | # Convert binary document formats to text before diffing them. This feature
54 | # is only available from the command line. Turn it on by uncommenting the
55 | # entries below.
56 | ###############################################################################
57 | #*.doc diff=astextplain
58 | #*.DOC diff=astextplain
59 | #*.docx diff=astextplain
60 | #*.DOCX diff=astextplain
61 | #*.dot diff=astextplain
62 | #*.DOT diff=astextplain
63 | #*.pdf diff=astextplain
64 | #*.PDF diff=astextplain
65 | #*.rtf diff=astextplain
66 | #*.RTF diff=astextplain
67 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | syntax: glob
2 |
3 | ### VisualStudio ###
4 | # Tool Runtime Dir
5 | [Tt]ools/
6 |
7 | #nuget lock files
8 | project.lock.json
9 |
10 | # User-specific files
11 | *.suo
12 | *.user
13 | *.userosscache
14 | *.sln.docstates
15 | *.VC.opendb
16 | .vs
17 |
18 | # Build results
19 | [Dd]ebug/
20 | [Dd]ebugPublic/
21 | [Rr]elease/
22 | [Rr]eleases/
23 | x64/
24 | x86/
25 | build/
26 | bld/
27 | [Bb]in/
28 | [Oo]bj/
29 | msbuild.log
30 |
31 | # Generated Stress Mixes
32 | /test/generated
33 |
34 | # Roslyn stuff
35 | *.sln.ide
36 | *.ide/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | #NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opensdf
84 | *.sdf
85 | *.cachefile
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding addin-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 | *.pubxml
143 | *.publishproj
144 |
145 | # NuGet Packages
146 | *.nupkg
147 | **/packages/*
148 |
149 | # Windows Azure Build Output
150 | csx/
151 | *.build.csdef
152 |
153 | # Windows Store app package directory
154 | AppPackages/
155 |
156 | # Others
157 | sql/
158 | *.Cache
159 | ClientBin/
160 | [Ss]tyle[Cc]op.*
161 | ~$*
162 | *.dbmdl
163 | *.dbproj.schemaview
164 | *.pfx
165 | *.publishsettings
166 | node_modules/
167 | *.metaproj
168 | *.metaproj.tmp
169 |
170 | # RIA/Silverlight projects
171 | Generated_Code/
172 |
173 | # Backup & report files from converting an old project file
174 | # to a newer Visual Studio version. Backup files are not needed,
175 | # because we have git ;-)
176 | _UpgradeReport_Files/
177 | Backup*/
178 | UpgradeLog*.XML
179 | UpgradeLog*.htm
180 |
181 | # SQL Server files
182 | *.mdf
183 | *.ldf
184 |
185 | # Business Intelligence projects
186 | *.rdl.data
187 | *.bim.layout
188 | *.bim_*.settings
189 |
190 | # Microsoft Fakes
191 | FakesAssemblies/
192 |
193 | ### MonoDevelop ###
194 |
195 | *.pidb
196 | *.userprefs
197 |
198 | ### Windows ###
199 |
200 | # Windows image file caches
201 | Thumbs.db
202 | ehthumbs.db
203 |
204 | # Folder config file
205 | Desktop.ini
206 |
207 | # Recycle Bin used on file shares
208 | $RECYCLE.BIN/
209 |
210 | # Windows Installer files
211 | *.cab
212 | *.msi
213 | *.msm
214 | *.msp
215 |
216 | # Windows shortcuts
217 | *.lnk
218 |
219 | ### Linux ###
220 |
221 | *~
222 |
223 | # KDE directory preferences
224 | .directory
225 |
226 | ### OSX ###
227 |
228 | .DS_Store
229 | .AppleDouble
230 | .LSOverride
231 |
232 | # Icon must end with two \r
233 | Icon
234 |
235 | # Thumbnails
236 | ._*
237 |
238 | # Files that might appear on external disk
239 | .Spotlight-V100
240 | .Trashes
241 |
242 | # Directories potentially created on remote AFP share
243 | .AppleDB
244 | .AppleDesktop
245 | Network Trash Folder
246 | Temporary Items
247 | .apdisk
248 |
249 | # vim temporary files
250 | [._]*.s[a-w][a-z]
251 | [._]s[a-w][a-z]
252 | *.un~
253 | Session.vim
254 | .netrwhist
255 | *~
256 |
257 | local_run.rsp
258 | local_run_win10.rsp
259 | out.txt
260 | usedvalues.txt
261 | .vscode/
--------------------------------------------------------------------------------
/AnyOS.AnyCPU.Debug-Test-Archive-List.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/dotnet-reliability/6addc13cfb3c4333733e787c0c06d53921398acb/AnyOS.AnyCPU.Debug-Test-Archive-List.txt
--------------------------------------------------------------------------------
/BuildToolsVersion.txt:
--------------------------------------------------------------------------------
1 | 1.0.26-prerelease-00820-01
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Information on contributing is in the [Contributing Guide](https://github.com/dotnet/corefx/wiki/Contributing).
4 |
--------------------------------------------------------------------------------
/Documentation/design/dumpling/events.md:
--------------------------------------------------------------------------------
1 | ####The Events
2 |
3 | The name scheme of the event types is:
4 | {*Emitting Service*}-{*Emitting Piece of Service*}-{*Event Type*}
5 |
6 | Where we see {os} means that any analyzer os we have setup will have a corresponding event.
7 |
8 | **rank**.`event type`
9 |
10 | 0. HelixServiceProxy-WorkItems-Status
11 | 1. DumplingService-WebAPI-StartUploadChunk
12 | 2. DumplingService-WebAPI-FinishedUploadChunk
13 | 3. DumplingService-WebAPI-Greeting
14 | 4. DumplingService-WebAPI-GetStatus
15 | 5. DumplingService-WebAPI-GetDumpURI
16 | 6. DumplingService-{os}Analyzer-StartService
17 | 7. DumplingService-{os}Analyzer-StartDownload
18 | 8. DumplingService-{os}Analyzer-StartUnzip
19 | 9. DumplingService-{os}Analyzer-StartAnalyze
20 | 10. DumplingService-{os}Analyzer-SaveResults
21 | 11. DumplingService-{os}Analyzer-Complete
22 | 12. DumplingService-{os}Analyzer-Failure
23 | 13. DumplingService-DataWorker-ReceiveMessage
24 | 14. DumplingService-DataWorker-DeadLetteredMessage
25 | 15. DumplingService-DataWorker-Exception
26 | 16. DumplingService-DataWorker-CompletedMessage
27 | 17. DumplingService-DataWorker-StartService
28 | 18. DumplingService-DataWorker-StopService
29 | 19. DumplingService-DataWorker-RunService
30 | 20. DumplingService-DataWorker-SqlIndex
31 |
--------------------------------------------------------------------------------
/Documentation/design/dumpling/images/drawing1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/dotnet-reliability/6addc13cfb3c4333733e787c0c06d53921398acb/Documentation/design/dumpling/images/drawing1.png
--------------------------------------------------------------------------------
/Documentation/design/dumpling/index_mvp.md:
--------------------------------------------------------------------------------
1 | ##`dumpling` service
2 |
3 | ###http://aka.ms/dumpling
4 |
5 | #####What is `dumpling` service?
6 |
7 | `dumpling` is the name of the DotNet dump analytics cli, and its storage service. Given a dump file, the service extracts information and catalogues it for future review.
8 |
9 | #####The Vision
10 | A runtime developer is looking for bugs to fix, and visits the `dumpling` website. They are presented with a view of the most impactful runtime issues. If they come across a failure they'd like to investigate, they may download the offending zipped up dump file and extract it to their machines for further review.
11 |
12 |
13 | #####`The Status`The Pieces
14 | 
15 | [Events that emit in to EventHub](events.md)
16 |
17 | 1. Supported Users
18 | - Automated Infrastructure
19 | - Tools
20 | - Humans
21 | 2. `stable`[RESTful Front-End](rest.md)
22 | - **upload dump file**
23 | - Get Status
24 | - Retrieve Dump File
25 | 3. `stable` [State Table](state-and-storage.md)
26 | 4. `stable` [**dump + runtime artifacts storage**](state-and-storage.md)
27 | 5. `stable`**analysis** Infrastructure
28 | - (**queue**) Azure Topic
29 | - Workers
30 | - Ubuntu 14.04 VM
31 | - CentOS VM
32 | 6. `stable` [**analysis artifacts storage**](state-and-storage.md)
33 | 7. `stable` Report Viewing
34 | - `cut?` PowerBI for high-level status
35 | - `stable` [ASP.Net WebView for actionable data](http://aka.ms/dumpling)
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Documentation/design/dumpling/rest.md:
--------------------------------------------------------------------------------
1 | # `dumpling` Service REST API
2 | `dumpling` should be accessible from any device that the supported DotNet runtimes are supported on. In order to enable this we're creating a simple REST interface so that a zip can be submitted from any platform.
3 |
4 | [Swagger View of API](http://dotnetrp.azurewebsites.net/swagger/ui/index)
5 |
6 | A *`dumplingid`* is a unique identifier that is assigned to a zipped up dump at the time it is uploaded. It is typed as a 'string', but its contents are nothing more than a GUID. This is *the* unique identifier of a zip file.
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Documentation/design/dumpling/state-and-storage.md:
--------------------------------------------------------------------------------
1 | #State Table
2 | Azure Storage Table
3 |
4 | Right before we begin receiving the dumpfile, we generate a dumpling-id. Upon generating the dumpling-id we create a row in the state table. The values within the state table update as dump moves through the pipeline. Upon creation the default state is 'uploading', and all of the uri values and the flight-messages are 'null'.
5 |
6 | | owner | dumpling-id | timestamp | state | symbols-uri | dump-uri | results-uri | messages |
7 | |---|---|---|---|---|---|---|---|
8 | |a |b | c | d |e |f | g | h |
9 | d: **possible states**
10 | - uploading
11 | - enqueued
12 | - downzipping
13 | - downloading symbols
14 | - analyzing
15 | - saving results
16 | - building report
17 | - done
18 | - error
19 |
20 | h: *messages*
21 | - JSON array of "message_type","message" objects
22 |
23 | #Storage
24 |
25 | **`todo`**Blob storage for the dump zip. Container names will be the value of 'owner' in the state table for the corresponding `dumpling-id`.
26 |
27 | **`stable`** Blob storage for the results json object. The container names will be the 'owner' in the state table for the corresponding `dumpling-id`. Then the first level of directory will be the `dumpling-id`. The `filename.zip` is preserved from upload.
28 |
29 | `todo`*Symbols VSTS* will store our symbol files - before this can be brought up, we must begin indexing our symbols in VSTS. There is a preview program available that I want to leverage here.
30 |
31 |
--------------------------------------------------------------------------------
/DotnetCLIVersion.txt:
--------------------------------------------------------------------------------
1 | 1.0.0-preview2-002733
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Microsoft Corporation
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## the `dumpling` service
2 | ###http://aka.ms/dumpling
3 |
4 | # dotnet-reliability
5 | Contains the tooling and infrastructure used for .NET stress testing and reliability investigation. More specifically this includes tools for, but not limited to :
6 |
7 | - authoring component specific stress and load tests
8 | - generating stress tests from existing framework and runtime tests
9 | - unified dump collection, storage, and bucketing across all .NET supported platforms
10 | - investigating and diagnosis of reliability failures
11 |
12 |
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | :: Note: We've disabled node reuse because it causes file locking issues.
5 | :: The issue is that we extend the build with our own targets which
6 | :: means that that rebuilding cannot successfully delete the task
7 | :: assembly.
8 |
9 | if not defined VisualStudioVersion (
10 | if defined VS140COMNTOOLS (
11 | call "%VS140COMNTOOLS%\VsDevCmd.bat"
12 | goto :EnvSet
13 | )
14 |
15 | if defined VS120COMNTOOLS (
16 | call "%VS120COMNTOOLS%\VsDevCmd.bat"
17 | goto :EnvSet
18 | )
19 |
20 | echo Error: build.cmd requires Visual Studio 2013 or 2015.
21 | echo Please see https://github.com/dotnet/corefx/blob/master/Documentation/developer-guide.md for build instructions.
22 | exit /b 1
23 | )
24 |
25 | :EnvSet
26 |
27 | call %~dp0init-tools.cmd
28 |
29 | :: Log build command line
30 | set _buildproj=%~dp0build.proj
31 | set _buildlog=%~dp0msbuild.log
32 | set _buildprefix=echo
33 | set _buildpostfix=^> "%_buildlog%"
34 | call :build %*
35 |
36 | :: Build
37 | set _buildprefix=
38 | set _buildpostfix=
39 | call :build %*
40 |
41 | goto :AfterBuild
42 |
43 | :build
44 | %_buildprefix% msbuild "%_buildproj%" /nologo /maxcpucount /verbosity:minimal /nodeReuse:false /fileloggerparameters:Verbosity=normal;LogFile="%_buildlog%";Append %* %_buildpostfix%
45 | set BUILDERRORLEVEL=%ERRORLEVEL%
46 | goto :eof
47 |
48 | :AfterBuild
49 |
50 | echo.
51 | :: Pull the build summary from the log file
52 | findstr /ir /c:".*Warning(s)" /c:".*Error(s)" /c:"Time Elapsed.*" "%_buildlog%"
53 | echo Build Exit Code = %BUILDERRORLEVEL%
54 |
55 | exit /b %BUILDERRORLEVEL%
56 |
--------------------------------------------------------------------------------
/build.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | true
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | BatchRestorePackages;
23 | CreateOrUpdateCurrentVersionFile;
24 | $(TraversalBuildDependsOn);
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | <_allPackagesConfigs Include="$(MSBuildProjectDirectory)\src\**\packages.config"/>
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/build_test.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | :: Note: We've disabled node reuse because it causes file locking issues.
5 | :: The issue is that we extend the build with our own targets which
6 | :: means that that rebuilding cannot successfully delete the task
7 | :: assembly.
8 |
9 | if not defined VisualStudioVersion (
10 | if defined VS140COMNTOOLS (
11 | call "%VS140COMNTOOLS%\VsDevCmd.bat"
12 | goto :EnvSet
13 | )
14 |
15 | if defined VS120COMNTOOLS (
16 | call "%VS120COMNTOOLS%\VsDevCmd.bat"
17 | goto :EnvSet
18 | )
19 |
20 | echo Error: build.cmd requires Visual Studio 2013 or 2015.
21 | echo Please see https://github.com/dotnet/corefx/blob/master/Documentation/developer-guide.md for build instructions.
22 | exit /b 1
23 | )
24 |
25 | :EnvSet
26 |
27 | :: The property FilterToTestTFM is temporarily required because of https://github.com/dotnet/buildtools/commit/e9007c16b1832dbd0ea9669fa578b61900b7f724
28 | call msbuild test/genstress.proj /maxcpucount %*
29 | set BUILDERRORLEVEL=%ERRORLEVEL%
30 |
31 |
32 | exit /b %BUILDERRORLEVEL%
33 |
--------------------------------------------------------------------------------
/dir.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/dir.traversal.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | $(MSBuildProjectDefaultTargets)
7 |
8 |
9 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Clean
31 |
32 |
33 |
35 |
40 |
41 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | RestorePackages
57 |
58 |
59 |
61 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | BuildAllProjects;
81 | $(TraversalBuildDependsOn);
82 |
83 |
84 |
85 | CleanAllProjects;
86 | $(TraversalCleanDependsOn);
87 |
88 |
89 |
90 | RestoreAllProjectPackages;
91 | $(TraversalRestorePackagesDependsOn)
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/init-tools.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | set INIT_TOOLS_LOG=%~dp0init-tools.log
5 | set PACKAGES_DIR=%~dp0packages\
6 | set TOOLRUNTIME_DIR=%~dp0Tools
7 | set DOTNET_PATH=%TOOLRUNTIME_DIR%\dotnetcli\
8 | set DOTNET_CMD=%DOTNET_PATH%dotnet.exe
9 | if [%BUILDTOOLS_SOURCE%]==[] set BUILDTOOLS_SOURCE=https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json
10 | set /P BUILDTOOLS_VERSION=< %~dp0BuildToolsVersion.txt
11 | set BUILD_TOOLS_PATH=%PACKAGES_DIR%Microsoft.DotNet.BuildTools\%BUILDTOOLS_VERSION%\lib\
12 | set PROJECT_JSON_PATH=%TOOLRUNTIME_DIR%\%BUILDTOOLS_VERSION%
13 | set PROJECT_JSON_FILE=%PROJECT_JSON_PATH%\project.json
14 | set PROJECT_JSON_CONTENTS={ "dependencies": { "Microsoft.DotNet.BuildTools": "%BUILDTOOLS_VERSION%" }, "frameworks": { "dnxcore50": { } } }
15 | set BUILD_TOOLS_SEMAPHORE=%PROJECT_JSON_PATH%\init-tools.completed
16 |
17 | :: if force option is specified then clean the tool runtime and build tools package directory to force it to get recreated
18 | if [%1]==[force] (
19 | if exist "%TOOLRUNTIME_DIR%" rmdir /S /Q "%TOOLRUNTIME_DIR%"
20 | if exist "%PACKAGES_DIR%Microsoft.DotNet.BuildTools" rmdir /S /Q "%PACKAGES_DIR%Microsoft.DotNet.BuildTools"
21 | )
22 |
23 | :: If sempahore exists do nothing
24 | if exist "%BUILD_TOOLS_SEMAPHORE%" (
25 | echo Tools are already initialized.
26 | goto :EOF
27 | )
28 |
29 | if exist "%TOOLRUNTIME_DIR%" rmdir /S /Q "%TOOLRUNTIME_DIR%"
30 |
31 | :: Download nuget
32 | if NOT exist "%PACKAGES_DIR%\NuGet.exe" (
33 | if NOT exist "PACKAGES_DIR" mkdir "%PACKAGES_DIR%"
34 | powershell -NoProfile -ExecutionPolicy unrestricted -Command "(New-Object Net.WebClient).DownloadFile('https://www.nuget.org/nuget.exe', '%PACKAGES_DIR%\NuGet.exe')
35 | )
36 |
37 | if NOT exist "%PROJECT_JSON_PATH%" mkdir "%PROJECT_JSON_PATH%"
38 | echo %PROJECT_JSON_CONTENTS% > %PROJECT_JSON_FILE%
39 | echo Running %0 > %INIT_TOOLS_LOG%
40 |
41 | if exist "%DOTNET_CMD%" goto :afterdotnetrestore
42 |
43 | echo Installing dotnet cli...
44 | if NOT exist "%DOTNET_PATH%" mkdir "%DOTNET_PATH%"
45 | set /p DOTNET_VERSION=< "%~dp0DotnetCLIVersion.txt"
46 | set DOTNET_ZIP_NAME=dotnet-dev-win-x64.%DOTNET_VERSION%.zip
47 | set DOTNET_REMOTE_PATH=https://dotnetcli.blob.core.windows.net/dotnet/preview/Binaries/%DOTNET_VERSION%/%DOTNET_ZIP_NAME%
48 | set DOTNET_LOCAL_PATH=%DOTNET_PATH%%DOTNET_ZIP_NAME%
49 | echo Installing '%DOTNET_REMOTE_PATH%' to '%DOTNET_LOCAL_PATH%' >> "%INIT_TOOLS_LOG%"
50 | powershell -NoProfile -ExecutionPolicy unrestricted -Command "(New-Object Net.WebClient).DownloadFile('%DOTNET_REMOTE_PATH%', '%DOTNET_LOCAL_PATH%'); Add-Type -Assembly 'System.IO.Compression.FileSystem' -ErrorVariable AddTypeErrors; if ($AddTypeErrors.Count -eq 0) { [System.IO.Compression.ZipFile]::ExtractToDirectory('%DOTNET_LOCAL_PATH%', '%DOTNET_PATH%') } else { (New-Object -com shell.application).namespace('%DOTNET_PATH%').CopyHere((new-object -com shell.application).namespace('%DOTNET_LOCAL_PATH%').Items(),16) }" >> "%INIT_TOOLS_LOG%"
51 | if NOT exist "%DOTNET_LOCAL_PATH%" (
52 | echo ERROR: Could not install dotnet cli correctly. See '%INIT_TOOLS_LOG%' for more details.
53 | exit /b 1
54 | )
55 | :afterdotnetrestore
56 |
57 | if exist "%BUILD_TOOLS_PATH%" goto :afterbuildtoolsrestore
58 | echo Restoring BuildTools version %BUILDTOOLS_VERSION%...
59 | echo Running: "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG%
60 | call "%DOTNET_CMD%" restore "%PROJECT_JSON_FILE%" --packages %PACKAGES_DIR% --source "%BUILDTOOLS_SOURCE%" >> %INIT_TOOLS_LOG%
61 | if NOT exist "%BUILD_TOOLS_PATH%init-tools.cmd" (
62 | echo ERROR: Could not restore build tools correctly. See '%INIT_TOOLS_LOG%' for more details.
63 | goto :EOF
64 | )
65 |
66 | :afterbuildtoolsrestore
67 |
68 | echo Initializing BuildTools ...
69 | echo Running: "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG%
70 | call "%BUILD_TOOLS_PATH%init-tools.cmd" "%~dp0" "%DOTNET_CMD%" "%TOOLRUNTIME_DIR%" >> %INIT_TOOLS_LOG%
71 |
72 | :: Create sempahore file
73 | echo Done initializing tools.
74 | echo Init-Tools.cmd completed for BuildTools Version: %BUILDTOOLS_VERSION% > "%BUILD_TOOLS_SEMAPHORE%"
--------------------------------------------------------------------------------
/mono.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 | true
12 | true
13 |
14 |
15 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/netci.groovy:
--------------------------------------------------------------------------------
1 | // Import the utility functionality.
2 |
3 | import jobs.generation.Utilities;
4 |
5 | def project = GithubProject
6 | def branch = GithubBranchName
7 |
8 | // Define build string
9 | def buildString = '''call "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\VsDevCmd.bat" && build.cmd /p:SkipTests=true'''
10 |
11 | // Generate the builds for debug and release
12 |
13 | [true, false].each { isPR ->
14 | def newJob = job(Utilities.getFullJobName(project, '', isPR)) {
15 | steps {
16 | batchFile(buildString)
17 | }
18 | }
19 |
20 | Utilities.setMachineAffinity(newJob, 'Windows_NT', 'latest-or-auto')
21 | Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}")
22 | if (isPR) {
23 | Utilities.addGithubPRTriggerForBranch(newJob, branch, 'Innerloop Windows Debug')
24 | }
25 | else {
26 | Utilities.addGithubPushTrigger(newJob)
27 | }
28 | }
--------------------------------------------------------------------------------
/override.targets:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/publishexe.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 | x64
9 | win7
10 |
11 |
12 |
14 |
15 |
16 |
17 | %(FileName)%(Extension)
18 |
19 |
20 |
21 | %(FileName)%(Extension)
22 |
23 |
24 |
25 | %(Filename)%(Extension)
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | $(Outdir)$(AssemblyName).dll
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/roslyn.xplat.targets:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | false
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/.nuget/packages.Windows_NT.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/BuildValues.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 | 00001
12 |
13 |
--------------------------------------------------------------------------------
/src/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/dir.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | $(BinDir)packages
6 | 1.0.0-alpha-00037
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/dir.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 |
8 |
10 |
12 |
13 |
15 |
17 |
18 |
19 |
20 |
21 |
22 | UpdateImportedProjectRelativePaths;$(CoreBuildDependsOn)
23 | UpdateImportedProjectRelativePaths;$(CoreCleanDependsOn)
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/dirs.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | $(ToolsDir)
24 |
25 |
26 |
27 |
28 |
29 | false
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/stress.codegen.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.DotNet.stress.codegen
5 | 1.0.0.1
6 | DotNet Stress Code Generation
7 | sschaab@microsoft.com
8 | Microsoft
9 |
10 | Contains tooling for the source generation of .NET stress test
11 |
12 | Supported platforms:
13 | - Desktop .NET 4.6
14 |
15 |
16 | en-US
17 | https://github.com/dotnet/corefx-tools
18 | https://raw.githubusercontent.com/dotnet/corefx-tools/master/LICENSE
19 | http://go.microsoft.com/fwlink/?LinkID=288859
20 | false
21 |
22 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/stress.codegen/GenerateStressSuiteTask.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using Microsoft.Build.Framework;
10 | using Microsoft.Build.Utilities;
11 | using stress.codegen.utils;
12 | using System.Diagnostics;
13 | using System.Windows;
14 |
15 | namespace stress.codegen
16 | {
17 | public class GenerateStressSuiteTask : Task
18 | {
19 | public bool DebugWaitForInput { get; set; }
20 |
21 | public bool UseLegacyProject { get; set; }
22 |
23 | public string Seed { get; set; }
24 |
25 | [Required]
26 | public string SuiteName { get; set; }
27 |
28 | [Required]
29 | public string SuitePath { get; set; }
30 |
31 | ///
32 | /// Semicolon separated list of paths containing unit test assemblies
33 | ///
34 | [Required]
35 | public string TestPaths { get; set; }
36 |
37 | ///
38 | /// Semicolon separated list of test assembly search strings used to find test assemblies
39 | ///
40 | public string TestSearchStrings { get; set; }
41 |
42 | ///
43 | /// Semicolon separated list of paths containing framework assemblies
44 | ///
45 | [Required]
46 | public string FrameworkPaths { get; set; }
47 |
48 | ///
49 | /// Path to the json config file containing the load suite configuration details
50 | ///
51 | [Required]
52 | public string ConfigPath { get; set; }
53 |
54 | ///
55 | /// Path to the project.json package config file to be used by all tests
56 | ///
57 | public string PackageConfigPath { get; set; }
58 |
59 | ///
60 | /// Path to the cache of previously discovered tests
61 | ///
62 | public string DiscoveryCachePath { get; set; }
63 |
64 | public override bool Execute()
65 | {
66 | if (DebugWaitForInput)
67 | {
68 | MessageBox.Show($"PID:{Process.GetCurrentProcess().Id} Attach debugger now.", "Debug GenerateStressSuiteTask", MessageBoxButton.OK);
69 | }
70 |
71 | try
72 | {
73 | CodeGenOutput.Redirect(new TaskLogOutputWriter(this.Log));
74 |
75 | LoadSuiteGenerator suiteGen = new LoadSuiteGenerator();
76 |
77 | suiteGen.GenerateSuite(this.ParseSeed(), this.SuiteName, this.SuitePath, this.ParseTestPaths(), this.ParseSearchStrings(), this.ParseFrameworkPaths(), this.GetSuiteConfig(), this.DiscoveryCachePath, this.UseLegacyProject, this.PackageConfigPath);
78 |
79 | return true;
80 | }
81 | catch (Exception e)
82 | {
83 | this.Log.LogErrorFromException(e);
84 |
85 | return false;
86 | }
87 | }
88 |
89 | private LoadSuiteConfig GetSuiteConfig()
90 | {
91 | return LoadSuiteConfig.Deserialize(this.ConfigPath);
92 | }
93 |
94 | private string[] ParseSearchStrings()
95 | {
96 | return (this.TestSearchStrings != null) ? this.TestSearchStrings.Split(';') : null;
97 | }
98 |
99 | private string[] ParseTestPaths()
100 | {
101 | return this.TestPaths.Split(';');
102 | }
103 |
104 | private string[] ParseFrameworkPaths()
105 | {
106 | return this.FrameworkPaths.Split(';');
107 | }
108 |
109 | private int ParseSeed()
110 | {
111 | int seed;
112 |
113 | if (this.Seed == null || !int.TryParse(this.Seed, out seed))
114 | {
115 | seed = new Random().Next();
116 | }
117 |
118 | return seed;
119 | }
120 |
121 | private class TaskLogOutputWriter : IOutputWriter
122 | {
123 | private TaskLoggingHelper _logHelper;
124 |
125 | public TaskLogOutputWriter(TaskLoggingHelper logHelper)
126 | {
127 | _logHelper = logHelper;
128 | }
129 |
130 | public void WriteError(string message)
131 | {
132 | _logHelper.LogError(message);
133 | }
134 |
135 | public void WriteInfo(string message)
136 | {
137 | _logHelper.LogMessage(message);
138 | }
139 |
140 | public void WriteWarning(string message)
141 | {
142 | _logHelper.LogWarning(message);
143 | }
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/stress.codegen/ITestDiscoverer.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace stress.codegen
13 | {
14 | public interface ITestDiscoverer
15 | {
16 | UnitTestInfo[] GetTests(TestAssemblyInfo assembly);
17 | }
18 |
19 | public interface ISourceFileGenerator
20 | {
21 | void GenerateSourceFile(LoadTestInfo loadTest);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadSuiteConfig.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using Newtonsoft.Json;
6 | using stress.execution;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 |
14 | namespace stress.codegen
15 | {
16 | public class LoadSuiteConfig
17 | {
18 | public LoadSuiteConfig()
19 | {
20 | this.LoadTestConfigs = new List();
21 | }
22 |
23 | public List LoadTestConfigs;
24 |
25 | public string Host;
26 |
27 | public void Serialize(string path)
28 | {
29 | // Serialize the RunConfiguration
30 | JsonSerializer serializer = JsonSerializer.CreateDefault();
31 |
32 | using (FileStream fs = new FileStream(path, FileMode.Create))
33 | {
34 | using (StreamWriter writer = new StreamWriter(fs))
35 | {
36 | serializer.Serialize(writer, this);
37 | }
38 | }
39 | }
40 |
41 | public static LoadSuiteConfig Deserialize(string path)
42 | {
43 | LoadSuiteConfig config = null;
44 |
45 | // Deserialize the RunConfiguration
46 | JsonSerializer serializer = JsonSerializer.CreateDefault();
47 |
48 | using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
49 | {
50 | using (StreamReader reader = new StreamReader(fs))
51 | {
52 | JsonTextReader jReader = new JsonTextReader(reader);
53 |
54 | // Call the Deserialize method to restore the object's state.
55 | config = serializer.Deserialize(jReader);
56 | }
57 | }
58 |
59 | return config;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadSuiteGenerator.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using stress.codegen.utils;
6 | using stress.execution;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 |
14 | namespace stress.codegen
15 | {
16 | public class LoadSuiteGenerator
17 | {
18 | private UnitTestSelector _unitTestSelector;
19 |
20 | public void GenerateSuite(int seed, string suiteName, string outputPath, string[] testPaths, string[] searchPatterns, string[] hintPaths, LoadSuiteConfig config, string cachePath = null, bool legacyProject = false, string globalPackageConfig = null)
21 | {
22 | Random rand = new Random(seed);
23 |
24 | int suiteTestCount = 0;
25 |
26 | _unitTestSelector = new UnitTestSelector();
27 |
28 | _unitTestSelector.Initialize(seed, testPaths, searchPatterns, hintPaths, cachePath);
29 |
30 | for (int iConfig = 0; iConfig < config.LoadTestConfigs.Count; iConfig++)
31 | {
32 | var loadTestConfig = config.LoadTestConfigs[iConfig];
33 |
34 | for (int i = 0; i < loadTestConfig.TestCount; i++)
35 | {
36 | var loadTestInfo = new LoadTestInfo(globalPackageConfig)
37 | {
38 | TestName = suiteName + "_" + suiteTestCount.ToString("X4"),
39 | Duration = loadTestConfig.Duration,
40 | LoadPatternType = typeof(StaticLoadPattern), //Type.GetType(loadTestConfig.LoadPattern),
41 | TestPatternType = typeof(RandomTestPattern), //Type.GetType(loadTestConfig.TestPattern),
42 | WorkerStrategyType = typeof(DedicatedThreadWorkerStrategy), //Type.GetType(loadTestConfig.WorkerStrategy),
43 | WorkerCount = loadTestConfig.NumWorkers,
44 | SelfDestruct = loadTestConfig.SelfDestruct,
45 | EnvironmentVariables = loadTestConfig.EnvironmentVariables,
46 | SuiteConfig = config,
47 | Seed = rand.Next(),
48 | };
49 |
50 | loadTestInfo.SourceDirectory = Path.Combine(outputPath, iConfig.ToString("00") + "_" + loadTestInfo.Duration.TotalHours.ToString("00.##") + "hr", loadTestInfo.TestName);
51 | loadTestInfo.UnitTests = _unitTestSelector.NextUnitTests(loadTestConfig.NumTests).ToArray();
52 |
53 | //build a list of all the sources files to generate for the load test
54 | var generators = new List()
55 | {
56 | new LoadTestSourceFileGenerator(),
57 | new ProgramSourceFileGenerator(),
58 | new ExecutionFileGeneratorWindows(),
59 | new ExecutionFileGeneratorLinux(),
60 | };
61 |
62 | //if we want to generate a legacy project file (i.e. ToF project file) use HelixToFProjectFileGenerator otherwise use LoadTestProjectFileGenerator
63 | var projectFileGenerator = legacyProject ? (ISourceFileGenerator)new HelixToFProjectFileGenerator() : (ISourceFileGenerator)new LoadTestProjectFileGenerator();
64 |
65 | if (!legacyProject)
66 | {
67 | generators.Add(new LoadTestProjectJsonFileGenerator());
68 | }
69 |
70 | //I believe the project file generator must be last, becuase it depends on discovering all the other source files
71 | //however the ordering beyond that should not matter
72 | generators.Add(projectFileGenerator);
73 |
74 | this.GenerateTestSources(loadTestInfo, generators);
75 | CodeGenOutput.Info($"Generated Load Test: {loadTestInfo.TestName}");
76 | suiteTestCount++;
77 | }
78 | }
79 | }
80 |
81 | private void GenerateTestSources(LoadTestInfo loadTest, IEnumerable sourceFileGenerators)
82 | {
83 | Directory.CreateDirectory(loadTest.SourceDirectory);
84 |
85 | CopyUnitTestAssemblyRefs(loadTest);
86 |
87 | foreach(var sourceGen in sourceFileGenerators)
88 | {
89 | sourceGen.GenerateSourceFile(loadTest);
90 | }
91 | }
92 |
93 | private void CopyUnitTestAssemblyRefs(LoadTestInfo loadTest)
94 | {
95 | string refDir = Path.Combine(loadTest.SourceDirectory, "refs");
96 |
97 | Directory.CreateDirectory(refDir);
98 |
99 | foreach (var assmPath in loadTest.UnitTests.Select(t => t.AssemblyPath).Union(loadTest.UnitTests.SelectMany(t => t.ReferenceInfo.ReferencedAssemblies.Select(ra => ra.Path))))
100 | {
101 | string destPath = Path.Combine(refDir, Path.GetFileName(assmPath));
102 |
103 | if (!File.Exists(destPath))
104 | {
105 | File.Copy(assmPath, destPath);
106 | }
107 | }
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadTestConfig.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace stress.codegen
12 | {
13 | public class LoadTestConfig
14 | {
15 | // The number of load tests we're generating for this template
16 | public int TestCount;
17 |
18 | // The number of unit tests in the load test
19 | public int NumTests;
20 |
21 | // The duration for this load test
22 | public TimeSpan Duration;
23 |
24 | // The number of workers used in the load test
25 | public int NumWorkers;
26 |
27 | // The unit test execution pattern for this load test
28 | public string TestPattern;
29 |
30 | //the load patern for this load test
31 | public string LoadPattern;
32 |
33 | // The execution strategy for this load test
34 | public string WorkerStrategy;
35 |
36 | //if true the load test will exit with unhandled exception to force dump collection
37 | public bool SelfDestruct;
38 |
39 | public Dictionary EnvironmentVariables;
40 |
41 | public LoadTestConfig()
42 | {
43 | EnvironmentVariables = new Dictionary();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadTestInfo.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Reflection;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 |
13 | namespace stress.codegen
14 | {
15 | public class LoadTestInfo
16 | {
17 | private string _globalPackageConfigPath = null;
18 |
19 | public LoadTestInfo(string globalPackageConfigPath)
20 | {
21 | _globalPackageConfigPath = globalPackageConfigPath;
22 |
23 | this.SourceFiles = new List();
24 | }
25 |
26 | public int Seed { get; set; }
27 |
28 | public string TestName { get; set; }
29 |
30 | public Type TestPatternType { get; set; }
31 |
32 | public Type LoadPatternType { get; set; }
33 |
34 | public Type WorkerStrategyType { get; set; }
35 |
36 | public TimeSpan Duration { get; set; }
37 |
38 | public int WorkerCount { get; set; }
39 |
40 | public bool SelfDestruct { get; set; }
41 |
42 | public string SourceDirectory { get; set; }
43 |
44 | public IEnumerable UnitTests { get; set; }
45 |
46 | public IList SourceFiles { get; private set; }
47 |
48 | public ProjectJsonDependencyInfo PackageInfo
49 | {
50 | get
51 | {
52 | if (string.IsNullOrEmpty(_globalPackageConfigPath))
53 | {
54 | var jsonRefInfo = this.UnitTests.Select(ut => ut.ReferenceInfo.PackageInfo);
55 |
56 | return ProjectJsonDependencyInfo.MergeToLatest(jsonRefInfo);
57 | }
58 | else
59 | {
60 | return ProjectJsonDependencyInfo.FromFile(_globalPackageConfigPath);
61 | }
62 | }
63 | }
64 |
65 | public IEnumerable AssemblyAliases
66 | {
67 | get
68 | {
69 | return this.UnitTests.Select(t => t.AssemblyAlias).Distinct();
70 | }
71 | }
72 |
73 | public Dictionary EnvironmentVariables { get; set; }
74 |
75 | public LoadSuiteConfig SuiteConfig { get; set; }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadTestProjectFileGenerator.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using stress.execution;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.IO;
9 | using System.Linq;
10 | using System.Reflection;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 |
14 | namespace stress.codegen
15 | {
16 | public class LoadTestProjectFileGenerator : ISourceFileGenerator
17 | {
18 | public void GenerateSourceFile(LoadTestInfo loadTest)
19 | {
20 | string refSnippet = GenerateTestReferencesSnippet(loadTest);
21 |
22 | string itemSnippet = GenerateSourceFileItemsSnippet(loadTest);
23 |
24 | string propertySnippet = GenerateTestPropertiesSnippet(loadTest);
25 |
26 | //format the project template {0} source files, {1} test references, {2} test properties
27 | string projFileContent = string.Format(PROJECT_TEMPLATE, itemSnippet, refSnippet, propertySnippet);
28 |
29 | File.WriteAllText(Path.Combine(loadTest.SourceDirectory, loadTest.TestName + ".csproj"), projFileContent);
30 | }
31 |
32 | private static string GenerateTestPropertiesSnippet(LoadTestInfo loadTest)
33 | {
34 | //timeout = test duration + 5 minutes for dump processing ect.
35 | string timeoutInSeconds = Convert.ToInt32((loadTest.Duration + TimeSpan.FromMinutes(5)).TotalSeconds).ToString();
36 |
37 | string propertyString = $@"
38 | {timeoutInSeconds}";
39 |
40 | return propertyString;
41 | }
42 |
43 | private static string GenerateSourceFileItemsSnippet(LoadTestInfo loadTest)
44 | {
45 | StringBuilder snippet = new StringBuilder();
46 |
47 | foreach (var file in loadTest.SourceFiles)
48 | {
49 | string itemSnippet = string.Empty;
50 | if (file.SourceFileAction == SourceFileAction.Compile)
51 | {
52 | itemSnippet = $@"
53 | ";
54 | }
55 | else if (file.SourceFileAction == SourceFileAction.Binplace)
56 | {
57 | itemSnippet = $@"
58 |
59 | PreserveNewest
60 | ";
61 | }
62 |
63 | snippet.Append(itemSnippet);
64 | }
65 |
66 | return snippet.ToString();
67 | }
68 |
69 | private static string GenerateTestReferencesSnippet(LoadTestInfo loadTest)
70 | {
71 | HashSet uniqueAssemblies = new HashSet();
72 |
73 | var packageInfo = loadTest.PackageInfo;
74 |
75 | StringBuilder snippet = new StringBuilder();
76 | foreach (var test in loadTest.UnitTests)
77 | {
78 | if (uniqueAssemblies.Add(test.AssemblyName))
79 | {
80 | string refSnippet = $@"
81 |
82 | $(MSBuildThisFileDirectory)\refs\{test.AssemblyName}
83 | {UnitTestInfo.GetAssemblyAlias(test.AssemblyName)}
84 | ";
85 |
86 | snippet.Append(refSnippet);
87 | }
88 |
89 | foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies)
90 | {
91 | if (uniqueAssemblies.Add(assmref.Name) && packageInfo.dependencies[Path.GetFileNameWithoutExtension(assmref.Name)] == null)
92 | {
93 | string refSnippet = $@"
94 |
95 | $(MSBuildThisFileDirectory)\refs\{assmref.Name}
96 | {UnitTestInfo.GetAssemblyAlias(assmref.Name)}
97 | ";
98 |
99 | snippet.Append(refSnippet);
100 | }
101 | }
102 | }
103 |
104 | string stressexecutionsnippet = $@"
105 |
106 | {typeof(stress.execution.UnitTest).Assembly.Location}
107 | ";
108 |
109 | snippet.Append(stressexecutionsnippet);
110 |
111 | return snippet.ToString();
112 | }
113 |
114 | private const string PROJECT_TEMPLATE = @"
115 |
116 |
117 |
118 | false
119 | true
120 | false
121 | stress.execution.dll
122 |
123 |
124 | {2}
125 |
126 |
127 | {0}
128 |
129 |
130 | {1}
131 |
132 |
133 | ";
134 |
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/stress.codegen/LoadTestProjectJsonFileGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace stress.codegen
9 | {
10 | public class LoadTestProjectJsonFileGenerator : ISourceFileGenerator
11 | {
12 | public void GenerateSourceFile(LoadTestInfo loadTest)
13 | {
14 | var loadTestRefInfo = loadTest.PackageInfo;
15 |
16 | var srcFilePath = Path.Combine(loadTest.SourceDirectory, "project.json");
17 |
18 | loadTestRefInfo.ToFile(srcFilePath);
19 |
20 | loadTest.SourceFiles.Add(new SourceFileInfo("project.json", SourceFileAction.None));
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/stress.codegen/MergeAllProjectJsonsTask.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Microsoft.Build.Framework;
6 | using Microsoft.Build.Utilities;
7 | using Newtonsoft.Json;
8 | using System.IO;
9 | using System.Diagnostics;
10 | using System.Windows;
11 | using Newtonsoft.Json.Linq;
12 |
13 | namespace stress.codegen
14 | {
15 |
16 | // This merge class walks all of the directory tree of InPath and produces a merged project json file. Then we
17 | // 'trim it down' to the type of run we'd like to support, and write that final project.json to disk at OutPath.
18 | public class MergeAllProjectJsonsTask : Task
19 | {
20 | // assumptions:
21 | // we assume that anyos test project.jsons (AND ONLY THESE; any other ones will mess up the merge) are
22 | // present in the directory or subdirectories of InPath
23 | [Required]
24 | public string InPath { get; set; }
25 |
26 | // the path to the project.json we are spawning.
27 | [Required]
28 | public string OutPath { get; set; }
29 |
30 | // not currently being used, but they exist to allow tests to be 'upgraded' in place.
31 | public string OldPrerelease { get; set; }
32 | public string NewPrerelease { get; set; }
33 |
34 | // set this to true when you want to debug. It causes a message box to show with the process id of the executing
35 | // msbuild instance that you can attach your debugger to. The execution of code will sit until you click ok.
36 | public bool Debug { get; set; }
37 |
38 | // this method walks the directory tree of inPath and uses the Newtonsoft JObject::Merge to merge together
39 | // our project jsons.
40 | // we require there to be at least ONE project.json present somewhere in the directory tree of inPath
41 | private JObject MergeProjectJsonsIn(string inPath)
42 | {
43 | var projectJsons = Directory.EnumerateFiles(InPath, "project.json", SearchOption.AllDirectories).Select(p => JObject.Parse(File.ReadAllText(p)));
44 | JObject merged = new JObject(projectJsons.First());
45 |
46 | foreach (var file in projectJsons)
47 | {
48 | //
49 | merged.Merge(file);
50 | }
51 |
52 | return merged;
53 | }
54 |
55 | // this method:
56 | // strips out test-runtime object if it is present in the dependencies list.
57 | // removes all frameworks except for the one that is to be targeted for the run
58 | private void ProduceAnyOsProjectJson(string outPath, JObject merged, string targetFramework)
59 | {
60 | // remove test-runtime if it is present.
61 | (merged["dependencies"] as JObject)?.Property("test-runtime")?.Remove();
62 |
63 | // remove all supports.
64 | merged["supports"]?.Children().ToList().ForEach(x => x.Remove());
65 |
66 | // remove all frameworks except the specified one
67 | merged["frameworks"]?.Children().ToList().ForEach(x => x.Remove());
68 | merged["frameworks"][targetFramework] = new JObject();
69 |
70 | // since we are creating an anyos test launcher we should list all known runtimes here.
71 | merged["runtimes"] = new JObject();
72 | merged["runtimes"]["win10-x64"] = new JObject();
73 | merged["runtimes"]["win7-x64"] = new JObject();
74 | merged["runtimes"]["win7-x86"] = new JObject();
75 | merged["runtimes"]["ubuntu.14.04-x64"] = new JObject();
76 | merged["runtimes"]["osx.10.10-x64"] = new JObject();
77 | merged["runtimes"]["centos.7-x64"] = new JObject();
78 | merged["runtimes"]["rhel.7-x64"] = new JObject();
79 | merged["runtimes"]["debian.8-x64"] = new JObject();
80 |
81 | // serialize, then write the project json file to OutPath
82 | File.WriteAllText(OutPath, JsonConvert.SerializeObject(merged));
83 | }
84 |
85 | public override bool Execute()
86 | {
87 | if (Debug)
88 | {
89 | MessageBox.Show($"PID:{Process.GetCurrentProcess().Id} Attach debugger now.", "Debug GenerateStressSuiteTask", MessageBoxButton.OK);
90 | }
91 |
92 | ProduceAnyOsProjectJson(OutPath, MergeProjectJsonsIn(InPath), "netcoreapp1.0");
93 |
94 | return true;
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/stress.codegen/ProgramSourceFileGenerator.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace stress.codegen
13 | {
14 | public class ProgramSourceFileGenerator : ISourceFileGenerator
15 | {
16 | public void GenerateSourceFile(LoadTestInfo loadTest)
17 | {
18 | string sourceCode = $@"
19 | using System;
20 | using System.Threading;
21 | using System.Threading.Tasks;
22 | using stress.execution;
23 |
24 | namespace stress.generated
25 | {{
26 | public static class Program
27 | {{
28 | static private bool s_selfdestruct = {loadTest.SelfDestruct.ToString().ToLower()};
29 |
30 | public static void Main(string[] args)
31 | {{
32 | TimeSpan duration = TimeSpan.Parse(""{loadTest.Duration.ToString()}"");
33 |
34 | CancellationTokenSource tokenSource = new CancellationTokenSource(duration);
35 |
36 | LoadTestClass.LoadTestMethod(tokenSource.Token);
37 |
38 | if(s_selfdestruct)
39 | {{
40 | SelfDestruct.WithException();
41 | }}
42 | }}
43 | }}
44 | }}
45 | ";
46 | string srcFilePath = Path.Combine(loadTest.SourceDirectory, "Program.cs");
47 |
48 | File.WriteAllText(srcFilePath, sourceCode);
49 |
50 | loadTest.SourceFiles.Add(new SourceFileInfo("Program.cs", SourceFileAction.Compile));
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/stress.codegen/ProjectJsonDependencyInfo.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Newtonsoft.Json.Linq;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace stress.codegen
11 | {
12 | public class ProjectJsonDependencyInfo
13 | {
14 | public JObject dependencies;
15 |
16 | public JObject frameworks;
17 |
18 | public JObject runtimes;
19 |
20 | public JObject supports;
21 |
22 | public ProjectJsonDependencyInfo()
23 | {
24 | dependencies = new JObject();
25 |
26 | frameworks = new JObject();
27 |
28 | runtimes = new JObject();
29 |
30 | supports = new JObject();
31 |
32 | supports.Add("coreFx.Test.netcoreapp1.0", new JObject());
33 | }
34 |
35 | public void ToFile(string path)
36 | {
37 | File.WriteAllText(path, JsonConvert.SerializeObject(this));
38 | }
39 |
40 | public static ProjectJsonDependencyInfo FromFile(string path)
41 | {
42 | ProjectJsonDependencyInfo dependInfo = null;
43 | //if a project.json file exists next to the test binary load it
44 | if (File.Exists(path))
45 | {
46 | var data = JObject.Parse(File.ReadAllText(path));
47 |
48 | (data["dependencies"] as JObject)?.Property("test-runtime")?.Remove();
49 |
50 | dependInfo = data.ToObject();
51 | }
52 |
53 | return dependInfo;
54 | }
55 |
56 | public static JEnumerable FetchPrimaryDependenciesProperties(JObject projectJsonObj)
57 | {
58 | return projectJsonObj["dependencies"].Children();
59 | }
60 |
61 |
62 |
63 | public static ProjectJsonDependencyInfo MergeToLatest(IEnumerable projectJsons, string oldprerelease = null, string newprerelease = null)
64 | {
65 | var merged = new ProjectJsonDependencyInfo();
66 |
67 | merged.dependencies = new JObject();
68 |
69 | foreach (var pjson in projectJsons)
70 | {
71 | if (pjson.dependencies != null)
72 | {
73 | foreach (var depend in pjson.dependencies)
74 | {
75 | var depVer = ComplexVersion.Parse(depend.Value.Value());
76 |
77 | if (newprerelease != null && depVer.Prerelease != null && depVer.Prerelease == oldprerelease)
78 | {
79 | depVer.Prerelease = newprerelease;
80 | }
81 |
82 | //if the dependency is not present in the merged dependencies OR the version in the current pjson is a greater than the one in merged
83 | //if string.Compare returns > 0 then depend.Value is greater than the one in merged, this should mean a later version
84 | if (merged.dependencies[depend.Key] == null || (ComplexVersion.Parse(merged.dependencies[depend.Key].Value()) < depVer))
85 | {
86 | merged.dependencies[depend.Key] = depVer.ToString();
87 | }
88 | }
89 | }
90 | }
91 |
92 | return merged;
93 | }
94 |
95 | private class ComplexVersion
96 | {
97 | public Version StrongVersion;
98 | public string Prerelease;
99 |
100 | public static ComplexVersion Parse(string verStr)
101 | {
102 | ComplexVersion ver = null;
103 |
104 | if(verStr != null)
105 | {
106 | var splitVerStr = verStr.Split(new char[] { '-' }, 2);
107 |
108 | var strongVerStr = splitVerStr[0];
109 |
110 | var prerelVerStr = splitVerStr.Length > 1 ? splitVerStr[1] : null;
111 |
112 | Version strongVer;
113 |
114 | if(Version.TryParse(strongVerStr, out strongVer))
115 | {
116 | ver = new ComplexVersion() { StrongVersion = strongVer, Prerelease = prerelVerStr };
117 | }
118 | }
119 |
120 | return ver;
121 | }
122 |
123 | public static bool operator >(ComplexVersion x, ComplexVersion y)
124 | {
125 | return (x.StrongVersion > y.StrongVersion) || (y.Prerelease == null || ((x.Prerelease != null) && (string.Compare(x.Prerelease, y.Prerelease, StringComparison.InvariantCultureIgnoreCase) > 0)));
126 | }
127 |
128 | public static bool operator <(ComplexVersion x, ComplexVersion y)
129 | {
130 | return (x.StrongVersion < y.StrongVersion) || (x.Prerelease == null && y.Prerelease != null) || ((y.Prerelease != null) && (string.Compare(x.Prerelease, y.Prerelease, StringComparison.InvariantCultureIgnoreCase) < 0));
131 | }
132 |
133 | public override string ToString()
134 | {
135 | string verStr = this.StrongVersion.ToString();
136 |
137 | if (!string.IsNullOrEmpty(this.Prerelease))
138 | {
139 | verStr += "-" + this.Prerelease;
140 | }
141 |
142 | return verStr;
143 | }
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/stress.codegen/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 | //
4 |
5 | using System.Reflection;
6 | using System.Runtime.CompilerServices;
7 | using System.Runtime.InteropServices;
8 |
9 | // General Information about an assembly is controlled through the following
10 | // set of attributes. Change these attribute values to modify the information
11 | // associated with an assembly.
12 | [assembly: AssemblyTitle("stress.codegen")]
13 | [assembly: AssemblyDescription("")]
14 | [assembly: AssemblyConfiguration("")]
15 | [assembly: AssemblyCompany("")]
16 | [assembly: AssemblyProduct("stress.codegen")]
17 | [assembly: AssemblyCopyright("Copyright \u00A9 2015")]
18 | [assembly: AssemblyTrademark("")]
19 | [assembly: AssemblyCulture("")]
20 |
21 | // Setting ComVisible to false makes the types in this assembly not visible
22 | // to COM components. If you need to access a type in this assembly from
23 | // COM, set the ComVisible attribute to true on that type.
24 | [assembly: ComVisible(false)]
25 |
26 | // The following GUID is for the ID of the typelib if this project is exposed to COM
27 | [assembly: Guid("b60a62ba-77b2-49fa-94b8-cffd2c3f5825")]
28 |
29 | // Version information for an assembly consists of the following four values:
30 | //
31 | // Major Version
32 | // Minor Version
33 | // Build Number
34 | // Revision
35 | //
36 | // You can specify all the values or you can default the Build and Revision Numbers
37 | // by using the '*' as shown below:
38 | // [assembly: AssemblyVersion("1.0.*")]
39 | [assembly: AssemblyVersion("1.0.0.0")]
40 | [assembly: AssemblyFileVersion("1.0.0.0")]
41 |
--------------------------------------------------------------------------------
/src/stress.codegen/SourceFileInfo.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace stress.codegen
12 | {
13 | // enum with action
14 | // Compile, Binplace, Resource
15 | public enum SourceFileAction
16 | {
17 | None,
18 | Binplace,
19 | Compile,
20 | Resource
21 | }
22 |
23 | public class SourceFileInfo
24 | {
25 | public string RelativePath { get; set; }
26 |
27 | public SourceFileAction SourceFileAction { get; set; }
28 |
29 | public SourceFileInfo()
30 | {
31 | RelativePath = "";
32 | SourceFileAction = SourceFileAction.None;
33 | }
34 |
35 | public SourceFileInfo(string relativePath, SourceFileAction sourceFileAction)
36 | {
37 | RelativePath = relativePath;
38 | SourceFileAction = sourceFileAction;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/stress.codegen/StandAloneTestDiscoverer.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace stress.codegen
13 | {
14 | public class StandAloneTestDiscoverer : ITestDiscoverer
15 | {
16 | public UnitTestInfo[] GetTests(TestAssemblyInfo assemblyInfo)
17 | {
18 | List assmRefs = new List();
19 |
20 | foreach (var assmName in assemblyInfo.Assembly.GetReferencedAssemblies())
21 | {
22 | assmRefs.Add(assmName.Name);
23 | }
24 |
25 | UnitTestInfo[] tests = null;
26 |
27 | MethodInfo entryInfo = assemblyInfo.Assembly.EntryPoint;
28 |
29 | if (entryInfo != null)
30 | {
31 | UnitTestInfo test = new UnitTestInfo()
32 | {
33 | AssemblyPath = assemblyInfo.Assembly.Location,
34 | ReferenceInfo = assemblyInfo.ReferenceInfo,
35 | Class = new TestClassInfo { FullName = entryInfo.DeclaringType.FullName, IsAbstract = entryInfo.DeclaringType.IsAbstract, IsGenericType = entryInfo.DeclaringType.IsGenericType, IsPublic = entryInfo.DeclaringType.IsPublic },
36 | Method = new TestMethodInfo { Name = entryInfo.Name, IsAbstract = entryInfo.IsAbstract, IsGenericMethodDefinition = entryInfo.IsGenericMethodDefinition, IsPublic = entryInfo.IsPublic, IsStatic = entryInfo.IsStatic },
37 | };
38 |
39 | tests = new UnitTestInfo[] { test };
40 | }
41 |
42 | return tests ?? new UnitTestInfo[] { };
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/stress.codegen/ToFProjectFileGenerator.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.IO;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace stress.codegen
13 | {
14 | public static class ToFProjectFileGenerator
15 | {
16 | public static void GenerateProjectFile(LoadTestInfo loadTest)
17 | {
18 | string refSnippet = GenerateReferencesSnippet(loadTest);
19 | string fxSnippet = GenerateFrameworkReferencesSnippet(loadTest);
20 | string itemSnippet = GenerateSourceFileItemsSnippet(loadTest);
21 | string projFileContent = string.Format(PROJECT_TEMPLATE, refSnippet, itemSnippet); //, fxSnippet);
22 |
23 | File.WriteAllText(Path.Combine(loadTest.SourceDirectory, loadTest.TestName + ".csproj"), projFileContent);
24 | }
25 |
26 | private static string GenerateSourceFileItemsSnippet(LoadTestInfo loadTest)
27 | {
28 | StringBuilder snippet = new StringBuilder();
29 |
30 | foreach (var file in loadTest.SourceFiles)
31 | {
32 | string itemSnippet = string.Empty;
33 | if (file.SourceFileAction == SourceFileAction.Compile)
34 | {
35 | itemSnippet = $@"
36 | ";
37 | }
38 | else if (file.SourceFileAction == SourceFileAction.Binplace)
39 | {
40 | itemSnippet = $@"
41 |
42 | PreserveNewest
43 | ";
44 | }
45 |
46 | snippet.Append(itemSnippet);
47 | }
48 |
49 | return snippet.ToString();
50 | }
51 |
52 | private static string GenerateReferencesSnippet(LoadTestInfo loadTest)
53 | {
54 | HashSet uniqueAssemblies = new HashSet();
55 |
56 | StringBuilder snippet = new StringBuilder();
57 | foreach (var test in loadTest.UnitTests)
58 | {
59 | if (uniqueAssemblies.Add(test.AssemblyPath))
60 | {
61 | string refSnippet = $@"
62 |
63 | $(MSBuildThisFileDirectory)\refs\{test.AssemblyName}
64 | {UnitTestInfo.GetAssemblyAlias(test.AssemblyPath)}
65 | true
66 | ";
67 |
68 | snippet.Append(refSnippet);
69 | }
70 |
71 | foreach (var assmref in test.ReferenceInfo.ReferencedAssemblies)
72 | {
73 | if (uniqueAssemblies.Add(assmref.Path))
74 | {
75 | string refSnippet = $@"
76 |
77 | $(MSBuildThisFileDirectory)\refs\{assmref.Name}
78 | {UnitTestInfo.GetAssemblyAlias(assmref.Path)}
79 | true
80 | ";
81 |
82 | snippet.Append(refSnippet);
83 | }
84 | }
85 | }
86 |
87 | return snippet.ToString();
88 | }
89 |
90 | private static string GenerateFrameworkReferencesSnippet(LoadTestInfo loadTest)
91 | {
92 | HashSet uniqueAssemblies = new HashSet();
93 |
94 | StringBuilder snippet = new StringBuilder();
95 |
96 | AssemblyReferenceSet fxRefSet = new AssemblyReferenceSet();
97 |
98 | foreach (var testfxRefs in loadTest.UnitTests.Select(t => t.ReferenceInfo.FrameworkReferences))
99 | {
100 | fxRefSet.UnionWith(testfxRefs);
101 | }
102 |
103 | foreach (var fxref in fxRefSet)
104 | {
105 | string refSnippet;
106 |
107 | if (fxref.Version != "4.0.0.0")
108 | {
109 | refSnippet = $@"
110 | ";
111 | }
112 | else
113 | {
114 | refSnippet = $@"
115 |
116 | {fxref.Version}
117 | ";
118 | }
119 |
120 | snippet.Append(refSnippet);
121 | }
122 |
123 | snippet.Append(@"
124 |
125 | true
126 | 1.0.0-alpha-00003
127 | ");
128 |
129 | return snippet.ToString();
130 | }
131 | private const string PROJECT_TEMPLATE = @"
132 |
133 |
134 |
135 | false
136 |
137 |
138 | sschaab
139 | BuildAndRun
140 | Weekly
141 |
142 |
143 | {1}
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | {0}
154 |
155 |
156 |
157 | {{7E6BD405-347A-4DDE-AE19-43372FA7D697}}
158 |
159 |
160 |
161 | ";
162 |
163 | private static readonly string[] s_systemRefs = new string[] { "System.Runtime", "System.Runtime.Extensions", "System.Linq", "System.Threading", "System.Threading.Tasks", "System.Collections" };
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/stress.codegen/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/stress.codegen/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/stress.codegen/resources/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace stress.codegen.resources {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("stress.codegen.resources.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Byte[].
65 | ///
66 | internal static byte[] runstress {
67 | get {
68 | object obj = ResourceManager.GetObject("runstress", resourceCulture);
69 | return ((byte[])(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/stress.codegen/resources/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | runstress.sh;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
--------------------------------------------------------------------------------
/src/stress.codegen/resources/runstress.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #download the dumpling client
4 | wget https://dumpling.azurewebsites.net/api/client/dumpling.py
5 |
6 | #install and make sure the client script is up to doate
7 | $HELIX_PYTHONPATH dumpling.py install --update
8 |
9 | #install the tooling without --update so that it will not pull down the debugger if it's already installed
10 | $HELIX_PYTHONPATH ~/.dumpling/dumpling.py install --full
11 |
12 | #Set the rlimit for coredumps
13 | echo "executing ulimit -c unlimited"
14 | ulimit -c unlimited
15 |
16 |
17 | echo "executing ulimit -a"
18 | ulimit -a
19 |
20 | echo 0x3F > /proc/self/coredump_filter
21 |
22 | #run the specified command line
23 | echo "executing $*"
24 | $*
25 |
26 | export _EXITCODE=$?
27 | echo command exited with ExitCode: $_EXITCODE
28 |
29 | if [ $_EXITCODE != 0 ]
30 | then
31 | #This is a temporary hack workaround for the fact that the process exits before the coredump file is completely written
32 | #We need to replace this with a more hardened way to guaruntee that we don't zip and upload before the coredump is available
33 | echo "command failed waiting for coredump"
34 | sleep 2m
35 |
36 | #test if the core file was created.
37 | #this condition makes the assumption that the file will be name either 'core' or 'core.*' and be in the current directory which is true all the distros tested so far
38 | #ideally this would be constrained more by setting /proc/sys/kernel/core_pattern to a specific file to look for
39 | #however we don't have root permissions from this script when executing in helix so this would have to depend on machine setup
40 | _corefile=$(ls $PWD | grep -E --max-count=1 '^core(\..*)?$')
41 |
42 | if [ -n '$_corefile' ]
43 | then
44 | echo "uploading core to dumpling service"
45 |
46 | echo "executing $HELIX_PYTHONPATH ~/.dumpling/dumpling.py upload --dumppath $_corefile --noprompt --triage full --displayname $STRESS_TESTID --incpaths $PWD --properties $DUMPLING_PROPERTIES"
47 | $HELIX_PYTHONPATH ~/.dumpling/dumpling.py upload --dumppath $_corefile --noprompt --triage full --displayname $STRESS_TESTID --incpaths "$PWD" --properties $DUMPLING_PROPERTIES
48 | else
49 | echo "no coredump file was found in $PWD"
50 | fi
51 |
52 | #the following code zips and uploads the entire execution directory to the helix results store
53 | #it is here as a backup source of dump file storage until we are satisfied that the uploading dumps to
54 | #the dumpling service is solid and complete. After that this can be removed as it is redundant
55 | echo "zipping work item data for coredump analysis"
56 | echo "executing $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py -zipFile $HELIX_WORKITEM_ROOT/$STRESS_TESTID.zip $PWD"
57 | $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/zip_script.py -zipFile $HELIX_WORKITEM_ROOT/$STRESS_TESTID.zip "$PWD"
58 |
59 | echo "uploading coredump zip to $HELIX_RESULTS_CONTAINER_URI$STRESS_TESTID.zip analysis"
60 | echo "executing $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/$STRESS_TESTID.zip -result_name $STRESS_TESTID.zip -upload_client_type Blob"
61 | $HELIX_PYTHONPATH $HELIX_SCRIPT_ROOT/upload_result.py -result $HELIX_WORKITEM_ROOT/$STRESS_TESTID.zip -result_name $STRESS_TESTID.zip -upload_client_type Blob
62 | fi
63 |
64 | exit $_EXITCODE
--------------------------------------------------------------------------------
/src/stress.codegen/stress.codegen.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B60A62BA-77B2-49FA-94B8-CFFD2C3F5825}
8 | Library
9 | Properties
10 | stress.codegen
11 | stress.codegen
12 | 512
13 | SAK
14 | SAK
15 | SAK
16 | SAK
17 |
18 |
19 | .NETFramework
20 | v4.5
21 |
22 |
23 | true
24 | full
25 | false
26 | DEBUG;TRACE
27 | prompt
28 | 4
29 |
30 |
31 | pdbonly
32 | true
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | ..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll
44 | True
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | {7e1e57d9-8587-4ea1-86f7-02813819b118}
96 | stress.execution
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
106 |
107 |
108 |
115 |
--------------------------------------------------------------------------------
/src/stress.codegen/utils/Output.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Threading;
11 |
12 | namespace stress.codegen.utils
13 | {
14 | public interface IOutputWriter
15 | {
16 | void WriteInfo(string message);
17 |
18 | void WriteWarning(string message);
19 |
20 | void WriteError(string message);
21 | }
22 |
23 |
24 | public class ConsoleOutputWriter : IOutputWriter
25 | {
26 | public void WriteInfo(string message)
27 | {
28 | WriteToConsole(message);
29 | }
30 |
31 | public void WriteWarning(string message)
32 | {
33 | WriteToConsole(message, ConsoleColor.Yellow);
34 | }
35 |
36 | public void WriteError(string message)
37 | {
38 | WriteToConsole(message, ConsoleColor.Red);
39 | }
40 |
41 | private static void WriteToConsole(string message, ConsoleColor? color = null)
42 | {
43 | lock (s_consoleLock)
44 | {
45 | var origFgColor = Console.ForegroundColor;
46 |
47 | if (color.HasValue)
48 | {
49 | Console.ForegroundColor = color.Value;
50 | }
51 |
52 | Console.WriteLine(message);
53 |
54 | Console.ForegroundColor = origFgColor;
55 | }
56 | }
57 |
58 | private static object s_consoleLock = new object();
59 | }
60 |
61 | //if TaskLog is
62 | //outputs to the console with color formatting by default
63 | public class CodeGenOutput
64 | {
65 | private static IOutputWriter s_writer = new ConsoleOutputWriter();
66 |
67 | private CodeGenOutput() { }
68 |
69 | //public static MSBuild.TaskLoggingHelper TaskLog { get; set; }
70 |
71 | public static void Redirect(IOutputWriter writer)
72 | {
73 | s_writer = writer;
74 | }
75 |
76 | public static void Info(string message)
77 | {
78 | s_writer.WriteInfo(message);
79 | }
80 |
81 | public static void Warning(string message)
82 | {
83 | s_writer.WriteWarning(message);
84 | }
85 |
86 | public static void Error(string message)
87 | {
88 | s_writer.WriteError(message);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/stress.execution.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Microsoft.DotNet.stress.execution
5 | 1.0.0.1
6 | DotNet Stress Execution
7 | sschaab@microsoft.com
8 | Microsoft
9 |
10 | Contains tooling for the composition of .NET stress tests
11 |
12 | Supported platforms:
13 | - Desktop .NET 4.6
14 | - .NET Core
15 | - Universal Windows Apps 10+
16 |
17 |
18 | en-US
19 | https://github.com/dotnet/corefx-tools
20 | https://raw.githubusercontent.com/dotnet/corefx-tools/master/LICENSE
21 | http://go.microsoft.com/fwlink/?LinkID=288859
22 | false
23 |
24 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/src/stress.execution/ActionUnitTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace stress.execution
8 | {
9 | public class ActionUnitTest : UnitTest
10 | {
11 | public ActionUnitTest(Action action = null, bool trapExceptions = true)
12 | : base(trapExceptions)
13 | {
14 | this.Action = action;
15 | }
16 |
17 | public Action Action { get; set; }
18 |
19 | protected override void ExecuteTest()
20 | {
21 | this.Action();
22 | }
23 |
24 |
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/stress.execution/AsyncWorkerStrategy.cs:
--------------------------------------------------------------------------------
1 | // Licensed to the .NET Foundation under one or more agreements.
2 | // The .NET Foundation licenses this file to you under the MIT license.
3 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace stress.execution
13 | {
14 | public class AsyncWorkerStrategy : IWorkerStrategy
15 | {
16 | public void SpawnWorker(ITestPattern pattern, CancellationToken cancelToken)
17 | {
18 | Task throwaway = this.ExecuteWorkerAsync(pattern, cancelToken);
19 | }
20 |
21 | public async Task ExecuteWorkerAsync(ITestPattern pattern, CancellationToken cancelToken)
22 | {
23 | while (!cancelToken.IsCancellationRequested)
24 | {
25 | UnitTest test = pattern.GetNextTest();
26 |
27 | await this.ExecuteTestAsync(test, cancelToken);
28 | }
29 | }
30 |
31 | public async Task ExecuteTestAsync(UnitTest test, CancellationToken cancelToken)
32 | {
33 | TaskCompletionSource