public async Task Publish_AggregateExceptionWithInnerRequestFailedExceptions_ShouldFail() { var dataSet = DataSets.Empty; var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled); var client = StrictMock.Of <ContainerRegistryBlobClient>(); client .Setup(m => m.UploadBlobAsync(It.IsAny <Stream>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new AggregateException(new RequestFailedException("Mock registry request failure 1."), new RequestFailedException("Mock registry request failure 2."))); var clientFactory = StrictMock.Of <IContainerRegistryClientFactory>(); clientFactory .Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny <RootConfiguration>(), new Uri("https://fake"), "fake")) .Returns(client.Object); var templateSpecRepositoryFactory = StrictMock.Of <ITemplateSpecRepositoryFactory>(); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), clientFactory.Object, templateSpecRepositoryFactory.Object); var(output, error, result) = await Bicep(settings, "publish", compiledFilePath, "--target", "br:fake/fake:v1"); using (new AssertionScope()) { error.Should().StartWith("Unable to publish module \"br:fake/fake:v1\": One or more errors occurred. (Mock registry request failure 1.) (Mock registry request failure 2.)"); output.Should().BeEmpty(); result.Should().Be(1); } }
public async Task Restore_ShouldSucceed(DataSet dataSet) { var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules), clientFactory, templateSpecRepositoryFactory); TestContext.WriteLine($"Cache root = {settings.Features.CacheRootDirectory}"); var(output, error, result) = await Bicep(settings, "restore", bicepFilePath); using (new AssertionScope()) { result.Should().Be(0); output.Should().BeEmpty(); error.Should().BeEmpty(); } if (dataSet.HasExternalModules) { // ensure something got restored settings.Features.Should().HaveValidModules(); } }
public async Task Restore_ByDigest_ShouldSucceed() { var registry = "example.com"; var registryUri = new Uri("https://" + registry); var repository = "hello/there"; var client = new MockRegistryBlobClient(); var clientFactory = StrictMock.Of <IContainerRegistryClientFactory>(); clientFactory.Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny <RootConfiguration>(), registryUri, repository)).Returns(client); var templateSpecRepositoryFactory = BicepTestConstants.TemplateSpecRepositoryFactory; var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), clientFactory.Object, BicepTestConstants.TemplateSpecRepositoryFactory); var tempDirectory = FileHelper.GetUniqueTestOutputPath(TestContext); Directory.CreateDirectory(tempDirectory); var publishedBicepFilePath = Path.Combine(tempDirectory, "published.bicep"); File.WriteAllText(publishedBicepFilePath, string.Empty); var(publishOutput, publishError, publishResult) = await Bicep(settings, "publish", publishedBicepFilePath, "--target", $"br:{registry}/{repository}:v1"); using (new AssertionScope()) { publishResult.Should().Be(0); publishOutput.Should().BeEmpty(); publishError.Should().BeEmpty(); } client.Blobs.Should().HaveCount(2); client.Manifests.Should().HaveCount(1); client.ManifestTags.Should().HaveCount(1); string digest = client.Manifests.Single().Key; var bicep = $@" module empty 'br:{registry}/{repository}@{digest}' = {{ name: 'empty' }} "; var restoreBicepFilePath = Path.Combine(tempDirectory, "restored.bicep"); File.WriteAllText(restoreBicepFilePath, bicep); var(output, error, result) = await Bicep(settings, "restore", restoreBicepFilePath); using (new AssertionScope()) { result.Should().Be(0); output.Should().BeEmpty(); error.Should().BeEmpty(); } }
public async Task Publish_OciDigestTarget_ShouldProduceExpectedError() { var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), BicepTestConstants.ClientFactory, BicepTestConstants.TemplateSpecRepositoryFactory); var(output, error, result) = await Bicep(settings, "publish", "WrongFile.bicep", "--target", "br:example.com/test@sha256:80f63ced0b80b63874c808a321f472755a3c9e93987d1fa0a51e13c65e4a52b9"); result.Should().Be(1); output.Should().BeEmpty(); error.Should().Contain("The specified module target \"br:example.com/test@sha256:80f63ced0b80b63874c808a321f472755a3c9e93987d1fa0a51e13c65e4a52b9\" is not supported."); }
public async Task Publish_InvalidInputFile_ShouldProduceExpectedError() { var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), BicepTestConstants.ClientFactory, BicepTestConstants.TemplateSpecRepositoryFactory); var(output, error, result) = await Bicep(settings, "publish", "WrongFile.bicep", "--target", "br:example.azurecr.io/hello/there:v1"); result.Should().Be(1); output.Should().BeEmpty(); error.Should().MatchRegex(@"An error occurred reading file\. Could not find file '.+WrongFile.bicep'\."); }
private CompilationHelper.CompilationHelperContext GetExtensibilityCompilationContext() { var features = BicepTestConstants.CreateFeaturesProvider(TestContext, importsEnabled: true, resourceTypedParamsAndOutputsEnabled: true); var resourceTypeLoader = BicepTestConstants.AzResourceTypeLoader; var namespaceProvider = new ExtensibilityNamespaceProvider(resourceTypeLoader, features); return(new( AzResourceTypeLoader : resourceTypeLoader, Features : features, NamespaceProvider : namespaceProvider)); }
public async Task Build_Valid_SingleFile_After_Restore_Should_Succeed(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules), clientFactory, templateSpecRepositoryFactory); var(restoreOutput, restoreError, restoreResult) = await Bicep(settings, "restore", bicepFilePath); using (new AssertionScope()) { restoreResult.Should().Be(0); restoreOutput.Should().BeEmpty(); restoreError.Should().BeEmpty(); } // run restore with the same feature settings, so it will use the mock local module cache // but break the client to ensure no outgoing calls are made var settingsWithBrokenClient = settings with { ClientFactory = Repository.Create <IContainerRegistryClientFactory>().Object }; var(output, error, result) = await Bicep(settingsWithBrokenClient, "build", "--stdout", "--no-restore", bicepFilePath); using (new AssertionScope()) { result.Should().Be(0); output.Should().NotBeEmpty(); AssertNoErrors(error); } var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled); File.Exists(compiledFilePath).Should().BeTrue(); var actual = JToken.Parse(output); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: Path.Combine("src", "Bicep.Core.Samples", "Files", dataSet.Name, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
public async Task Publish_InvalidFile_ShouldFail_WithExpectedErrorMessage(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); // publish won't actually happen, so broken client factory is fine var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), BicepTestConstants.ClientFactory, BicepTestConstants.TemplateSpecRepositoryFactory); var diagnostics = GetAllDiagnostics(bicepFilePath, settings.ClientFactory, settings.TemplateSpecRepositoryFactory); var(output, error, result) = await Bicep(settings, "publish", bicepFilePath, "--target", $"br:example.com/fail/{dataSet.Name.ToLowerInvariant()}:v1"); using (new AssertionScope()) { result.Should().Be(1); output.Should().BeEmpty(); error.Should().ContainAll(diagnostics); } }
public async Task Publish_ValidFile_ShouldSucceed(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var registryStr = "example.com"; var registryUri = new Uri($"https://{registryStr}"); var repository = $"test/{dataSet.Name}".ToLowerInvariant(); var clientFactory = dataSet.CreateMockRegistryClients(TestContext, (registryUri, repository)); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled); // mock client factory caches the clients var testClient = (MockRegistryBlobClient)clientFactory.CreateAuthenticatedBlobClient(BicepTestConstants.BuiltInConfiguration, registryUri, repository); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), clientFactory, templateSpecRepositoryFactory); var(output, error, result) = await Bicep(settings, "publish", bicepFilePath, "--target", $"br:{registryStr}/{repository}:v1"); result.Should().Be(0); output.Should().BeEmpty(); AssertNoErrors(error); using var expectedCompiledStream = new FileStream(compiledFilePath, FileMode.Open, FileAccess.Read); // verify the module was published testClient.Should().OnlyHaveModule("v1", expectedCompiledStream); // publish the same content again var(output2, error2, result2) = await Bicep(settings, "publish", bicepFilePath, "--target", $"br:{registryStr}/{repository}:v1"); result2.Should().Be(0); output2.Should().BeEmpty(); AssertNoErrors(error2); // we should still only have 1 module expectedCompiledStream.Position = 0; testClient.Should().OnlyHaveModule("v1", expectedCompiledStream); }
public async Task Build_command_should_generate_template_with_symbolic_names_if_enabled() { var diagnosticsListener = new MultipleMessageListener <PublishDiagnosticsParams>(); var features = BicepTestConstants.CreateFeaturesProvider( TestContext, symbolicNameCodegenEnabled: true, assemblyFileVersion: BicepTestConstants.DevAssemblyFileVersion); using var helper = await LanguageServerHelper.StartServerWithClientConnectionAsync( this.TestContext, options => options.OnPublishDiagnostics(diagnosticsParams => diagnosticsListener.AddMessage(diagnosticsParams)), new LanguageServer.Server.CreationOptions( NamespaceProvider: BuiltInTestTypes.Create(), Features: features)); var client = helper.Client; var outputDirectory = FileHelper.SaveEmbeddedResourcesWithPathPrefix( TestContext, typeof(ExamplesTests).Assembly, "Bicep.Core.Samples/Resources_CRLF"); var bicepFilePath = Path.Combine(outputDirectory, "main.bicep"); var expectedJson = File.ReadAllText(Path.Combine(outputDirectory, "main.symbolicnames.json")); client.TextDocument.DidOpenTextDocument(TextDocumentParamHelper.CreateDidOpenDocumentParamsFromFile(bicepFilePath, 1)); await diagnosticsListener.WaitNext(); await client.Workspace.ExecuteCommand(new Command { Name = "build", Arguments = new JArray { bicepFilePath, } }); var buildCommandOutput = File.ReadAllText(Path.ChangeExtension(bicepFilePath, ".json")); buildCommandOutput.Should().BeEquivalentToIgnoringNewlines(expectedJson); }
public async Task Restore_NonExistentModules_ShouldFail(DataSet dataSet) { var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); // do not publish modules to the registry var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules), clientFactory, templateSpecRepositoryFactory); TestContext.WriteLine($"Cache root = {settings.Features.CacheRootDirectory}"); var(output, error, result) = await Bicep(settings, "restore", bicepFilePath); using (new AssertionScope()) { result.Should().Be(1); output.Should().BeEmpty(); error.Should().ContainAll(": Error BCP192: Unable to restore the module with reference ", "The module does not exist in the registry."); } }
public async Task Build_Valid_SingleFile_ShouldSucceed(DataSet dataSet) { var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules), clientFactory, templateSpecRepositoryFactory); var(output, error, result) = await Bicep(settings, "build", bicepFilePath); using (new AssertionScope()) { result.Should().Be(0); output.Should().BeEmpty(); AssertNoErrors(error); } if (dataSet.HasExternalModules) { // ensure something got restored Directory.Exists(settings.Features.CacheRootDirectory).Should().BeTrue(); Directory.EnumerateFiles(settings.Features.CacheRootDirectory, "*.json", SearchOption.AllDirectories).Should().NotBeEmpty(); } var compiledFilePath = Path.Combine(outputDirectory, DataSet.TestFileMainCompiled); File.Exists(compiledFilePath).Should().BeTrue(); var actual = JToken.Parse(File.ReadAllText(compiledFilePath)); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: Path.Combine("src", "Bicep.Core.Samples", "Files", dataSet.Name, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
public static async Task <(Compilation compilation, string outputDirectory, Uri fileUri)> SetupPrerequisitesAndCreateCompilation(this DataSet dataSet, TestContext testContext) { var features = BicepTestConstants.CreateFeaturesProvider(testContext, registryEnabled: dataSet.HasExternalModules); var outputDirectory = dataSet.SaveFilesToTestDirectory(testContext); var clientFactory = dataSet.CreateMockRegistryClients(testContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, testContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(testContext); var fileUri = PathHelper.FilePathToFileUrl(Path.Combine(outputDirectory, DataSet.TestFileMain)); var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, features)); var workspace = new Workspace(); var namespaceProvider = new DefaultNamespaceProvider(new AzResourceTypeLoader(), features); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(fileUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, fileUri, configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } return(new Compilation(namespaceProvider, sourceFileGrouping, configuration, new LinterAnalyzer(configuration)), outputDirectory, fileUri); }
public async Task Restore_RequestFailedException_ShouldFail() { var dataSet = DataSets.Registry_LF; var outputDirectory = FileHelper.GetUniqueTestOutputPath(TestContext); Directory.CreateDirectory(outputDirectory); var compiledFilePath = Path.Combine(outputDirectory, "main.bicep"); File.WriteAllText(compiledFilePath, @"module foo 'br:fake/fake:v1'"); var client = StrictMock.Of <ContainerRegistryBlobClient>(); client .Setup(m => m.DownloadManifestAsync(It.IsAny <DownloadManifestOptions>(), It.IsAny <CancellationToken>())) .ThrowsAsync(new RequestFailedException("Mock registry request failure.")); var clientFactory = StrictMock.Of <IContainerRegistryClientFactory>(); clientFactory .Setup(m => m.CreateAuthenticatedBlobClient(It.IsAny <RootConfiguration>(), new Uri("https://fake"), "fake")) .Returns(client.Object); var templateSpecRepositoryFactory = StrictMock.Of <ITemplateSpecRepositoryFactory>(); var settings = new InvocationSettings(BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: true), clientFactory.Object, templateSpecRepositoryFactory.Object); var(output, error, result) = await Bicep(settings, "restore", compiledFilePath); using (new AssertionScope()) { result.Should().Be(1); output.Should().BeEmpty(); error.Should().Contain("main.bicep(1,12) : Error BCP192: Unable to restore the module with reference \"br:fake/fake:v1\": Mock registry request failure."); } }
public async Task ValidBicepTextWriter_TemplateEmiterShouldProduceExpectedTemplate(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var bicepFileUri = PathHelper.FilePathToFileUrl(bicepFilePath); MemoryStream memoryStream = new MemoryStream(); // emitting the template should be successful var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasExternalModules))); var workspace = new Workspace(); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(bicepFileUri); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, PathHelper.FilePathToFileUrl(bicepFilePath), configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } var result = this.EmitTemplate(sourceFileGrouping, BicepTestConstants.EmitterSettings, memoryStream); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); // normalizing the formatting in case there are differences in indentation // this way the diff between actual and expected will be clean var actual = JToken.ReadFrom(new JsonTextReader(new StreamReader(new MemoryStream(memoryStream.ToArray())))); var compiledFilePath = FileHelper.SaveResultFile(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiled), actual.ToString(Formatting.Indented)); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.Compiled !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiled), actualLocation: compiledFilePath); }
public async Task ValidBicep_EmitTemplate_should_produce_expected_symbolicname_template(DataSet dataSet) { var outputDirectory = dataSet.SaveFilesToTestDirectory(TestContext); var clientFactory = dataSet.CreateMockRegistryClients(TestContext); var templateSpecRepositoryFactory = dataSet.CreateMockTemplateSpecRepositoryFactory(TestContext); await dataSet.PublishModulesToRegistryAsync(clientFactory, TestContext); var bicepFilePath = Path.Combine(outputDirectory, DataSet.TestFileMain); var bicepFileUri = PathHelper.FilePathToFileUrl(bicepFilePath); var compiledFilePath = FileHelper.GetResultFilePath(this.TestContext, Path.Combine(dataSet.Name, DataSet.TestFileMainCompiledWithSymbolicNames)); var configuration = BicepTestConstants.ConfigurationManager.GetConfiguration(bicepFileUri); // emitting the template should be successful var dispatcher = new ModuleDispatcher(new DefaultModuleRegistryProvider(BicepTestConstants.FileResolver, clientFactory, templateSpecRepositoryFactory, BicepTestConstants.CreateFeaturesProvider(TestContext, registryEnabled: dataSet.HasRegistryModules))); Workspace workspace = new(); var sourceFileGrouping = SourceFileGroupingBuilder.Build(BicepTestConstants.FileResolver, dispatcher, workspace, bicepFileUri, configuration); if (await dispatcher.RestoreModules(configuration, dispatcher.GetValidModuleReferences(sourceFileGrouping.ModulesToRestore, configuration))) { sourceFileGrouping = SourceFileGroupingBuilder.Rebuild(dispatcher, workspace, sourceFileGrouping, configuration); } var result = this.EmitTemplate(sourceFileGrouping, BicepTestConstants.EmitterSettingsWithSymbolicNames, compiledFilePath); result.Diagnostics.Should().NotHaveErrors(); result.Status.Should().Be(EmitStatus.Succeeded); var outputFile = File.ReadAllText(compiledFilePath); var actual = JToken.Parse(outputFile); actual.Should().EqualWithJsonDiffOutput( TestContext, JToken.Parse(dataSet.CompiledWithSymbolicNames !), expectedLocation: DataSet.GetBaselineUpdatePath(dataSet, DataSet.TestFileMainCompiledWithSymbolicNames), actualLocation: compiledFilePath); // validate that the template is parseable by the deployment engine TemplateHelper.TemplateShouldBeValid(outputFile); }
private CompilationHelper.CompilationResult Compile(string bicep, bool symbolicNameCodegenEnabled) { var context = new CompilationHelper.CompilationHelperContext(Features: BicepTestConstants.CreateFeaturesProvider(this.TestContext, symbolicNameCodegenEnabled: symbolicNameCodegenEnabled)); return(CompilationHelper.Compile(context, bicep)); }