Example #1
0
        public async Task ModuleRestoreContentionShouldProduceConsistentState()
        {
            var dataSet = DataSets.Registry_LF;

            var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext);
            var clientFactory   = dataSet.CreateMockRegistryClients(TestContext);
            var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext);
            await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext);

            var cacheDirectory = FileHelper.GetCacheRootPath(TestContext);

            Directory.CreateDirectory(cacheDirectory);

            var features = StrictMock.Of <IFeatureProvider>();

            features.Setup(m => m.RegistryEnabled).Returns(true);
            features.Setup(m => m.CacheRootDirectory).Returns(cacheDirectory);

            var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(new FileResolver(), clientFactory, templateSpecRepositoryFactory, features.Object));

            var configuration    = BicepTestConstants.BuiltInConfigurationWithAnalyzersDisabled;
            var moduleReferences = dataSet.RegistryModules.Values
                                   .OrderBy(m => m.Metadata.Target)
                                   .Select(m => dispatcher.TryGetModuleReference(m.Metadata.Target, configuration, out _) ?? throw new AssertFailedException($"Invalid module target '{m.Metadata.Target}'."))
                                   .ToImmutableList();

            moduleReferences.Should().HaveCount(7);

            // initially the cache should be empty
            foreach (var moduleReference in moduleReferences)
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Unknown);
            }

            const int ConcurrentTasks = 50;
            var       tasks           = new List <Task <bool> >();

            for (int i = 0; i < ConcurrentTasks; i++)
            {
                tasks.Add(Task.Run(() => dispatcher.RestoreModules(BicepTestConstants.BuiltInConfiguration, moduleReferences)));
            }

            var result = await Task.WhenAll(tasks);

            result.Should().HaveCount(ConcurrentTasks);

            // modules should now be in the cache
            foreach (var moduleReference in moduleReferences)
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Succeeded);
            }
        }
Example #2
0
        public async Task ForceModuleRestoreShouldRestoreAllModules(IEnumerable <ExternalModuleInfo> moduleInfos, int moduleCount)
        {
            var dataSet = DataSets.Registry_LF;

            var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext);
            var clientFactory   = dataSet.CreateMockRegistryClients(TestContext);
            var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext);
            await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext);

            var cacheDirectory = FileHelper.GetCacheRootPath(TestContext);

            Directory.CreateDirectory(cacheDirectory);

            var features = StrictMock.Of <IFeatureProvider>();

            features.Setup(m => m.RegistryEnabled).Returns(true);
            features.Setup(m => m.CacheRootDirectory).Returns(cacheDirectory);

            FileResolver fileResolver = new FileResolver();
            var          dispatcher   = new ModuleDispatcher(new DefaultModuleRegistryProvider(fileResolver, clientFactory, templateSpecRepositoryFactory, features.Object));

            var configuration    = BicepTestConstants.BuiltInConfigurationWithAnalyzersDisabled;
            var moduleReferences = moduleInfos
                                   .OrderBy(m => m.Metadata.Target)
                                   .Select(m => dispatcher.TryGetModuleReference(m.Metadata.Target, configuration, out _) ?? throw new AssertFailedException($"Invalid module target '{m.Metadata.Target}'."))
                                   .ToImmutableList();

            moduleReferences.Should().HaveCount(moduleCount);

            // initially the cache should be empty
            foreach (var moduleReference in moduleReferences)
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Unknown);
            }

            var moduleFileUri = dispatcher.TryGetLocalModuleEntryPointUri(new Uri("file://main.bicep"), moduleReferences[0], configuration, out _) !;

            moduleFileUri.Should().NotBeNull();

            var moduleFilePath  = moduleFileUri.LocalPath;
            var moduleDirectory = Path.GetDirectoryName(moduleFilePath) !;

            Directory.CreateDirectory(moduleDirectory);

            (await dispatcher.RestoreModules(BicepTestConstants.BuiltInConfiguration, moduleReferences, forceModulesRestore: true)).Should().BeTrue();

            // all other modules should have succeeded
            foreach (var moduleReference in moduleReferences)
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Succeeded);
            }
        }
Example #3
0
        public async Task ModuleRestoreWithStuckFileLockShouldFailAfterTimeout(IEnumerable <ExternalModuleInfo> moduleInfos, int moduleCount)
        {
            var dataSet = DataSets.Registry_LF;

            var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext);
            var clientFactory   = dataSet.CreateMockRegistryClients(TestContext);
            var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext);
            await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext);

            var cacheDirectory = FileHelper.GetCacheRootPath(TestContext);

            Directory.CreateDirectory(cacheDirectory);

            var features = StrictMock.Of <IFeatureProvider>();

            features.Setup(m => m.RegistryEnabled).Returns(true);
            features.Setup(m => m.CacheRootDirectory).Returns(cacheDirectory);

            FileResolver fileResolver = new FileResolver();
            var          dispatcher   = new ModuleDispatcher(new DefaultModuleRegistryProvider(fileResolver, clientFactory, templateSpecRepositoryFactory, features.Object));

            var configuration    = BicepTestConstants.BuiltInConfigurationWithAnalyzersDisabled;
            var moduleReferences = moduleInfos
                                   .OrderBy(m => m.Metadata.Target)
                                   .Select(m => dispatcher.TryGetModuleReference(m.Metadata.Target, configuration, out _) ?? throw new AssertFailedException($"Invalid module target '{m.Metadata.Target}'."))
                                   .ToImmutableList();

            moduleReferences.Should().HaveCount(moduleCount);

            // initially the cache should be empty
            foreach (var moduleReference in moduleReferences)
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Unknown);
            }

            var moduleFileUri = dispatcher.TryGetLocalModuleEntryPointUri(new Uri("file://main.bicep"), moduleReferences[0], configuration, out _) !;

            moduleFileUri.Should().NotBeNull();

            var moduleFilePath  = moduleFileUri.LocalPath;
            var moduleDirectory = Path.GetDirectoryName(moduleFilePath) !;

            Directory.CreateDirectory(moduleDirectory);

            var lockFileName = Path.Combine(moduleDirectory, "lock");
            var lockFileUri  = new Uri(lockFileName);

            var @lock = fileResolver.TryAcquireFileLock(lockFileUri);

            @lock.Should().NotBeNull();

            // let's try to restore a module while holding a lock
            using (@lock)
            {
                (await dispatcher.RestoreModules(BicepTestConstants.BuiltInConfiguration, moduleReferences)).Should().BeTrue();
            }

            // the first module should have failed due to a timeout
            dispatcher.GetModuleRestoreStatus(moduleReferences[0], configuration, out var failureBuilder).Should().Be(ModuleRestoreStatus.Failed);
            using (new AssertionScope())
            {
                failureBuilder !.Should().HaveCode("BCP192");
                failureBuilder !.Should().HaveMessageStartWith($"Unable to restore the module with reference \"{moduleReferences[0].FullyQualifiedReference}\": Exceeded the timeout of \"00:00:05\" to acquire the lock on file \"");
            }

            // all other modules should have succeeded
            foreach (var moduleReference in moduleReferences.Skip(1))
            {
                dispatcher.GetModuleRestoreStatus(moduleReference, configuration, out _).Should().Be(ModuleRestoreStatus.Succeeded);
            }
        }