private async Task TestLoadSmartDetectorSimple(Type smartDetectorType, string expectedTitle = "test test test")
        {
            SmartDetectorManifest manifest = new SmartDetectorManifest("3", "simple", "description", Version.Parse("1.0"), smartDetectorType.Assembly.GetName().Name, smartDetectorType.FullName, new List <ResourceType>()
            {
                ResourceType.Subscription
            }, new List <int> {
                60
            });
            SmartDetectorPackage package = new SmartDetectorPackage(manifest, this.assemblies["3"]);

            await this.TestLoadSmartDetectorSimple(package, expectedTitle);
        }
        private async Task TestLoadSmartDetectorSimple(Type smartDetectorType, string expectedTitle = "test test test")
        {
            SmartDetectorManifest manifest = new SmartDetectorManifest("3", "simple", "description", Version.Parse("1.0"), smartDetectorType.Assembly.GetName().Name, smartDetectorType.FullName, new List <ResourceType>()
            {
                ResourceType.Subscription
            }, new List <int> {
                60
            }, null, null);
            Dictionary <string, byte[]> packageContent = this.assemblies["3"];

            packageContent["manifest.json"] = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(manifest));
            SmartDetectorPackage package = new SmartDetectorPackage(packageContent);

            await this.TestLoadSmartDetectorSimple(package, expectedTitle);
        }
        public async Task WhenLoadingSmartDetectorFromPackageThenItWorks()
        {
            // Create the detector package from the detector's folder (instead of from the current folder),
            // and check that it can be loaded correctly, with its dependencies.
            DirectoryInfo currentFolder = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            string        flavor        = Path.Combine(currentFolder.Parent.Name, currentFolder.Name);

            while (currentFolder.Name.ToUpperInvariant() != "TEST")
            {
                currentFolder = currentFolder.Parent;
            }

            string packageFolder         = Path.Combine(currentFolder.FullName, @"testSmartDetector\TestSmartDetectorLibrary\bin", flavor);
            SmartDetectorPackage package = SmartDetectorPackage.CreateFromFolder(packageFolder);

            await this.TestLoadSmartDetectorSimple(package, "test title - with dependency - [1,2,3]");
        }
        /// <summary>
        /// Reads a Smart Detector's package from the repository
        /// </summary>
        /// <param name="smartDetectorId">The Smart Detector's ID</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>A <see cref="Task{TResult}"/> returning the Smart Detector package</returns>
        public async Task <SmartDetectorPackage> ReadSmartDetectorPackageAsync(string smartDetectorId, CancellationToken cancellationToken)
        {
            this.tracer.TraceInformation($"Getting Smart Detector {smartDetectorId} package");
            try
            {
                CloudBlob latestVersionSmartDetectorBlob = await this.GetLatestSmartDetectorBlobVersionAsync(smartDetectorId, cancellationToken);

                this.tracer.TraceInformation($"Last version Smart Detector BLOB is {latestVersionSmartDetectorBlob.Name}");

                using (var blobMemoryStream = new MemoryStream())
                {
                    // Download the blob to a stream and generate the Smart Detector package from it
                    await latestVersionSmartDetectorBlob.DownloadToStreamAsync(blobMemoryStream, cancellationToken);

                    return(SmartDetectorPackage.CreateFromStream(blobMemoryStream, this.tracer));
                }
            }
            catch (StorageException e)
            {
                throw new SmartDetectorRepositoryException("Failed to get Smart Detector package from storage", e);
            }
        }
        private async Task TestLoadSmartDetectorSimple(SmartDetectorPackage package, string expectedTitle)
        {
            ISmartDetectorLoader loader   = new SmartDetectorLoader(this.tempFolder, this.tracerMock.Object);
            ISmartDetector       detector = loader.LoadSmartDetector(package);

            Assert.IsNotNull(detector, "Smart Detector is NULL");

            var resource        = new ResourceIdentifier(ResourceType.VirtualMachine, "someSubscription", "someGroup", "someVM");
            var analysisRequest = new AnalysisRequest(
                new List <ResourceIdentifier> {
                resource
            },
                TimeSpan.FromDays(1),
                null,
                new Mock <IAnalysisServicesFactory>().Object,
                new Mock <IStateRepository>().Object);
            List <Alert> alerts = await detector.AnalyzeResourcesAsync(analysisRequest, this.tracerMock.Object, default(CancellationToken));

            Assert.AreEqual(1, alerts.Count, "Incorrect number of alerts returned");
            Assert.AreEqual(expectedTitle, alerts.Single().Title, "Alert title is wrong");
            Assert.AreEqual(resource, alerts.Single().ResourceIdentifier, "Alert resource identifier is wrong");
        }
        /// <summary>
        /// Loads the Smart Detector, runs it, and returns the generated alert presentations
        /// </summary>
        /// <param name="request">The Smart Detector request</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>A <see cref="Task{TResult}"/>, returning the list of Alerts presentations generated by the Smart Detector</returns>
        public async Task <List <ContractsAlert> > RunAsync(SmartDetectorExecutionRequest request, CancellationToken cancellationToken)
        {
            // Read the Smart Detector's package
            this.tracer.TraceInformation($"Loading Smart Detector package for Smart Detector ID {request.SmartDetectorId}");
            SmartDetectorPackage smartDetectorPackage = await this.smartDetectorRepository.ReadSmartDetectorPackageAsync(request.SmartDetectorId, cancellationToken);

            SmartDetectorManifest smartDetectorManifest = smartDetectorPackage.Manifest;

            this.tracer.TraceInformation($"Read Smart Detector package, ID {smartDetectorManifest.Id}, Version {smartDetectorManifest.Version}");

            // Load the Smart Detector
            ISmartDetector smartDetector = this.smartDetectorLoader.LoadSmartDetector(smartDetectorPackage);

            this.tracer.TraceInformation($"Smart Detector instance loaded successfully, ID {smartDetectorManifest.Id}");

            // Get the resources on which to run the Smart Detector
            List <ResourceIdentifier> resources = await this.GetResourcesForSmartDetector(request.ResourceIds, smartDetectorManifest, cancellationToken);

            // Create state repository
            IStateRepository stateRepository = this.stateRepositoryFactory.Create(request.SmartDetectorId);

            // Run the Smart Detector
            this.tracer.TraceInformation($"Started running Smart Detector ID {smartDetectorManifest.Id}, Name {smartDetectorManifest.Name}");
            List <Alert> alerts;

            try
            {
                var analysisRequest = new AnalysisRequest(resources, request.DataEndTime, request.Cadence, request.AlertRuleResourceId, this.analysisServicesFactory, stateRepository);
                alerts = await smartDetector.AnalyzeResourcesAsync(analysisRequest, this.tracer, cancellationToken);

                this.tracer.TraceInformation($"Completed running Smart Detector ID {smartDetectorManifest.Id}, Name {smartDetectorManifest.Name}, returning {alerts.Count} alerts");
            }
            catch (Exception e)
            {
                this.tracer.TraceInformation($"Failed running Smart Detector ID {smartDetectorManifest.Id}, Name {smartDetectorManifest.Name}: {e.Message}");
                throw new SmartDetectorCustomException(e.GetType().ToString(), e.Message, e.StackTrace);
            }

            // Verify that each alert belongs to one of the types declared in the Smart Detector manifest
            foreach (Alert alert in alerts)
            {
                if (!smartDetectorManifest.SupportedResourceTypes.Contains(alert.ResourceIdentifier.ResourceType))
                {
                    throw new UnidentifiedAlertResourceTypeException(alert.ResourceIdentifier);
                }
            }

            // Trace the number of alerts of each type
            foreach (var alertType in alerts.GroupBy(x => x.GetType().Name))
            {
                this.tracer.TraceInformation($"Got {alertType.Count()} Alerts of type '{alertType.Key}'");
                this.tracer.ReportMetric("AlertType", alertType.Count(), new Dictionary <string, string>()
                {
                    { "AlertType", alertType.Key }
                });
            }

            // Create results
            List <ContractsAlert> results = new List <ContractsAlert>();

            foreach (var alert in alerts)
            {
                QueryRunInfo queryRunInfo = await this.queryRunInfoProvider.GetQueryRunInfoAsync(new List <ResourceIdentifier>() { alert.ResourceIdentifier }, cancellationToken);

                results.Add(alert.CreateContractsAlert(request, smartDetectorManifest.Name, queryRunInfo));
            }

            this.tracer.TraceInformation($"Returning {results.Count} results");
            return(results);
        }
        private void TestInitialize(ResourceType requestResourceType, ResourceType smartDetectorResourceType)
        {
            this.testContainer = new UnityContainer();

            this.testContainer.RegisterType <ISmartDetectorRunner, SmartDetectorRunner>();

            this.testContainer.RegisterInstance(new Mock <IExtendedTracer>().Object);

            ResourceIdentifier resourceId;

            switch (requestResourceType)
            {
            case ResourceType.Subscription:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", string.Empty, string.Empty);
                break;

            case ResourceType.ResourceGroup:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", string.Empty);
                break;

            default:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", "resourceName");
                break;
            }

            this.resourceIds = new List <string>()
            {
                resourceId.ToResourceId()
            };
            this.request = new SmartDetectorExecutionRequest
            {
                ResourceIds     = this.resourceIds,
                Cadence         = TimeSpan.FromDays(1),
                SmartDetectorId = "1"
            };

            var smartDetectorManifest = new SmartDetectorManifest("1", "Test Smart Detector", "Test Smart Detector description", Version.Parse("1.0"), "assembly", "class", new List <ResourceType>()
            {
                smartDetectorResourceType
            }, new List <int> {
                60
            }, null);

            this.smartDetectorPackage = new SmartDetectorPackage(smartDetectorManifest, new Dictionary <string, byte[]> {
                ["TestSmartDetectorLibrary"] = Array.Empty <byte>()
            });

            var smartDetectorRepositoryMock = new Mock <ISmartDetectorRepository>();

            smartDetectorRepositoryMock
            .Setup(x => x.ReadSmartDetectorPackageAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => this.smartDetectorPackage);
            this.testContainer.RegisterInstance <ISmartDetectorRepository>(smartDetectorRepositoryMock.Object);

            this.testContainer.RegisterInstance <IInternalAnalysisServicesFactory>(new Mock <IInternalAnalysisServicesFactory>().Object);

            this.smartDetector = new TestSmartDetector {
                ExpectedResourceType = smartDetectorResourceType
            };

            var smartDetectorLoaderMock = new Mock <ISmartDetectorLoader>();

            smartDetectorLoaderMock
            .Setup(x => x.LoadSmartDetector(this.smartDetectorPackage))
            .Returns(this.smartDetector);
            this.testContainer.RegisterInstance <ISmartDetectorLoader>(smartDetectorLoaderMock.Object);

            var azureResourceManagerClientMock = new Mock <IExtendedAzureResourceManagerClient>();

            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourceGroupsInSubscriptionAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.ResourceGroup, subscriptionId, "resourceGroupName", string.Empty)
            });
            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInSubscriptionAsync(It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, "resourceGroupName", "resourceName")
            });
            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInResourceGroupAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, string resourceGroupName, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, resourceGroupName, "resourceName")
            });
            this.testContainer.RegisterInstance <IExtendedAzureResourceManagerClient>(azureResourceManagerClientMock.Object);

            this.testContainer.RegisterInstance <IQueryRunInfoProvider>(new Mock <IQueryRunInfoProvider>().Object);

            var stateRepositoryMock        = new Mock <IStateRepository>();
            var stateRepositoryFactoryMock = new Mock <IStateRepositoryFactory>();

            stateRepositoryFactoryMock.Setup(m => m.Create(It.IsAny <string>(), It.IsAny <string>())).Returns(stateRepositoryMock.Object);
            this.testContainer.RegisterInstance <IStateRepositoryFactory>(stateRepositoryFactoryMock.Object);
        }
        /// <summary>
        /// Loads a Smart Detector.
        /// This method load the Smart Detector's assembly into the current application domain,
        /// and creates the Smart Detector object using reflection.
        /// </summary>
        /// <param name="smartDetectorPackage">The Smart Detector package.</param>
        /// <returns>The Smart Detector object.</returns>
        /// <exception cref="SmartDetectorLoadException">
        /// Thrown if an error occurred during the Smart Detector load (either due to assembly load
        /// error or failure to create the Smart Detector object).
        /// </exception>
        public ISmartDetector LoadSmartDetector(SmartDetectorPackage smartDetectorPackage)
        {
            SmartDetectorManifest smartDetectorManifest = smartDetectorPackage.Manifest;

            try
            {
                this.tracer.TraceInformation($"Read {smartDetectorPackage.Content.Count} assemblies for Smart Detector ID {smartDetectorManifest.Id}");

                // Write all DLLs to the temp folder
                foreach (var assemblyNameAndBytes in smartDetectorPackage.Content)
                {
                    string fileName = Path.Combine(this.tempFolder, assemblyNameAndBytes.Key);
                    Directory.CreateDirectory(Directory.GetParent(fileName).FullName);
                    File.WriteAllBytes(fileName, assemblyNameAndBytes.Value);
                }

                // Add assembly resolver, that uses the Smart Detector's assemblies
                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
                {
                    this.tracer.TraceInformation($"Resolving assembly {args.Name} for Smart Detector ID {smartDetectorManifest.Id}");
                    return(this.LoadAssembly(args.Name));
                };

                // Load the main Smart Detector assembly
                Assembly mainSmartDetectorAssembly = this.LoadAssembly(smartDetectorManifest.AssemblyName);
                if (mainSmartDetectorAssembly == null)
                {
                    throw new SmartDetectorLoadException($"Unable to find main Smart Detector assembly: {smartDetectorManifest.AssemblyName}");
                }

                // Get the Smart Detector type from the assembly
                this.tracer.TraceInformation($"Creating Smart Detector for {smartDetectorManifest.Name}, version {smartDetectorManifest.Version}, using type {smartDetectorManifest.ClassName}");
                Type smartDetectorType = mainSmartDetectorAssembly.GetType(smartDetectorManifest.ClassName);
                if (smartDetectorType == null)
                {
                    throw new SmartDetectorLoadException($"Smart Detector type {smartDetectorManifest.ClassName} was not found in the main Smart Detector assembly {smartDetectorManifest.AssemblyName}");
                }

                // Check if the type inherits from ISmartDetector
                if (!typeof(ISmartDetector).IsAssignableFrom(smartDetectorType))
                {
                    throw new SmartDetectorLoadException($"Smart Detector type {smartDetectorType.Name} does not extend ISmartDetector");
                }

                // Check that type is not abstract
                if (smartDetectorType.IsAbstract)
                {
                    throw new SmartDetectorLoadException($"Smart Detector type {smartDetectorType.Name} is abstract - a Smart Detector must be a concrete type");
                }

                // Check that type is not generic
                if (smartDetectorType.IsGenericTypeDefinition)
                {
                    throw new SmartDetectorLoadException($"Smart Detector type {smartDetectorType.Name} is generic - a Smart Detector must be a closed constructed type");
                }

                // Check that type has a parameter-less constructor
                if (smartDetectorType.GetConstructor(Type.EmptyTypes) == null)
                {
                    throw new SmartDetectorLoadException($"Smart Detector type {smartDetectorType.Name} does not have a public, parameter-less constructor");
                }

                // Create the Smart Detector object
                ISmartDetector smartDetector = Activator.CreateInstance(smartDetectorType) as ISmartDetector;
                if (smartDetector == null)
                {
                    throw new SmartDetectorLoadException($"Smart Detector {smartDetectorType.Name} failed to be created - instance is null");
                }

                this.tracer.TraceInformation($"Successfully created Smart Detector of type {smartDetectorType.Name}");
                return(smartDetector);
            }
            catch (Exception e)
            {
                this.tracer.TrackEvent(
                    "FailedToLoadSmartDetector",
                    properties: new Dictionary <string, string>
                {
                    { "smartDetectorId", smartDetectorManifest.Id },
                    { "SmartDetectorName", smartDetectorManifest.Name },
                    { "ExceptionType", e.GetType().Name },
                    { "ExceptionMessage", e.Message },
                });

                throw new SmartDetectorLoadException($"Failed to load Smart Detector {smartDetectorManifest.Name}", e);
            }
        }
        /// <summary>
        /// Raises the <see cref="Application.Startup" /> event.
        /// </summary>
        /// <param name="e">A <see cref="StartupEventArgs" /> that contains the event data.</param>
        protected override void OnStartup(StartupEventArgs e)
        {
            // Cleanup previous temp folders (that are at least 2 days old), and create a new temp folder
            FileSystemExtensions.CleanupTempFolders(TempSubFolderName, 48);
            tempFolder = FileSystemExtensions.CreateTempFolder(TempSubFolderName);

            NotificationService notificationService = new NotificationService();
            ITracer             consoleTracer       = new ConsoleTracer(string.Empty);
            var smartDetectorLoader = new SmartDetectorLoader(tempFolder, consoleTracer);

            // *Temporary*: if package file path wasn't accepted, raise file selection window to allow package file selection.
            // This option should be removed before launching version for customers (bug for tracking: 1177247)
            string smartDetectorPackagePath = e.Args.Length != 1 ?
                                              GetSmartDetectorPackagePath() :
                                              Diagnostics.EnsureStringNotNullOrWhiteSpace(() => e.Args[0]);

            SmartDetectorPackage smartDetectorPackage;

            using (var fileStream = new FileStream(smartDetectorPackagePath, FileMode.Open))
            {
                smartDetectorPackage = SmartDetectorPackage.CreateFromStream(fileStream);
            }

            try
            {
                SmartDetectorManifest smartDetectorManifest = smartDetectorPackage.Manifest;
                ISmartDetector        detector = smartDetectorLoader.LoadSmartDetector(smartDetectorPackage);

                // Authenticate the user to Active Directory
                IAuthenticationServices authenticationServices = new AuthenticationServices();
                authenticationServices.AuthenticateUserAsync().Wait();
                ICredentialsFactory credentialsFactory = new ActiveDirectoryCredentialsFactory(authenticationServices);
                IHttpClientWrapper  httpClientWrapper  = new HttpClientWrapper();
                IExtendedAzureResourceManagerClient azureResourceManagerClient = new ExtendedAzureResourceManagerClient(httpClientWrapper, credentialsFactory, consoleTracer);

                // Create analysis service factory
                IInternalAnalysisServicesFactory analysisServicesFactory = new AnalysisServicesFactory(consoleTracer, httpClientWrapper, credentialsFactory, azureResourceManagerClient);

                // Create state repository factory
                IStateRepositoryFactory stateRepositoryFactory = new EmulationStateRepositoryFactory();

                // Load user settings
                var userSettings = UserSettings.LoadUserSettings();

                // Create the detector runner
                IPageableLogArchive           logArchive          = new PageableLogArchive(smartDetectorManifest.Name);
                IEmulationSmartDetectorRunner smartDetectorRunner = new SmartDetectorRunner(
                    detector,
                    analysisServicesFactory,
                    smartDetectorManifest,
                    stateRepositoryFactory,
                    azureResourceManagerClient,
                    logArchive);

                // Create a Unity container with all the required models and view models registrations
                Container = new UnityContainer();
                Container
                .RegisterInstance(notificationService)
                .RegisterInstance <ITracer>(consoleTracer)
                .RegisterInstance(new AlertsRepository())
                .RegisterInstance(authenticationServices)
                .RegisterInstance(azureResourceManagerClient)
                .RegisterInstance(detector)
                .RegisterInstance(smartDetectorManifest)
                .RegisterInstance(analysisServicesFactory)
                .RegisterInstance(logArchive)
                .RegisterInstance(smartDetectorRunner)
                .RegisterInstance(stateRepositoryFactory)
                .RegisterInstance(userSettings);
            }
            catch (Exception exception)
            {
                var message = $"{exception.Message}. {Environment.NewLine}{exception.InnerException?.Message}";
                MessageBox.Show(message);
                System.Diagnostics.Trace.WriteLine(message);
                Environment.Exit(1);
            }
        }
