Skip to content

Commit

Permalink
9038 Support private module completions
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenWeatherford committed Jan 9, 2025
1 parent bddc1b3 commit 01772fd
Show file tree
Hide file tree
Showing 40 changed files with 2,741 additions and 1,434 deletions.
12 changes: 6 additions & 6 deletions src/Bicep.Cli.IntegrationTests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ namespace Bicep.Cli.IntegrationTests
{
public abstract class TestBase : Bicep.Core.UnitTests.TestBase
{
private static BicepCompiler CreateCompiler(IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicRegistryModuleIndexClient? moduleMetadataClient)
private static BicepCompiler CreateCompiler(IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicRegistryModuleIndexHttpClient? moduleMetadataClient)
=> ServiceBuilder.Create(
services =>
{
services
.AddSingleton(clientFactory)
.AddSingleton(templateSpecRepositoryFactory)
.AddSingleton<IPublicRegistryModuleMetadataProvider, PublicRegistryModuleMetadataProvider>();
.AddRegistryIndexerServices();

IServiceCollectionExtensions.AddMockHttpClientIfNotNull(services, moduleMetadataClient);
}
Expand All @@ -49,21 +49,21 @@ protected record InvocationSettings
public IContainerRegistryClientFactory ClientFactory { get; init; }
public ITemplateSpecRepositoryFactory TemplateSpecRepositoryFactory { get; init; }
public IEnvironment? Environment { get; init; }
public IPublicRegistryModuleIndexClient ModuleMetadataClient { get; init; }
public IPublicRegistryModuleIndexHttpClient ModuleMetadataClient { get; init; }

public InvocationSettings(
FeatureProviderOverrides? FeatureOverrides = null,
IContainerRegistryClientFactory? ClientFactory = null,
ITemplateSpecRepositoryFactory? TemplateSpecRepositoryFactory = null,
IEnvironment? Environment = null,
IPublicRegistryModuleIndexClient? ModuleMetadataClient = null)
IPublicRegistryModuleIndexHttpClient? ModuleMetadataClient = null)
{
this.FeatureOverrides = FeatureOverrides;
this.ClientFactory = ClientFactory ?? Repository.Create<IContainerRegistryClientFactory>().Object;
this.TemplateSpecRepositoryFactory = TemplateSpecRepositoryFactory ?? Repository.Create<ITemplateSpecRepositoryFactory>().Object;
this.Environment = Environment;

this.ModuleMetadataClient = ModuleMetadataClient ?? StrictMock.Of<IPublicRegistryModuleIndexClient>().Object;
this.ModuleMetadataClient = ModuleMetadataClient ?? StrictMock.Of<IPublicRegistryModuleIndexHttpClient>().Object;
}
}

Expand Down Expand Up @@ -109,7 +109,7 @@ protected static void AssertNoErrors(string error)
}
}

protected static async Task<IEnumerable<string>> GetAllDiagnostics(string bicepFilePath, IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicRegistryModuleIndexClient? moduleMetadataClient = null)
protected static async Task<IEnumerable<string>> GetAllDiagnostics(string bicepFilePath, IContainerRegistryClientFactory clientFactory, ITemplateSpecRepositoryFactory templateSpecRepositoryFactory, IPublicRegistryModuleIndexHttpClient? moduleMetadataClient = null)
{
var compilation = await CreateCompiler(clientFactory, templateSpecRepositoryFactory, moduleMetadataClient).CreateCompilation(PathHelper.FilePathToFileUrl(bicepFilePath));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class UseRecentModuleVersionsIntegrationTests : TestBase

private class Options(string CacheRoot)
{
private IPublicRegistryModuleIndexClient? _metadataClient = null;
private IPublicRegistryModuleIndexHttpClient? _metadataClient = null;
private string? _config = null;

public string Bicep { get; init; } = "/* bicep contents */";
Expand Down Expand Up @@ -73,8 +73,8 @@ public string? BicepConfig
}
}

