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); } } }
public void VerifyUserAgentIsVstsAgent() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); // Act. var connect = ApiUtil.CreateConnection(new Uri("https://github.com/Microsoft/vsts-agent"), new VssCredentials()); // Trace foreach (var ua in connect.Settings.UserAgent ?? new List<ProductInfoHeaderValue>()) { if (ua.Product != null) { trace.Info(ua.Product.Name); trace.Info(ua.Product.Version); } if (!string.IsNullOrEmpty(ua.Comment)) { trace.Info(ua.Comment); } } // Assert. Assert.True(connect.Settings.UserAgent?.Exists(u => u.Product.Name.IndexOf("vstsagentcore", StringComparison.OrdinalIgnoreCase) >= 0)); } }
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); } } }
public async Task TestCancel() { const int SecondsToRun = 20; using (TestHostContext hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = hc.GetTrace(); var processInvoker = new ProcessInvoker(); processInvoker.Initialize(hc); Stopwatch watch = Stopwatch.StartNew(); #if OS_WINDOWS Task execTask = processInvoker.ExecuteAsync("", "cmd.exe", $"/c \"choice /T {SecondsToRun} /D y\"", null, tokenSource.Token); #endif #if (OS_OSX || OS_LINUX) Task execTask = processInvoker.ExecuteAsync("", "bash", $"-c \"sleep {SecondsToRun}s\"", null, tokenSource.Token); #endif await Task.Delay(500); tokenSource.Cancel(); await Task.WhenAny(execTask); Assert.True(execTask.IsCompleted); Assert.True(!execTask.IsFaulted); Assert.True(execTask.IsCanceled); watch.Stop(); var elapsedSeconds = watch.ElapsedMilliseconds / 1000; //if cancellation fails, then execution time is more than 10 seconds Assert.True(elapsedSeconds < SecondsToRun / 2, $"cancellation failed, because task took too long to run. {elapsedSeconds}"); } }
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(IOUtil.GetBinPath(), 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); } } } }
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"); } }
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"); } }
public void VerifyUserAgentHasPlatformInfo() { Regex _serverSideAgentPlatformMatchingRegex = new Regex("vstsagentcore-(.+)(?=/)", RegexOptions.Compiled | RegexOptions.IgnoreCase); using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); // Act. var connect = ApiUtil.CreateConnection(new Uri("https://github.com/Microsoft/vsts-agent"), new VssCredentials()); string platformInfo = null; // Trace foreach (var ua in connect.Settings.UserAgent ?? new List<ProductInfoHeaderValue>()) { if (ua.Product != null) { trace.Info(ua.Product.Name); trace.Info(ua.Product.Version); if (ua.Product.Name.IndexOf("vstsagentcore", StringComparison.OrdinalIgnoreCase) >= 0) { platformInfo = ua.Product.Name + '/' + ua.Product.Version; } } if (!string.IsNullOrEmpty(ua.Comment)) { trace.Info(ua.Comment); } } // Assert. var regMatch = _serverSideAgentPlatformMatchingRegex.Match(platformInfo); Assert.True(regMatch.Success && regMatch.Groups != null && regMatch.Groups.Count == 2); string platform = regMatch.Groups[1].Value; List<string> validPackageNames = new List<string>() { "win7-x64", "ubuntu.14.04-x64", "centos.7-x64", "rhel.7.2-x64", "osx.10.11-x64" }; Assert.True(validPackageNames.Contains(platform)); } }
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"); }); } }
public void UseWhichFindGit() { using (TestHostContext hc = new TestHostContext(this)) { //Arrange Tracing trace = hc.GetTrace(); var whichTool = new WhichUtil(); whichTool.Initialize(hc); // Act. string gitPath = whichTool.Which("git"); 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)}"); } }
public async Task SuccessExitsWithCodeZero() { using (TestHostContext hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = hc.GetTrace(); Int32 exitCode = -1; var processInvoker = new ProcessInvoker(); processInvoker.Initialize(hc); #if OS_WINDOWS exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"dir >nul\"", null, tokenSource.Token); #endif #if (OS_OSX || OS_LINUX) exitCode = await processInvoker.ExecuteAsync("", "bash", "-c echo .", null, tokenSource.Token); #endif trace.Info("Exit Code: {0}", exitCode); Assert.Equal(0, exitCode); } }
public void VerifyOverwriteVssConnectionSetting() { Regex _serverSideAgentPlatformMatchingRegex = new Regex("vstsagentcore-(.+)(?=/)", RegexOptions.Compiled | RegexOptions.IgnoreCase); using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); // Act. try { trace.Info("Set httpretry to 10."); Environment.SetEnvironmentVariable("VSTS_HTTP_RETRY", "10"); trace.Info("Set httptimeout to 360."); Environment.SetEnvironmentVariable("VSTS_HTTP_TIMEOUT", "360"); var connect = ApiUtil.CreateConnection(new Uri("https://github.com/Microsoft/vsts-agent"), 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("VSTS_HTTP_RETRY", "100"); trace.Info("Set httptimeout to 3600."); Environment.SetEnvironmentVariable("VSTS_HTTP_TIMEOUT", "3600"); connect = ApiUtil.CreateConnection(new Uri("https://github.com/Microsoft/vsts-agent"), new VssCredentials()); // Assert. Assert.Equal(connect.Settings.MaxRetryRequest.ToString(), "10"); Assert.Equal(connect.Settings.SendTimeout.TotalSeconds.ToString(), "1200"); } finally { Environment.SetEnvironmentVariable("VSTS_HTTP_RETRY", ""); Environment.SetEnvironmentVariable("VSTS_HTTP_TIMEOUT", ""); } } }
public async void CreatesSession() { using (TestHostContext tc = CreateTestContext()) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = tc.GetTrace(); // Arrange. var expectedSession = new TaskAgentSession(); _runnerServer .Setup(x => x.CreateAgentSessionAsync( _settings.PoolId, It.Is <TaskAgentSession>(y => y != null), tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); _credMgr.Setup(x => x.LoadCredentials()).Returns(new VssCredentials()); _store.Setup(x => x.GetCredentials()).Returns(new CredentialData() { Scheme = Constants.Configuration.OAuthAccessToken }); _store.Setup(x => x.GetMigratedCredentials()).Returns(default(CredentialData)); // Act. MessageListener listener = new MessageListener(); listener.Initialize(tc); bool result = await listener.CreateSessionAsync(tokenSource.Token); trace.Info("result: {0}", result); // Assert. Assert.True(result); _runnerServer .Verify(x => x.CreateAgentSessionAsync( _settings.PoolId, It.Is <TaskAgentSession>(y => y != null), tokenSource.Token), Times.Once()); } }
public async Task TestDownloadArtifactAsyncWithMinimatchPattern() { byte[] sourceContent1 = GenerateRandomData(); byte[] sourceContent2 = GenerateRandomData(); TestFile sourceFile1 = new TestFile(sourceContent1); TestFile sourceFile2 = new TestFile(sourceContent2); sourceFile1.PlaceItem(Path.Combine(Directory.GetCurrentDirectory(), Path.Combine(TestDownloadSourceFolder, "drop/test2.txt"))); sourceFile2.PlaceItem(Path.Combine(Directory.GetCurrentDirectory(), Path.Combine(TestDownloadSourceFolder, "drop/test3.txt"))); using (var hostContext = new TestHostContext(this)) { var context = new AgentTaskPluginExecutionContext(hostContext.GetTrace()); var provider = new FileShareProvider(context, new CallbackAppTraceSource(str => context.Output(str), System.Diagnostics.SourceLevels.Information)); string sourcePath = Path.Combine(Directory.GetCurrentDirectory(), TestDownloadSourceFolder); string destPath = Path.Combine(Directory.GetCurrentDirectory(), TestDestFolder); PipelineArtifactDownloadParameters downloadParameters = new PipelineArtifactDownloadParameters(); downloadParameters.TargetDirectory = destPath; downloadParameters.MinimatchFilters = new string[] { "drop/test2.txt" }; BuildArtifact buildArtifact = new BuildArtifact(); buildArtifact.Name = "drop"; buildArtifact.Resource = new ArtifactResource(); buildArtifact.Resource.Data = sourcePath; await provider.DownloadMultipleArtifactsAsync(downloadParameters, new List <BuildArtifact> { buildArtifact }, CancellationToken.None); var sourceFiles = Directory.GetFiles(sourcePath); var destFiles = Directory.GetFiles(Path.Combine(destPath, buildArtifact.Name)); Assert.Equal(1, destFiles.Length); foreach (var file in sourceFiles) { string destFile = destFiles.FirstOrDefault(f => Path.GetFileName(f).Equals(Path.GetFileName(file))); Assert.True(StructuralComparisons.StructuralEqualityComparer.Equals(ComputeHash(file), ComputeHash(destFile))); } TestCleanup(); } }
public void GetSourceGitClonePR() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); // Arrange. string dumySourceFolder = Path.Combine(tc.GetDirectory(WellKnownDirectory.Bin), "SourceProviderL0"); var executionContext = GetTestExecutionContext(tc, dumySourceFolder, "refs/pull/12345", "a596e13f5db8869f44574be0392fb8fe1e790ce4", false); var endpoint = GetTestSourceEndpoint("https://github.com/microsoft/azure-pipelines-agent", false, false); var _gitCommandManager = GetDefaultGitCommandMock(); tc.SetSingleton <IGitCommandManager>(_gitCommandManager.Object); tc.SetSingleton <IVstsAgentWebProxy>(new VstsAgentWebProxy()); var _configStore = new Mock <IConfigurationStore>(); _configStore.Setup(x => x.GetSettings()).Returns(() => new AgentSettings() { ServerUrl = "http://localhost:8080/tfs" }); tc.SetSingleton <IConfigurationStore>(_configStore.Object); tc.SetSingleton <IAgentCertificateManager>(new AgentCertificateManager()); GitSourceProvider gitSourceProvider = new ExternalGitSourceProvider(); gitSourceProvider.Initialize(tc); gitSourceProvider.SetVariablesInEndpoint(executionContext.Object, endpoint); // Act. gitSourceProvider.GetSourceAsync(executionContext.Object, endpoint, default(CancellationToken)).GetAwaiter().GetResult(); // Assert. _gitCommandManager.Verify(x => x.GitInit(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitRemoteAdd(executionContext.Object, dumySourceFolder, "origin", "https://github.com/microsoft/azure-pipelines-agent")); _gitCommandManager.Verify(x => x.GitFetch(executionContext.Object, dumySourceFolder, "origin", It.IsAny <int>(), new List <string>() { "+refs/heads/*:refs/remotes/origin/*", "+refs/pull/12345:refs/remotes/pull/12345" }, It.IsAny <string>(), It.IsAny <CancellationToken>())); _gitCommandManager.Verify(x => x.GitRemoteSetUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/microsoft/azure-pipelines-agent")); _gitCommandManager.Verify(x => x.GitRemoteSetPushUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/microsoft/azure-pipelines-agent")); _gitCommandManager.Verify(x => x.GitCheckout(executionContext.Object, dumySourceFolder, It.Is <string>(s => s.Equals("refs/remotes/pull/12345")), It.IsAny <CancellationToken>())); } }
public void EchoProcessCommandInvalid() { using (TestHostContext _hc = new TestHostContext(this)) { var extensionManager = new Mock <IExtensionManager>(); var echoCommand = new EchoCommandExtension(); echoCommand.Initialize(_hc); extensionManager.Setup(x => x.GetExtensions <IActionCommandExtension>()) .Returns(new List <IActionCommandExtension>() { echoCommand }); _hc.SetSingleton <IExtensionManager>(extensionManager.Object); Mock <IExecutionContext> _ec = new Mock <IExecutionContext>(); _ec.Setup(x => x.Write(It.IsAny <string>(), It.IsAny <string>())) .Returns((string tag, string line) => { _hc.GetTrace().Info($"{tag} {line}"); return(1); }); _ec.SetupAllProperties(); ActionCommandManager commandManager = new ActionCommandManager(); commandManager.Initialize(_hc); // Echo commands below are considered "processed", but are invalid // 1. Invalid echo value Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::invalid")); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.False(_ec.Object.EchoOnActionCommand); // 2. No value Assert.True(commandManager.TryProcessCommand(_ec.Object, "::echo::")); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.False(_ec.Object.EchoOnActionCommand); } }
public void GetSourceGitFetchWithLFS() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); // Arrange. string dumySourceFolder = Path.Combine(IOUtil.GetBinPath(), "SourceProviderL0"); try { Directory.CreateDirectory(dumySourceFolder); var executionContext = GetTestExecutionContext(tc, dumySourceFolder, "refs/remotes/origin/master", "", false); var endpoint = GetTestSourceEndpoint("https://github.com/Microsoft/vsts-agent", false, false, true); var _gitCommandManager = GetDefaultGitCommandMock(); tc.SetSingleton <IGitCommandManager>(_gitCommandManager.Object); tc.SetSingleton <IWhichUtil>(new WhichUtil()); GitSourceProvider gitSourceProvider = new ExternalGitSourceProvider(); gitSourceProvider.Initialize(tc); gitSourceProvider.SetVariablesInEndpoint(executionContext.Object, endpoint); // Act. gitSourceProvider.GetSourceAsync(executionContext.Object, endpoint, default(CancellationToken)).GetAwaiter().GetResult(); // Assert. _gitCommandManager.Verify(x => x.GitInit(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitRemoteAdd(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitLFSInstall(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitConfig(executionContext.Object, dumySourceFolder, "remote.origin.lfsurl", "https://*****:*****@github.com/Microsoft/vsts-agent.git/info/lfs")); _gitCommandManager.Verify(x => x.GitConfig(executionContext.Object, dumySourceFolder, "remote.origin.lfspushurl", "https://*****:*****@github.com/Microsoft/vsts-agent.git/info/lfs")); _gitCommandManager.Verify(x => x.GitLFSFetch(executionContext.Object, dumySourceFolder, "origin", It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>())); _gitCommandManager.Verify(x => x.GitFetch(executionContext.Object, dumySourceFolder, "origin", It.IsAny <int>(), It.IsAny <List <string> >(), It.IsAny <string>(), It.IsAny <CancellationToken>())); _gitCommandManager.Verify(x => x.GitCheckout(executionContext.Object, dumySourceFolder, "refs/remotes/origin/master", It.IsAny <CancellationToken>())); } finally { IOUtil.DeleteDirectory(dumySourceFolder, CancellationToken.None); } } }
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { var hc = new TestHostContext(this, testName); Dictionary <string, VariableValue> variablesToCopy = new Dictionary <string, VariableValue>(); _variables = new Variables( hostContext: hc, copy: variablesToCopy); _env = new Dictionary <string, string>() { { "env1", "1" }, { "test", "github_actions" } }; _ec = new Mock <IExecutionContext>(); _ec.SetupAllProperties(); _ec.Setup(x => x.Variables).Returns(_variables); _contexts = new DictionaryContextData(); _jobContext = new JobContext(); _contexts["github"] = new DictionaryContextData(); _contexts["runner"] = new DictionaryContextData(); _contexts["job"] = _jobContext; _ec.Setup(x => x.ExpressionValues).Returns(_contexts); _ec.Setup(x => x.ExpressionFunctions).Returns(new List <IFunctionInfo>()); _ec.Setup(x => x.JobContext).Returns(_jobContext); _stepContext = new StepsContext(); _ec.Setup(x => x.StepsContext).Returns(_stepContext); _ec.Setup(x => x.PostJobSteps).Returns(new Stack <IStep>()); var trace = hc.GetTrace(); _ec.Setup(x => x.Write(It.IsAny <string>(), It.IsAny <string>())).Callback((string tag, string message) => { trace.Info($"[{tag}]{message}"); }); _stepsRunner = new StepsRunner(); _stepsRunner.Initialize(hc); return(hc); }
public void ComputeHash_should_throw_when_parameters_invalid() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); var repo = new RepositoryTrackingInfo() { Identifier = "MyRepo", RepositoryUrl = "https://[email protected]/jpricket/MyFirstProject/_git/repo1_url", }; string collectionId = "866A5D79-7735-49E3-87DA-02E76CF8D03A"; string definitionId = "123"; Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(null, null, null)); Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, null)); Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { new RepositoryTrackingInfo() })); Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(null, null, new[] { repo })); Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(null, definitionId, new[] { repo })); Assert.Throws <ArgumentNullException>(() => TrackingConfigHashAlgorithm.ComputeHash(collectionId, null, new[] { repo })); } }
public void GuessRepositoryType_should_return_correct_values_when_called() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType(null)); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("garbage")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("github")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("azuredevops")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("https://githubenterprise.com/microsoft/somerepo.git")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("https://almost.visual.studio.com/microsoft/somerepo.git")); Assert.Equal(string.Empty, RepositoryUtil.GuessRepositoryType("https://almost.dev2.azure.com/microsoft/somerepo.git")); Assert.Equal(RepositoryTypes.GitHub, RepositoryUtil.GuessRepositoryType("https://github.com/microsoft/somerepo.git")); Assert.Equal(RepositoryTypes.Git, RepositoryUtil.GuessRepositoryType("https://[email protected]/org/project/_git/reponame")); Assert.Equal(RepositoryTypes.Git, RepositoryUtil.GuessRepositoryType("https://[email protected]/project/_git/reponame")); Assert.Equal(RepositoryTypes.Tfvc, RepositoryUtil.GuessRepositoryType("https://[email protected]/project")); Assert.Equal(RepositoryTypes.Tfvc, RepositoryUtil.GuessRepositoryType("https://[email protected]/org/project")); Assert.Equal(RepositoryTypes.Bitbucket, RepositoryUtil.GuessRepositoryType("https://[email protected]/user1/mybucket.git")); } }
public void HasMultipleCheckouts_should_return_false_when_not_set_correctly() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(null)); var dict = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); dict[WellKnownJobSettings.HasMultipleCheckouts] = "!true"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); dict[WellKnownJobSettings.HasMultipleCheckouts] = "false"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); dict[WellKnownJobSettings.HasMultipleCheckouts] = "FALSE"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); dict[WellKnownJobSettings.HasMultipleCheckouts] = "False"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); dict[WellKnownJobSettings.HasMultipleCheckouts] = "0"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); dict[WellKnownJobSettings.HasMultipleCheckouts] = "1"; Assert.Equal(false, RepositoryUtil.HasMultipleCheckouts(dict)); } }
public async Task JobExtensionManagementScriptStep() { using (TestHostContext hc = CreateTestContext()) { hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); Environment.SetEnvironmentVariable("VSTS_AGENT_INIT_INTERNAL_TEMP_HACK", "C:\\init.ps1"); Environment.SetEnvironmentVariable("VSTS_AGENT_CLEANUP_INTERNAL_TEMP_HACK", "C:\\clenup.ps1"); try { TestJobExtension testExtension = new TestJobExtension(); testExtension.Initialize(hc); JobInitializeResult result = await testExtension.InitializeJob(_jobEc, _message); var trace = hc.GetTrace(); trace.Info(string.Join(", ", result.PreJobSteps.Select(x => x.DisplayName))); trace.Info(string.Join(", ", result.JobSteps.Select(x => x.DisplayName))); trace.Info(string.Join(", ", result.PostJobStep.Select(x => x.DisplayName))); Assert.Equal(5, result.PreJobSteps.Count); Assert.Equal(4, result.JobSteps.Count); Assert.Equal(5, result.PostJobStep.Count); Assert.True(result.PreJobSteps[0] is ManagementScriptStep); Assert.True(result.PostJobStep[4] is ManagementScriptStep); Assert.Equal(result.PreJobSteps[0].DisplayName, "Agent Initialization"); Assert.Equal(result.PostJobStep[4].DisplayName, "Agent Cleanup"); } finally { Environment.SetEnvironmentVariable("VSTS_AGENT_INIT_INTERNAL_TEMP_HACK", ""); Environment.SetEnvironmentVariable("VSTS_AGENT_CLEANUP_INTERNAL_TEMP_HACK", ""); } } }
public async void TestSelfUpdateAsync() { using (var hc = new TestHostContext(this)) { //Arrange var updater = new Runner.Listener.SelfUpdater(); hc.SetSingleton <ITerminal>(_term.Object); hc.SetSingleton <IRunnerServer>(_runnerServer.Object); hc.SetSingleton <IConfigurationStore>(_configStore.Object); hc.SetSingleton <IHttpClientHandlerFactory>(new HttpClientHandlerFactory()); var p = new ProcessInvokerWrapper(); p.Initialize(hc); hc.EnqueueInstance <IProcessInvoker>(p); updater.Initialize(hc); _runnerServer.Setup(x => x.UpdateAgentUpdateStateAsync(1, 1, It.IsAny <string>(), It.IsAny <string>())) .Callback((int p, int a, string s, string t) => { hc.GetTrace().Info(t); }) .Returns(Task.FromResult(new TaskAgent())); try { var result = await updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken); Assert.True(result); Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"))); Assert.True(Directory.Exists(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"))); } finally { IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "bin.2.299.0"), CancellationToken.None); IOUtil.DeleteDirectory(Path.Combine(hc.GetDirectory(WellKnownDirectory.Root), "externals.2.299.0"), CancellationToken.None); } } }
public async void CreatesSession() { using (TestHostContext tc = CreateTestContext()) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = tc.GetTrace(); // Arrange. var expectedSession = new TaskAgentSession(); _agentServer .Setup(x => x.CreateAgentSessionAsync( _settings.PoolId, It.Is <TaskAgentSession>(y => y != null), tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); _capabilitiesManager.Setup(x => x.GetCapabilitiesAsync(_settings, It.IsAny <CancellationToken>())).Returns(Task.FromResult(new Dictionary <string, string>())); _credMgr.Setup(x => x.LoadCredentials()).Returns(new Common.VssCredentials()); // Act. MessageListener listener = new MessageListener(); listener.Initialize(tc); bool result = await listener.CreateSessionAsync(tokenSource.Token); trace.Info("result: {0}", result); // Assert. Assert.True(result); Assert.Equal(expectedSession, listener.Session); _agentServer .Verify(x => x.CreateAgentSessionAsync( _settings.PoolId, It.Is <TaskAgentSession>(y => y != null), tokenSource.Token), Times.Once()); } }
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("10", connect.Settings.MaxRetryRequest.ToString()); Assert.Equal("360", connect.Settings.SendTimeout.TotalSeconds.ToString()); 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("10", connect.Settings.MaxRetryRequest.ToString()); Assert.Equal("1200", connect.Settings.SendTimeout.TotalSeconds.ToString()); } finally { Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_RETRY", ""); Environment.SetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_HTTP_TIMEOUT", ""); } } }
public async Task JobExtensionBuildPreStepsList() { using (TestHostContext hc = CreateTestContext()) { var jobExtension = new JobExtension(); jobExtension.Initialize(hc); _actionManager.Setup(x => x.PrepareActionsAsync(It.IsAny <IExecutionContext>(), It.IsAny <IEnumerable <Pipelines.JobStep> >(), It.IsAny <Guid>())) .Returns(Task.FromResult(new PrepareResult(new List <JobExtensionRunner>() { new JobExtensionRunner(null, "", "prepare1", null), new JobExtensionRunner(null, "", "prepare2", null) }, new Dictionary <Guid, IActionRunner>()))); List <IStep> result = await jobExtension.InitializeJob(_jobEc, _message); var trace = hc.GetTrace(); trace.Info(string.Join(", ", result.Select(x => x.DisplayName))); Assert.Equal(7, result.Count); Assert.Equal("prepare1", result[0].DisplayName); Assert.Equal("prepare2", result[1].DisplayName); Assert.Equal("action1", result[2].DisplayName); Assert.Equal("action2", result[3].DisplayName); Assert.Equal("action3", result[4].DisplayName); Assert.Equal("action4", result[5].DisplayName); Assert.Equal("action5", result[6].DisplayName); Assert.NotNull(result[0].ExecutionContext); Assert.NotNull(result[1].ExecutionContext); Assert.NotNull(result[2].ExecutionContext); Assert.NotNull(result[3].ExecutionContext); Assert.NotNull(result[4].ExecutionContext); Assert.NotNull(result[5].ExecutionContext); Assert.NotNull(result[6].ExecutionContext); } }
public void GetRepository_should_return_correct_value_when_called() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); var repo1 = new RepositoryResource { Alias = "repo1", Id = "repo1", Type = "git", }; var repo2 = new RepositoryResource { Alias = "repo2", Id = "repo2", Type = "git", }; var repoSelf = new RepositoryResource { Alias = "self", Id = "repo3", Type = "git", }; Assert.Equal(null, RepositoryUtil.GetRepository(null, null)); Assert.Equal(null, RepositoryUtil.GetRepository(null, "repo1")); Assert.Equal(null, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, null)); Assert.Equal(null, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "unknown")); Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo1")); Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repo1, repo2 }, "repo2")); Assert.Equal(repo1, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo1")); Assert.Equal(repo2, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "repo2")); Assert.Equal(repoSelf, RepositoryUtil.GetRepository(new[] { repoSelf, repo1, repo2 }, "self")); } }
public void GetRelativePathNonWindows() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); string relativePath; /// 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}"); } }
public async Task RepositoryPlugin_UpdatePathEvenCheckoutFail() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); Setup(tc); _sourceProvider.Setup(x => x.GetSourceAsync(It.IsAny <AgentTaskPluginExecutionContext>(), It.IsAny <Pipelines.RepositoryResource>(), It.IsAny <CancellationToken>())) .Throws(new InvalidOperationException("RIGHT")); var repository = _executionContext.Repositories.Single(); var currentPath = repository.Properties.Get <string>(Pipelines.RepositoryPropertyNames.Path); Directory.CreateDirectory(currentPath); var ex = await Assert.ThrowsAsync <InvalidOperationException>(async() => await _checkoutTask.RunAsync(_executionContext, CancellationToken.None)); Assert.True(ex.Message.Contains("RIGHT")); var temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); File.Copy(tc.TraceFileName, temp); Assert.True(File.ReadAllText(temp).Contains($"##vso[plugininternal.updaterepositorypath alias=myRepo;]{currentPath}")); } }
public void EchoProcessCommandInvalid() { using (TestHostContext hc = CreateTestContext()) { _ec.Setup(x => x.Write(It.IsAny <string>(), It.IsAny <string>())) .Returns((string tag, string line) => { hc.GetTrace().Info($"{tag} {line}"); return(1); }); // Echo commands below are considered "processed", but are invalid // 1. Invalid echo value Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::invalid", null)); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.False(_ec.Object.EchoOnActionCommand); // 2. No value Assert.True(_commandManager.TryProcessCommand(_ec.Object, "::echo::", null)); Assert.Equal(TaskResult.Failed, _ec.Object.CommandResult); Assert.False(_ec.Object.EchoOnActionCommand); } }
public void GeneratePluginExecutionContextHostInfoTest() { using (TestHostContext tc = CreateTestContext()) { Tracing trace = tc.GetTrace(); var agentPluginManager = new AgentPluginManager(); agentPluginManager.Initialize(tc); var inputs = new Dictionary <string, string>() { { "input1", "foo" }, { "input2", tc.GetDirectory(WellKnownDirectory.Work) }, }; var variables = new Dictionary <string, VariableValue>() { { "variable1", "foo" }, { "variable2", tc.GetDirectory(WellKnownDirectory.Work) }, }; var taskVariables = new Dictionary <string, VariableValue>() { { "taskVariable1", "foo" }, { "taskVariable2", tc.GetDirectory(WellKnownDirectory.Work) }, }; var executionContext = CreateTestExecutionContext(tc, variables: variables, taskVariables: taskVariables); var pluginContext = agentPluginManager.GeneratePluginExecutionContext(executionContext, inputs, executionContext.Variables); Assert.True(pluginContext != null, "PluginContext for Host Step Target is not null"); // inputs should match exactly for Host Step Targets Assert.True(inputs.All(e => pluginContext.Inputs.Contains(e))); // variables should match exactly for Host Step Targets Assert.True(variables.All(e => pluginContext.Variables.Contains(e))); // task variables should match exactly for Host Step Targets Assert.True(taskVariables.All(e => pluginContext.TaskVariables.Contains(e))); } }
public void ComputeHash_with_single_repo_should_return_correct_hash() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); var repo1 = new RepositoryTrackingInfo() { Identifier = "alias", RepositoryType = "git", RepositoryUrl = "https://[email protected]/jpricket/MyFirstProject/_git/repo1_url", }; var repo2 = new RepositoryTrackingInfo() { Identifier = "alias2", RepositoryType = "git2", RepositoryUrl = "https://[email protected]/jpricket/MyFirstProject/_git/repo1_url", }; string collectionId = "866A5D79-7735-49E3-87DA-02E76CF8D03A"; string definitionId = "123"; // Make sure that only the coll, def, and url are used in the hash Assert.Equal("9a89eaa7b8b603633ef1dd5c46464355c716268f", TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { repo1 })); Assert.Equal("9a89eaa7b8b603633ef1dd5c46464355c716268f", TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { repo2 })); Assert.Equal(TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { repo1 }), TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { repo1 })); // Make sure that different coll creates different hash Assert.Equal("2a41800cd3e7f5983a7643698f67104ed95101f3", TrackingConfigHashAlgorithm.ComputeHash("FFFA5D79-7735-49E3-87DA-02E76CF8D03A", definitionId, new[] { repo1 })); // Make sure that different def creates different hash Assert.Equal("84b4463d95631b4d358f4b67d8994fe7d5b0c013", TrackingConfigHashAlgorithm.ComputeHash(collectionId, "321", new[] { repo1 })); // Make sure that different url creates different hash repo1.RepositoryUrl = "https://[email protected]/jpricket/MyFirstProject/_git/new_url"; Assert.Equal("6505a9272091df39b90d6fd359e3bf39a7883e9e", TrackingConfigHashAlgorithm.ComputeHash(collectionId, definitionId, new[] { repo1 })); } }
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); } } } }
public async Task RepositoryPlugin_NoPathInputMoveBackToDefault() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); Setup(tc); var repository = _executionContext.Repositories.Single(); repository.Properties.Set(Pipelines.RepositoryPropertyNames.Path, Path.Combine(tc.GetDirectory(WellKnownDirectory.Work), "1", "test")); var currentPath = repository.Properties.Get <string>(Pipelines.RepositoryPropertyNames.Path); Directory.CreateDirectory(currentPath); await _checkoutTask.RunAsync(_executionContext, CancellationToken.None); var actualPath = repository.Properties.Get <string>(Pipelines.RepositoryPropertyNames.Path); Assert.Equal(actualPath, Path.Combine(tc.GetDirectory(WellKnownDirectory.Work), "1", "s")); Assert.True(Directory.Exists(actualPath)); Assert.False(Directory.Exists(currentPath)); var temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); File.Copy(tc.TraceFileName, temp); Assert.True(File.ReadAllText(temp).Contains($"##vso[plugininternal.updaterepositorypath alias=myRepo;]{actualPath}")); } }
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); } } } }
public async Task RepositoryPlugin_MultiCheckout_UpdatePathForAllRepos() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); var repos = new List <Pipelines.RepositoryResource>() { GetRepository(tc, "self", "self"), GetRepository(tc, "repo2", "repo2"), GetRepository(tc, "repo3", "repo3"), }; Setup(tc, repos); foreach (var repository in _executionContext.Repositories) { var currentPath = repository.Properties.Get <string>(Pipelines.RepositoryPropertyNames.Path); Directory.CreateDirectory(currentPath); _executionContext.Inputs[Pipelines.PipelineConstants.CheckoutTaskInputs.Repository] = repository.Alias; _executionContext.Inputs["Path"] = Path.Combine("test", repository.Alias); await _checkoutTask.RunAsync(_executionContext, CancellationToken.None); var actualPath = repository.Properties.Get <string>(Pipelines.RepositoryPropertyNames.Path); Assert.NotEqual(actualPath, currentPath); Assert.Equal(actualPath, Path.Combine(tc.GetDirectory(WellKnownDirectory.Work), "1", Path.Combine("test", repository.Alias))); Assert.True(Directory.Exists(actualPath)); Assert.False(Directory.Exists(currentPath)); var temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); File.Copy(tc.TraceFileName, temp); Assert.True(File.ReadAllText(temp).Contains($"##vso[plugininternal.updaterepositorypath alias={repository.Alias};]{actualPath}"), $"Repo {repository.Alias} did not get updated to {actualPath}. CurrentPath = {currentPath}"); } } }
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); } } } }
private Mock<IExecutionContext> GetTestExecutionContext(TestHostContext tc, string sourceFolder, string sourceBranch, string sourceVersion, bool enableAuth) { var trace = tc.GetTrace(); var executionContext = new Mock<IExecutionContext>(); List<string> warnings; executionContext .Setup(x => x.Variables) .Returns(new Variables(tc, copy: new Dictionary<string, string>(), maskHints: new List<MaskHint>(), warnings: out warnings)); executionContext .Setup(x => x.Write(It.IsAny<string>(), It.IsAny<string>())) .Callback((string tag, string message) => { trace.Info($"{tag}{message}"); }); executionContext .Setup(x => x.WriteDebug) .Returns(true); executionContext.Object.Variables.Set(Constants.Variables.Build.SourcesDirectory, sourceFolder); executionContext.Object.Variables.Set(Constants.Variables.Build.SourceBranch, sourceBranch); executionContext.Object.Variables.Set(Constants.Variables.Build.SourceVersion, sourceVersion); executionContext.Object.Variables.Set(Constants.Variables.System.EnableAccessToken, enableAuth.ToString()); return executionContext; }
public async Task CanEnsureMachineGroupAgentConfigureVSTSScenarioWithTags() { Guid receivedProjectId = Guid.Empty; string expectedProcessedTags = string.Empty; string tags = "Tag3, ,, Tag4 , , , Tag1, , tag3 "; string expectedTags = "Tag3,Tag4,Tag1"; int receivedMachineId = -1; int expectedDeploymentGroupId = 7; int receivedDeploymentGroupId = -1; _machineGroupServer.Setup(x => x.UpdateDeploymentTargetsAsync(It.IsAny <Guid>(), It.IsAny <int>(), It.IsAny <List <DeploymentMachine> >())).Callback((Guid project, int deploymentGroupId, List <DeploymentMachine> deploymentMachine) => { receivedProjectId = project; expectedProcessedTags = string.Join(",", deploymentMachine.FirstOrDefault().Tags.ToArray()); receivedMachineId = deploymentMachine.FirstOrDefault().Id; receivedDeploymentGroupId = deploymentGroupId; } ); using (TestHostContext tc = CreateTestContext()) { Tracing trace = tc.GetTrace(); trace.Info("Creating config manager"); IConfigurationManager configManager = new ConfigurationManager(); configManager.Initialize(tc); trace.Info("Preparing command line arguments for vsts scenario"); var command = new CommandSettings( tc, new[] { "configure", "--acceptteeeula", "--machinegroup", "--adddeploymentgrouptags", "--url", _expectedVSTSServerUrl, "--agent", _expectedAgentName, "--projectname", _expectedProjectName, "--deploymentgroupname", _expectedMachineGroupName, "--work", _expectedWorkFolder, "--auth", _expectedAuthType, "--token", _expectedToken, "--deploymentgrouptags", tags }); trace.Info("Constructed."); _store.Setup(x => x.IsConfigured()).Returns(false); _configMgrAgentSettings = null; _extnMgr.Setup(x => x.GetExtensions <IConfigurationProvider>()).Returns(GetConfigurationProviderList(tc)); _machineGroupServer.Setup(x => x.GetDeploymentGroupsAsync(It.IsAny <string>(), It.IsAny <string>())).Returns(Task.FromResult(GetDeploymentGroups(expectedDeploymentGroupId, 3))); trace.Info("Ensuring all the required parameters are available in the command line parameter"); await configManager.ConfigureAsync(command); _store.Setup(x => x.IsConfigured()).Returns(true); trace.Info("Configured, verifying all the parameter value"); var s = configManager.LoadSettings(); Assert.NotNull(s); Assert.True(s.ServerUrl.Equals(_expectedVSTSServerUrl, StringComparison.CurrentCultureIgnoreCase)); Assert.True(s.AgentName.Equals(_expectedAgentName)); Assert.True(s.PoolId.Equals(3)); Assert.True(s.DeploymentGroupId.Equals(7)); Assert.True(s.WorkFolder.Equals(_expectedWorkFolder)); Assert.True(s.MachineGroupId.Equals(0)); Assert.Null(s.ProjectName); Assert.True(s.ProjectId.Equals(_expectedProjectId)); Assert.True(receivedProjectId.Equals(new Guid(_expectedProjectId)), "UpdateDeploymentMachinesGroupAsync should get call with correct project name"); Assert.True(expectedTags.Equals(expectedProcessedTags), "Before applying the tags, should get processed ( Trim, Remove duplicate)"); Assert.True(receivedMachineId.Equals(_expectedDeploymentMachineId), "UpdateDeploymentMachinesGroupAsync should get call with correct machine id"); Assert.True(receivedDeploymentGroupId.Equals(expectedDeploymentGroupId), "UpdateDeploymentMachinesGroupAsync should get call with correct deployment group id"); // Tags logic should get trigger _machineGroupServer.Verify(x => x.UpdateDeploymentTargetsAsync(It.IsAny <Guid>(), It.IsAny <int>(), It.IsAny <List <DeploymentMachine> >()), Times.Once); } }
public void GetSourceReCloneOnUrlNotMatch() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); // Arrange. string dumySourceFolder = Path.Combine(IOUtil.GetBinPath(), "SourceProviderL0"); try { Directory.CreateDirectory(dumySourceFolder); string dumyGitFolder = Path.Combine(dumySourceFolder, ".git"); Directory.CreateDirectory(dumyGitFolder); string dumyGitConfig = Path.Combine(dumyGitFolder, "config"); File.WriteAllText(dumyGitConfig, "test git confg file"); var executionContext = GetTestExecutionContext(tc, dumySourceFolder, "refs/heads/users/user1", "", true); var endpoint = GetTestSourceEndpoint("https://github.com/Microsoft/vsts-agent", false, false); var _gitCommandManager = GetDefaultGitCommandMock(); _gitCommandManager .Setup(x => x.GitGetFetchUrl(It.IsAny<IExecutionContext>(), It.IsAny<string>())) .Returns(Task.FromResult<Uri>(new Uri("https://github.com/Microsoft/vsts-another-agent"))); tc.SetSingleton<IGitCommandManager>(_gitCommandManager.Object); tc.SetSingleton<IWhichUtil>(new WhichUtil()); GitSourceProvider gitSourceProvider = new GitSourceProvider(); gitSourceProvider.Initialize(tc); // Act. gitSourceProvider.GetSourceAsync(executionContext.Object, endpoint, default(CancellationToken)).GetAwaiter().GetResult(); // Assert. _gitCommandManager.Verify(x => x.GitInit(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitRemoteAdd(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitCheckout(executionContext.Object, dumySourceFolder, "refs/remotes/origin/users/user1", It.IsAny<CancellationToken>())); } finally { IOUtil.DeleteDirectory(dumySourceFolder, CancellationToken.None); } } }
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(IOUtil.GetBinPath(), 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); } } } }
public void GetSourceGitFetchWithClean() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); // Arrange. string dumySourceFolder = Path.Combine(IOUtil.GetBinPath(), "SourceProviderL0"); try { Directory.CreateDirectory(dumySourceFolder); string dumyGitFolder = Path.Combine(dumySourceFolder, ".git"); Directory.CreateDirectory(dumyGitFolder); string dumyGitConfig = Path.Combine(dumyGitFolder, "config"); File.WriteAllText(dumyGitConfig, "test git confg file"); var executionContext = GetTestExecutionContext(tc, dumySourceFolder, "refs/remotes/origin/master", "", false); var endpoint = GetTestSourceEndpoint("https://github.com/Microsoft/vsts-agent", true, false); var _gitCommandManager = GetDefaultGitCommandMock(); tc.SetSingleton<IGitCommandManager>(_gitCommandManager.Object); tc.SetSingleton<IWhichUtil>(new WhichUtil()); GitSourceProvider gitSourceProvider = new GitSourceProvider(); gitSourceProvider.Initialize(tc); // Act. gitSourceProvider.GetSourceAsync(executionContext.Object, endpoint, default(CancellationToken)).GetAwaiter().GetResult(); // Assert. _gitCommandManager.Verify(x => x.GitClean(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitReset(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitDisableAutoGC(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitRemoteSetUrl(executionContext.Object, dumySourceFolder, "origin", It.Is<string>(s => s.Equals("https://*****:*****@github.com/Microsoft/vsts-agent")))); _gitCommandManager.Verify(x => x.GitRemoteSetPushUrl(executionContext.Object, dumySourceFolder, "origin", It.Is<string>(s => s.Equals("https://*****:*****@github.com/Microsoft/vsts-agent")))); _gitCommandManager.Verify(x => x.GitFetch(executionContext.Object, dumySourceFolder, "origin", It.IsAny<List<string>>(), It.IsAny<string>(), It.IsAny<CancellationToken>())); _gitCommandManager.Verify(x => x.GitRemoteSetUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitRemoteSetPushUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitCheckout(executionContext.Object, dumySourceFolder, "refs/remotes/origin/master", It.IsAny<CancellationToken>())); } finally { IOUtil.DeleteDirectory(dumySourceFolder, CancellationToken.None); } } }
public void DeleteDirectory_DeletesReadOnlyRootDirectory() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); // Arrange: Create a read-only directory. string directory = Path.Combine(IOUtil.GetBinPath(), 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(); } } } }
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(IOUtil.GetBinPath(), 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); } } } }
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"); }); } }
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(IOUtil.GetBinPath(), 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); } } } }
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(IOUtil.GetBinPath(), 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); } } } }
public async void GetNextMessage() { using (TestHostContext tc = CreateTestContext()) using (var tokenSource = new CancellationTokenSource()) { Tracing trace = tc.GetTrace(); // Arrange. var expectedSession = new TaskAgentSession(); PropertyInfo sessionIdProperty = expectedSession.GetType().GetProperty("SessionId", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Assert.NotNull(sessionIdProperty); sessionIdProperty.SetValue(expectedSession, Guid.NewGuid()); _agentServer .Setup(x => x.CreateAgentSessionAsync( _settings.PoolId, It.Is <TaskAgentSession>(y => y != null), tokenSource.Token)) .Returns(Task.FromResult(expectedSession)); _capabilitiesManager.Setup(x => x.GetCapabilitiesAsync(_settings, It.IsAny <CancellationToken>())).Returns(Task.FromResult(new Dictionary <string, string>())); _credMgr.Setup(x => x.LoadCredentials()).Returns(new Common.VssCredentials()); // Act. MessageListener listener = new MessageListener(); listener.Initialize(tc); bool result = await listener.CreateSessionAsync(tokenSource.Token); Assert.True(result); Assert.Equal(expectedSession, listener.Session); var arMessages = new TaskAgentMessage[] { new TaskAgentMessage { Body = "somebody1", MessageId = 4234, MessageType = JobRequestMessageTypes.AgentJobRequest }, new TaskAgentMessage { Body = "somebody2", MessageId = 4235, MessageType = JobCancelMessage.MessageType }, null, //should be skipped by GetNextMessageAsync implementation null, new TaskAgentMessage { Body = "somebody3", MessageId = 4236, MessageType = JobRequestMessageTypes.AgentJobRequest } }; var messages = new Queue <TaskAgentMessage>(arMessages); _agentServer .Setup(x => x.GetAgentMessageAsync( _settings.PoolId, expectedSession.SessionId, It.IsAny <long?>(), tokenSource.Token)) .Returns(async(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken) => { await Task.Yield(); return(messages.Dequeue()); }); TaskAgentMessage message1 = await listener.GetNextMessageAsync(tokenSource.Token); TaskAgentMessage message2 = await listener.GetNextMessageAsync(tokenSource.Token); TaskAgentMessage message3 = await listener.GetNextMessageAsync(tokenSource.Token); Assert.Equal(arMessages[0], message1); Assert.Equal(arMessages[1], message2); Assert.Equal(arMessages[4], message3); //Assert _agentServer .Verify(x => x.GetAgentMessageAsync( _settings.PoolId, expectedSession.SessionId, It.IsAny <long?>(), tokenSource.Token), Times.Exactly(arMessages.Length)); } }
private void ValidateLocStrings(TestHostContext hc, string project) { using (hc) { Tracing trace = hc.GetTrace(); var keys = new List<string>(); var badLines = new List<BadLineInfo>(); // Search for source files within the project. trace.Verbose("Searching source files:"); string[] sourceFiles = Directory.GetFiles( TestUtil.GetProjectPath(project), "*.cs", SearchOption.AllDirectories); foreach (string sourceFile in sourceFiles) { // Skip files in the obj directory. if (sourceFile.Contains(StringUtil.Format("{0}obj{0}", Path.DirectorySeparatorChar))) { continue; } trace.Verbose($" {sourceFile}"); foreach (string line in File.ReadAllLines(sourceFile)) { // Search for calls to the StringUtil.Loc method within the line. const string Pattern = "StringUtil.Loc("; int searchIndex = 0; int patternIndex; while (searchIndex < line.Length && (patternIndex = line.IndexOf(Pattern, searchIndex)) >= 0) { // Bump the search index in preparation for the for the next iteration within the same line. searchIndex = patternIndex + Pattern.Length; // Extract the resource key. int keyStartIndex = patternIndex + Pattern.Length; int keyEndIndex; if (keyStartIndex + 2 < line.Length && // Key should start with a ", be followed by at least line[keyStartIndex] == '"' && // one character, and end with a ". (keyEndIndex = line.IndexOf('"', keyStartIndex + 1)) > 0) { // Remove the first and last double quotes. keyStartIndex++; keyEndIndex--; string key = line.Substring( startIndex: keyStartIndex, length: keyEndIndex - keyStartIndex + 1); if (ValidKeyRegex.IsMatch(key)) { // A valid key was extracted. keys.Add(key); continue; } } // Something went wrong. The pattern was found, but the resource key could not be determined. badLines.Add(new BadLineInfo { File = sourceFile, Line = line }); } } } // Load the strings. string stringsFile = Path.Combine(TestUtil.GetSrcPath(), "Misc", "layoutbin", "en-US", "strings.json"); Assert.True(File.Exists(stringsFile), $"File does not exist: {stringsFile}"); var resourceDictionary = IOUtil.LoadObject<Dictionary<string, object>>(stringsFile); // Find missing keys. string[] missingKeys = keys .Where(x => !resourceDictionary.ContainsKey(x)) .OrderBy(x => x) .ToArray(); if (missingKeys.Length > 0) { trace.Error("One or more resource keys missing from resources file:"); foreach (string missingKey in missingKeys) { trace.Error($" {missingKey}"); } } // Validate whether resource keys couldn't be interpreted. if (badLines.Count > 0) { trace.Error("Bad lines detected. Unable to interpret resource key(s)."); IEnumerable<IGrouping<string, BadLineInfo>> badLineGroupings = badLines .GroupBy(x => x.File) .OrderBy(x => x.Key) .ToArray(); foreach (IGrouping<string, BadLineInfo> badLineGrouping in badLineGroupings) { trace.Error($"File: {badLineGrouping.First().File}"); foreach (BadLineInfo badLine in badLineGrouping) { trace.Error($" Line: {badLine.Line}"); } } } Assert.True(missingKeys.Length == 0, $"One or more resource keys missing from resources files. Consult the trace log: {hc.TraceFileName}"); Assert.True(badLines.Count == 0, $"Unable to determine one or more resource keys. Consult the trace log: {hc.TraceFileName}"); } }
public void GetRelativPath() { 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 } }
public void DeleteFile_IgnoresDirectory() { using (TestHostContext hc = new TestHostContext(this)) { Tracing trace = hc.GetTrace(); // Arrange: Create a directory. string directory = Path.Combine(IOUtil.GetBinPath(), 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); } } } }
public async void DispatcherRenewJobRequestStopOnExpiredRequest() { //Arrange using (var hc = new TestHostContext(this)) { int poolId = 1; Int64 requestId = 1000; int count = 0; var trace = hc.GetTrace(nameof(DispatcherRenewJobRequestStopOnExpiredRequest)); TaskCompletionSource <int> firstJobRequestRenewed = new TaskCompletionSource <int>(); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); TaskAgentJobRequest request = new TaskAgentJobRequest(); PropertyInfo lockUntilProperty = request.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Assert.NotNull(lockUntilProperty); lockUntilProperty.SetValue(request, DateTime.UtcNow.AddMinutes(5)); hc.SetSingleton <IRunnerServer>(_runnerServer.Object); hc.SetSingleton <IConfigurationStore>(_configurationStore.Object); _configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 }); _runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny <int>(), It.IsAny <long>(), It.IsAny <Guid>(), It.IsAny <CancellationToken>())) .Returns(() => { count++; if (!firstJobRequestRenewed.Task.IsCompletedSuccessfully) { trace.Info("First renew happens."); } if (count == 1) { return(Task.FromResult <TaskAgentJobRequest>(request)); } else if (count < 5) { throw new TimeoutException(""); } else if (count == 5) { lockUntilProperty.SetValue(request, DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(11))); throw new TimeoutException(""); } else { cancellationTokenSource.CancelAfter(10000); throw new InvalidOperationException("Should not reach here."); } }); var jobDispatcher = new JobDispatcher(); jobDispatcher.Initialize(hc); await jobDispatcher.RenewJobRequestAsync(poolId, requestId, Guid.Empty, firstJobRequestRenewed, cancellationTokenSource.Token); Assert.True(firstJobRequestRenewed.Task.IsCompletedSuccessfully, "First renew should succeed."); Assert.False(cancellationTokenSource.IsCancellationRequested); _runnerServer.Verify(x => x.RenewAgentRequestAsync(It.IsAny <int>(), It.IsAny <long>(), It.IsAny <Guid>(), It.IsAny <CancellationToken>()), Times.Exactly(5)); _runnerServer.Verify(x => x.RefreshConnectionAsync(RunnerConnectionType.JobRequest, It.IsAny <TimeSpan>()), Times.Exactly(3)); _runnerServer.Verify(x => x.SetConnectionTimeout(RunnerConnectionType.JobRequest, It.IsAny <TimeSpan>()), Times.Never); } }
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(IOUtil.GetBinPath(), 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); } } } }
public async Task CanEnsureEnvironmentVMResourceConfigureVSTSScenario() { SetEnvironmentVMResourceMocks(); var projectId = Guid.NewGuid(); using (TestHostContext tc = CreateTestContext()) { Tracing trace = tc.GetTrace(); trace.Info("Creating config manager"); IConfigurationManager configManager = new ConfigurationManager(); configManager.Initialize(tc); trace.Info("Preparing command line arguments for Environment VM resource config vsts scenario"); var command = new CommandSettings( tc, new[] { "configure", "--acceptteeeula", "--environment", "--url", _expectedVSTSServerUrl, "--agent", "environmentVMResourceName", "--projectname", "environmentPrj", "--environmentname", "env1", "--work", _expectedWorkFolder, "--auth", _expectedAuthType, "--token", _expectedToken }); trace.Info("Constructed."); _store.Setup(x => x.IsConfigured()).Returns(false); _configMgrAgentSettings = null; _extnMgr.Setup(x => x.GetExtensions <IConfigurationProvider>()).Returns(GetConfigurationProviderList(tc)); _environmentsServer.Setup(x => x.GetEnvironmentsAsync(It.IsAny <string>(), It.IsAny <string>())).Returns(Task.FromResult(GetEnvironments("environmentPrj", projectId))); trace.Info("Ensuring all the required parameters are available in the command line parameter"); await configManager.ConfigureAsync(command); _store.Setup(x => x.IsConfigured()).Returns(true); trace.Info("Configured, verifying all the parameter value"); var s = configManager.LoadSettings(); Assert.NotNull(s); Assert.True(s.ServerUrl.Equals(_expectedVSTSServerUrl, StringComparison.CurrentCultureIgnoreCase)); Assert.True(s.AgentName.Equals("environmentVMResourceName")); Assert.True(s.AgentId.Equals(35)); Assert.True(s.PoolId.Equals(57)); Assert.True(s.WorkFolder.Equals(_expectedWorkFolder)); Assert.True(s.MachineGroupId.Equals(0)); Assert.True(s.DeploymentGroupId.Equals(0)); Assert.True(s.EnvironmentId.Equals(54)); Assert.True(s.ProjectName.Equals("environmentPrj")); Assert.True(s.ProjectId.Equals(projectId.ToString())); Assert.True(s.EnvironmentVMResourceId.Equals(_expectedEnvironmentVMResourceId)); // Validate mock calls _environmentsServer.Verify(x => x.ConnectAsync(It.IsAny <VssConnection>()), Times.Once); _environmentsServer.Verify(x => x.AddEnvironmentVMAsync(It.IsAny <Guid>(), It.Is <int>(e => e == 54), It.Is <VirtualMachineResource>(v => v.Agent.Name == "environmentVMResourceName")), Times.Once); _environmentsServer.Verify(x => x.GetEnvironmentVMsAsync(It.IsAny <Guid>(), It.Is <int>(e => e == 54), It.Is <string>(v => v == "environmentVMResourceName")), Times.Once); _environmentsServer.Verify(x => x.GetEnvironmentsAsync(It.IsAny <string>(), It.Is <string>(e => e == "env1")), Times.Once); _environmentsServer.Verify(x => x.GetEnvironmentPoolAsync(It.Is <Guid>(p => p == projectId), It.Is <int>(e => e == 54)), Times.Once); } }
public void GetSourceGitClonePR() { using (TestHostContext tc = new TestHostContext(this)) { var trace = tc.GetTrace(); // Arrange. string dumySourceFolder = Path.Combine(IOUtil.GetBinPath(), "SourceProviderL0"); var executionContext = GetTestExecutionContext(tc, dumySourceFolder, "refs/pull/12345", "a596e13f5db8869f44574be0392fb8fe1e790ce4", false); var endpoint = GetTestSourceEndpoint("https://github.com/Microsoft/vsts-agent", false, false); var _gitCommandManager = GetDefaultGitCommandMock(); tc.SetSingleton<IGitCommandManager>(_gitCommandManager.Object); tc.SetSingleton<IWhichUtil>(new WhichUtil()); GitSourceProvider gitSourceProvider = new GitSourceProvider(); gitSourceProvider.Initialize(tc); // Act. gitSourceProvider.GetSourceAsync(executionContext.Object, endpoint, default(CancellationToken)).GetAwaiter().GetResult(); // Assert. _gitCommandManager.Verify(x => x.GitInit(executionContext.Object, dumySourceFolder)); _gitCommandManager.Verify(x => x.GitRemoteAdd(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitFetch(executionContext.Object, dumySourceFolder, "origin", new List<string>() { "+refs/pull/12345:refs/remotes/pull/12345" }, It.IsAny<string>(), It.IsAny<CancellationToken>())); _gitCommandManager.Verify(x => x.GitRemoteSetUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitRemoteSetPushUrl(executionContext.Object, dumySourceFolder, "origin", "https://github.com/Microsoft/vsts-agent")); _gitCommandManager.Verify(x => x.GitCheckout(executionContext.Object, dumySourceFolder, It.Is<string>(s => s.Equals("refs/remotes/pull/12345")), It.IsAny<CancellationToken>())); } }