diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/DetectorExperiments.cs b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/DetectorExperiments.cs index 8ea8c0f16..10561cd28 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/DetectorExperiments.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/DetectorExperiments.cs @@ -7,6 +7,11 @@ namespace Microsoft.ComponentDetection.Orchestrator.Experiments; /// public static class DetectorExperiments { + /// + /// Check to automatically proccess experiments. + /// + public static bool AutomaticallyProcessExperiments { get; set; } = true; + /// /// Manually enables detector experiments. /// diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/ExperimentService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/ExperimentService.cs index 7a5a3c3a9..46eef35c2 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/ExperimentService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/ExperimentService.cs @@ -116,6 +116,11 @@ public async Task FinishAsync() return; } + if (!DetectorExperiments.AutomaticallyProcessExperiments) + { + return; + } + foreach (var (config, experiment) in this.experiments) { var controlComponents = experiment.ControlGroupComponents; diff --git a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentServiceTests.cs b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentServiceTests.cs index a9d2372ac..e399579f9 100644 --- a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentServiceTests.cs +++ b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentServiceTests.cs @@ -55,7 +55,11 @@ private void SetupGraphMock(IEnumerable components) } [TestInitialize] - public void EnableDetectorExperiments() => DetectorExperiments.Enable = true; + public void TestInitialize() + { + DetectorExperiments.Enable = true; + DetectorExperiments.AutomaticallyProcessExperiments = true; + } [TestMethod] public void RecordDetectorRun_AddsComponentsToControlAndExperimentGroup() @@ -195,6 +199,48 @@ public async Task FinishAsync_SkipsEmptyExperimentsAsync() Times.Never()); } + [TestMethod] + public async Task FinishAsync_AutomaticallyProcessesExperimentsAsync() + { + var components = ExperimentTestUtils.CreateRandomComponents(); + this.SetupGraphMock(components); + + var service = new ExperimentService( + new[] { this.experimentConfigMock.Object }, + new[] { this.experimentProcessorMock.Object }, + this.graphTranslationServiceMock.Object, + this.loggerMock.Object); + service.RecordDetectorRun(this.detectorMock.Object, this.componentRecorder, this.detectionArgsMock.Object); + + await service.FinishAsync(); + + this.experimentProcessorMock.Verify( + x => x.ProcessExperimentAsync(this.experimentConfigMock.Object, It.IsAny()), + Times.Once()); + } + + [TestMethod] + public async Task FinishAsync_DoesNotAutomaticallyProcessExperimentsAsync() + { + DetectorExperiments.AutomaticallyProcessExperiments = false; + + var components = ExperimentTestUtils.CreateRandomComponents(); + this.SetupGraphMock(components); + + var service = new ExperimentService( + new[] { this.experimentConfigMock.Object }, + new[] { this.experimentProcessorMock.Object }, + this.graphTranslationServiceMock.Object, + this.loggerMock.Object); + service.RecordDetectorRun(this.detectorMock.Object, this.componentRecorder, this.detectionArgsMock.Object); + + await service.FinishAsync(); + + this.experimentProcessorMock.Verify( + x => x.ProcessExperimentAsync(this.experimentConfigMock.Object, It.IsAny()), + Times.Never()); + } + [TestMethod] public async Task FinishAsync_Respects_DetectorExperiments_EnableAsync() {