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); List <IStep> result = await testExtension.InitializeJob(_jobEc, _message); var trace = hc.GetTrace(); trace.Info(string.Join(", ", result.Select(x => x.DisplayName))); Assert.Equal(14, result.Count); Assert.True(result[0] is ManagementScriptStep); Assert.True(result[13] is ManagementScriptStep); Assert.Equal(result[0].DisplayName, "Agent Initialization"); Assert.Equal(result[13].DisplayName, "Agent Cleanup"); } finally { Environment.SetEnvironmentVariable("VSTS_AGENT_INIT_INTERNAL_TEMP_HACK", ""); Environment.SetEnvironmentVariable("VSTS_AGENT_CLEANUP_INTERNAL_TEMP_HACK", ""); } } }
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { TestHostContext tc = new TestHostContext(this, testName); tc.SetSingleton <ICredentialManager>(_credMgr.Object); tc.SetSingleton <IPromptManager>(_promptManager.Object); tc.SetSingleton <IConfigurationStore>(_store.Object); tc.SetSingleton <IExtensionManager>(_extnMgr.Object); tc.SetSingleton <IAgentServer>(_agentServer.Object); tc.SetSingleton <IMachineGroupServer>(_machineGroupServer.Object); tc.SetSingleton <ICapabilitiesManager>(_capabilitiesManager); #if OS_WINDOWS tc.SetSingleton <IWindowsServiceControlManager>(_serviceControlManager.Object); #endif #if !OS_WINDOWS tc.SetSingleton <ILinuxServiceControlManager>(_serviceControlManager.Object); #endif tc.SetSingleton <IRSAKeyManager>(_rsaKeyManager.Object); tc.EnqueueInstance <IAgentServer>(_agentServer.Object); tc.EnqueueInstance <IMachineGroupServer>(_machineGroupServer.Object); return(tc); }
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { TestHostContext tc = new TestHostContext(this, testName); tc.SetSingleton <ICredentialManager>(_credMgr.Object); tc.SetSingleton <IPromptManager>(_promptManager.Object); tc.SetSingleton <IConfigurationStore>(_store.Object); tc.SetSingleton <IExtensionManager>(_extnMgr.Object); tc.SetSingleton <IAgentServer>(_agentServer.Object); tc.SetSingleton <IDeploymentGroupServer>(_machineGroupServer.Object); tc.SetSingleton <INetFrameworkUtil>(_netFrameworkUtil.Object); tc.SetSingleton <ICapabilitiesManager>(_capabilitiesManager); tc.SetSingleton <IVstsAgentWebProxy>(_vstsAgentWebProxy.Object); tc.SetSingleton <IAgentCertificateManager>(_cert.Object); #if OS_WINDOWS tc.SetSingleton <IWindowsServiceControlManager>(_serviceControlManager.Object); #else tc.SetSingleton <ILinuxServiceControlManager>(_serviceControlManager.Object); #endif tc.SetSingleton <IRSAKeyManager>(_rsaKeyManager.Object); tc.EnqueueInstance <IAgentServer>(_agentServer.Object); tc.EnqueueInstance <IDeploymentGroupServer>(_machineGroupServer.Object); return(tc); }
public async void SetGitHubContextActionRepoRef() { //Arrange Setup(); var actionId = Guid.NewGuid(); var actionInputs = new MappingToken(null, null, null); actionInputs.Add(new StringToken(null, null, null, "input1"), new StringToken(null, null, null, "test1")); actionInputs.Add(new StringToken(null, null, null, "input2"), new StringToken(null, null, null, "test2")); var action = new Pipelines.ActionStep() { Name = "action", Id = actionId, Reference = new Pipelines.RepositoryPathReference() { Name = "actions/test", Ref = "master" }, Inputs = actionInputs }; _actionRunner.Action = action; Dictionary <string, string> finialInputs = new Dictionary <string, string>(); _handlerFactory.Setup(x => x.Create(It.IsAny <IExecutionContext>(), It.IsAny <ActionStepDefinitionReference>(), It.IsAny <IStepHost>(), It.IsAny <ActionExecutionData>(), It.IsAny <Dictionary <string, string> >(), It.IsAny <Dictionary <string, string> >(), It.IsAny <Variables>(), It.IsAny <string>(), It.IsAny <List <JobExtensionRunner> >())) .Callback((IExecutionContext executionContext, Pipelines.ActionStepDefinitionReference actionReference, IStepHost stepHost, ActionExecutionData data, Dictionary <string, string> inputs, Dictionary <string, string> environment, Variables runtimeVariables, string taskDirectory, List <JobExtensionRunner> localActionContainerSetupSteps) => { finialInputs = inputs; }) .Returns(new Mock <IHandler>().Object); //Act await _actionRunner.RunAsync(); //Assert _ec.Verify(x => x.SetGitHubContext("action_repository", "actions/test"), Times.Once); _ec.Verify(x => x.SetGitHubContext("action_ref", "master"), Times.Once); action = new Pipelines.ActionStep() { Name = "action", Id = actionId, Reference = new Pipelines.ScriptReference(), Inputs = actionInputs }; _actionRunner.Action = action; _hc.EnqueueInstance <IDefaultStepHost>(_defaultStepHost.Object); _hc.EnqueueInstance(_fileCommandManager.Object); //Act await _actionRunner.RunAsync(); //Assert _ec.Verify(x => x.SetGitHubContext("action_repository", null), Times.Once); _ec.Verify(x => x.SetGitHubContext("action_ref", null), Times.Once); }
public async void DispatchRunNewJob() { //Arrange using (var hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { var worker = new Microsoft.VisualStudio.Services.Agent.Worker.Worker(); hc.EnqueueInstance <IProcessChannel>(_processChannel.Object); hc.EnqueueInstance <IJobRunner>(_jobRunner.Object); hc.SetSingleton <IVstsAgentWebProxy>(_proxy.Object); hc.SetSingleton <IAgentCertificateManager>(_cert.Object); worker.Initialize(hc); var jobMessage = CreateJobRequestMessage("job1"); var arWorkerMessages = new WorkerMessage[] { new WorkerMessage { Body = JsonUtility.ToString(jobMessage), MessageType = MessageType.NewJobRequest } }; var workerMessages = new Queue <WorkerMessage>(arWorkerMessages); _processChannel .Setup(x => x.ReceiveAsync(It.IsAny <CancellationToken>())) .Returns(async() => { // Return the job message. if (workerMessages.Count > 0) { return(workerMessages.Dequeue()); } // Wait for the text to run await Task.Delay(-1, tokenSource.Token); return(default(WorkerMessage)); }); _jobRunner.Setup(x => x.RunAsync(It.IsAny <Pipelines.AgentJobRequestMessage>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <TaskResult>(TaskResult.Succeeded)); //Act await worker.RunAsync(pipeIn : "1", pipeOut : "2"); //Assert _processChannel.Verify(x => x.StartClient("1", "2"), Times.Once()); _jobRunner.Verify(x => x.RunAsync( It.Is <Pipelines.AgentJobRequestMessage>(y => IsMessageIdentical(y, jobMessage)), It.IsAny <CancellationToken>())); tokenSource.Cancel(); } }
public async void DispatchesOneTimeJobRequest() { //Arrange using (var hc = new TestHostContext(this)) { var jobDispatcher = new JobDispatcher(); hc.SetSingleton <IConfigurationStore>(_configurationStore.Object); hc.SetSingleton <IRunnerServer>(_runnerServer.Object); hc.EnqueueInstance <IProcessChannel>(_processChannel.Object); hc.EnqueueInstance <IProcessInvoker>(_processInvoker.Object); _configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings() { PoolId = 1 }); jobDispatcher.Initialize(hc); var ts = new CancellationTokenSource(); Pipelines.AgentJobRequestMessage message = CreateJobRequestMessage(); string strMessage = JsonUtility.ToString(message); _processInvoker.Setup(x => x.ExecuteAsync(It.IsAny <String>(), It.IsAny <String>(), "spawnclient 1 2", null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult <int>(56)); _processChannel.Setup(x => x.StartServer(It.IsAny <StartProcessDelegate>())) .Callback((StartProcessDelegate startDel) => { startDel("1", "2"); }); _processChannel.Setup(x => x.SendAsync(MessageType.NewJobRequest, It.Is <string>(s => s.Equals(strMessage)), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); var request = new TaskAgentJobRequest(); PropertyInfo sessionIdProperty = request.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Assert.NotNull(sessionIdProperty); sessionIdProperty.SetValue(request, DateTime.UtcNow.AddMinutes(5)); _runnerServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny <int>(), It.IsAny <long>(), It.IsAny <Guid>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <TaskAgentJobRequest>(request)); _runnerServer.Setup(x => x.FinishAgentRequestAsync(It.IsAny <int>(), It.IsAny <long>(), It.IsAny <Guid>(), It.IsAny <DateTime>(), It.IsAny <TaskResult>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <TaskAgentJobRequest>(new TaskAgentJobRequest())); //Act jobDispatcher.Run(message, true); //Assert await jobDispatcher.WaitAsync(CancellationToken.None); Assert.True(jobDispatcher.RunOnceJobCompleted.Task.IsCompleted, "JobDispatcher should set task complete token for one time agent."); Assert.True(jobDispatcher.RunOnceJobCompleted.Task.Result, "JobDispatcher should set task complete token to 'TRUE' for one time agent."); } }
public async void DispatchCancellation() { //Arrange using (var hc = new TestHostContext(this)) { var worker = new Microsoft.VisualStudio.Services.Agent.Worker.Worker(); hc.EnqueueInstance <IProcessChannel>(_processChannel.Object); hc.EnqueueInstance <IJobRunner>(_jobRunner.Object); hc.SetSingleton <IVstsAgentWebProxy>(_proxy.Object); hc.SetSingleton <IAgentCertificateManager>(_cert.Object); worker.Initialize(hc); var jobMessage = CreateJobRequestMessage("job1"); var cancelMessage = CreateJobCancelMessage(jobMessage.JobId); var arWorkerMessages = new WorkerMessage[] { new WorkerMessage { Body = JsonUtility.ToString(jobMessage), MessageType = MessageType.NewJobRequest }, new WorkerMessage { Body = JsonUtility.ToString(cancelMessage), MessageType = MessageType.CancelRequest } }; var workerMessages = new Queue <WorkerMessage>(arWorkerMessages); _processChannel.Setup(x => x.ReceiveAsync(It.IsAny <CancellationToken>())) .Returns(() => Task.FromResult(workerMessages.Dequeue())); _jobRunner.Setup(x => x.RunAsync(It.IsAny <Pipelines.AgentJobRequestMessage>(), It.IsAny <CancellationToken>())) .Returns( async(Pipelines.AgentJobRequestMessage jm, CancellationToken ct) => { await Task.Delay(-1, ct); return(TaskResult.Canceled); }); //Act await Assert.ThrowsAsync <TaskCanceledException>( async() => await worker.RunAsync("1", "2")); //Assert _processChannel.Verify(x => x.StartClient("1", "2"), Times.Once()); _jobRunner.Verify(x => x.RunAsync( It.Is <Pipelines.AgentJobRequestMessage>(y => IsMessageIdentical(y, jobMessage)), It.IsAny <CancellationToken>())); } }
public void VerifySkippedTimeLineRecord() { using (TestHostContext hc = CreateTestContext()) { // Arrange: Create the execution context. var jobServerQueue = new Mock <IJobServerQueue>(); hc.SetSingleton(jobServerQueue.Object); // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); var ec = new Agent.Worker.ExecutionContext(); ec.Initialize(hc); ec.InitializeJob(CreateJobRequestMessage(), CancellationToken.None); // Act ec.Skip(); // Assert Assert.Equal(TaskResult.Skipped, ec.Result); jobServerQueue.Verify( x => x.QueueTimelineRecordUpdate( It.IsAny <Guid>(), It.Is <TimelineRecord>(r => r.StartTime != null && r.StartTime == r.FinishTime && r.State == TimelineRecordState.Completed && r.Result == TaskResult.Skipped && r.PercentComplete == 0)), Times.AtLeastOnce()); } }
public async void TestSelfUpdateAsync_ValidateHash() { 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()); _runnerServer.Setup(x => x.GetPackageAsync("agent", BuildConstants.RunnerPackage.PackageName, "2.299.0", true, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName, Version = new PackageVersion("2.299.0"), DownloadUrl = _packageUrl, HashValue = "bad_hash" })); 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())); var ex = await Assert.ThrowsAsync <Exception>(() => updater.SelfUpdate(_refreshMessage, _jobDispatcher.Object, true, hc.RunnerShutdownToken)); Assert.Contains("did not match expected Runner Hash", ex.Message); } }
public void InitializeJob_should_set_JobSettings() { using (TestHostContext hc = CreateTestContext()) using (var ec = new Agent.Worker.ExecutionContext()) { // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); List <TaskInstance> tasks = new List <TaskInstance>(); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks)); // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); ec.Initialize(hc); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); // Assert. Assert.NotNull(ec.JobSettings); Assert.Equal(Boolean.FalseString, ec.JobSettings[WellKnownJobSettings.HasMultipleCheckouts]); } }
public void InitializeJob_LogsWarningsFromVariables() { using (TestHostContext hc = CreateTestContext()) { // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); environment.Variables["v1"] = "v1-$(v2)"; environment.Variables["v2"] = "v2-$(v1)"; List <TaskInstance> tasks = new List <TaskInstance>(); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks); // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); var ec = new Agent.Worker.ExecutionContext(); ec.Initialize(hc); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); // Assert. pagingLogger.Verify(x => x.Write(It.Is <string>(y => y.IndexOf("##[warning]") >= 0)), Times.Exactly(2)); } }
private void SetupMocks([CallerMemberName] string name = "", bool includePipelineVariables = false) { _hc = new TestHostContext(this, name); _hc.SetSingleton(_mockResultReader.Object); _mockExtensionManager = new Mock <IExtensionManager>(); _mockExtensionManager.Setup(x => x.GetExtensions <IResultReader>()).Returns(new List <IResultReader> { _mockResultReader.Object, new JUnitResultReader(), new NUnitResultReader() }); _hc.SetSingleton(_mockExtensionManager.Object); _hc.SetSingleton(_mockTestRunPublisher.Object); _mockCommandContext = new Mock <IAsyncCommandContext>(); _hc.EnqueueInstance(_mockCommandContext.Object); var endpointAuthorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.OAuth }; List <string> warnings; _variables = new Variables(_hc, new Dictionary <string, VariableValue>(), out warnings); _variables.Set("build.buildId", "1"); if (includePipelineVariables) { _variables.Set("system.jobName", "job1"); _variables.Set("system.phaseName", "phase1"); _variables.Set("system.stageName", "stage1"); _variables.Set("system.jobAttempt", "1"); _variables.Set("system.phaseAttempt", "1"); _variables.Set("system.stageAttempt", "1"); } endpointAuthorization.Parameters[EndpointAuthorizationParameters.AccessToken] = "accesstoken"; _ec = new Mock <IExecutionContext>(); _ec.Setup(x => x.Endpoints).Returns(new List <ServiceEndpoint> { new ServiceEndpoint { Url = new Uri("http://dummyurl"), Name = WellKnownServiceEndpointNames.SystemVssConnection, Authorization = endpointAuthorization } }); _ec.Setup(x => x.Variables).Returns(_variables); var asyncCommands = new List <IAsyncCommandContext>(); _ec.Setup(x => x.AsyncCommands).Returns(asyncCommands); _ec.Setup(x => x.AddIssue(It.IsAny <Issue>())) .Callback <Issue> ((issue) => { if (issue.Type == IssueType.Warning) { _warnings.Add(issue.Message); } else if (issue.Type == IssueType.Error) { _errors.Add(issue.Message); } }); }
public void InitializeJob_should_mark_primary_repository_in_multicheckout() { // Note: the primary repository is defined as the first repository that is checked out in the job using (TestHostContext hc = CreateTestContext()) using (var ec = new Agent.Worker.ExecutionContext()) { // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); List <TaskInstance> tasks = new List <TaskInstance>(); tasks.Add(new TaskInstance() { Id = Pipelines.PipelineConstants.CheckoutTask.Id, Version = Pipelines.PipelineConstants.CheckoutTask.Version, Inputs = { { Pipelines.PipelineConstants.CheckoutTaskInputs.Repository, "repo2" } } }); tasks.Add(new TaskInstance() { Id = Pipelines.PipelineConstants.CheckoutTask.Id, Version = Pipelines.PipelineConstants.CheckoutTask.Version, Inputs = { { Pipelines.PipelineConstants.CheckoutTaskInputs.Repository, "repo3" } } }); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, environment, tasks)); var repo1 = new Pipelines.RepositoryResource() { Alias = "self" }; var repo2 = new Pipelines.RepositoryResource() { Alias = "repo2" }; var repo3 = new Pipelines.RepositoryResource() { Alias = "repo3" }; jobRequest.Resources.Repositories.Add(repo1); jobRequest.Resources.Repositories.Add(repo2); jobRequest.Resources.Repositories.Add(repo3); // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); ec.Initialize(hc); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); // Assert. Assert.NotNull(ec.JobSettings); Assert.Equal(Boolean.TrueString, ec.JobSettings[WellKnownJobSettings.HasMultipleCheckouts]); Assert.Equal("repo2", ec.JobSettings[WellKnownJobSettings.FirstRepositoryCheckedOut]); Assert.Equal(Boolean.FalseString, repo1.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString)); Assert.Equal(Boolean.TrueString, repo2.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString)); Assert.Equal(Boolean.FalseString, repo3.Properties.Get <string>(RepositoryUtil.IsPrimaryRepository, Boolean.FalseString)); } }
public void TranslatePathForStepTarget_should_convert_path_only_for_containers(bool isCheckout, string jobTarget, string stepTarget) { // Note: the primary repository is defined as the first repository that is checked out in the job using (TestHostContext hc = CreateTestContext()) using (var ec = new Agent.Worker.ExecutionContext()) { ec.Initialize(hc); // Arrange: Create a container. var pipeContainer = new Pipelines.ContainerResource { Alias = "container" }; pipeContainer.Properties.Set <string>("image", "someimage"); // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>(); steps.Add(new Pipelines.TaskStep { Target = new Pipelines.StepTarget { Target = stepTarget }, Reference = new Pipelines.TaskStepDefinitionReference() }); var resources = new Pipelines.JobResources(); resources.Containers.Add(pipeContainer); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, jobTarget, new Dictionary <string, string>(), new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps); // Arrange var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); ec.SetStepTarget(steps[0].Target); ec.Variables.Set(Constants.Variables.Task.SkipTranslatorForCheckout, isCheckout.ToString()); string stringBeforeTranslation = hc.GetDirectory(WellKnownDirectory.Work); string stringAfterTranslation = ec.TranslatePathForStepTarget(stringBeforeTranslation); // Assert. if ((stepTarget == "container") || (isCheckout is false && jobTarget == "container" && stepTarget == null)) { string stringContainer = "C:\\__w"; if (ec.StepTarget().ExecutionOS != PlatformUtil.OS.Windows) { stringContainer = "/__w"; } Assert.Equal(stringContainer, stringAfterTranslation); }
public async void DispatchesJobRequest() { //Arrange using (var hc = new TestHostContext(this)) { var jobDispatcher = new JobDispatcher(); hc.SetSingleton<IConfigurationStore>(_configurationStore.Object); hc.SetSingleton<IAgentServer>(_agentServer.Object); hc.EnqueueInstance<IProcessChannel>(_processChannel.Object); hc.EnqueueInstance<IProcessInvoker>(_processInvoker.Object); _configurationStore.Setup(x => x.GetSettings()).Returns(new AgentSettings() { PoolId = 1 }); jobDispatcher.Initialize(hc); var ts = new CancellationTokenSource(); JobRequestMessage message = CreateJobRequestMessage(); string strMessage = JsonUtility.ToString(message); _processInvoker.Setup(x => x.ExecuteAsync(It.IsAny<String>(), It.IsAny<String>(), "spawnclient 1 2", null, It.IsAny<CancellationToken>())) .Returns(Task.FromResult<int>(56)); _processChannel.Setup(x => x.StartServer(It.IsAny<StartProcessDelegate>())) .Callback((StartProcessDelegate startDel) => { startDel("1","2"); }); _processChannel.Setup(x => x.SendAsync(MessageType.NewJobRequest, It.Is<string>(s => s.Equals(strMessage)), It.IsAny<CancellationToken>())) .Returns(Task.CompletedTask); var request = new TaskAgentJobRequest(); PropertyInfo sessionIdProperty = request.GetType().GetProperty("LockedUntil", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Assert.NotNull(sessionIdProperty); sessionIdProperty.SetValue(request, DateTime.UtcNow.AddMinutes(5)); _agentServer.Setup(x => x.RenewAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(request)); _agentServer.Setup(x => x.FinishAgentRequestAsync(It.IsAny<int>(), It.IsAny<long>(), It.IsAny<Guid>(), It.IsAny<DateTime>(), It.IsAny<TaskResult>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult<TaskAgentJobRequest>(new TaskAgentJobRequest())); //Actt jobDispatcher.Run(message); //Assert await jobDispatcher.WaitAsync(CancellationToken.None); } }
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { TestHostContext tc = new TestHostContext(this, testName); tc.SetSingleton<ICredentialManager>(_credMgr.Object); tc.SetSingleton<IPromptManager>(_promptManager.Object); tc.SetSingleton<IConfigurationStore>(_store.Object); tc.EnqueueInstance<IAgentServer>(_agentServer.Object); return tc; }
private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { TestHostContext tc = new TestHostContext(this, testName); tc.SetSingleton <ICredentialManager>(_credMgr.Object); tc.SetSingleton <IPromptManager>(_promptManager.Object); tc.SetSingleton <IConfigurationStore>(_store.Object); tc.EnqueueInstance <IAgentServer>(_agentServer.Object); return(tc); }
public void SidecarContainers_VerifyNotJobContainers() { using (TestHostContext hc = CreateTestContext()) using (var ec = new Agent.Worker.ExecutionContext()) { ec.Initialize(hc); var pipeContainer = new Pipelines.ContainerResource { Alias = "container" }; var pipeContainerSidecar = new Pipelines.ContainerResource { Alias = "sidecar" }; var pipeContainerExtra = new Pipelines.ContainerResource { Alias = "extra" }; pipeContainer.Properties.Set <string>("image", "someimage"); pipeContainerSidecar.Properties.Set <string>("image", "someimage"); pipeContainerExtra.Properties.Set <string>("image", "someimage"); // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>(); steps.Add(new Pipelines.TaskStep { Reference = new Pipelines.TaskStepDefinitionReference() }); var resources = new Pipelines.JobResources(); resources.Containers.Add(pipeContainer); resources.Containers.Add(pipeContainerSidecar); resources.Containers.Add(pipeContainerExtra); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var sidecarContainers = new Dictionary <string, string>(); sidecarContainers.Add("sidecar", "sidecar"); var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, null, sidecarContainers, new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps); // Arrange: Setup command manager var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); // Assert. Assert.Equal(2, ec.Containers.Count()); Assert.Equal(1, ec.SidecarContainers.Count()); Assert.False(ec.SidecarContainers.First().IsJobContainer); } }
public void ActionResult_Lowercase() { using (TestHostContext hc = CreateTestContext()) { TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null, null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, Id = "github", Version = "sha1" }); jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true"; // Arrange: Setup the paging logger. var pagingLogger1 = new Mock <IPagingLogger>(); var jobServerQueue = new Mock <IJobServerQueue>(); hc.EnqueueInstance(pagingLogger1.Object); hc.SetSingleton(jobServerQueue.Object); var jobContext = new Runner.Worker.ExecutionContext(); jobContext.Initialize(hc); // Act. jobContext.InitializeJob(jobRequest, CancellationToken.None); jobContext.Global.StepsContext.SetConclusion(null, "step1", ActionResult.Success); var conclusion1 = (jobContext.Global.StepsContext.GetScope(null)["step1"] as DictionaryContextData)["conclusion"].ToString(); Assert.Equal(conclusion1, conclusion1.ToLowerInvariant()); jobContext.Global.StepsContext.SetOutcome(null, "step2", ActionResult.Cancelled); var outcome1 = (jobContext.Global.StepsContext.GetScope(null)["step2"] as DictionaryContextData)["outcome"].ToString(); Assert.Equal(outcome1, outcome1.ToLowerInvariant()); jobContext.Global.StepsContext.SetConclusion(null, "step3", ActionResult.Failure); var conclusion2 = (jobContext.Global.StepsContext.GetScope(null)["step3"] as DictionaryContextData)["conclusion"].ToString(); Assert.Equal(conclusion2, conclusion2.ToLowerInvariant()); jobContext.Global.StepsContext.SetOutcome(null, "step4", ActionResult.Skipped); var outcome2 = (jobContext.Global.StepsContext.GetScope(null)["step4"] as DictionaryContextData)["outcome"].ToString(); Assert.Equal(outcome2, outcome2.ToLowerInvariant()); jobContext.JobContext.Status = ActionResult.Success; Assert.Equal(jobContext.JobContext["status"].ToString(), jobContext.JobContext["status"].ToString().ToLowerInvariant()); } }
private TestHostContext SetupMocks([CallerMemberName] string name = "") { var _hc = new TestHostContext(this, name); _hc.SetSingleton(new TaskRestrictionsChecker() as ITaskRestrictionsChecker); _mockCiService = new Mock <ICustomerIntelligenceServer>(); _hc.SetSingleton(_mockCiService.Object); _mockCommandContext = new Mock <IAsyncCommandContext>(); _hc.EnqueueInstance(_mockCommandContext.Object); var endpointAuthorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.OAuth }; List <string> warnings; var variables = new Variables(_hc, new Dictionary <string, VariableValue>(), out warnings); endpointAuthorization.Parameters[EndpointAuthorizationParameters.AccessToken] = "accesstoken"; _ec = new Mock <IExecutionContext>(); _ec.Setup(x => x.Restrictions).Returns(new List <TaskRestrictions>()); _ec.Setup(x => x.Endpoints).Returns(new List <ServiceEndpoint> { new ServiceEndpoint { Url = new Uri("http://dummyurl"), Name = WellKnownServiceEndpointNames.SystemVssConnection, Authorization = endpointAuthorization } }); _ec.Setup(x => x.Variables).Returns(variables); var asyncCommands = new List <IAsyncCommandContext>(); _ec.Setup(x => x.AsyncCommands).Returns(asyncCommands); _ec.Setup(x => x.AddIssue(It.IsAny <Issue>())) .Callback <Issue> ((issue) => { if (issue.Type == IssueType.Warning) { _warnings.Add(issue.Message); } else if (issue.Type == IssueType.Error) { _errors.Add(issue.Message); } }); _ec.Setup(x => x.GetHostContext()).Returns(_hc); return(_hc); }
public void EchoProcessCommandDebugOn() { using (TestHostContext hc = CreateTestContext()) { // Set up a few things // 1. Job request message (with ACTIONS_STEP_DEBUG = true) TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null, null, null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, Id = "github", Version = "sha1" }); jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true"; // Some service dependencies var jobServerQueue = new Mock <IJobServerQueue>(); jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>())); hc.SetSingleton(jobServerQueue.Object); var configurationStore = new Mock <IConfigurationStore>(); configurationStore.Setup(x => x.GetSettings()).Returns(new RunnerSettings()); hc.SetSingleton(configurationStore.Object); var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); // Initialize the job (to exercise logic that sets EchoOnActionCommand) var ec = new Runner.Worker.ExecutionContext(); ec.Initialize(hc); ec.InitializeJob(jobRequest, System.Threading.CancellationToken.None); ec.Complete(); Assert.True(ec.EchoOnActionCommand); Assert.True(_commandManager.TryProcessCommand(ec, "::echo::off", null)); Assert.False(ec.EchoOnActionCommand); Assert.True(_commandManager.TryProcessCommand(ec, "::echo::on", null)); Assert.True(ec.EchoOnActionCommand); } }
public void TestRun() { using (var hc = new TestHostContext(this)) using (var workerManager = new WorkerManager()) { hc.EnqueueInstance <IJobDispatcher>(_jobDispatcher.Object); workerManager.Initialize(hc); JobRequestMessage jobMessage = CreateJobRequestMessage(); _jobDispatcher.Setup(x => x.RunAsync(jobMessage, It.IsAny <CancellationToken>())) .Returns(Task.FromResult <int>(21)); workerManager.Run(jobMessage); _jobDispatcher.Verify(x => x.RunAsync(jobMessage, It.IsAny <CancellationToken>()), "IJobDispatcher.RunAsync not invoked"); } }
public void StepTarget_RestrictedCommands_Host() { using (TestHostContext hc = CreateTestContext()) using (var ec = new Agent.Worker.ExecutionContext()) { ec.Initialize(hc); var pipeContainer = new Pipelines.ContainerResource { Alias = "container" }; pipeContainer.Properties.Set <string>("image", "someimage"); // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); List <Pipelines.JobStep> steps = new List <Pipelines.JobStep>(); steps.Add(new Pipelines.TaskStep { Target = new Pipelines.StepTarget { Target = "host", Commands = "restricted" }, Reference = new Pipelines.TaskStepDefinitionReference() }); var resources = new Pipelines.JobResources(); resources.Containers.Add(pipeContainer); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, null, new Dictionary <string, string>(), new Dictionary <string, VariableValue>(), new List <MaskHint>(), resources, new Pipelines.WorkspaceOptions(), steps); // Arrange: Setup command manager var commandMock = new Mock <IWorkerCommandManager>(); hc.SetSingleton(commandMock.Object); var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); ec.SetStepTarget(steps[0].Target); // Assert. Assert.IsType <HostInfo>(ec.StepTarget()); commandMock.Verify(x => x.SetCommandRestrictionPolicy(It.IsAny <AttributeBasedWorkerCommandRestrictionPolicy>())); } }
public async void DispatchRunNewJob() { //Arrange using (var hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { var worker = new Microsoft.VisualStudio.Services.Agent.Worker.Worker(); hc.EnqueueInstance<IProcessChannel>(_processChannel.Object); hc.SetSingleton<IJobRunner>(_jobRunner.Object); worker.Initialize(hc); var jobMessage = CreateJobRequestMessage("job1"); var arWorkerMessages = new WorkerMessage[] { new WorkerMessage { Body = JsonUtility.ToString(jobMessage), MessageType = MessageType.NewJobRequest } }; var workerMessages = new Queue<WorkerMessage>(arWorkerMessages); _processChannel .Setup(x => x.ReceiveAsync(It.IsAny<CancellationToken>())) .Returns(async () => { // Return the job message. if (workerMessages.Count > 0) { return workerMessages.Dequeue(); } // Wait for the text to run await Task.Delay(-1, tokenSource.Token); return default(WorkerMessage); }); _jobRunner.Setup(x => x.RunAsync(It.IsAny<JobRequestMessage>(), It.IsAny<CancellationToken>())) .Returns(Task.FromResult<TaskResult>(TaskResult.Succeeded)); //Act await worker.RunAsync(pipeIn: "1", pipeOut: "2"); //Assert _processChannel.Verify(x => x.StartClient("1", "2"), Times.Once()); _jobRunner.Verify(x => x.RunAsync( It.Is<JobRequestMessage>(y => JsonUtility.ToString(y) == arWorkerMessages[0].Body), It.IsAny<CancellationToken>())); tokenSource.Cancel(); } }
public void InitializeJob_LogsWarningsFromVariables() { using (TestHostContext hc = new TestHostContext(this)) { // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); JobEnvironment environment = new JobEnvironment(); environment.SystemConnection = new ServiceEndpoint(); environment.Variables["v1"] = "v1-$(v2)"; environment.Variables["v2"] = "v2-$(v1)"; List <TaskInstance> tasks = new List <TaskInstance>(); Guid JobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new AgentJobRequestMessage(plan, timeline, JobId, jobName, environment, tasks); // Arrange: Setup the configation store. var configurationStore = new Mock <IConfigurationStore>(); configurationStore.Setup(x => x.GetSettings()).Returns(new AgentSettings()); hc.SetSingleton(configurationStore.Object); // Arrange: Setup the secret masker. var secretMasker = new Mock <ISecretMasker>(); secretMasker.Setup(x => x.MaskSecrets(It.IsAny <string>())) .Returns((string x) => x); hc.SetSingleton(secretMasker.Object); // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); // Arrange: Setup the proxy configation. var proxy = new Mock <IProxyConfiguration>(); hc.SetSingleton(proxy.Object); // Arrange: Create the execution context. hc.SetSingleton(new Mock <IJobServerQueue>().Object); var ec = new Microsoft.VisualStudio.Services.Agent.Worker.ExecutionContext(); ec.Initialize(hc); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); // Assert. pagingLogger.Verify(x => x.Write(It.Is <string>(y => y.IndexOf("##[warning]") >= 0)), Times.Exactly(2)); } }
public void Debug_Multilines() { using (TestHostContext hc = CreateTestContext()) { // Arrange: Create a job request message. TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new TimelineReference(); Guid jobId = Guid.NewGuid(); string jobName = "some job name"; var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary <string, VariableValue>(), new List <MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List <Pipelines.ActionStep>(), null); jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, Id = "github", Version = "sha1" }); jobRequest.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData(); jobRequest.Variables["ACTIONS_STEP_DEBUG"] = "true"; // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); var jobServerQueue = new Mock <IJobServerQueue>(); jobServerQueue.Setup(x => x.QueueTimelineRecordUpdate(It.IsAny <Guid>(), It.IsAny <TimelineRecord>())); jobServerQueue.Setup(x => x.QueueWebConsoleLine(It.IsAny <Guid>(), It.IsAny <string>())).Callback((Guid id, string msg) => { hc.GetTrace().Info(msg); }); hc.EnqueueInstance(pagingLogger.Object); hc.SetSingleton(jobServerQueue.Object); var ec = new Runner.Worker.ExecutionContext(); ec.Initialize(hc); // Act. ec.InitializeJob(jobRequest, CancellationToken.None); ec.Debug(null); ec.Debug(""); ec.Debug("\n"); ec.Debug("\r\n"); ec.Debug("test"); ec.Debug("te\nst"); ec.Debug("te\r\nst"); ec.Complete(); jobServerQueue.Verify(x => x.QueueWebConsoleLine(It.IsAny <Guid>(), It.IsAny <string>()), Times.Exactly(10)); } }
public async void TestCancel() { //Arrange using (var hc = new TestHostContext(this)) using (var workerManager = new WorkerManager()) { hc.EnqueueInstance <IJobDispatcher>(_jobDispatcher.Object); workerManager.Initialize(hc); JobRequestMessage jobMessage = CreateJobRequestMessage(); JobCancelMessage cancelMessage = CreateJobCancelMessage(jobMessage.JobId); bool started = false; Task jobTask = null; _jobDispatcher.Setup(x => x.RunAsync(jobMessage, It.IsAny <CancellationToken>())) .Returns(async(JobRequestMessage message, CancellationToken token) => { jobTask = Task.Delay(5000, token); started = true; await jobTask; return(0); }); workerManager.Run(jobMessage); int i = 20; while (i > 0 && (!started)) { await Task.Delay(10); i--; } Assert.True(started); //Act //send cancel message workerManager.Cancel(cancelMessage); //Assert //wait up to 2 sec for cancellation to be processed Task[] taskToWait = { jobTask, Task.Delay(2000) }; await Task.WhenAny(taskToWait); _jobDispatcher.Verify(x => x.RunAsync(jobMessage, It.IsAny <CancellationToken>()), $"{nameof(_jobDispatcher.Object.RunAsync)} not invoked"); Assert.True(jobTask.IsCompleted); Assert.True(jobTask.IsCanceled); } }
public void CanNotSkipTimelineAfterStarting() { using (TestHostContext hc = CreateTestContext()) { // Arrange: Setup the paging logger. var pagingLogger = new Mock <IPagingLogger>(); hc.EnqueueInstance(pagingLogger.Object); var ec = new Agent.Worker.ExecutionContext(); ec.Initialize(hc); var jobRequest = CreateJobRequestMessage(); ec.InitializeJob(jobRequest, CancellationToken.None); // Act ec.Start(); // Assert Assert.Throws <InvalidOperationException>(() => ec.Skip()); } }
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); } } }
private void SetupMocks([CallerMemberName] string name = "") { _hc = new TestHostContext(this, name); _hc.SetSingleton(_mockResultReader.Object); _mockExtensionManager = new Mock<IExtensionManager>(); _mockExtensionManager.Setup(x => x.GetExtensions<IResultReader>()).Returns(new List<IResultReader> { _mockResultReader.Object, new JUnitResultReader(), new NUnitResultReader() }); _hc.SetSingleton(_mockExtensionManager.Object); _hc.SetSingleton(_mockTestRunPublisher.Object); _mockCommandContext = new Mock<IAsyncCommandContext>(); _hc.EnqueueInstance(_mockCommandContext.Object); var endpointAuthorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.OAuth }; List<string> warnings; _variables = new Variables(_hc, new Dictionary<string, string>(), new List<MaskHint>(), out warnings); _variables.Set("build.buildId", "1"); endpointAuthorization.Parameters[EndpointAuthorizationParameters.AccessToken] = "accesstoken"; _ec = new Mock<IExecutionContext>(); _ec.Setup(x => x.Endpoints).Returns(new List<ServiceEndpoint> { new ServiceEndpoint { Url = new Uri("http://dummyurl"), Name = ServiceEndpoints.SystemVssConnection, Authorization = endpointAuthorization } }); _ec.Setup(x => x.Variables).Returns(_variables); var asyncCommands = new List<IAsyncCommandContext>(); _ec.Setup(x => x.AsyncCommands).Returns(asyncCommands); _ec.Setup(x => x.AddIssue(It.IsAny<Issue>())) .Callback<Issue> ((issue) => { if (issue.Type == IssueType.Warning) { _warnings.Add(issue.Message); } else if (issue.Type == IssueType.Error) { _errors.Add(issue.Message); } }); }
//process 2 new job messages, and one cancel message public async void TestRunAsync() { using (var hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { //Arrange var agent = new Agent.Listener.Agent(); agent.TokenSource = tokenSource; hc.SetSingleton <IConfigurationManager>(_configurationManager.Object); hc.SetSingleton <IJobNotification>(_jobNotification.Object); hc.SetSingleton <IMessageListener>(_messageListener.Object); hc.SetSingleton <IPromptManager>(_promptManager.Object); hc.SetSingleton <IAgentServer>(_agentServer.Object); hc.SetSingleton <IVstsAgentWebProxy>(_proxy.Object); agent.Initialize(hc); var settings = new AgentSettings { PoolId = 43242 }; var message = new TaskAgentMessage() { Body = JsonUtility.ToString(CreateJobRequestMessage("job1")), MessageId = 4234, MessageType = JobRequestMessageTypes.AgentJobRequest }; var messages = new Queue <TaskAgentMessage>(); messages.Enqueue(message); var signalWorkerComplete = new SemaphoreSlim(0, 1); _configurationManager.Setup(x => x.LoadSettings()) .Returns(settings); _configurationManager.Setup(x => x.IsConfigured()) .Returns(true); _messageListener.Setup(x => x.CreateSessionAsync(It.IsAny <CancellationToken>())) .Returns(Task.FromResult <bool>(true)); _messageListener.Setup(x => x.GetNextMessageAsync(It.IsAny <CancellationToken>())) .Returns(async() => { if (0 == messages.Count) { signalWorkerComplete.Release(); await Task.Delay(2000, tokenSource.Token); } return(messages.Dequeue()); }); _messageListener.Setup(x => x.DeleteSessionAsync()) .Returns(Task.CompletedTask); _messageListener.Setup(x => x.DeleteMessageAsync(It.IsAny <TaskAgentMessage>())) .Returns(Task.CompletedTask); _jobDispatcher.Setup(x => x.Run(It.IsAny <AgentJobRequestMessage>())) .Callback(() => { }); _jobNotification.Setup(x => x.StartClient(It.IsAny <String>(), It.IsAny <CancellationToken>())) .Callback(() => { }); _jobNotification.Setup(x => x.StartClient(It.IsAny <String>())) .Callback(() => { }); hc.EnqueueInstance <IJobDispatcher>(_jobDispatcher.Object); //Act var command = new CommandSettings(hc, new string[] { "run" }); Task agentTask = agent.ExecuteCommand(command); //Assert //wait for the agent to run one job if (!await signalWorkerComplete.WaitAsync(2000)) { Assert.True(false, $"{nameof(_messageListener.Object.GetNextMessageAsync)} was not invoked."); } else { //Act tokenSource.Cancel(); //stop Agent //Assert Task[] taskToWait2 = { agentTask, Task.Delay(2000) }; //wait for the Agent to exit await Task.WhenAny(taskToWait2); Assert.True(agentTask.IsCompleted, $"{nameof(agent.ExecuteCommand)} timed out."); Assert.True(!agentTask.IsFaulted, agentTask.Exception?.ToString()); Assert.True(agentTask.IsCanceled); _jobDispatcher.Verify(x => x.Run(It.IsAny <AgentJobRequestMessage>()), Times.Once(), $"{nameof(_jobDispatcher.Object.Run)} was not invoked."); _messageListener.Verify(x => x.GetNextMessageAsync(It.IsAny <CancellationToken>()), Times.AtLeastOnce()); _messageListener.Verify(x => x.CreateSessionAsync(It.IsAny <CancellationToken>()), Times.Once()); _messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once()); _messageListener.Verify(x => x.DeleteMessageAsync(It.IsAny <TaskAgentMessage>()), Times.AtLeastOnce()); } } }
private TestHostContext CreateTestContext(CancellationTokenSource _tokenSource, [CallerMemberName] String testName = "") { var hc = new TestHostContext(this, testName); _jobEc = new Agent.Worker.ExecutionContext(); _taskManager = new Mock <ITaskManager>(); _jobServerQueue = new Mock <IJobServerQueue>(); _config = new Mock <IConfigurationStore>(); _logger = new Mock <IPagingLogger>(); _proxy = new Mock <IVstsAgentWebProxy>(); _cert = new Mock <IAgentCertificateManager>(); _express = new Mock <IExpressionManager>(); _containerProvider = new Mock <IContainerOperationProvider>(); _logPlugin = new Mock <IAgentLogPlugin>(); TaskRunner step1 = new TaskRunner(); TaskRunner step2 = new TaskRunner(); TaskRunner step3 = new TaskRunner(); TaskRunner step4 = new TaskRunner(); TaskRunner step5 = new TaskRunner(); TaskRunner step6 = new TaskRunner(); TaskRunner step7 = new TaskRunner(); TaskRunner step8 = new TaskRunner(); TaskRunner step9 = new TaskRunner(); TaskRunner step10 = new TaskRunner(); TaskRunner step11 = new TaskRunner(); TaskRunner step12 = new TaskRunner(); _logger.Setup(x => x.Setup(It.IsAny <Guid>(), It.IsAny <Guid>())); var settings = new AgentSettings { AgentId = 1, AgentName = "agent1", ServerUrl = "https://test.visualstudio.com", WorkFolder = "_work", }; _config.Setup(x => x.GetSettings()) .Returns(settings); _proxy.Setup(x => x.ProxyAddress) .Returns(string.Empty); TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference(); TimelineReference timeline = new Timeline(Guid.NewGuid()); JobEnvironment environment = new JobEnvironment(); environment.Variables[Constants.Variables.System.Culture] = "en-US"; environment.SystemConnection = new ServiceEndpoint() { Name = WellKnownServiceEndpointNames.SystemVssConnection, Url = new Uri("https://test.visualstudio.com"), Authorization = new EndpointAuthorization() { Scheme = "Test", } }; environment.SystemConnection.Authorization.Parameters["AccessToken"] = "token"; List <TaskInstance> tasks = new List <TaskInstance>() { new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task1", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task2", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task3", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task4", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task5", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task6", }, new TaskInstance() { InstanceId = Guid.NewGuid(), DisplayName = "task7", }, }; Guid JobId = Guid.NewGuid(); _message = Pipelines.AgentJobRequestMessageUtil.Convert(new AgentJobRequestMessage(plan, timeline, JobId, testName, testName, environment, tasks)); _taskManager.Setup(x => x.DownloadAsync(It.IsAny <IExecutionContext>(), It.IsAny <IEnumerable <Pipelines.TaskStep> >())) .Returns(Task.CompletedTask); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task1"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = null, Execution = new ExecutionData(), PostJobExecution = null, }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task2"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = new ExecutionData(), Execution = new ExecutionData(), PostJobExecution = new ExecutionData(), }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task3"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = new ExecutionData(), Execution = null, PostJobExecution = new ExecutionData(), }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task4"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = new ExecutionData(), Execution = null, PostJobExecution = null, }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task5"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = null, Execution = null, PostJobExecution = new ExecutionData(), }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task6"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = new ExecutionData(), Execution = new ExecutionData(), PostJobExecution = null, }, }); _taskManager.Setup(x => x.Load(It.Is <Pipelines.TaskStep>(t => t.DisplayName == "task7"))) .Returns(new Definition() { Data = new DefinitionData() { PreJobExecution = null, Execution = new ExecutionData(), PostJobExecution = new ExecutionData(), }, }); hc.SetSingleton(_taskManager.Object); hc.SetSingleton(_config.Object); hc.SetSingleton(_jobServerQueue.Object); hc.SetSingleton(_proxy.Object); hc.SetSingleton(_cert.Object); hc.SetSingleton(_express.Object); hc.SetSingleton(_containerProvider.Object); hc.SetSingleton(_logPlugin.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); // jobcontext logger hc.EnqueueInstance <IPagingLogger>(_logger.Object); // init step logger hc.EnqueueInstance <IPagingLogger>(_logger.Object); // step 1 hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); hc.EnqueueInstance <IPagingLogger>(_logger.Object); // step 12 hc.EnqueueInstance <ITaskRunner>(step1); hc.EnqueueInstance <ITaskRunner>(step2); hc.EnqueueInstance <ITaskRunner>(step3); hc.EnqueueInstance <ITaskRunner>(step4); hc.EnqueueInstance <ITaskRunner>(step5); hc.EnqueueInstance <ITaskRunner>(step6); hc.EnqueueInstance <ITaskRunner>(step7); hc.EnqueueInstance <ITaskRunner>(step8); hc.EnqueueInstance <ITaskRunner>(step9); hc.EnqueueInstance <ITaskRunner>(step10); hc.EnqueueInstance <ITaskRunner>(step11); hc.EnqueueInstance <ITaskRunner>(step12); _jobEc.Initialize(hc); _jobEc.InitializeJob(_message, _tokenSource.Token); return(hc); }
private void SetupMocks([CallerMemberName] string name = "") { _hc = new TestHostContext(this, name); _codeCoverageStatistics = new List <CodeCoverageStatistics> { new CodeCoverageStatistics { Label = "label", Covered = 10, Total = 10, Position = 1 } }; _mocksummaryReader = new Mock <ICodeCoverageSummaryReader>(); if (String.Equals(name, "Publish_CoberturaNewIndexFile")) { _mocksummaryReader.Setup(x => x.Name).Returns("cobertura"); } else { _mocksummaryReader.Setup(x => x.Name).Returns("mockCCTool"); } _mocksummaryReader.Setup(x => x.GetCodeCoverageSummary(It.IsAny <IExecutionContext>(), It.IsAny <string>())) .Returns(_codeCoverageStatistics); _hc.SetSingleton(_mocksummaryReader.Object); _mockCodeCoverageEnabler = new Mock <ICodeCoverageEnabler>(); _mockCodeCoverageEnabler.Setup(x => x.Name).Returns("mockCCTool_mockBuildTool"); _mockCodeCoverageEnabler.Setup(x => x.EnableCodeCoverage(It.IsAny <IExecutionContext>(), It.IsAny <CodeCoverageEnablerInputs>())); _hc.SetSingleton(_mockCodeCoverageEnabler.Object); _mockExtensionManager = new Mock <IExtensionManager>(); _mockExtensionManager.Setup(x => x.GetExtensions <ICodeCoverageSummaryReader>()).Returns(new List <ICodeCoverageSummaryReader> { _mocksummaryReader.Object }); _mockExtensionManager.Setup(x => x.GetExtensions <ICodeCoverageEnabler>()).Returns(new List <ICodeCoverageEnabler> { _mockCodeCoverageEnabler.Object }); _hc.SetSingleton(_mockExtensionManager.Object); _mockCodeCoveragePublisher = new Mock <ICodeCoveragePublisher>(); _hc.SetSingleton(_mockCodeCoveragePublisher.Object); _mockCommandContext = new Mock <IAsyncCommandContext>(); _hc.EnqueueInstance(_mockCommandContext.Object); var endpointAuthorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.OAuth }; List <string> warnings; _variables = new Variables(_hc, new Dictionary <string, string>(), new List <MaskHint>(), out warnings); _variables.Set("build.buildId", "1"); _variables.Set("build.containerId", "1"); _variables.Set("system.teamProjectId", "46075F24-A6B9-447E-BEF0-E1D5592D9E39"); _variables.Set("system.hostType", "build"); endpointAuthorization.Parameters[EndpointAuthorizationParameters.AccessToken] = "accesstoken"; _ec = new Mock <IExecutionContext>(); _ec.Setup(x => x.Endpoints).Returns(new List <ServiceEndpoint> { new ServiceEndpoint { Url = new Uri("http://dummyurl"), Name = ServiceEndpoints.SystemVssConnection, Authorization = endpointAuthorization } }); _ec.Setup(x => x.Variables).Returns(_variables); var asyncCommands = new List <IAsyncCommandContext>(); _ec.Setup(x => x.AsyncCommands).Returns(asyncCommands); _ec.Setup(x => x.AddIssue(It.IsAny <Issue>())) .Callback <Issue> ((issue) => { if (issue.Type == IssueType.Warning) { _warnings.Add(issue.Message); } else if (issue.Type == IssueType.Error) { _errors.Add(issue.Message); } }); }
private void SetupTestEnv(TestHostContext hc, string securityId) { _powerCfgCalledForACOption = _powerCfgCalledForDCOption = false; _autoLogonSettings = null; _windowsServiceHelper = new Mock <INativeWindowsServiceHelper>(); hc.SetSingleton <INativeWindowsServiceHelper>(_windowsServiceHelper.Object); _promptManager = new Mock <IPromptManager>(); hc.SetSingleton <IPromptManager>(_promptManager.Object); _promptManager .Setup(x => x.ReadValue( Constants.Agent.CommandLine.Args.WindowsLogonAccount, // argName It.IsAny <string>(), // description It.IsAny <bool>(), // secret It.IsAny <string>(), // defaultValue Validators.NTAccountValidator, // validator It.IsAny <bool>())) // unattended .Returns(string.Format(@"{0}\{1}", _domainName, _userName)); _windowsServiceHelper.Setup(x => x.IsValidAutoLogonCredential(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())).Returns(true); _windowsServiceHelper.Setup(x => x.SetAutoLogonPassword(It.IsAny <string>())); _windowsServiceHelper.Setup(x => x.GetSecurityId(It.IsAny <string>(), It.IsAny <string>())).Returns(() => securityId); _windowsServiceHelper.Setup(x => x.IsRunningInElevatedMode()).Returns(true); _processInvoker = new Mock <IProcessInvoker>(); hc.EnqueueInstance <IProcessInvoker>(_processInvoker.Object); hc.EnqueueInstance <IProcessInvoker>(_processInvoker.Object); _processInvoker.Setup(x => x.ExecuteAsync( It.IsAny <String>(), "powercfg.exe", "/Change monitor-timeout-ac 0", null, It.IsAny <CancellationToken>())).Returns(Task.FromResult <int>(SetPowerCfgFlags(true))); _processInvoker.Setup(x => x.ExecuteAsync( It.IsAny <String>(), "powercfg.exe", "/Change monitor-timeout-dc 0", null, It.IsAny <CancellationToken>())).Returns(Task.FromResult <int>(SetPowerCfgFlags(false))); _mockRegManager = new MockRegistryManager(); hc.SetSingleton <IWindowsRegistryManager>(_mockRegManager); _command = new CommandSettings( hc, new[] { "configure", "--windowslogonaccount", "wont be honored", "--windowslogonpassword", "sssh", "--norestart", _runOnce }); _store = new Mock <IConfigurationStore>(); _store.Setup(x => x.SaveAutoLogonSettings(It.IsAny <AutoLogonSettings>())) .Callback((AutoLogonSettings settings) => { _autoLogonSettings = settings; }); _store.Setup(x => x.IsAutoLogonConfigured()).Returns(() => _autoLogonSettings != null); _store.Setup(x => x.GetAutoLogonSettings()).Returns(() => _autoLogonSettings); hc.SetSingleton <IConfigurationStore>(_store.Object); hc.SetSingleton <IAutoLogonRegistryManager>(new AutoLogonRegistryManager()); }
public async void DispatchCancellation() { //Arrange using (var hc = new TestHostContext(this)) { var worker = new Microsoft.VisualStudio.Services.Agent.Worker.Worker(); hc.EnqueueInstance<IProcessChannel>(_processChannel.Object); hc.SetSingleton<IJobRunner>(_jobRunner.Object); worker.Initialize(hc); var jobMessage = CreateJobRequestMessage("job1"); var cancelMessage = CreateJobCancelMessage(jobMessage.JobId); var arWorkerMessages = new WorkerMessage[] { new WorkerMessage { Body = JsonUtility.ToString(jobMessage), MessageType = MessageType.NewJobRequest }, new WorkerMessage { Body = JsonUtility.ToString(cancelMessage), MessageType = MessageType.CancelRequest } }; var workerMessages = new Queue<WorkerMessage>(arWorkerMessages); _processChannel.Setup(x => x.ReceiveAsync(It.IsAny<CancellationToken>())) .Returns(() => Task.FromResult(workerMessages.Dequeue())); _jobRunner.Setup(x => x.RunAsync(It.IsAny<JobRequestMessage>(), It.IsAny<CancellationToken>())) .Returns( async (JobRequestMessage jm, CancellationToken ct) => { await Task.Delay(-1, ct); return TaskResult.Canceled; }); //Act await Assert.ThrowsAsync<TaskCanceledException>( async () => await worker.RunAsync("1", "2")); //Assert _processChannel.Verify(x => x.StartClient("1", "2"), Times.Once()); _jobRunner.Verify(x => x.RunAsync( It.Is<JobRequestMessage>(y => JsonUtility.ToString(y) == arWorkerMessages[0].Body), It.IsAny<CancellationToken>())); } }
private void SetupMocks([CallerMemberName] string name = "") { _hc = new TestHostContext(this, name); _codeCoverageStatistics = new List<CodeCoverageStatistics> { new CodeCoverageStatistics { Label = "label", Covered = 10, Total = 10, Position = 1 } }; _mocksummaryReader = new Mock<ICodeCoverageSummaryReader>(); _mocksummaryReader.Setup(x => x.Name).Returns("mockCCTool"); _mocksummaryReader.Setup(x => x.GetCodeCoverageSummary(It.IsAny<IExecutionContext>(), It.IsAny<string>())) .Returns(_codeCoverageStatistics); _hc.SetSingleton(_mocksummaryReader.Object); _mockCodeCoverageEnabler = new Mock<ICodeCoverageEnabler>(); _mockCodeCoverageEnabler.Setup(x => x.Name).Returns("mockCCTool_mockBuildTool"); _mockCodeCoverageEnabler.Setup(x => x.EnableCodeCoverage(It.IsAny<IExecutionContext>(), It.IsAny<CodeCoverageEnablerInputs>())); _hc.SetSingleton(_mockCodeCoverageEnabler.Object); _mockExtensionManager = new Mock<IExtensionManager>(); _mockExtensionManager.Setup(x => x.GetExtensions<ICodeCoverageSummaryReader>()).Returns(new List<ICodeCoverageSummaryReader> { _mocksummaryReader.Object }); _mockExtensionManager.Setup(x => x.GetExtensions<ICodeCoverageEnabler>()).Returns(new List<ICodeCoverageEnabler> { _mockCodeCoverageEnabler.Object }); _hc.SetSingleton(_mockExtensionManager.Object); _mockCodeCoveragePublisher = new Mock<ICodeCoveragePublisher>(); _hc.SetSingleton(_mockCodeCoveragePublisher.Object); _mockCommandContext = new Mock<IAsyncCommandContext>(); _hc.EnqueueInstance(_mockCommandContext.Object); var endpointAuthorization = new EndpointAuthorization() { Scheme = EndpointAuthorizationSchemes.OAuth }; List<string> warnings; _variables = new Variables(_hc, new Dictionary<string, string>(), new List<MaskHint>(), out warnings); _variables.Set("build.buildId", "1"); _variables.Set("build.containerId", "1"); _variables.Set("system.teamProjectId", "46075F24-A6B9-447E-BEF0-E1D5592D9E39"); _variables.Set("system.hostType", "build"); endpointAuthorization.Parameters[EndpointAuthorizationParameters.AccessToken] = "accesstoken"; _ec = new Mock<IExecutionContext>(); _ec.Setup(x => x.Endpoints).Returns(new List<ServiceEndpoint> { new ServiceEndpoint { Url = new Uri("http://dummyurl"), Name = ServiceEndpoints.SystemVssConnection, Authorization = endpointAuthorization } }); _ec.Setup(x => x.Variables).Returns(_variables); var asyncCommands = new List<IAsyncCommandContext>(); _ec.Setup(x => x.AsyncCommands).Returns(asyncCommands); _ec.Setup(x => x.AddIssue(It.IsAny<Issue>())) .Callback<Issue> ((issue) => { if (issue.Type == IssueType.Warning) { _warnings.Add(issue.Message); } else if (issue.Type == IssueType.Error) { _errors.Add(issue.Message); } }); }
//process 2 new job messages, and one cancel message public async void TestRunAsync() { using (var hc = new TestHostContext(this)) using (var tokenSource = new CancellationTokenSource()) { //Arrange var agent = new Agent.Listener.Agent(); agent.TokenSource = tokenSource; hc.SetSingleton<IConfigurationManager>(_configurationManager.Object); hc.SetSingleton<IJobNotification>(_jobNotification.Object); hc.SetSingleton<IMessageListener>(_messageListener.Object); hc.SetSingleton<IPromptManager>(_promptManager.Object); hc.SetSingleton<IAgentServer>(_agentServer.Object); agent.Initialize(hc); var settings = new AgentSettings { PoolId = 43242 }; var taskAgentSession = new TaskAgentSession(); //we use reflection to achieve this, because "set" is internal PropertyInfo sessionIdProperty = taskAgentSession.GetType().GetProperty("SessionId", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Assert.NotNull(sessionIdProperty); sessionIdProperty.SetValue(taskAgentSession, Guid.NewGuid()); var message = new TaskAgentMessage() { Body = JsonUtility.ToString(CreateJobRequestMessage("job1")), MessageId = 4234, MessageType = JobRequestMessage.MessageType }; var messages = new Queue<TaskAgentMessage>(); messages.Enqueue(message); var signalWorkerComplete = new SemaphoreSlim(0, 1); _configurationManager.Setup(x => x.LoadSettings()) .Returns(settings); _configurationManager.Setup(x => x.IsConfigured()) .Returns(true); _configurationManager.Setup(x => x.EnsureConfiguredAsync(It.IsAny<CommandSettings>())) .Returns(Task.CompletedTask); _messageListener.Setup(x => x.CreateSessionAsync(It.IsAny<CancellationToken>())) .Returns(Task.FromResult<bool>(true)); _messageListener.Setup(x => x.Session) .Returns(taskAgentSession); _messageListener.Setup(x => x.GetNextMessageAsync(It.IsAny<CancellationToken>())) .Returns(async () => { if (0 == messages.Count) { signalWorkerComplete.Release(); await Task.Delay(2000, tokenSource.Token); } return messages.Dequeue(); }); _messageListener.Setup(x => x.DeleteSessionAsync()) .Returns(Task.CompletedTask); _jobDispatcher.Setup(x => x.Run(It.IsAny<JobRequestMessage>())) .Callback(()=> { }); _agentServer.Setup(x => x.DeleteAgentMessageAsync(settings.PoolId, message.MessageId, taskAgentSession.SessionId, It.IsAny<CancellationToken>())) .Returns((Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken) => { return Task.CompletedTask; }); _jobNotification.Setup(x => x.StartClient(It.IsAny<String>(), It.IsAny<CancellationToken>())) .Callback(() => { }); hc.EnqueueInstance<IJobDispatcher>(_jobDispatcher.Object); //Act var command = new CommandSettings(hc, new string[0]); Task agentTask = agent.ExecuteCommand(command); //Assert //wait for the agent to run one job if (!await signalWorkerComplete.WaitAsync(2000)) { Assert.True(false, $"{nameof(_messageListener.Object.GetNextMessageAsync)} was not invoked."); } else { //Act tokenSource.Cancel(); //stop Agent //Assert Task[] taskToWait2 = { agentTask, Task.Delay(2000) }; //wait for the Agent to exit await Task.WhenAny(taskToWait2); Assert.True(agentTask.IsCompleted, $"{nameof(agent.ExecuteCommand)} timed out."); Assert.True(!agentTask.IsFaulted, agentTask.Exception?.ToString()); Assert.True(agentTask.IsCanceled); _jobDispatcher.Verify(x => x.Run(It.IsAny<JobRequestMessage>()), Times.Once(), $"{nameof(_jobDispatcher.Object.Run)} was not invoked."); _messageListener.Verify(x => x.GetNextMessageAsync(It.IsAny<CancellationToken>()), Times.AtLeastOnce()); _messageListener.Verify(x => x.CreateSessionAsync(It.IsAny<CancellationToken>()), Times.Once()); _messageListener.Verify(x => x.DeleteSessionAsync(), Times.Once()); _agentServer.Verify(x => x.DeleteAgentMessageAsync(settings.PoolId, message.MessageId, taskAgentSession.SessionId, It.IsAny<CancellationToken>()), Times.AtLeastOnce()); } } }