Example #10
0
 public void WhenCreatingPackageWithEmptyContentThenExceptionIsThrown()
 {
     var package = new SmartDetectorPackage(new ReadOnlyDictionary <string, byte[]>(new Dictionary <string, byte[]>()));
 }
Example #11
0
 public void WhenCreatingPackageWithNullContentThenExceptionIsThrown()
 {
     var package = new SmartDetectorPackage(null);
 }
Example #12
0
 public void WhenCreatingPackageWithValidValuesThenPackageIsCreated()
 {
     var package = new SmartDetectorPackage(GetDefaultPackageContent());
 }
        private void TestInitialize(ResourceType requestResourceType, ResourceType smartDetectorResourceType)
        {
            this.testContainer = new UnityContainer();

            this.testContainer.RegisterType <ISmartDetectorRunner, SmartDetectorRunner>();

            this.testContainer.RegisterInstance(new Mock <ITracer>().Object);

            ResourceIdentifier resourceId;

            switch (requestResourceType)
            {
            case ResourceType.Subscription:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", string.Empty, string.Empty);
                break;

            case ResourceType.ResourceGroup:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", string.Empty);
                break;

            default:
                resourceId = new ResourceIdentifier(requestResourceType, "subscriptionId", "resourceGroup", "resourceName");
                break;
            }

            this.resourceIds = new List <string> {
                resourceId.ToResourceId()
            };
            this.analysisRequest = new SmartDetectorAnalysisRequest
            {
                ResourceIds         = this.resourceIds,
                Cadence             = TimeSpan.FromDays(1),
                AlertRuleResourceId = "alertRule",
                SmartDetectorId     = "1",
                DetectorParameters  = new Dictionary <string, object>
                {
                    { "param1", "value1" },
                    { "param2", 2 },
                }
            };
            this.alertResolutionCheckRequest = new ContractsAlertResolutionCheckRequest
            {
                OriginalAnalysisRequest = new SmartDetectorAnalysisRequest
                {
                    ResourceIds         = this.resourceIds,
                    Cadence             = TimeSpan.FromDays(1),
                    AlertRuleResourceId = "alertRule",
                    SmartDetectorId     = "2",
                    DetectorParameters  = new Dictionary <string, object>
                    {
                        { "param1", "value1" },
                        { "param2", 2 },
                    }
                },
                AlertCorrelationHash = "correlationHash",
                TargetResource       = resourceId.ToResourceId(),
                AlertFireTime        = new DateTime(1985, 7, 3)
            };

            var smartDetectorManifest = new SmartDetectorManifest(
                "1",
                "Test Smart Detector",
                "Test Smart Detector description",
                Version.Parse("1.0"),
                "TestSmartDetectorLibrary",
                "class",
                new List <ResourceType>()
            {
                smartDetectorResourceType
            },
                new List <int> {
                60
            },
                null,
                null);

            this.smartDetectorPackage = new SmartDetectorPackage(new Dictionary <string, byte[]>
            {
                ["manifest.json"]            = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(smartDetectorManifest)),
                ["TestSmartDetectorLibrary"] = Array.Empty <byte>(),
            });

            var autoResolveSmartDetectorManifest = new SmartDetectorManifest(
                "2",
                "Test Auto Resolve Smart Detector",
                "Test Auto Resolve Smart Detector description",
                Version.Parse("1.0"),
                "TestSmartDetectorLibrary",
                "class",
                new List <ResourceType>()
            {
                smartDetectorResourceType
            },
                new List <int> {
                60
            },
                null,
                null);

            this.autoResolveSmartDetectorPackage = new SmartDetectorPackage(new Dictionary <string, byte[]>
            {
                ["manifest.json"]            = Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(autoResolveSmartDetectorManifest)),
                ["TestSmartDetectorLibrary"] = Array.Empty <byte>(),
            });

            var smartDetectorRepositoryMock = new Mock <ISmartDetectorRepository>();

            smartDetectorRepositoryMock
            .Setup(x => x.ReadSmartDetectorPackageAsync("1", It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => this.smartDetectorPackage);
            smartDetectorRepositoryMock
            .Setup(x => x.ReadSmartDetectorPackageAsync("2", It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => this.autoResolveSmartDetectorPackage);
            this.testContainer.RegisterInstance(smartDetectorRepositoryMock.Object);

            this.testContainer.RegisterInstance(new Mock <IInternalAnalysisServicesFactory>().Object);

            this.smartDetector = new TestSmartDetector {
                ExpectedResourceType = smartDetectorResourceType
            };
            this.autoResolveSmartDetector = new TestAutoResolveSmartDetector {
                ExpectedResourceType = smartDetectorResourceType
            };

            var smartDetectorLoaderMock = new Mock <ISmartDetectorLoader>();

            smartDetectorLoaderMock
            .Setup(x => x.LoadSmartDetector(this.smartDetectorPackage))
            .Returns(() => this.smartDetector);
            smartDetectorLoaderMock
            .Setup(x => x.LoadSmartDetector(this.autoResolveSmartDetectorPackage))
            .Returns(() => this.autoResolveSmartDetector);
            this.testContainer.RegisterInstance(smartDetectorLoaderMock.Object);

            var azureResourceManagerClientMock = new Mock <IExtendedAzureResourceManagerClient>();

            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourceGroupsInSubscriptionAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.ResourceGroup, subscriptionId, "resourceGroupName", string.Empty)
            });
            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInSubscriptionAsync(It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, "resourceGroupName", "resourceName")
            });
            azureResourceManagerClientMock
            .Setup(x => x.GetAllResourcesInResourceGroupAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <IEnumerable <ResourceType> >(), It.IsAny <CancellationToken>()))
            .ReturnsAsync((string subscriptionId, string resourceGroupName, IEnumerable <ResourceType> resourceTypes, CancellationToken cancellationToken) => new List <ResourceIdentifier>()
            {
                new ResourceIdentifier(ResourceType.VirtualMachine, subscriptionId, resourceGroupName, "resourceName")
            });
            this.testContainer.RegisterInstance(azureResourceManagerClientMock.Object);

            this.stateRepository     = new Dictionary <string, object>();
            this.stateRepositoryMock = new Mock <IStateRepository>();
            this.stateRepositoryMock
            .Setup(m => m.StoreStateAsync(It.IsAny <string>(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .Callback <string, object, CancellationToken>((key, value, token) => this.stateRepository[key] = value)
            .Returns(Task.CompletedTask);
            this.stateRepositoryMock
            .Setup(m => m.GetStateAsync <ResolutionState>(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Returns <string, CancellationToken>((key, token) => Task.FromResult((ResolutionState)(this.stateRepository.ContainsKey(key) ? this.stateRepository[key] : null)));
            this.stateRepositoryMock
            .Setup(m => m.DeleteStateAsync(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .Callback <string, CancellationToken>((key, token) => this.stateRepository.Remove(key))
            .Returns(Task.CompletedTask);
            this.stateRepositoryFactoryMock = new Mock <IStateRepositoryFactory>();
            this.stateRepositoryFactoryMock.Setup(m => m.Create(It.IsAny <string>(), It.IsAny <string>())).Returns(this.stateRepositoryMock.Object);
            this.testContainer.RegisterInstance(this.stateRepositoryFactoryMock.Object);
        }