Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4b52e7da
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4b52e7da
编写于
2月 19, 2016
作者:
J
Jared Parsons
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #8943 from jaredpar/fix-cache
Fix an issue in the test caching layer
上级
5edb9a8a
0c657bb9
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
131 addition
and
82 deletion
+131
-82
src/Tools/Source/RunTests/Cache/CachingTestExecutor.cs
src/Tools/Source/RunTests/Cache/CachingTestExecutor.cs
+42
-22
src/Tools/Source/RunTests/Cache/IDataStorage.cs
src/Tools/Source/RunTests/Cache/IDataStorage.cs
+26
-2
src/Tools/Source/RunTests/Cache/LocalDataStorage.cs
src/Tools/Source/RunTests/Cache/LocalDataStorage.cs
+13
-29
src/Tools/Source/RunTests/ITestExecutor.cs
src/Tools/Source/RunTests/ITestExecutor.cs
+2
-0
src/Tools/Source/RunTests/ProcessTestExecutor.cs
src/Tools/Source/RunTests/ProcessTestExecutor.cs
+48
-29
未找到文件。
src/Tools/Source/RunTests/Cache/CachingTestExecutor.cs
浏览文件 @
4b52e7da
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System
;
using
System.IO
;
using
System.Text
;
using
System.Threading
;
...
...
@@ -20,6 +21,11 @@ internal CachingTestExecutor(Options options, ITestExecutor testExecutor, IDataS
_contentUtil
=
new
ContentUtil
(
options
);
}
public
string
GetCommandLine
(
string
assemblyPath
)
{
return
_testExecutor
.
GetCommandLine
(
assemblyPath
);
}
public
async
Task
<
TestResult
>
RunTestAsync
(
string
assemblyPath
,
CancellationToken
cancellationToken
)
{
var
contentFile
=
_contentUtil
.
GetTestResultContentFile
(
assemblyPath
);
...
...
@@ -31,16 +37,17 @@ public async Task<TestResult> RunTestAsync(string assemblyPath, CancellationToke
Logger
.
Log
(
builder
.
ToString
());
TestResult
testResult
;
if
(!
_dataStorage
.
TryGetTestResult
(
contentFile
.
Checksum
,
out
testResult
))
CachedTestResult
cachedTestResult
;
if
(!
_dataStorage
.
TryGetCachedTestResult
(
contentFile
.
Checksum
,
out
cachedTestResult
))
{
Logger
.
Log
(
$"
{
Path
.
GetFileName
(
assemblyPath
)}
- running"
);
testResult
=
await
_testExecutor
.
RunTestAsync
(
assemblyPath
,
cancellationToken
);
Logger
.
Log
(
$"
{
Path
.
GetFileName
(
assemblyPath
)}
- caching"
);
_dataStorage
.
Add
TestResult
(
contentFile
,
testResult
);
Cache
TestResult
(
contentFile
,
testResult
);
}
else
{
testResult
=
Migrate
(
t
estResult
);
testResult
=
Migrate
(
assemblyPath
,
cachedT
estResult
);
Logger
.
Log
(
$"
{
Path
.
GetFileName
(
assemblyPath
)}
- cache hit"
);
}
...
...
@@ -48,32 +55,45 @@ public async Task<TestResult> RunTestAsync(string assemblyPath, CancellationToke
}
/// <summary>
///
The results file is specified in terms of the cache storage. Need to make it local
///
to the current output folder
///
Recreate the on disk artifacts for the cached data and return the correct <see cref="TestResult"/>
///
value.
/// </summary>
/// <param name="testResult"></param>
/// <returns></returns>
private
static
TestResult
Migrate
(
TestResult
testResult
)
{
if
(
string
.
IsNullOrEmpty
(
testResult
.
ResultsFilePath
))
private
TestResult
Migrate
(
string
assemblyPath
,
CachedTestResult
cachedTestResult
)
{
return
testResult
;
}
var
resultsDir
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
testResult
.
AssemblyPath
),
Constants
.
ResultsDirectoryName
);
var
resultsDir
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
assemblyPath
),
Constants
.
ResultsDirectoryName
);
FileUtil
.
EnsureDirectory
(
resultsDir
);
var
resultsFilePath
=
Path
.
Combine
(
resultsDir
,
Path
.
GetFileName
(
testResult
.
ResultsFilePath
));
File
.
Copy
(
testResult
.
ResultsFilePath
,
resultsFilePath
,
overwrite
:
true
);
var
resultsFilePath
=
Path
.
Combine
(
resultsDir
,
cachedTestResult
.
ResultsFileName
);
File
.
WriteAllText
(
resultsFilePath
,
cachedTestResult
.
ResultsFileContent
);
var
commandLine
=
_testExecutor
.
GetCommandLine
(
assemblyPath
);
return
new
TestResult
(
exitCode
:
t
estResult
.
ExitCode
,
assemblyPath
:
testResult
.
AssemblyName
,
exitCode
:
cachedT
estResult
.
ExitCode
,
assemblyPath
:
assemblyPath
,
resultDir
:
resultsDir
,
resultsFilePath
:
resultsFilePath
,
commandLine
:
testResult
.
CommandLine
,
elapsed
:
testResult
.
Elapsed
,
commandLine
:
commandLine
,
elapsed
:
TimeSpan
.
FromMilliseconds
(
0
),
standardOutput
:
cachedTestResult
.
StandardOutput
,
errorOutput
:
cachedTestResult
.
ErrorOutput
);
}
private
void
CacheTestResult
(
ContentFile
contentFile
,
TestResult
testResult
)
{
try
{
var
resultFileContent
=
File
.
ReadAllText
(
testResult
.
ResultsFilePath
);
var
cachedTestResult
=
new
CachedTestResult
(
exitCode
:
testResult
.
ExitCode
,
standardOutput
:
testResult
.
StandardOutput
,
errorOutput
:
testResult
.
ErrorOutput
);
errorOutput
:
testResult
.
ErrorOutput
,
resultsFileName
:
Path
.
GetFileName
(
testResult
.
ResultsFilePath
),
resultsFileContent
:
resultFileContent
);
_dataStorage
.
AddCachedTestResult
(
contentFile
,
cachedTestResult
);
}
catch
(
Exception
ex
)
{
Logger
.
Log
(
$"Failed to create cached
{
ex
}
"
);
}
}
}
}
src/Tools/Source/RunTests/Cache/IDataStorage.cs
浏览文件 @
4b52e7da
...
...
@@ -10,8 +10,32 @@ namespace RunTests.Cache
{
internal
interface
IDataStorage
{
bool
TryGet
TestResult
(
string
checksum
,
out
TestResult
testResult
);
bool
TryGet
CachedTestResult
(
string
checksum
,
out
Cached
TestResult
testResult
);
void
AddTestResult
(
ContentFile
conentFile
,
TestResult
testResult
);
void
AddCachedTestResult
(
ContentFile
conentFile
,
CachedTestResult
testResult
);
}
internal
struct
CachedTestResult
{
internal
int
ExitCode
{
get
;
}
internal
string
StandardOutput
{
get
;
}
internal
string
ErrorOutput
{
get
;
}
internal
string
ResultsFileName
{
get
;
}
internal
string
ResultsFileContent
{
get
;
}
internal
CachedTestResult
(
int
exitCode
,
string
standardOutput
,
string
errorOutput
,
string
resultsFileName
,
string
resultsFileContent
)
{
ExitCode
=
exitCode
;
StandardOutput
=
standardOutput
;
ErrorOutput
=
errorOutput
;
ResultsFileName
=
resultsFileName
;
ResultsFileContent
=
resultsFileContent
;
}
}
}
src/Tools/Source/RunTests/Cache/LocalDataStorage.cs
浏览文件 @
4b52e7da
...
...
@@ -17,12 +17,11 @@ internal sealed class LocalDataStorage : IDataStorage
{
private
enum
StorageKind
{
AssemblyPath
,
ExitCode
,
CommandLine
,
StandardOutput
,
ErrorOutput
,
ResultsFile
,
ResultsFileContent
,
ResultsFileName
,
Content
}
...
...
@@ -36,9 +35,9 @@ internal LocalDataStorage(string storagePath = null)
_storagePath
=
storagePath
??
Path
.
Combine
(
Environment
.
GetFolderPath
(
Environment
.
SpecialFolder
.
LocalApplicationData
),
DirectoryName
);
}
public
bool
TryGet
TestResult
(
string
checksum
,
out
TestResult
testResult
)
public
bool
TryGet
CachedTestResult
(
string
checksum
,
out
Cached
TestResult
testResult
)
{
testResult
=
default
(
TestResult
);
testResult
=
default
(
Cached
TestResult
);
var
storageFolder
=
GetStorageFolder
(
checksum
);
if
(!
Directory
.
Exists
(
storageFolder
))
...
...
@@ -49,27 +48,17 @@ public bool TryGetTestResult(string checksum, out TestResult testResult)
try
{
var
exitCode
=
Read
(
checksum
,
StorageKind
.
ExitCode
);
var
commandLine
=
Read
(
checksum
,
StorageKind
.
CommandLine
);
var
assemblyPath
=
Read
(
checksum
,
StorageKind
.
AssemblyPath
);
var
standardOutput
=
Read
(
checksum
,
StorageKind
.
StandardOutput
);
var
errorOutput
=
Read
(
checksum
,
StorageKind
.
ErrorOutput
);
var
resultsFileName
=
Read
(
checksum
,
StorageKind
.
ResultsFileName
);
var
resultsFileContent
=
Read
(
checksum
,
StorageKind
.
ResultsFileContent
);
var
resultsFilePath
=
GetStoragePath
(
checksum
,
StorageKind
.
ResultsFile
);
var
resultDir
=
Path
.
GetDirectoryName
(
resultsFilePath
);
if
(!
File
.
Exists
(
resultsFilePath
))
{
resultsFilePath
=
null
;
}
testResult
=
new
TestResult
(
testResult
=
new
CachedTestResult
(
exitCode
:
int
.
Parse
(
exitCode
),
assemblyPath
:
assemblyPath
,
resultDir
:
resultDir
,
resultsFilePath
:
resultsFilePath
,
commandLine
:
commandLine
,
elapsed
:
TimeSpan
.
FromSeconds
(
0
),
standardOutput
:
standardOutput
,
errorOutput
:
errorOutput
);
errorOutput
:
errorOutput
,
resultsFileName
:
resultsFileName
,
resultsFileContent
:
resultsFileContent
);
return
true
;
}
catch
(
Exception
e
)
...
...
@@ -81,7 +70,7 @@ public bool TryGetTestResult(string checksum, out TestResult testResult)
return
false
;
}
public
void
Add
TestResult
(
ContentFile
contentFile
,
TestResult
testResult
)
public
void
Add
CachedTestResult
(
ContentFile
contentFile
,
Cached
TestResult
testResult
)
{
var
checksum
=
contentFile
.
Checksum
;
var
storagePath
=
Path
.
Combine
(
_storagePath
,
checksum
);
...
...
@@ -93,16 +82,11 @@ public void AddTestResult(ContentFile contentFile, TestResult testResult)
}
Write
(
checksum
,
StorageKind
.
ExitCode
,
testResult
.
ExitCode
.
ToString
());
Write
(
checksum
,
StorageKind
.
AssemblyPath
,
testResult
.
AssemblyPath
);
Write
(
checksum
,
StorageKind
.
StandardOutput
,
testResult
.
StandardOutput
);
Write
(
checksum
,
StorageKind
.
ErrorOutput
,
testResult
.
ErrorOutput
);
Write
(
checksum
,
StorageKind
.
CommandLine
,
testResult
.
CommandLine
);
Write
(
checksum
,
StorageKind
.
ResultsFileName
,
testResult
.
ResultsFileName
);
Write
(
checksum
,
StorageKind
.
ResultsFileContent
,
testResult
.
ResultsFileContent
);
Write
(
checksum
,
StorageKind
.
Content
,
contentFile
.
Content
);
if
(!
string
.
IsNullOrEmpty
(
testResult
.
ResultsFilePath
))
{
File
.
Copy
(
testResult
.
ResultsFilePath
,
GetStoragePath
(
checksum
,
StorageKind
.
ResultsFile
));
}
}
catch
(
Exception
e
)
{
...
...
src/Tools/Source/RunTests/ITestExecutor.cs
浏览文件 @
4b52e7da
...
...
@@ -41,6 +41,8 @@ internal TestResult(int exitCode, string assemblyPath, string resultDir, string
internal
interface
ITestExecutor
{
string
GetCommandLine
(
string
assemblyPath
);
Task
<
TestResult
>
RunTestAsync
(
string
assemblyPath
,
CancellationToken
cancellationToken
);
}
}
src/Tools/Source/RunTests/ProcessTestExecutor.cs
浏览文件 @
4b52e7da
...
...
@@ -20,20 +20,15 @@ internal ProcessTestExecutor(Options options)
_options
=
options
;
}
public
async
Task
<
TestResult
>
RunTestAsync
(
string
assemblyPath
,
CancellationToken
cancellationToken
)
public
string
GetCommandLine
(
string
assemblyPath
)
{
try
return
$"
{
_options
.
XunitPath
}
{
GetCommandLineArguments
(
assemblyPath
)}
"
;
}
public
string
GetCommandLineArguments
(
string
assemblyPath
)
{
var
assemblyName
=
Path
.
GetFileName
(
assemblyPath
);
var
resultsDir
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
assemblyPath
),
Constants
.
ResultsDirectoryName
);
var
resultsFilePath
=
Path
.
Combine
(
resultsDir
,
$"
{
assemblyName
}
.
{(
_options
.
UseHtml
?
"html"
:
"xml"
)}
"
);
// NOTE: xUnit doesn't always create the log directory
Directory
.
CreateDirectory
(
resultsDir
);
// NOTE: xUnit seems to have an occasional issue creating logs create
// an empty log just in case, so our runner will still fail.
File
.
Create
(
resultsFilePath
).
Close
();
var
resultsFilePath
=
GetResultsFilePath
(
assemblyPath
);
var
builder
=
new
StringBuilder
();
builder
.
AppendFormat
(
@"""{0}"""
,
assemblyPath
);
...
...
@@ -58,12 +53,36 @@ public async Task<TestResult> RunTestAsync(string assemblyPath, CancellationToke
}
}
var
start
=
DateTime
.
UtcNow
;
return
builder
.
ToString
();
}
private
string
GetResultsFilePath
(
string
assemblyPath
)
{
var
assemblyName
=
Path
.
GetFileName
(
assemblyPath
);
var
resultsDir
=
Path
.
Combine
(
Path
.
GetDirectoryName
(
assemblyPath
),
Constants
.
ResultsDirectoryName
);
return
Path
.
Combine
(
resultsDir
,
$"
{
assemblyName
}
.
{(
_options
.
UseHtml
?
"html"
:
"xml"
)}
"
);
}
public
async
Task
<
TestResult
>
RunTestAsync
(
string
assemblyPath
,
CancellationToken
cancellationToken
)
{
try
{
var
commandLineArguments
=
GetCommandLineArguments
(
assemblyPath
);
var
resultsFilePath
=
GetResultsFilePath
(
assemblyPath
);
var
resultsDir
=
Path
.
GetDirectoryName
(
resultsFilePath
);
// NOTE: xUnit doesn't always create the log directory
Directory
.
CreateDirectory
(
resultsDir
);
// NOTE: xUnit seems to have an occasional issue creating logs create
// an empty log just in case, so our runner will still fail.
File
.
Create
(
resultsFilePath
).
Close
();
var
start
=
DateTime
.
UtcNow
;
var
xunitPath
=
_options
.
XunitPath
;
var
processOutput
=
await
ProcessRunner
.
RunProcessAsync
(
xunitPath
,
builder
.
ToString
()
,
commandLineArguments
,
lowPriority
:
false
,
displayWindow
:
false
,
captureOutput
:
true
,
...
...
@@ -94,7 +113,7 @@ public async Task<TestResult> RunTestAsync(string assemblyPath, CancellationToke
}
}
var
commandLine
=
$"
{
xunitPath
}
{
builder
.
ToString
()}
"
;
var
commandLine
=
GetCommandLine
(
assemblyPath
)
;
var
standardOutput
=
string
.
Join
(
Environment
.
NewLine
,
processOutput
.
OutputLines
);
var
errorOutput
=
string
.
Join
(
Environment
.
NewLine
,
processOutput
.
ErrorLines
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录