// Automatically created from ModulesMetadata by default
public IPublicRegistryModuleIndexClient MetadataClient
// Automatically created from ModulesMetadata by default (set manually for testing)
internal IPublicRegistryModuleIndexHttpClient MetadataClient
{
set
{
Expand All @@ -84,7 +84,7 @@ public IPublicRegistryModuleIndexClient MetadataClient
ModulesMetadata.Select(mm => new PublicRegistryModuleIndexEntry(
mm.module,
[.. mm.versions],
new Dictionary<string, PublicRegistryModuleProperties>().ToImmutableDictionary()))).Object;
new Dictionary<string, PublicRegistryModuleIndexProperties>().ToImmutableDictionary()))).Object;
}

}
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Cli/Helpers/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public static IServiceCollection AddBicepCore(this IServiceCollection services)
.AddSingleton<IBicepAnalyzer, LinterAnalyzer>()
.AddSingleton<IFeatureProviderFactory, FeatureProviderFactory>()
.AddSingleton<ILinterRulesProvider, LinterRulesProvider>()
.AddPublicRegistryModuleMetadataProviderServices()
.AddRegistryIndexerServices()
.AddSingleton<BicepCompiler>();

public static IServiceCollection AddBicepDecompiler(this IServiceCollection services) => services
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//using Bicep.Core.Diagnostics;
//using Bicep.Core.Semantics;
//using FluentAssertions;
//using FluentAssertions.Execution;
//using FluentAssertions.Primitives;
//using Moq;
//using OmniSharp.Extensions.LanguageServer.Protocol.Models;

//namespace Bicep.Core.UnitTests.Assertions
//{
// public static class CompletionItemsExtensions
// {
// public static CompletionItemsAssertions Should(this CompletionList completionList)
// {
// return new CompletionItemsAssertions(completionList);
// }
// }

// public class CompletionItemsAssertions : ReferenceTypeAssertions<CompletionList, CompletionItemsAssertions>
// {
// public CompletionItemsAssertions(CompletionList completionList)
// : base(completionList)
// {
// }

// protected override string Identifier => "CompletionList";

// public AndConstraint<CompletionItem> ContainByLabel(string label, string because = "", params object[] becauseArgs)
// {
// var matchingItem = Subject.Items.FirstOrDefault(item => item.Label == label);

// Execute.Assertion
// .BecauseOf(because, becauseArgs)
// .ForCondition(matchingItem != null)
// .FailWith("Expected to find a CompletionItem with label {0}{reason}, but did not.", label);

