using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker; using Moq; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Xunit; using System.Threading; using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Common.Tests.Worker { public sealed class JobRunnerL0 { private IExecutionContext _jobEc; private JobRunner _jobRunner; private List _initResult = new(); private CancellationTokenSource _tokenSource; private Mock _jobServer; private Mock _runServer; private Mock _jobServerQueue; private Mock _config; private Mock _extensions; private Mock _stepRunner; private Mock _jobExtension; private Mock _logger; private Mock _temp; private Mock _diagnosticLogManager; private TestHostContext CreateTestContext([CallerMemberName] String testName = "") { var hc = new TestHostContext(this, testName); _jobEc = new Runner.Worker.ExecutionContext(); _config = new Mock(); _extensions = new Mock(); _jobExtension = new Mock(); _jobServer = new Mock(); _runServer = new Mock(); _jobServerQueue = new Mock(); _stepRunner = new Mock(); _logger = new Mock(); _temp = new Mock(); _diagnosticLogManager = new Mock(); if (_tokenSource != null) { _tokenSource.Dispose(); _tokenSource = null; } _tokenSource = new CancellationTokenSource(); _jobRunner = new JobRunner(); _jobRunner.Initialize(hc); _initResult.Clear(); _jobExtension.Setup(x => x.InitializeJob(It.IsAny(), It.IsAny())). Returns(Task.FromResult(_initResult)); var settings = new RunnerSettings { AgentId = 1, AgentName = "agent1", ServerUrl = "https://pipelines.actions.githubusercontent.com", WorkFolder = "_work", }; _config.Setup(x => x.GetSettings()) .Returns(settings); _logger.Setup(x => x.Setup(It.IsAny(), It.IsAny())); hc.SetSingleton(_config.Object); hc.SetSingleton(_jobServer.Object); hc.SetSingleton(_runServer.Object); hc.SetSingleton(_jobServerQueue.Object); hc.SetSingleton(_stepRunner.Object); hc.SetSingleton(_extensions.Object); hc.SetSingleton(_temp.Object); hc.SetSingleton(_diagnosticLogManager.Object); hc.EnqueueInstance(_jobEc); hc.EnqueueInstance(_logger.Object); hc.EnqueueInstance(_jobExtension.Object); return hc; } private Pipelines.AgentJobRequestMessage GetMessage(String messageType = JobRequestMessageTypes.PipelineAgentJobRequest, [CallerMemberName] String testName = "") { TaskOrchestrationPlanReference plan = new(); TimelineReference timeline = new Timeline(Guid.NewGuid()); Guid jobId = Guid.NewGuid(); var message = new Pipelines.AgentJobRequestMessage( plan, timeline, jobId, testName, testName, null, null, null, new Dictionary(), new List(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List(), null, null, null, new ActionsEnvironmentReference("staging"), messageType: messageType); message.Variables[Constants.Variables.System.Culture] = "en-US"; message.Resources.Endpoints.Add(new ServiceEndpoint() { Name = WellKnownServiceEndpointNames.SystemVssConnection, Url = new Uri("https://pipelines.actions.githubusercontent.com"), Authorization = new EndpointAuthorization() { Scheme = "Test", Parameters = { {"AccessToken", "token"} } }, }); message.Resources.Repositories.Add(new Pipelines.RepositoryResource() { Alias = Pipelines.PipelineConstants.SelfAlias, Id = "github", Version = "sha1" }); message.ContextData.Add("github", new Pipelines.ContextData.DictionaryContextData()); return message; } [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] public async Task JobExtensionInitializeFailure() { using (TestHostContext hc = CreateTestContext()) { _jobExtension.Setup(x => x.InitializeJob(It.IsAny(), It.IsAny())) .Throws(new Exception()); await _jobRunner.RunAsync(GetMessage(), _tokenSource.Token); Assert.Equal(TaskResult.Failed, _jobEc.Result); _stepRunner.Verify(x => x.RunAsync(It.IsAny()), Times.Never); } } [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] public async Task JobExtensionInitializeCancelled() { using (TestHostContext hc = CreateTestContext()) { _jobExtension.Setup(x => x.InitializeJob(It.IsAny(), It.IsAny())) .Throws(new OperationCanceledException()); _tokenSource.Cancel(); await _jobRunner.RunAsync(GetMessage(), _tokenSource.Token); Assert.Equal(TaskResult.Canceled, _jobEc.Result); _stepRunner.Verify(x => x.RunAsync(It.IsAny()), Times.Never); } } [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] public async Task WorksWithRunnerJobRequestMessageType() { using (TestHostContext hc = CreateTestContext()) { var message = GetMessage(JobRequestMessageTypes.RunnerJobRequest); await _jobRunner.RunAsync(message, _tokenSource.Token); Assert.Equal(TaskResult.Succeeded, _jobEc.Result); } } } }