mirror of
https://github.com/actions/runner.git
synced 2025-12-27 20:13:15 +08:00
GitHub Actions Runner
This commit is contained in:
148
src/Test/L0/Util/ArgUtilL0.cs
Normal file
148
src/Test/L0/Util/ArgUtilL0.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public sealed class ArgUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_MatchesObjectEquality()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
string expected = "Some string".ToLower(); // ToLower is required to avoid reference equality
|
||||
string actual = "Some string".ToLower(); // due to compile-time string interning.
|
||||
|
||||
// Act/Assert.
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_MatchesReferenceEquality()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
object expected = new object();
|
||||
object actual = expected;
|
||||
|
||||
// Act/Assert.
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_MatchesStructEquality()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
int expected = 123;
|
||||
int actual = expected;
|
||||
|
||||
// Act/Assert.
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_ThrowsWhenActualObjectIsNull()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
object expected = new object();
|
||||
object actual = null;
|
||||
|
||||
// Act/Assert.
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_ThrowsWhenExpectedObjectIsNull()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
object expected = null;
|
||||
object actual = new object();
|
||||
|
||||
// Act/Assert.
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_ThrowsWhenObjectsAreNotEqual()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
object expected = new object();
|
||||
object actual = new object();
|
||||
|
||||
// Act/Assert.
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Equal_ThrowsWhenStructsAreNotEqual()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
int expected = 123;
|
||||
int actual = 456;
|
||||
|
||||
// Act/Assert.
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
ArgUtil.Equal(expected: expected, actual: actual, name: "Some parameter");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
957
src/Test/L0/Util/IOUtilL0.cs
Normal file
957
src/Test/L0/Util/IOUtilL0.cs
Normal file
@@ -0,0 +1,957 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public sealed class IOUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Delete_DeletesDirectory()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
|
||||
// Act.
|
||||
IOUtil.Delete(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void Delete_DeletesFile()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
|
||||
// Act.
|
||||
IOUtil.Delete(file, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_DeletesDirectoriesRecursively()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a grandchild directory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine(directory, "some child directory", "some grandchild directory"));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public async Task DeleteDirectory_DeletesDirectoryReparsePointChain()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create the following structure:
|
||||
// randomDir
|
||||
// randomDir/<guid 1> -> <guid 2>
|
||||
// randomDir/<guid 2> -> <guid 3>
|
||||
// randomDir/<guid 3> -> <guid 4>
|
||||
// randomDir/<guid 4> -> <guid 5>
|
||||
// randomDir/<guid 5> -> targetDir
|
||||
// randomDir/targetDir
|
||||
// randomDir/targetDir/file.txt
|
||||
//
|
||||
// The purpose of this test is to verify that DirectoryNotFoundException is gracefully handled when
|
||||
// deleting a chain of reparse point directories. Since the reparse points are named in a random order,
|
||||
// the DirectoryNotFoundException case is likely to be encountered.
|
||||
string randomDir = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string targetDir = Directory.CreateDirectory(Path.Combine(randomDir, "targetDir")).FullName;
|
||||
string file = Path.Combine(targetDir, "file.txt");
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
string linkDir1 = Path.Combine(randomDir, $"{Guid.NewGuid()}_linkDir1");
|
||||
string linkDir2 = Path.Combine(randomDir, $"{Guid.NewGuid()}_linkDir2");
|
||||
string linkDir3 = Path.Combine(randomDir, $"{Guid.NewGuid()}_linkDir3");
|
||||
string linkDir4 = Path.Combine(randomDir, $"{Guid.NewGuid()}_linkDir4");
|
||||
string linkDir5 = Path.Combine(randomDir, $"{Guid.NewGuid()}_linkDir5");
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir1, target: linkDir2);
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir2, target: linkDir3);
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir3, target: linkDir4);
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir4, target: linkDir5);
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir5, target: targetDir);
|
||||
|
||||
// Sanity check to verify the link was created properly:
|
||||
Assert.True(Directory.Exists(linkDir1));
|
||||
Assert.True(new DirectoryInfo(linkDir1).Attributes.HasFlag(FileAttributes.ReparsePoint));
|
||||
Assert.True(File.Exists(Path.Combine(linkDir1, "file.txt")));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(randomDir, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(linkDir1));
|
||||
Assert.False(Directory.Exists(targetDir));
|
||||
Assert.False(File.Exists(file));
|
||||
Assert.False(Directory.Exists(randomDir));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(randomDir))
|
||||
{
|
||||
Directory.Delete(randomDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public async Task DeleteDirectory_DeletesDirectoryReparsePointsBeforeDirectories()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create the following structure:
|
||||
// randomDir
|
||||
// randomDir/linkDir -> targetDir
|
||||
// randomDir/targetDir
|
||||
// randomDir/targetDir/file.txt
|
||||
//
|
||||
// The accuracy of this test relies on an assumption that IOUtil sorts the directories in
|
||||
// descending order before deleting them - either by length or by default sort order.
|
||||
string randomDir = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string targetDir = Directory.CreateDirectory(Path.Combine(randomDir, "targetDir")).FullName;
|
||||
string file = Path.Combine(targetDir, "file.txt");
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
string linkDir = Path.Combine(randomDir, "linkDir");
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir, target: targetDir);
|
||||
|
||||
// Sanity check to verify the link was created properly:
|
||||
Assert.True(Directory.Exists(linkDir));
|
||||
Assert.True(new DirectoryInfo(linkDir).Attributes.HasFlag(FileAttributes.ReparsePoint));
|
||||
Assert.True(File.Exists(Path.Combine(linkDir, "file.txt")));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(randomDir, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(linkDir));
|
||||
Assert.False(Directory.Exists(targetDir));
|
||||
Assert.False(File.Exists(file));
|
||||
Assert.False(Directory.Exists(randomDir));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(randomDir))
|
||||
{
|
||||
Directory.Delete(randomDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_DeletesFilesRecursively()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a grandchild file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string file = Path.Combine(directory, "some subdirectory", "some file");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_DeletesReadOnlyDirectories()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a read-only subdirectory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string subdirectory = Path.Combine(directory, "some subdirectory");
|
||||
try
|
||||
{
|
||||
var subdirectoryInfo = new DirectoryInfo(subdirectory);
|
||||
subdirectoryInfo.Create();
|
||||
subdirectoryInfo.Attributes = subdirectoryInfo.Attributes | FileAttributes.ReadOnly;
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
var subdirectoryInfo = new DirectoryInfo(subdirectory);
|
||||
if (subdirectoryInfo.Exists)
|
||||
{
|
||||
subdirectoryInfo.Attributes = subdirectoryInfo.Attributes & ~FileAttributes.ReadOnly;
|
||||
}
|
||||
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_DeletesReadOnlyRootDirectory()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a read-only directory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
directoryInfo.Create();
|
||||
directoryInfo.Attributes = directoryInfo.Attributes | FileAttributes.ReadOnly;
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
if (directoryInfo.Exists)
|
||||
{
|
||||
directoryInfo.Attributes = directoryInfo.Attributes & ~FileAttributes.ReadOnly;
|
||||
directoryInfo.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_DeletesReadOnlyFiles()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a read-only file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
File.SetAttributes(file, File.GetAttributes(file) | FileAttributes.ReadOnly);
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(directory, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.SetAttributes(file, File.GetAttributes(file) & ~FileAttributes.ReadOnly);
|
||||
}
|
||||
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public async Task DeleteDirectory_DoesNotFollowDirectoryReparsePoint()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create the following structure:
|
||||
// randomDir
|
||||
// randomDir/targetDir
|
||||
// randomDir/targetDir/file.txt
|
||||
// randomDir/linkDir -> targetDir
|
||||
string randomDir = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string targetDir = Directory.CreateDirectory(Path.Combine(randomDir, "targetDir")).FullName;
|
||||
string file = Path.Combine(targetDir, "file.txt");
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
string linkDir = Path.Combine(randomDir, "linkDir");
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir, target: targetDir);
|
||||
|
||||
// Sanity check to verify the link was created properly:
|
||||
Assert.True(Directory.Exists(linkDir));
|
||||
Assert.True(new DirectoryInfo(linkDir).Attributes.HasFlag(FileAttributes.ReparsePoint));
|
||||
Assert.True(File.Exists(Path.Combine(linkDir, "file.txt")));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(linkDir, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(linkDir));
|
||||
Assert.True(Directory.Exists(targetDir));
|
||||
Assert.True(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(randomDir))
|
||||
{
|
||||
Directory.Delete(randomDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public async Task DeleteDirectory_DoesNotFollowNestLevel1DirectoryReparsePoint()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create the following structure:
|
||||
// randomDir
|
||||
// randomDir/targetDir
|
||||
// randomDir/targetDir/file.txt
|
||||
// randomDir/subDir
|
||||
// randomDir/subDir/linkDir -> ../targetDir
|
||||
string randomDir = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string targetDir = Directory.CreateDirectory(Path.Combine(randomDir, "targetDir")).FullName;
|
||||
string file = Path.Combine(targetDir, "file.txt");
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
string subDir = Directory.CreateDirectory(Path.Combine(randomDir, "subDir")).FullName;
|
||||
string linkDir = Path.Combine(subDir, "linkDir");
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir, target: targetDir);
|
||||
|
||||
// Sanity check to verify the link was created properly:
|
||||
Assert.True(Directory.Exists(linkDir));
|
||||
Assert.True(new DirectoryInfo(linkDir).Attributes.HasFlag(FileAttributes.ReparsePoint));
|
||||
Assert.True(File.Exists(Path.Combine(linkDir, "file.txt")));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(subDir, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(subDir));
|
||||
Assert.True(Directory.Exists(targetDir));
|
||||
Assert.True(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(randomDir))
|
||||
{
|
||||
Directory.Delete(randomDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public async Task DeleteDirectory_DoesNotFollowNestLevel2DirectoryReparsePoint()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create the following structure:
|
||||
// randomDir
|
||||
// randomDir/targetDir
|
||||
// randomDir/targetDir/file.txt
|
||||
// randomDir/subDir1
|
||||
// randomDir/subDir1/subDir2
|
||||
// randomDir/subDir1/subDir2/linkDir -> ../../targetDir
|
||||
string randomDir = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
string targetDir = Directory.CreateDirectory(Path.Combine(randomDir, "targetDir")).FullName;
|
||||
string file = Path.Combine(targetDir, "file.txt");
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
string subDir1 = Directory.CreateDirectory(Path.Combine(randomDir, "subDir1")).FullName;
|
||||
string subDir2 = Directory.CreateDirectory(Path.Combine(subDir1, "subDir2")).FullName;
|
||||
string linkDir = Path.Combine(subDir2, "linkDir");
|
||||
await CreateDirectoryReparsePoint(context: hc, link: linkDir, target: targetDir);
|
||||
|
||||
// Sanity check to verify the link was created properly:
|
||||
Assert.True(Directory.Exists(linkDir));
|
||||
Assert.True(new DirectoryInfo(linkDir).Attributes.HasFlag(FileAttributes.ReparsePoint));
|
||||
Assert.True(File.Exists(Path.Combine(linkDir, "file.txt")));
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteDirectory(subDir1, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.False(Directory.Exists(subDir1));
|
||||
Assert.True(Directory.Exists(targetDir));
|
||||
Assert.True(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(randomDir))
|
||||
{
|
||||
Directory.Delete(randomDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteDirectory_IgnoresFile()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
|
||||
// Act: Call "DeleteDirectory" against the file. The method should not blow up and
|
||||
// should simply ignore the file since it is not a directory.
|
||||
IOUtil.DeleteDirectory(file, CancellationToken.None);
|
||||
|
||||
// Assert.
|
||||
Assert.True(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteFile_DeletesFile()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteFile(file);
|
||||
|
||||
// Assert.
|
||||
Assert.False(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteFile_DeletesReadOnlyFile()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory with a read-only file.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
string file = Path.Combine(directory, "some file");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
File.WriteAllText(path: file, contents: "some contents");
|
||||
File.SetAttributes(file, File.GetAttributes(file) | FileAttributes.ReadOnly);
|
||||
|
||||
// Act.
|
||||
IOUtil.DeleteFile(file);
|
||||
|
||||
// Assert.
|
||||
Assert.False(File.Exists(file));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (File.Exists(file))
|
||||
{
|
||||
File.SetAttributes(file, File.GetAttributes(file) & ~FileAttributes.ReadOnly);
|
||||
}
|
||||
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void DeleteFile_IgnoresDirectory()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
// Act: Call "DeleteFile" against a directory. The method should not blow up and
|
||||
// should simply ignore the directory since it is not a file.
|
||||
IOUtil.DeleteFile(directory);
|
||||
|
||||
// Assert.
|
||||
Assert.True(Directory.Exists(directory));
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetRelativePath()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
string relativePath;
|
||||
#if OS_WINDOWS
|
||||
/// MakeRelative(@"d:\src\project\foo.cpp", @"d:\src") -> @"project\foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\src\project\foo.cpp", @"d:\src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project\foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:\", @"d:\specs") -> @"d:\"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\", @"d:\specs");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"d:\", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:\src\project\foo.cpp", @"d:\src\proj") -> @"d:\src\project\foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\src\project\foo.cpp", @"d:\src\proj");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"d:\src\project\foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:\src\project\foo", @"d:\src") -> @"project\foo"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\src\project\foo", @"d:\src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project\foo", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:\src\project\foo.cpp", @"d:\src\project\foo.cpp") -> @""
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\src\project", @"d:\src\project");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, string.Empty, StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:/src/project/foo.cpp", @"d:/src") -> @"project/foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:/src/project/foo.cpp", @"d:/src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project\foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:/src/project/foo.cpp", @"d:\src") -> @"d:/src/project/foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:/src/project/foo.cpp", @"d:/src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project\foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d:/src/project/foo", @"d:/src") -> @"project/foo"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:/src/project/foo", @"d:/src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project\foo", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"d\src\project", @"d:/src/project") -> @""
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"d:\src\project", @"d:/src/project");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, string.Empty, StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
#else
|
||||
/// MakeRelative(@"/user/src/project/foo.cpp", @"/user/src") -> @"project/foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"/user/src/project/foo.cpp", @"/user/src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project/foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"/user", @"/user/specs") -> @"/user"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"/user", @"/user/specs");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"/user", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"/user/src/project/foo.cpp", @"/user/src/proj") -> @"/user/src/project/foo.cpp"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"/user/src/project/foo.cpp", @"/user/src/proj");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"/user/src/project/foo.cpp", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"/user/src/project/foo", @"/user/src") -> @"project/foo"
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"/user/src/project/foo", @"/user/src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, @"project/foo", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
|
||||
/// MakeRelative(@"/user/src/project", @"/user/src/project") -> @""
|
||||
// Act.
|
||||
relativePath = IOUtil.MakeRelative(@"/user/src/project", @"/user/src/project");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(relativePath, string.Empty, StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {relativePath}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ResolvePath()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
string resolvePath;
|
||||
#if OS_WINDOWS
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\src\project\", @"foo");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\src\project\foo", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\", @"specs");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\specs", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\src\project\", @"src\proj");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\src\project\src\proj", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\src\project\foo", @"..");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\src\project", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\src\project", @"..\..\");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:/src/project", @"../.");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\src", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:/src/project/", @"../../foo");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\foo", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:/src/project/foo", @".././bar/.././../foo");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\src\foo", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"d:\", @".");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"d:\", StringComparison.OrdinalIgnoreCase), $"resolvePath does not expected: {resolvePath}");
|
||||
#else
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/user/src/project", @"foo");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/user/src/project/foo", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/root", @"./user/./specs");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/root/user/specs", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/", @"user/specs/.");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/user/specs", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/user/src/project", @"../");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/user/src", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/user/src/project", @"../../");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/user", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/user/src/project/foo", @"../../../../user/./src");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/user/src", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/user/src", @"../../.");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
|
||||
// Act.
|
||||
resolvePath = IOUtil.ResolvePath(@"/", @"./");
|
||||
// Assert.
|
||||
Assert.True(string.Equals(resolvePath, @"/", StringComparison.OrdinalIgnoreCase), $"RelativePath does not expected: {resolvePath}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ValidateExecutePermission_DoesNotExceedFailsafe()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a directory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName());
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
// Act/Assert: Call "ValidateExecutePermission". The method should not blow up.
|
||||
IOUtil.ValidateExecutePermission(directory);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ValidateExecutePermission_ExceedsFailsafe()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange: Create a deep directory.
|
||||
string directory = Path.Combine(hc.GetDirectory(WellKnownDirectory.Bin), Path.GetRandomFileName(), "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20");
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
Environment.SetEnvironmentVariable("AGENT_TEST_VALIDATE_EXECUTE_PERMISSIONS_FAILSAFE", "20");
|
||||
|
||||
try
|
||||
{
|
||||
// Act: Call "ValidateExecutePermission". The method should throw since
|
||||
// it exceeds the failsafe recursion depth.
|
||||
IOUtil.ValidateExecutePermission(directory);
|
||||
|
||||
// Assert.
|
||||
throw new Exception("Should have thrown not supported exception.");
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup.
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
Directory.Delete(directory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task CreateDirectoryReparsePoint(IHostContext context, string link, string target)
|
||||
{
|
||||
#if OS_WINDOWS
|
||||
string fileName = Environment.GetEnvironmentVariable("ComSpec");
|
||||
string arguments = $@"/c ""mklink /J ""{link}"" {target}""""";
|
||||
#else
|
||||
string fileName = "/bin/ln";
|
||||
string arguments = $@"-s ""{target}"" ""{link}""";
|
||||
#endif
|
||||
ArgUtil.File(fileName, nameof(fileName));
|
||||
using (var processInvoker = new ProcessInvokerWrapper())
|
||||
{
|
||||
processInvoker.Initialize(context);
|
||||
await processInvoker.ExecuteAsync(
|
||||
workingDirectory: context.GetDirectory(WellKnownDirectory.Bin),
|
||||
fileName: fileName,
|
||||
arguments: arguments,
|
||||
environment: null,
|
||||
requireExitCodeZero: true,
|
||||
cancellationToken: CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
190
src/Test/L0/Util/StringUtilL0.cs
Normal file
190
src/Test/L0/Util/StringUtilL0.cs
Normal file
@@ -0,0 +1,190 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System.Globalization;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public class StringUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void FormatAlwaysCallsFormat()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
var variableSets = new[]
|
||||
{
|
||||
new { Format = null as string, Args = null as object[], Expected = string.Empty },
|
||||
new { Format = null as string, Args = new object[0], Expected = string.Empty },
|
||||
new { Format = null as string, Args = new object[] { 123 }, Expected = string.Empty },
|
||||
new { Format = "Some message", Args = null as object[], Expected = "Some message" },
|
||||
new { Format = "Some message", Args = new object[0], Expected = "Some message" },
|
||||
new { Format = "Some message", Args = new object[] { 123 }, Expected = "Some message" },
|
||||
new { Format = "Some format '{0}'", Args = null as object[], Expected = "Some format ''" },
|
||||
new { Format = "Some format '{0}'", Args = new object[0], Expected = "Some format ''" },
|
||||
new { Format = "Some format '{0}'", Args = new object[] { 123 }, Expected = "Some format '123'" },
|
||||
};
|
||||
foreach (var variableSet in variableSets)
|
||||
{
|
||||
trace.Info($"{nameof(variableSet)}:");
|
||||
trace.Info(variableSet);
|
||||
|
||||
// Act.
|
||||
string actual = StringUtil.Format(variableSet.Format, variableSet.Args);
|
||||
|
||||
// Assert.
|
||||
Assert.Equal(variableSet.Expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void FormatHandlesFormatException()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Arrange.
|
||||
var variableSets = new[]
|
||||
{
|
||||
new { Format = "Bad format { 0}", Args = null as object[], Expected = "Bad format { 0}" },
|
||||
new { Format = "Bad format { 0}", Args = new object[0], Expected = "Bad format { 0} " },
|
||||
new { Format = "Bad format { 0}", Args = new object[] { null }, Expected = "Bad format { 0} " },
|
||||
new { Format = "Bad format { 0}", Args = new object[] { 123, 456 }, Expected = "Bad format { 0} 123, 456" },
|
||||
};
|
||||
foreach (var variableSet in variableSets)
|
||||
{
|
||||
trace.Info($"{nameof(variableSet)}:");
|
||||
trace.Info(variableSet);
|
||||
|
||||
// Act.
|
||||
string actual = StringUtil.Format(variableSet.Format, variableSet.Args);
|
||||
|
||||
// Assert.
|
||||
Assert.Equal(variableSet.Expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void FormatUsesInvariantCulture()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
// Arrange.
|
||||
CultureInfo originalCulture = CultureInfo.CurrentCulture;
|
||||
try
|
||||
{
|
||||
CultureInfo.CurrentCulture = new CultureInfo("it-IT");
|
||||
|
||||
// Act.
|
||||
string actual = StringUtil.Format("{0:N2}", 123456.789);
|
||||
|
||||
// Actual
|
||||
Assert.Equal("123,456.79", actual);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CultureInfo.CurrentCulture = originalCulture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ConvertNullOrEmptryStringToBool()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
// Arrange.
|
||||
string nullString = null;
|
||||
string emptyString = string.Empty;
|
||||
|
||||
// Act.
|
||||
bool result1 = StringUtil.ConvertToBoolean(nullString);
|
||||
bool result2 = StringUtil.ConvertToBoolean(emptyString);
|
||||
|
||||
// Actual
|
||||
Assert.False(result1, "Null String should convert to false.");
|
||||
Assert.False(result2, "Empty String should convert to false.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ConvertNullOrEmptryStringToDefaultBool()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
// Arrange.
|
||||
string nullString = null;
|
||||
string emptyString = string.Empty;
|
||||
|
||||
// Act.
|
||||
bool result1 = StringUtil.ConvertToBoolean(nullString, true);
|
||||
bool result2 = StringUtil.ConvertToBoolean(emptyString, true);
|
||||
|
||||
// Actual
|
||||
Assert.True(result1, "Null String should convert to true since default value is set to true.");
|
||||
Assert.True(result2, "Empty String should convert to true since default value is set to true.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void ConvertStringToBool()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
// Arrange.
|
||||
string trueString1 = "1";
|
||||
string trueString2 = "True";
|
||||
string trueString3 = "$TRUE";
|
||||
string falseString1 = "0";
|
||||
string falseString2 = "false";
|
||||
string falseString3 = "$False";
|
||||
|
||||
string undefineString1 = "-1";
|
||||
string undefineString2 = "sometext";
|
||||
string undefineString3 = "2015-03-21";
|
||||
|
||||
// Act.
|
||||
bool result1 = StringUtil.ConvertToBoolean(trueString1, false);
|
||||
bool result2 = StringUtil.ConvertToBoolean(trueString2);
|
||||
bool result3 = StringUtil.ConvertToBoolean(trueString3, true);
|
||||
bool result4 = StringUtil.ConvertToBoolean(falseString1, true);
|
||||
bool result5 = StringUtil.ConvertToBoolean(falseString2);
|
||||
bool result6 = StringUtil.ConvertToBoolean(falseString3, false);
|
||||
|
||||
bool result7 = StringUtil.ConvertToBoolean(undefineString1, true);
|
||||
bool result8 = StringUtil.ConvertToBoolean(undefineString2);
|
||||
bool result9 = StringUtil.ConvertToBoolean(undefineString3, false);
|
||||
|
||||
// Actual
|
||||
Assert.True(result1, $"'{trueString1}' should convert to true.");
|
||||
Assert.True(result2, $"'{trueString2}' should convert to true.");
|
||||
Assert.True(result3, $"'{trueString3}' should convert to true.");
|
||||
Assert.False(result4, $"'{falseString1}' should convert to false.");
|
||||
Assert.False(result5, $"'{falseString2}' should convert to false.");
|
||||
Assert.False(result6, $"'{falseString3}' should convert to false.");
|
||||
|
||||
Assert.True(result7, $"'{undefineString1}' should convert to true, since default is true.");
|
||||
Assert.False(result8, $"'{undefineString2}' should convert to false.");
|
||||
Assert.False(result9, $"'{undefineString3}' should convert to false.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
206
src/Test/L0/Util/TaskResultUtilL0.cs
Normal file
206
src/Test/L0/Util/TaskResultUtilL0.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using GitHub.DistributedTask.WebApi;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public class TaskResultUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void TaskResultReturnCodeTranslate()
|
||||
{
|
||||
// Arrange.
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
// Act.
|
||||
TaskResult abandon = TaskResultUtil.TranslateFromReturnCode(TaskResultUtil.TranslateToReturnCode(TaskResult.Abandoned));
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, abandon);
|
||||
|
||||
// Act.
|
||||
TaskResult canceled = TaskResultUtil.TranslateFromReturnCode(TaskResultUtil.TranslateToReturnCode(TaskResult.Canceled));
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, canceled);
|
||||
|
||||
// Act.
|
||||
TaskResult failed = TaskResultUtil.TranslateFromReturnCode(TaskResultUtil.TranslateToReturnCode(TaskResult.Failed));
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, failed);
|
||||
|
||||
// Act.
|
||||
TaskResult skipped = TaskResultUtil.TranslateFromReturnCode(TaskResultUtil.TranslateToReturnCode(TaskResult.Skipped));
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, skipped);
|
||||
|
||||
// Act.
|
||||
TaskResult succeeded = TaskResultUtil.TranslateFromReturnCode(TaskResultUtil.TranslateToReturnCode(TaskResult.Succeeded));
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Succeeded, succeeded);
|
||||
|
||||
// Act.
|
||||
TaskResult unknowReturnCode1 = TaskResultUtil.TranslateFromReturnCode(0);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, unknowReturnCode1);
|
||||
|
||||
// Act.
|
||||
TaskResult unknowReturnCode2 = TaskResultUtil.TranslateFromReturnCode(1);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, unknowReturnCode2);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void TaskResultsMerge()
|
||||
{
|
||||
// Arrange.
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
TaskResult merged;
|
||||
|
||||
//
|
||||
// No current result merge.
|
||||
//
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(null, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Succeeded, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(null, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(null, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(null, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(null, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
|
||||
//
|
||||
// Same result merge.
|
||||
//
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Succeeded, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Succeeded, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Abandoned, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Canceled, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Failed, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Skipped, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
|
||||
//
|
||||
// Forward result merge
|
||||
//
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Succeeded, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Succeeded, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Succeeded, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Succeeded, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
|
||||
//
|
||||
// No backward merge
|
||||
//
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Abandoned, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Canceled, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Failed, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Failed, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Skipped, TaskResult.Succeeded);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
|
||||
//
|
||||
// Worst result no change
|
||||
//
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Abandoned, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Abandoned, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Abandoned, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Canceled, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Canceled, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Canceled, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Failed, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Abandoned, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Failed, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Canceled, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Failed, TaskResult.Skipped);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Skipped, TaskResult.Abandoned);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Skipped, TaskResult.Canceled);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
// Act.
|
||||
merged = TaskResultUtil.MergeTaskResults(TaskResult.Skipped, TaskResult.Failed);
|
||||
// Actual
|
||||
Assert.Equal(TaskResult.Skipped, merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/Test/L0/Util/UrlUtilL0.cs
Normal file
65
src/Test/L0/Util/UrlUtilL0.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public class UrlUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetCredentialEmbeddedUrl_NoUsernameAndPassword()
|
||||
{
|
||||
// Act.
|
||||
Uri result = UrlUtil.GetCredentialEmbeddedUrl(new Uri("https://github.com/actions/runner.git"), string.Empty, string.Empty);
|
||||
// Actual
|
||||
Assert.Equal("https://github.com/actions/runner.git", result.AbsoluteUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetCredentialEmbeddedUrl_NoUsername()
|
||||
{
|
||||
// Act.
|
||||
Uri result = UrlUtil.GetCredentialEmbeddedUrl(new Uri("https://github.com/actions/runner.git"), string.Empty, "password123");
|
||||
// Actual
|
||||
Assert.Equal("https://emptyusername:password123@github.com/actions/runner.git", result.AbsoluteUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetCredentialEmbeddedUrl_NoPassword()
|
||||
{
|
||||
// Act.
|
||||
Uri result = UrlUtil.GetCredentialEmbeddedUrl(new Uri("https://github.com/actions/runner.git"), "user123", string.Empty);
|
||||
// Actual
|
||||
Assert.Equal("https://user123@github.com/actions/runner.git", result.AbsoluteUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetCredentialEmbeddedUrl_HasUsernameAndPassword()
|
||||
{
|
||||
// Act.
|
||||
Uri result = UrlUtil.GetCredentialEmbeddedUrl(new Uri("https://github.com/actions/runner.git"), "user123", "password123");
|
||||
// Actual
|
||||
Assert.Equal("https://user123:password123@github.com/actions/runner.git", result.AbsoluteUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void GetCredentialEmbeddedUrl_UsernameAndPasswordEncoding()
|
||||
{
|
||||
// Act.
|
||||
Uri result = UrlUtil.GetCredentialEmbeddedUrl(new Uri("https://github.com/actions/runner.git"), "user 123", "password 123");
|
||||
// Actual
|
||||
Assert.Equal("https://user%20123:password%20123@github.com/actions/runner.git", result.AbsoluteUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/Test/L0/Util/VssUtilL0.cs
Normal file
56
src/Test/L0/Util/VssUtilL0.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Services.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http.Headers;
|
||||
using Xunit;
|
||||
using System.Text.RegularExpressions;
|
||||
using GitHub.Runner.Sdk;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public sealed class VssUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void VerifyOverwriteVssConnectionSetting()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Act.
|
||||
try
|
||||
{
|
||||
trace.Info("Set httpretry to 10.");
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "10");
|
||||
trace.Info("Set httptimeout to 360.");
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_TIMEOUT", "360");
|
||||
|
||||
var connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
||||
|
||||
// Assert.
|
||||
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10");
|
||||
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "360");
|
||||
|
||||
trace.Info("Set httpretry to 100.");
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "100");
|
||||
trace.Info("Set httptimeout to 3600.");
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_TIMEOUT", "3600");
|
||||
|
||||
connect = VssUtil.CreateConnection(new Uri("https://github.com/actions/runner"), new VssCredentials());
|
||||
|
||||
// Assert.
|
||||
Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10");
|
||||
Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "1200");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", "");
|
||||
Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_TIMEOUT", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/Test/L0/Util/WhichUtilL0.cs
Normal file
74
src/Test/L0/Util/WhichUtilL0.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using GitHub.Runner.Common.Util;
|
||||
using GitHub.Runner.Sdk;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace GitHub.Runner.Common.Tests.Util
|
||||
{
|
||||
public sealed class WhichUtilL0
|
||||
{
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void UseWhichFindGit()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
//Arrange
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Act.
|
||||
string gitPath = WhichUtil.Which("git", trace: trace);
|
||||
|
||||
trace.Info($"Which(\"git\") returns: {gitPath ?? string.Empty}");
|
||||
|
||||
// Assert.
|
||||
Assert.True(!string.IsNullOrEmpty(gitPath) && File.Exists(gitPath), $"Unable to find Git through: {nameof(WhichUtil.Which)}");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void WhichReturnsNullWhenNotFound()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
//Arrange
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Act.
|
||||
string nosuch = WhichUtil.Which("no-such-file-cf7e351f", trace: trace);
|
||||
|
||||
trace.Info($"result: {nosuch ?? string.Empty}");
|
||||
|
||||
// Assert.
|
||||
Assert.True(string.IsNullOrEmpty(nosuch), "Path should not be resolved");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Common")]
|
||||
public void WhichThrowsWhenRequireAndNotFound()
|
||||
{
|
||||
using (TestHostContext hc = new TestHostContext(this))
|
||||
{
|
||||
//Arrange
|
||||
Tracing trace = hc.GetTrace();
|
||||
|
||||
// Act.
|
||||
try
|
||||
{
|
||||
WhichUtil.Which("no-such-file-cf7e351f", require: true, trace: trace);
|
||||
throw new Exception("which should have thrown");
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
Assert.Equal("no-such-file-cf7e351f", ex.FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user