// return new AndConstraint<CompletionItem>(matchingItem!);
// }
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ private static CompilationResult Compile(
string? downloadError = null)
{
var publicRegistryModuleMetadataProvider = StrictMock.Of<IPublicRegistryModuleMetadataProvider>();
publicRegistryModuleMetadataProvider.Setup(x => x.GetModulesMetadata())
.Returns(availableModules.Select(m => new PublicRegistryModuleMetadata(m, null, null)).ToImmutableArray());
publicRegistryModuleMetadataProvider.Setup(x => x.GetModuleVersionsMetadata(It.IsAny<string>()))
publicRegistryModuleMetadataProvider.Setup(x => x.GetCachedModules())
.Returns([.. availableModules.Select(m => new RegistryModuleMetadata("mcr.microsoft.com", "bicep/" + m, null, null))]);
publicRegistryModuleMetadataProvider.Setup(x => x.GetCachedModuleVersions(It.IsAny<string>()))
.Returns((string module) =>
{
return availableModules.Contains(module) ?
availableVersions.Select(v => new PublicRegistryModuleVersionMetadata(v, null, null)).ToImmutableArray() :
[.. availableVersions.Select(v => new RegistryModuleVersionMetadata(v, null, null))] :
[];
});
publicRegistryModuleMetadataProvider.Setup(x => x.IsCached)
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Core.UnitTests/IServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static IServiceCollection AddBicepCore(this IServiceCollection services)
.AddSingleton<IBicepAnalyzer, LinterAnalyzer>()
.AddSingleton<IFeatureProviderFactory, FeatureProviderFactory>()
.AddSingleton<ILinterRulesProvider, LinterRulesProvider>()
.AddPublicRegistryModuleMetadataProviderServices()
.AddRegistryIndexerServices()
.AddSingleton<BicepCompiler>();

AddMockHttpClient(services, PublicRegistryModuleIndexClientMock.Create([]).Object);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ public static class PublicRegistryModuleIndexClientMock
{
// CONSIDER: Mock HttpClient rather than the typed client

public static Mock<IPublicRegistryModuleIndexClient> Create(IEnumerable<PublicRegistryModuleIndexEntry> metadata)
public static Mock<IPublicRegistryModuleIndexHttpClient> Create(IEnumerable<PublicRegistryModuleIndexEntry> metadata)
{
var mock = StrictMock.Of<IPublicRegistryModuleIndexClient>();
var mock = StrictMock.Of<IPublicRegistryModuleIndexHttpClient>();
mock
.Setup(client => client.GetModuleIndexAsync())
.ReturnsAsync(() => metadata.ToImmutableArray());
.ReturnsAsync(() => [.. metadata]);
return mock;
}

public static Mock<IPublicRegistryModuleIndexClient> CreateToThrow(Exception exception)
public static Mock<IPublicRegistryModuleIndexHttpClient> CreateToThrow(Exception exception)
{
var mock = StrictMock.Of<IPublicRegistryModuleIndexClient>();
var mock = StrictMock.Of<IPublicRegistryModuleIndexHttpClient>();
mock
.Setup(client => client.GetModuleIndexAsync())
.ThrowsAsync(exception);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.


//asdfg do for private


using System.Net.Http;
using System.Text;
using System.Text.Json;
using Bicep.Core.Extensions;
using Bicep.Core.Registry.PublicRegistry;
using Bicep.Core.UnitTests;
using Bicep.LanguageServer.Providers;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
Expand All @@ -15,15 +17,21 @@
namespace Bicep.Core.UnitTests.Registry.PublicRegistry
{
[TestClass]
public class PublicRegistryModuleMetadataProviderTests
public class PublicRegistryModuleMetadataProviderTests //asdfgasdfg existing core tests
{
private IServiceProvider GetServiceProvider()
{
//private IServiceProvider GetServiceProvider() asdfg remove
//{
// var httpClient = MockHttpMessageHandler.ToHttpClient();
// return new ServiceBuilder().WithRegistration(x =>
// x.AddSingleton<IPublicRegistryModuleIndexHttpClient>(new PublicRegistryModuleMetadataHttpClient(httpClient))
// ).Build().Construct<IServiceProvider>();
//}

private PublicRegistryModuleMetadataHttpClient CreateTypedClient() { //asdfg extract
var httpClient = MockHttpMessageHandler.ToHttpClient();
return new ServiceBuilder().WithRegistration(x =>
x.AddSingleton<IPublicRegistryModuleIndexClient>(new PublicRegistryModuleMetadataClient(httpClient))
).Build().Construct<IServiceProvider>();
return new PublicRegistryModuleMetadataHttpClient(httpClient);
}

private const string ModuleIndexJson = """
[
{
Expand Down Expand Up @@ -762,6 +770,7 @@ private IServiceProvider GetServiceProvider()
},
{
"moduleName": "samples/array-loop",
"$comment": "Tags intentionally out of order",
"tags": [
"1.0.1",
"1.10.1",
Expand Down Expand Up @@ -1098,12 +1107,13 @@ public static void ClassInitialize(TestContext _)
.Respond("application/json", ModuleIndexJson);
}

//asdfg move?
[TestMethod]
public void GetExponentialDelay_ZeroCount_ShouldGiveInitialDelay()
{
TimeSpan initial = TimeSpan.FromDays(2.5);
TimeSpan max = TimeSpan.FromDays(10);
var delay = PublicRegistryModuleMetadataProvider.GetExponentialDelay(initial, 0, max);
var delay = RegistryModuleMetadataProviderBase.GetExponentialDelay(initial, 0, max);

delay.Should().Be(initial);
}
Expand All @@ -1113,7 +1123,7 @@ public void GetExponentialDelay_1Count_ShouldGiveDoubleInitialDelay()
{
TimeSpan initial = TimeSpan.FromDays(2.5);
TimeSpan max = TimeSpan.FromDays(10);
var delay = PublicRegistryModuleMetadataProvider.GetExponentialDelay(initial, 1, max);
var delay = RegistryModuleMetadataProviderBase.GetExponentialDelay(initial, 1, max);

delay.Should().Be(initial * 2);
}
Expand All @@ -1123,7 +1133,7 @@ public void GetExponentialDelay_2Count_ShouldGiveQuadrupleInitialDelay()
{
TimeSpan initial = TimeSpan.FromDays(2.5);
TimeSpan max = TimeSpan.FromDays(10);
var delay = PublicRegistryModuleMetadataProvider.GetExponentialDelay(initial, 2, max);
var delay = RegistryModuleMetadataProviderBase.GetExponentialDelay(initial, 2, max);

delay.Should().Be(initial * 4);
}
Expand Down Expand Up @@ -1174,43 +1184,41 @@ public void GetModules_ForwardsCompatibleWithOriginalVersion()
[TestMethod]
public async Task GetModules_Count_SanityCheck()
{
PublicRegistryModuleMetadataProvider provider = new(GetServiceProvider());
PublicRegistryModuleMetadataProvider provider = new(CreateTypedClient());
(await provider.TryUpdateCacheAsync()).Should().BeTrue();
var modules = provider.GetModulesMetadata();
var modules = await provider.GetModulesAsync();
modules.Should().HaveCount(50);
}

[TestMethod]
public async Task GetModules_OnlyLastTagHasDescription()
public async Task GetModules_IfOnlyLastTagHasDescription()
{
PublicRegistryModuleMetadataProvider provider = new(GetServiceProvider());
PublicRegistryModuleMetadataProvider provider = new(CreateTypedClient());
(await provider.TryUpdateCacheAsync()).Should().BeTrue();
var modules = provider.GetModulesMetadata();
var m = modules.Should().Contain(m => m.Name == "samples/hello-world")
var modules = await provider.GetModulesAsync();
var m = modules.Should().Contain(m => m.ModuleName == "bicep/samples/hello-world")
.Which;
m.Description.Should().Be("A \"שָׁלוֹם עוֹלָם\" sample Bicep registry module");
m.DocumentationUri.Should().Be("https://github.com/Azure/bicep-registry-modules/tree/samples/hello-world/1.0.4/modules/samples/hello-world/README.md");
}

[TestMethod]
public async Task GetModules_MultipleTagsHaveDescriptions()
public async Task GetModules_IfMultipleTagsHaveDescriptions()
{
PublicRegistryModuleMetadataProvider provider = new(GetServiceProvider());
PublicRegistryModuleMetadataProvider provider = new(CreateTypedClient());
(await provider.TryUpdateCacheAsync()).Should().BeTrue();
var modules = provider.GetModulesMetadata();
var m = modules.Should().Contain(m => m.Name == "lz/sub-vending")
var modules = await provider.GetModulesAsync();
var m = modules.Should().Contain(m => m.ModuleName == "bicep/lz/sub-vending")
.Which;
m.Description.Should().Be("This module is designed to accelerate deployment of landing zones (aka Subscriptions) within an Azure AD Tenant.");
m.DocumentationUri.Should().Be("https://github.com/Azure/bicep-registry-modules/tree/lz/sub-vending/1.4.2/modules/lz/sub-vending/README.md");
}

[TestMethod]
public async Task GetModuleVerionsMetadata_ByDefault_ReturnsMetadataSortedByVersion()
public async Task GetModuleVersions_SortsBySemver() //asdfg test for private
{
PublicRegistryModuleMetadataProvider provider = new(GetServiceProvider());
(await provider.TryUpdateCacheAsync()).Should().BeTrue();

var versions = provider.GetModuleVersionsMetadata("samples/array-loop").Select(x => x.Version);
PublicRegistryModuleMetadataProvider provider = new(CreateTypedClient());
var versions = (await provider.GetModuleVersionsAsync("bicep/samples/array-loop")).Select(x => x.Version);//asdfg test

versions.Should().Equal(
"1.10.1",
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Core.UnitTests/Utils/OciRegistryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public static (OciArtifactRegistry, MockRegistryBlobClient) CreateModuleRegistry
clientFactory.Object,
featureProvider,
BicepTestConstants.BuiltInConfiguration,
StrictMock.Of<IPublicRegistryModuleMetadataProvider>().Object,
StrictMock.Of<IPublicRegistryModuleMetadataProvider>().Object,// asdfg mock start cache?
parentModuleUri);

return (registry, blobClient);
Expand Down
Loading

0 comments on commit 01772fd

Please sign in to comment.