From cf3a23eee5ae6c8399a0cd295a3c159b66594b0c Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Wed, 4 Dec 2024 15:45:22 +0800 Subject: [PATCH] refine those test cases --- .../ClientProviderAuthTests.cs | 339 +++++-- .../ClientProviderNoAuthTests.cs | 784 ++++++++-------- .../ClientProviderOAuth2AuthTests.cs | 872 +++++++++--------- .../ClientProviders/ClientProviderTests.cs | 17 + 4 files changed, 1120 insertions(+), 892 deletions(-) diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderAuthTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderAuthTests.cs index 50b01e993e..27ca430fe9 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderAuthTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderAuthTests.cs @@ -29,50 +29,136 @@ public class ClientProviderAuthTests private static readonly InputClient _dogClient = new("dog", "DogClient description", [], [], _animalClient.Name); private static readonly InputClient _huskyClient = new("husky", "HuskyClient description", [], [], _dogClient.Name); + private bool _containsSubClients; + private bool _hasKeyAuth; + private bool _hasOAuth2; + private bool _hasAuth; + [SetUp] public void SetUp() { var categories = TestContext.CurrentContext.Test?.Properties["Category"]; - bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; - bool hasKeyAuth = categories?.Contains(KeyAuthCategory) ?? false; - bool hasOAuth2 = categories?.Contains(OAuth2Category) ?? false; + _containsSubClients = categories?.Contains(SubClientsCategory) ?? false; + _hasKeyAuth = categories?.Contains(KeyAuthCategory) ?? false; + _hasOAuth2 = categories?.Contains(OAuth2Category) ?? false; + _hasAuth = _hasKeyAuth || _hasOAuth2; - Func>? clients = containsSubClients ? + Func>? clients = _containsSubClients ? () => [_animalClient, _dogClient, _huskyClient] : null; - Func? apiKeyAuth = hasKeyAuth ? () => new InputApiKeyAuth("mock", null) : null; - Func? oauth2Auth = hasOAuth2 ? () => new InputOAuth2Auth(["mock"]) : null; + Func? apiKeyAuth = _hasKeyAuth ? () => new InputApiKeyAuth("mock", null) : null; + Func? oauth2Auth = _hasOAuth2 ? () => new InputOAuth2Auth(["mock"]) : null; MockHelpers.LoadMockPlugin( apiKeyAuth: apiKeyAuth, oauth2Auth: oauth2Auth, - clients: clients); + clients: clients, + clientPipelineApi: TestClientPipelineApi.Instance); } [TestCaseSource(nameof(BuildFieldsTestCases), Category = KeyAuthCategory)] - public void TestBuildFields(List inputParameters) + public void TestBuildFields_WithAuth(List inputParameters) + { + var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + var clientProvider = new ClientProvider(client); + + Assert.IsNotNull(clientProvider); + + if (_hasKeyAuth) + { + // key auth should have the following fields: AuthorizationHeader, _keyCredential + AssertHasFields(clientProvider, new List + { + new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), + new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") + }); + } + if (_hasOAuth2) + { + // oauth2 auth should have the following fields: AuthorizationScopes, _tokenCredential + AssertHasFields(clientProvider, new List + { + new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + }); + } + } + + [TestCaseSource(nameof(BuildFieldsTestCases))] + public void TestBuildFields_NoAuth(List inputParameters) { var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); var clientProvider = new ClientProvider(client); Assert.IsNotNull(clientProvider); - // key auth should have the following fields: AuthorizationHeader, _keyCredential + // fields here should not have anything related with auth + bool authFieldFound = false; + foreach (var field in clientProvider.Fields) + { + if (field.Name.EndsWith("Credential") || field.Name.Contains("Authorization")) + { + authFieldFound = true; + } + } - AssertHasFields(clientProvider, expectedFields); + Assert.IsFalse(authFieldFound); } - // validates the fields are built correctly when a client has sub-clients + // validates the credential fields are built correctly when a client has sub-clients [TestCaseSource(nameof(SubClientFieldsTestCases), Category = SubClientsCategory)] - public void TestBuildFields_WithSubClients(InputClient client, List expectedFields) + public void TestBuildFields_WithSubClients_NoAuth(InputClient client) { var clientProvider = new ClientProvider(client); Assert.IsNotNull(clientProvider); - AssertHasFields(clientProvider, expectedFields); + // fields here should not have anything related with auth + bool authFieldFound = false; + foreach (var field in clientProvider.Fields) + { + if (field.Name.EndsWith("Credential") || field.Name.Contains("Authorization")) + { + authFieldFound = true; + } + } + + Assert.IsFalse(authFieldFound); + } + + // validates the credential fields are built correctly when a client has sub-clients + [TestCaseSource(nameof(SubClientFieldsTestCases), Category = $"{SubClientsCategory},{KeyAuthCategory}")] + [TestCaseSource(nameof(SubClientFieldsTestCases), Category = $"{SubClientsCategory},{OAuth2Category}")] + [TestCaseSource(nameof(SubClientFieldsTestCases), Category = $"{SubClientsCategory},{KeyAuthCategory},{OAuth2Category}")] + public void TestBuildFields_WithSubClients_WithAuth(InputClient client) + { + var clientProvider = new ClientProvider(client); + + Assert.IsNotNull(clientProvider); + + if (_hasKeyAuth) + { + // key auth should have the following fields: AuthorizationHeader, _keyCredential + AssertHasFields(clientProvider, new List + { + new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), + new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") + }); + } + if (_hasOAuth2) + { + // oauth2 auth should have the following fields: AuthorizationScopes, _tokenCredential + AssertHasFields(clientProvider, new List + { + new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + }); + } } [TestCaseSource(nameof(BuildConstructorsTestCases))] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = KeyAuthCategory)] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = OAuth2Category)] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = $"{KeyAuthCategory},{OAuth2Category}")] public void TestBuildConstructors_PrimaryConstructor(List inputParameters) { var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); @@ -81,14 +167,25 @@ public void TestBuildConstructors_PrimaryConstructor(List inputP Assert.IsNotNull(clientProvider); var constructors = clientProvider.Constructors; - Assert.AreEqual(3, constructors.Count); - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidatePrimaryConstructor(primaryPublicConstructor, inputParameters); + var primaryPublicConstructors = constructors.Where( + c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public).ToArray(); + + // for no auth or one auth case, this should be 1 + // for both auth case, this should be 2 + var expectedPrimaryCtorCount = _hasKeyAuth && _hasOAuth2 ? 2 : 1; + Assert.AreEqual(expectedPrimaryCtorCount, primaryPublicConstructors.Length); + + foreach (var primaryCtor in primaryPublicConstructors) + { + ValidatePrimaryConstructor(primaryCtor, inputParameters); + } } [TestCaseSource(nameof(BuildConstructorsTestCases))] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = KeyAuthCategory)] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = OAuth2Category)] + [TestCaseSource(nameof(BuildConstructorsTestCases), Category = $"{KeyAuthCategory},{OAuth2Category}")] public void TestBuildConstructors_SecondaryConstructor(List inputParameters) { var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); @@ -98,19 +195,46 @@ public void TestBuildConstructors_SecondaryConstructor(List inpu var constructors = clientProvider.Constructors; - Assert.AreEqual(3, constructors.Count); - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + var primaryPublicConstructors = constructors.Where( + c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public).ToArray(); + var secondaryPublicConstructors = constructors.Where( + c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public).ToArray(); - Assert.IsNotNull(primaryPublicConstructor); + // for no auth or one auth case, this should be 1 + // for both auth case, this should be 2 + var expectedSecondaryCtorCount = _hasKeyAuth && _hasOAuth2 ? 2 : 1; + Assert.AreEqual(expectedSecondaryCtorCount, secondaryPublicConstructors.Length); + foreach (var secondaryPublicConstructor in secondaryPublicConstructors) + { + ValidateSecondaryConstructor(primaryPublicConstructors, secondaryPublicConstructor, inputParameters); + } + } - var secondaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidateSecondaryConstructor(primaryPublicConstructor, secondaryPublicConstructor, inputParameters); + [TestCase] + public void TestBuildConstructors_ForSubClient_NoAuth() + { + var clientProvider = new ClientProvider(_animalClient); + + Assert.IsNotNull(clientProvider); + + var constructors = clientProvider.Constructors; + + Assert.AreEqual(2, constructors.Count); + var internalConstructor = constructors.FirstOrDefault( + c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); + Assert.IsNotNull(internalConstructor); + // in the no auth case, the ctor no longer has the credentail parameter therefore here we expect 2 parameters. + var ctorParams = internalConstructor?.Signature?.Parameters; + Assert.AreEqual(2, ctorParams?.Count); + + var mockingConstructor = constructors.FirstOrDefault( + c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); + Assert.IsNotNull(mockingConstructor); } - [Test] - public void TestBuildConstructors_ForSubClient() + [TestCase(Category = KeyAuthCategory)] + [TestCase(Category = OAuth2Category)] + public void TestBuildConstructors_ForSubClient_KeyAuthOrOAuth2Auth() { var clientProvider = new ClientProvider(_animalClient); @@ -122,6 +246,7 @@ public void TestBuildConstructors_ForSubClient() var internalConstructor = constructors.FirstOrDefault( c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); Assert.IsNotNull(internalConstructor); + // when there is only one approach of auth, we have 3 parameters in the ctor. var ctorParams = internalConstructor?.Signature?.Parameters; Assert.AreEqual(3, ctorParams?.Count); @@ -130,22 +255,43 @@ public void TestBuildConstructors_ForSubClient() Assert.IsNotNull(mockingConstructor); } - private static void ValidatePrimaryConstructor( - ConstructorProvider? primaryPublicConstructor, - List inputParameters) + [TestCase(Category = $"{KeyAuthCategory},{OAuth2Category}")] + public void TestBuildConstructors_ForSubClient_BothAuth() { - Assert.IsNotNull(primaryPublicConstructor); + var clientProvider = new ClientProvider(_animalClient); + + Assert.IsNotNull(clientProvider); + + var constructors = clientProvider.Constructors; + + Assert.AreEqual(2, constructors.Count); + var internalConstructor = constructors.FirstOrDefault( + c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); + Assert.IsNotNull(internalConstructor); + // when we have both auths, we have 4 parameters in the ctor, because now we should have two credential parameters + var ctorParams = internalConstructor?.Signature?.Parameters; + Assert.AreEqual(4, ctorParams?.Count); + var mockingConstructor = constructors.FirstOrDefault( + c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); + Assert.IsNotNull(mockingConstructor); + } + + private void ValidatePrimaryConstructor( + ConstructorProvider primaryPublicConstructor, + List inputParameters) + { var primaryCtorParams = primaryPublicConstructor?.Signature?.Parameters; - var expectedPrimaryCtorParamCount = 3; + // in no auth case, the ctor only have two parameters: endpoint and options + // in other cases, the ctor should have three parameters: endpoint, credential, options + // specifically, in both auth cases, we should have two ctors corresponding to each credential type as the second parameter + var expectedPrimaryCtorParamCount = !_hasKeyAuth && !_hasOAuth2 ? 2 : 3; Assert.AreEqual(expectedPrimaryCtorParamCount, primaryCtorParams?.Count); - // validate the order of the parameters (endpoint, credential, client options) + // the first should be endpoint var endpointParam = primaryCtorParams?[0]; Assert.AreEqual(KnownParameters.Endpoint.Name, endpointParam?.Name); - Assert.AreEqual("keyCredential", primaryCtorParams?[1].Name); - Assert.AreEqual("options", primaryCtorParams?[2].Name); if (endpointParam?.DefaultValue != null) { @@ -154,41 +300,76 @@ private static void ValidatePrimaryConstructor( Assert.AreEqual(Literal(parsedValue), endpointParam?.InitializationValue); } + // the last parameter should be the options + var optionsParam = primaryCtorParams?[^1]; + Assert.AreEqual("options", optionsParam?.Name); + + if (_hasAuth) + { + // when there is any auth, the second should be auth parameter + var authParam = primaryCtorParams?[1]; + Assert.IsNotNull(authParam); + if (authParam?.Name == "keyCredential") + { + Assert.AreEqual(new CSharpType(typeof(ApiKeyCredential)), authParam?.Type); + } + else if (authParam?.Name == "tokenCredential") + { + Assert.AreEqual(new CSharpType(typeof(TestTokenCredential)), authParam?.Type); + } + else + { + Assert.Fail("Unexpected auth parameter"); + } + } + // validate the body of the primary ctor var primaryCtorBody = primaryPublicConstructor?.BodyStatements; Assert.IsNotNull(primaryCtorBody); } private void ValidateSecondaryConstructor( - ConstructorProvider? primaryConstructor, - ConstructorProvider? secondaryPublicConstructor, + IReadOnlyList primaryConstructors, + ConstructorProvider secondaryPublicConstructor, List inputParameters) { - Assert.IsNotNull(secondaryPublicConstructor); - var ctorParams = secondaryPublicConstructor?.Signature?.Parameters; + var ctorParams = secondaryPublicConstructor.Signature?.Parameters; - // secondary ctor should consist of all required parameters + auth parameter + // secondary ctor should consist of all required parameters + auth parameter (when present) var requiredParams = inputParameters.Where(p => p.IsRequired).ToList(); - Assert.AreEqual(requiredParams.Count + 1, ctorParams?.Count); + var authParameterCount = _hasAuth ? 1 : 0; + Assert.AreEqual(requiredParams.Count + authParameterCount, ctorParams?.Count); var endpointParam = ctorParams?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); if (requiredParams.Count == 0) { - // auth should be the only parameter if endpoint is optional - Assert.AreEqual("keyCredential", ctorParams?[0].Name); + // auth should be the only parameter if endpoint is optional when there is auth + if (_hasAuth) + { + Assert.IsTrue(ctorParams?[0].Name.EndsWith("Credential")); + } + else + { + // when there is no auth, the ctor should not have parameters + Assert.AreEqual(0, ctorParams?.Count); + } } else { // otherwise, it should only consist of the auth parameter Assert.AreEqual(KnownParameters.Endpoint.Name, ctorParams?[0].Name); - Assert.AreEqual("keyCredential", ctorParams?[1].Name); + if (_hasAuth) + { + Assert.IsTrue(ctorParams?[1].Name.EndsWith("Credential")); + } } Assert.AreEqual(MethodBodyStatement.Empty, secondaryPublicConstructor?.BodyStatements); // validate the initializer var initializer = secondaryPublicConstructor?.Signature?.Initializer; - Assert.AreEqual(primaryConstructor?.Signature?.Parameters?.Count, initializer?.Arguments?.Count); + Assert.NotNull(initializer); + Assert.IsTrue(primaryConstructors.Any(pc => pc.Signature.Parameters.Count == initializer?.Arguments.Count)); } [TestCaseSource(nameof(EndpointParamInitializationValueTestCases))] @@ -302,26 +483,10 @@ public static IEnumerable SubClientFieldsTestCases { get { - yield return new TestCaseData(InputFactory.Client(TestClientName), new List - { - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") - }); - yield return new TestCaseData(_animalClient, new List - { - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") - }); - yield return new TestCaseData(_dogClient, new List - { - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") - }); - yield return new TestCaseData(_huskyClient, new List - { - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string)), "AuthorizationHeader"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(ApiKeyCredential)), "_keyCredential") - }); + yield return new TestCaseData(InputFactory.Client(TestClientName)); + yield return new TestCaseData(_animalClient); + yield return new TestCaseData(_dogClient); + yield return new TestCaseData(_huskyClient); } } @@ -390,5 +555,51 @@ private static IEnumerable EndpointParamInitializationValueTestCas New.Instance(KnownParameters.Endpoint.Type, Literal("mockvalue"))); } } + + // TODO -- this is temporary here before System.ClientModel officially supports OAuth2 auth + private record TestClientPipelineApi : ClientPipelineApi + { + private static ClientPipelineApi? _instance; + internal static ClientPipelineApi Instance => _instance ??= new TestClientPipelineApi(Empty); + + public TestClientPipelineApi(ValueExpression original) : base(typeof(string), original) + { + } + + public override CSharpType ClientPipelineType => typeof(string); + + public override CSharpType ClientPipelineOptionsType => typeof(string); + + public override CSharpType PipelinePolicyType => typeof(string); + + public override CSharpType KeyCredentialType => typeof(ApiKeyCredential); + + public override CSharpType TokenCredentialType => typeof(TestTokenCredential); + + public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies) + => Original.Invoke("GetFakeCreate", [options, perRetryPolicies]); + + public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier) + => Original.Invoke("GetFakeCreateMessage", [requestOptions, responseClassifier]); + + public override ClientPipelineApi FromExpression(ValueExpression expression) + => new TestClientPipelineApi(expression); + + public override ValueExpression ConsumeKeyAuth(ValueExpression credential, ValueExpression headerName, ValueExpression? keyPrefix = null) + => Original.Invoke("GetFakeApiKeyAuthorizationPolicy", keyPrefix != null ? [credential, headerName, keyPrefix] : [credential, headerName]); + + public override ValueExpression ConsumeOAuth2Auth(ValueExpression credential, ValueExpression scopes) + => Original.Invoke("GetFakeTokenAuthorizationPolicy", [credential, scopes]); + + public override ClientPipelineApi ToExpression() => this; + + public override MethodBodyStatement[] ProcessMessage(HttpMessageApi message, HttpRequestOptionsApi options) + => [Original.Invoke("GetFakeProcessMessage", [message, options]).Terminate()]; + + public override MethodBodyStatement[] ProcessMessageAsync(HttpMessageApi message, HttpRequestOptionsApi options) + => [Original.Invoke("GetFakeProcessMessageAsync", [message, options]).Terminate()]; + } + + internal class TestTokenCredential { } } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderNoAuthTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderNoAuthTests.cs index 79072a1dab..6ec27a48bc 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderNoAuthTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderNoAuthTests.cs @@ -20,396 +20,396 @@ namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.ClientProviders { - public class ClientProviderNoAuthTests - { - private const string SubClientsCategory = "WithSubClients"; - private const string TestClientName = "TestClient"; - private static readonly InputClient _animalClient = new("animal", "AnimalClient description", [], [], TestClientName); - private static readonly InputClient _dogClient = new("dog", "DogClient description", [], [], _animalClient.Name); - private static readonly InputClient _huskyClient = new("husky", "HuskyClient description", [], [], _dogClient.Name); - - [SetUp] - public void SetUp() - { - var categories = TestContext.CurrentContext.Test?.Properties["Category"]; - bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; - - if (containsSubClients) - { - MockHelpers.LoadMockPlugin( - clients: () => [_animalClient, _dogClient, _huskyClient]); - } - else - { - MockHelpers.LoadMockPlugin(); - } - } - - [Test] - public void TestBuildProperties() - { - var client = InputFactory.Client(TestClientName); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - // validate the properties - var properties = clientProvider.Properties; - Assert.IsTrue(properties.Count > 0); - // there should be a pipeline property - Assert.AreEqual(1, properties.Count); - - var pipelineProperty = properties[0]; - Assert.AreEqual(typeof(ClientPipeline), pipelineProperty.Type.FrameworkType); - Assert.AreEqual("Pipeline", pipelineProperty.Name); - Assert.AreEqual(MethodSignatureModifiers.Public, pipelineProperty.Modifiers); - } - - [TestCaseSource(nameof(BuildFieldsTestCases))] - public void TestBuildFields(List inputParameters, List expectedFields) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - AssertClientFields(clientProvider, expectedFields); - } - - // validates the fields are built correctly when a client has sub-clients - [TestCaseSource(nameof(SubClientFieldsTestCases), Category = SubClientsCategory)] - public void TestBuildFields_WithSubClients(InputClient client, List expectedFields) - { - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - AssertClientFields(clientProvider, expectedFields); - } - - [TestCaseSource(nameof(BuildConstructorsTestCases))] - public void TestBuildConstructors_PrimaryConstructor(List inputParameters, int expectedCount) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - Assert.AreEqual(expectedCount, constructors.Count); - - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidatePrimaryConstructor(primaryPublicConstructor, inputParameters); - } - - [TestCaseSource(nameof(BuildConstructorsTestCases))] - public void TestBuildConstructors_SecondaryConstructor(List inputParameters, int expectedCount) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - - Assert.AreEqual(expectedCount, constructors.Count); - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - - Assert.IsNotNull(primaryPublicConstructor); - - var secondaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidateSecondaryConstructor(primaryPublicConstructor, secondaryPublicConstructor, inputParameters); - } - - [Test] - public void TestBuildConstructors_ForSubClient() - { - var clientProvider = new ClientProvider(_animalClient); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - - Assert.AreEqual(2, constructors.Count); - var internalConstructor = constructors.FirstOrDefault( - c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); - Assert.IsNotNull(internalConstructor); - var ctorParams = internalConstructor?.Signature?.Parameters; - Assert.AreEqual(2, ctorParams?.Count); // only 2 because there is no credential parameter - - var mockingConstructor = constructors.FirstOrDefault( - c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); - Assert.IsNotNull(mockingConstructor); - } - - private static void ValidatePrimaryConstructor( - ConstructorProvider? primaryPublicConstructor, - List inputParameters) - { - Assert.IsNotNull(primaryPublicConstructor); - - var primaryCtorParams = primaryPublicConstructor?.Signature?.Parameters; - - Assert.AreEqual(2, primaryCtorParams?.Count); // only 2 because there is no credential parameter - - // validate the order of the parameters (endpoint, credential, client options) - var endpointParam = primaryCtorParams?[0]; - Assert.AreEqual(KnownParameters.Endpoint.Name, endpointParam?.Name); - Assert.AreEqual("options", primaryCtorParams?[1].Name); - - if (endpointParam?.DefaultValue != null) - { - var inputEndpointParam = inputParameters.FirstOrDefault(p => p.IsEndpoint); - var parsedValue = inputEndpointParam?.DefaultValue?.Value; - Assert.AreEqual(Literal(parsedValue), endpointParam?.InitializationValue); - } - - // validate the body of the primary ctor - var primaryCtorBody = primaryPublicConstructor?.BodyStatements; - Assert.IsNotNull(primaryCtorBody); - } - - private void ValidateSecondaryConstructor( - ConstructorProvider? primaryConstructor, - ConstructorProvider? secondaryPublicConstructor, - List inputParameters) - { - Assert.IsNotNull(secondaryPublicConstructor); - var ctorParams = secondaryPublicConstructor?.Signature?.Parameters; - - // secondary ctor should consist of all required parameters + auth parameter, but here we do not have auth, therefore they should be the same - var requiredParams = inputParameters.Where(p => p.IsRequired).ToList(); - Assert.AreEqual(requiredParams.Count, ctorParams?.Count); - var endpointParam = ctorParams?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); - - if (requiredParams.Count == 0) - { - // there should be no parameter if endpoint is optional and we do not have an auth - Assert.AreEqual(0, ctorParams?.Count); - } - else - { - // otherwise, it should only consist of the endpoint parameter - Assert.AreEqual(KnownParameters.Endpoint.Name, ctorParams?[0].Name); - } - - Assert.AreEqual(MethodBodyStatement.Empty, secondaryPublicConstructor?.BodyStatements); - - // validate the initializer - var initializer = secondaryPublicConstructor?.Signature?.Initializer; - Assert.AreEqual(primaryConstructor?.Signature?.Parameters?.Count, initializer?.Arguments?.Count); - } - - [TestCaseSource(nameof(EndpointParamInitializationValueTestCases))] - public void EndpointInitializationValue(InputParameter endpointParameter, ValueExpression? expectedValue) - { - var client = InputFactory.Client(TestClientName, parameters: [endpointParameter]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - // find the endpoint parameter from the primary constructor - var primaryConstructor = clientProvider.Constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - var endpoint = primaryConstructor?.Signature?.Parameters?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); - - Assert.IsNotNull(endpoint); - Assert.AreEqual(expectedValue?.GetType(), endpoint?.InitializationValue?.GetType()); - if (expectedValue != null) - { - Assert.IsTrue(endpoint?.InitializationValue is NewInstanceExpression); - } - } - - [TestCaseSource(nameof(SubClientFactoryMethodTestCases), Category = SubClientsCategory)] - public void TestSubClientAccessorFactoryMethods(InputClient client, bool hasSubClients) - { - var clientProvider = new ClientProvider(client); - Assert.IsNotNull(clientProvider); - - var methods = clientProvider.Methods; - List subClientAccessorFactoryMethods = []; - foreach (var method in methods) - { - var methodSignature = method.Signature; - if (methodSignature != null && - methodSignature.Name.StartsWith("Get") && - methodSignature.Modifiers.HasFlag(MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual)) - { - subClientAccessorFactoryMethods.Add(method); - } - } - - if (hasSubClients) - { - Assert.AreEqual(1, subClientAccessorFactoryMethods.Count); - var factoryMethod = subClientAccessorFactoryMethods[0]; - Assert.AreEqual(0, factoryMethod.Signature?.Parameters.Count); - - // method body should not be empty - Assert.AreNotEqual(MethodBodyStatement.Empty, factoryMethod.BodyStatements); - } - else - { - Assert.AreEqual(0, subClientAccessorFactoryMethods.Count); - } - } - - public static IEnumerable BuildFieldsTestCases - { - get - { - yield return new TestCaseData(new List - { - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location:RequestLocation.None, - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }, - new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalParam") - } - ); - yield return new TestCaseData(new List - { - // have to explicitly set isRequired because we now call CreateParameter in buildFields - InputFactory.Parameter( - "optionalNullableParam", - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isRequired: false), - InputFactory.Parameter( - "requiredParam2", - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isRequired: true), - InputFactory.Parameter( - "requiredParam3", - InputPrimitiveType.Int64, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.Int64(2), - kind: InputOperationParameterKind.Client, - isRequired: true), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: null, - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }, - new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalNullableParam"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), false), "_requiredParam2"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(long), false), "_requiredParam3") - }); - } - } - - public static IEnumerable SubClientFieldsTestCases - { - get - { - yield return new TestCaseData(InputFactory.Client(TestClientName), new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private, new ExpectedCSharpType("Animal", "Sample", true), "_cachedAnimal"), - }); - yield return new TestCaseData(_animalClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private, new ExpectedCSharpType("Dog", "Sample", true), "_cachedDog"), - }); - yield return new TestCaseData(_dogClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private, new ExpectedCSharpType("Husky", "Sample", true), "_cachedHusky"), - }); - yield return new TestCaseData(_huskyClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - }); - } - } - - public static IEnumerable SubClientFactoryMethodTestCases - { - get - { - yield return new TestCaseData(InputFactory.Client(TestClientName), true); - yield return new TestCaseData(_animalClient, true); - yield return new TestCaseData(_dogClient, true); - yield return new TestCaseData(_huskyClient, false); - } - } - - public static IEnumerable BuildConstructorsTestCases - { - get - { - yield return new TestCaseData(new List - { - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }, 2); // in this case, the secondary ctor has the same ctor list as the protected ctor - // scenario where endpoint is required - yield return new TestCaseData(new List - { - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client, - isRequired: true, - isEndpoint: true), - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client) - }, 3); - } - } - - private static IEnumerable EndpointParamInitializationValueTestCases() - { - // string primitive type - yield return new TestCaseData( - InputFactory.Parameter( - "param", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client, - isEndpoint: true, - defaultValue: InputFactory.Constant.String("mockValue")), - New.Instance(KnownParameters.Endpoint.Type, Literal("mockvalue"))); - } - } + //public class ClientProviderNoAuthTests + //{ + // private const string SubClientsCategory = "WithSubClients"; + // private const string TestClientName = "TestClient"; + // private static readonly InputClient _animalClient = new("animal", "AnimalClient description", [], [], TestClientName); + // private static readonly InputClient _dogClient = new("dog", "DogClient description", [], [], _animalClient.Name); + // private static readonly InputClient _huskyClient = new("husky", "HuskyClient description", [], [], _dogClient.Name); + + // [SetUp] + // public void SetUp() + // { + // var categories = TestContext.CurrentContext.Test?.Properties["Category"]; + // bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; + + // if (containsSubClients) + // { + // MockHelpers.LoadMockPlugin( + // clients: () => [_animalClient, _dogClient, _huskyClient]); + // } + // else + // { + // MockHelpers.LoadMockPlugin(); + // } + // } + + // [Test] + // public void TestBuildProperties() + // { + // var client = InputFactory.Client(TestClientName); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // // validate the properties + // var properties = clientProvider.Properties; + // Assert.IsTrue(properties.Count > 0); + // // there should be a pipeline property + // Assert.AreEqual(1, properties.Count); + + // var pipelineProperty = properties[0]; + // Assert.AreEqual(typeof(ClientPipeline), pipelineProperty.Type.FrameworkType); + // Assert.AreEqual("Pipeline", pipelineProperty.Name); + // Assert.AreEqual(MethodSignatureModifiers.Public, pipelineProperty.Modifiers); + // } + + // [TestCaseSource(nameof(BuildFieldsTestCases))] + // public void TestBuildFields(List inputParameters, List expectedFields) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // AssertClientFields(clientProvider, expectedFields); + // } + + // // validates the fields are built correctly when a client has sub-clients + // [TestCaseSource(nameof(SubClientFieldsTestCases), Category = SubClientsCategory)] + // public void TestBuildFields_WithSubClients(InputClient client, List expectedFields) + // { + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // AssertClientFields(clientProvider, expectedFields); + // } + + // [TestCaseSource(nameof(BuildConstructorsTestCases))] + // public void TestBuildConstructors_PrimaryConstructor(List inputParameters, int expectedCount) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + // Assert.AreEqual(expectedCount, constructors.Count); + + // var primaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // ValidatePrimaryConstructor(primaryPublicConstructor, inputParameters); + // } + + // [TestCaseSource(nameof(BuildConstructorsTestCases))] + // public void TestBuildConstructors_SecondaryConstructor(List inputParameters, int expectedCount) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + + // Assert.AreEqual(expectedCount, constructors.Count); + // var primaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + + // Assert.IsNotNull(primaryPublicConstructor); + + // var secondaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // ValidateSecondaryConstructor(primaryPublicConstructor, secondaryPublicConstructor, inputParameters); + // } + + // [Test] + // public void TestBuildConstructors_ForSubClient() + // { + // var clientProvider = new ClientProvider(_animalClient); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + + // Assert.AreEqual(2, constructors.Count); + // var internalConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); + // Assert.IsNotNull(internalConstructor); + // var ctorParams = internalConstructor?.Signature?.Parameters; + // Assert.AreEqual(2, ctorParams?.Count); // only 2 because there is no credential parameter + + // var mockingConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); + // Assert.IsNotNull(mockingConstructor); + // } + + // private static void ValidatePrimaryConstructor( + // ConstructorProvider? primaryPublicConstructor, + // List inputParameters) + // { + // Assert.IsNotNull(primaryPublicConstructor); + + // var primaryCtorParams = primaryPublicConstructor?.Signature?.Parameters; + + // Assert.AreEqual(2, primaryCtorParams?.Count); // only 2 because there is no credential parameter + + // // validate the order of the parameters (endpoint, credential, client options) + // var endpointParam = primaryCtorParams?[0]; + // Assert.AreEqual(KnownParameters.Endpoint.Name, endpointParam?.Name); + // Assert.AreEqual("options", primaryCtorParams?[1].Name); + + // if (endpointParam?.DefaultValue != null) + // { + // var inputEndpointParam = inputParameters.FirstOrDefault(p => p.IsEndpoint); + // var parsedValue = inputEndpointParam?.DefaultValue?.Value; + // Assert.AreEqual(Literal(parsedValue), endpointParam?.InitializationValue); + // } + + // // validate the body of the primary ctor + // var primaryCtorBody = primaryPublicConstructor?.BodyStatements; + // Assert.IsNotNull(primaryCtorBody); + // } + + // private void ValidateSecondaryConstructor( + // ConstructorProvider? primaryConstructor, + // ConstructorProvider? secondaryPublicConstructor, + // List inputParameters) + // { + // Assert.IsNotNull(secondaryPublicConstructor); + // var ctorParams = secondaryPublicConstructor?.Signature?.Parameters; + + // // secondary ctor should consist of all required parameters + auth parameter, but here we do not have auth, therefore they should be the same + // var requiredParams = inputParameters.Where(p => p.IsRequired).ToList(); + // Assert.AreEqual(requiredParams.Count, ctorParams?.Count); + // var endpointParam = ctorParams?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); + + // if (requiredParams.Count == 0) + // { + // // there should be no parameter if endpoint is optional and we do not have an auth + // Assert.AreEqual(0, ctorParams?.Count); + // } + // else + // { + // // otherwise, it should only consist of the endpoint parameter + // Assert.AreEqual(KnownParameters.Endpoint.Name, ctorParams?[0].Name); + // } + + // Assert.AreEqual(MethodBodyStatement.Empty, secondaryPublicConstructor?.BodyStatements); + + // // validate the initializer + // var initializer = secondaryPublicConstructor?.Signature?.Initializer; + // Assert.AreEqual(primaryConstructor?.Signature?.Parameters?.Count, initializer?.Arguments?.Count); + // } + + // [TestCaseSource(nameof(EndpointParamInitializationValueTestCases))] + // public void EndpointInitializationValue(InputParameter endpointParameter, ValueExpression? expectedValue) + // { + // var client = InputFactory.Client(TestClientName, parameters: [endpointParameter]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + // // find the endpoint parameter from the primary constructor + // var primaryConstructor = clientProvider.Constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // var endpoint = primaryConstructor?.Signature?.Parameters?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); + + // Assert.IsNotNull(endpoint); + // Assert.AreEqual(expectedValue?.GetType(), endpoint?.InitializationValue?.GetType()); + // if (expectedValue != null) + // { + // Assert.IsTrue(endpoint?.InitializationValue is NewInstanceExpression); + // } + // } + + // [TestCaseSource(nameof(SubClientFactoryMethodTestCases), Category = SubClientsCategory)] + // public void TestSubClientAccessorFactoryMethods(InputClient client, bool hasSubClients) + // { + // var clientProvider = new ClientProvider(client); + // Assert.IsNotNull(clientProvider); + + // var methods = clientProvider.Methods; + // List subClientAccessorFactoryMethods = []; + // foreach (var method in methods) + // { + // var methodSignature = method.Signature; + // if (methodSignature != null && + // methodSignature.Name.StartsWith("Get") && + // methodSignature.Modifiers.HasFlag(MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual)) + // { + // subClientAccessorFactoryMethods.Add(method); + // } + // } + + // if (hasSubClients) + // { + // Assert.AreEqual(1, subClientAccessorFactoryMethods.Count); + // var factoryMethod = subClientAccessorFactoryMethods[0]; + // Assert.AreEqual(0, factoryMethod.Signature?.Parameters.Count); + + // // method body should not be empty + // Assert.AreNotEqual(MethodBodyStatement.Empty, factoryMethod.BodyStatements); + // } + // else + // { + // Assert.AreEqual(0, subClientAccessorFactoryMethods.Count); + // } + // } + + // public static IEnumerable BuildFieldsTestCases + // { + // get + // { + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location:RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }, + // new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalParam") + // } + // ); + // yield return new TestCaseData(new List + // { + // // have to explicitly set isRequired because we now call CreateParameter in buildFields + // InputFactory.Parameter( + // "optionalNullableParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isRequired: false), + // InputFactory.Parameter( + // "requiredParam2", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isRequired: true), + // InputFactory.Parameter( + // "requiredParam3", + // InputPrimitiveType.Int64, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.Int64(2), + // kind: InputOperationParameterKind.Client, + // isRequired: true), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: null, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }, + // new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalNullableParam"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), false), "_requiredParam2"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(long), false), "_requiredParam3") + // }); + // } + // } + + // public static IEnumerable SubClientFieldsTestCases + // { + // get + // { + // yield return new TestCaseData(InputFactory.Client(TestClientName), new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Animal", "Sample", true), "_cachedAnimal"), + // }); + // yield return new TestCaseData(_animalClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Dog", "Sample", true), "_cachedDog"), + // }); + // yield return new TestCaseData(_dogClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Husky", "Sample", true), "_cachedHusky"), + // }); + // yield return new TestCaseData(_huskyClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // }); + // } + // } + + // public static IEnumerable SubClientFactoryMethodTestCases + // { + // get + // { + // yield return new TestCaseData(InputFactory.Client(TestClientName), true); + // yield return new TestCaseData(_animalClient, true); + // yield return new TestCaseData(_dogClient, true); + // yield return new TestCaseData(_huskyClient, false); + // } + // } + + // public static IEnumerable BuildConstructorsTestCases + // { + // get + // { + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }, 2); // in this case, the secondary ctor has the same ctor list as the protected ctor + // // scenario where endpoint is required + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isRequired: true, + // isEndpoint: true), + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client) + // }, 3); + // } + // } + + // private static IEnumerable EndpointParamInitializationValueTestCases() + // { + // // string primitive type + // yield return new TestCaseData( + // InputFactory.Parameter( + // "param", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true, + // defaultValue: InputFactory.Constant.String("mockValue")), + // New.Instance(KnownParameters.Endpoint.Type, Literal("mockvalue"))); + // } + //} } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderOAuth2AuthTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderOAuth2AuthTests.cs index efbb7d254d..b389232ee9 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderOAuth2AuthTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderOAuth2AuthTests.cs @@ -20,440 +20,440 @@ namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.ClientProviders { - public class ClientProviderOAuth2AuthTests - { - private const string SubClientsCategory = "WithSubClients"; - private const string TestClientName = "TestClient"; - private static readonly InputClient _animalClient = new("animal", "AnimalClient description", [], [], TestClientName); - private static readonly InputClient _dogClient = new("dog", "DogClient description", [], [], _animalClient.Name); - private static readonly InputClient _huskyClient = new("husky", "HuskyClient description", [], [], _dogClient.Name); - - [SetUp] - public void SetUp() - { - var categories = TestContext.CurrentContext.Test?.Properties["Category"]; - bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; - - if (containsSubClients) - { - MockHelpers.LoadMockPlugin( - oauth2Auth: () => new InputOAuth2Auth(["mock"]), - clients: () => [_animalClient, _dogClient, _huskyClient], - clientPipelineApi: TestClientPipelineApi.Instance); - } - else - { - MockHelpers.LoadMockPlugin( - oauth2Auth: () => new InputOAuth2Auth(["mock"]), - clientPipelineApi: TestClientPipelineApi.Instance); - } - } - - [TestCaseSource(nameof(BuildFieldsTestCases))] - public void TestBuildFields(List inputParameters, List expectedFields) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - AssertClientFields(clientProvider, expectedFields); - } - - // validates the fields are built correctly when a client has sub-clients - [TestCaseSource(nameof(SubClientFieldsTestCases), Category = SubClientsCategory)] - public void TestBuildFields_WithSubClients(InputClient client, List expectedFields) - { - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - AssertClientFields(clientProvider, expectedFields); - } - - [TestCaseSource(nameof(BuildConstructorsTestCases))] - public void TestBuildConstructors_PrimaryConstructor(List inputParameters) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - Assert.AreEqual(3, constructors.Count); - - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidatePrimaryConstructor(primaryPublicConstructor, inputParameters); - } - - [TestCaseSource(nameof(BuildConstructorsTestCases))] - public void TestBuildConstructors_SecondaryConstructor(List inputParameters) - { - var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - - Assert.AreEqual(3, constructors.Count); - var primaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - - Assert.IsNotNull(primaryPublicConstructor); - - var secondaryPublicConstructor = constructors.FirstOrDefault( - c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - ValidateSecondaryConstructor(primaryPublicConstructor, secondaryPublicConstructor, inputParameters); - } - - [Test] - public void TestBuildConstructors_ForSubClient() - { - var clientProvider = new ClientProvider(_animalClient); - - Assert.IsNotNull(clientProvider); - - var constructors = clientProvider.Constructors; - - Assert.AreEqual(2, constructors.Count); - var internalConstructor = constructors.FirstOrDefault( - c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); - Assert.IsNotNull(internalConstructor); - var ctorParams = internalConstructor?.Signature?.Parameters; - Assert.AreEqual(3, ctorParams?.Count); - - var mockingConstructor = constructors.FirstOrDefault( - c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); - Assert.IsNotNull(mockingConstructor); - } - - private static void ValidatePrimaryConstructor( - ConstructorProvider? primaryPublicConstructor, - List inputParameters) - { - Assert.IsNotNull(primaryPublicConstructor); - - var primaryCtorParams = primaryPublicConstructor?.Signature?.Parameters; - var expectedPrimaryCtorParamCount = 3; - - Assert.AreEqual(expectedPrimaryCtorParamCount, primaryCtorParams?.Count); - - // validate the order of the parameters (endpoint, credential, client options) - var endpointParam = primaryCtorParams?[0]; - Assert.AreEqual(KnownParameters.Endpoint.Name, endpointParam?.Name); - Assert.AreEqual("tokenCredential", primaryCtorParams?[1].Name); - Assert.AreEqual("options", primaryCtorParams?[2].Name); - - if (endpointParam?.DefaultValue != null) - { - var inputEndpointParam = inputParameters.FirstOrDefault(p => p.IsEndpoint); - var parsedValue = inputEndpointParam?.DefaultValue?.Value; - Assert.AreEqual(Literal(parsedValue), endpointParam?.InitializationValue); - } - - // validate the body of the primary ctor - var primaryCtorBody = primaryPublicConstructor?.BodyStatements; - Assert.IsNotNull(primaryCtorBody); - } - - private void ValidateSecondaryConstructor( - ConstructorProvider? primaryConstructor, - ConstructorProvider? secondaryPublicConstructor, - List inputParameters) - { - Assert.IsNotNull(secondaryPublicConstructor); - var ctorParams = secondaryPublicConstructor?.Signature?.Parameters; - - // secondary ctor should consist of all required parameters + auth parameter - var requiredParams = inputParameters.Where(p => p.IsRequired).ToList(); - Assert.AreEqual(requiredParams.Count + 1, ctorParams?.Count); - var endpointParam = ctorParams?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); - - if (requiredParams.Count == 0) - { - // auth should be the only parameter if endpoint is optional - Assert.AreEqual("tokenCredential", ctorParams?[0].Name); - } - else - { - // otherwise, it should only consist of the auth parameter - Assert.AreEqual(KnownParameters.Endpoint.Name, ctorParams?[0].Name); - Assert.AreEqual("tokenCredential", ctorParams?[1].Name); - } - - Assert.AreEqual(MethodBodyStatement.Empty, secondaryPublicConstructor?.BodyStatements); - - // validate the initializer - var initializer = secondaryPublicConstructor?.Signature?.Initializer; - Assert.AreEqual(primaryConstructor?.Signature?.Parameters?.Count, initializer?.Arguments?.Count); - } - - [TestCaseSource(nameof(EndpointParamInitializationValueTestCases))] - public void EndpointInitializationValue(InputParameter endpointParameter, ValueExpression? expectedValue) - { - var client = InputFactory.Client(TestClientName, parameters: [endpointParameter]); - var clientProvider = new ClientProvider(client); - - Assert.IsNotNull(clientProvider); - // find the endpoint parameter from the primary constructor - var primaryConstructor = clientProvider.Constructors.FirstOrDefault( - c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); - var endpoint = primaryConstructor?.Signature?.Parameters?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); - - Assert.IsNotNull(endpoint); - Assert.AreEqual(expectedValue?.GetType(), endpoint?.InitializationValue?.GetType()); - if (expectedValue != null) - { - Assert.IsTrue(endpoint?.InitializationValue is NewInstanceExpression); - } - } - - [TestCaseSource(nameof(SubClientFactoryMethodTestCases), Category = SubClientsCategory)] - public void TestSubClientAccessorFactoryMethods(InputClient client, bool hasSubClients) - { - var clientProvider = new ClientProvider(client); - Assert.IsNotNull(clientProvider); - - var methods = clientProvider.Methods; - List subClientAccessorFactoryMethods = []; - foreach (var method in methods) - { - var methodSignature = method.Signature; - if (methodSignature != null && - methodSignature.Name.StartsWith("Get") && - methodSignature.Modifiers.HasFlag(MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual)) - { - subClientAccessorFactoryMethods.Add(method); - } - } - - if (hasSubClients) - { - Assert.AreEqual(1, subClientAccessorFactoryMethods.Count); - var factoryMethod = subClientAccessorFactoryMethods[0]; - Assert.AreEqual(0, factoryMethod.Signature?.Parameters.Count); - - // method body should not be empty - Assert.AreNotEqual(MethodBodyStatement.Empty, factoryMethod.BodyStatements); - } - else - { - Assert.AreEqual(0, subClientAccessorFactoryMethods.Count); - } - } - - public static IEnumerable BuildFieldsTestCases - { - get - { - yield return new TestCaseData(new List - { - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location:RequestLocation.None, - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }, - new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalParam") - } - ); - yield return new TestCaseData(new List - { - // have to explicitly set isRequired because we now call CreateParameter in buildFields - InputFactory.Parameter( - "optionalNullableParam", - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isRequired: false), - InputFactory.Parameter( - "requiredParam2", - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isRequired: true), - InputFactory.Parameter( - "requiredParam3", - InputPrimitiveType.Int64, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.Int64(2), - kind: InputOperationParameterKind.Client, - isRequired: true), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: null, - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }, - new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalNullableParam"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), false), "_requiredParam2"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(long), false), "_requiredParam3") - }); - } - } - - public static IEnumerable SubClientFieldsTestCases - { - get - { - yield return new TestCaseData(InputFactory.Client(TestClientName), new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), - new(FieldModifiers.Private, new ExpectedCSharpType("Animal", "Sample", true), "_cachedAnimal"), - }); - yield return new TestCaseData(_animalClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), - new(FieldModifiers.Private, new ExpectedCSharpType("Dog", "Sample", true), "_cachedDog"), - }); - yield return new TestCaseData(_dogClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), - new(FieldModifiers.Private, new ExpectedCSharpType("Husky", "Sample", true), "_cachedHusky"), - }); - yield return new TestCaseData(_huskyClient, new List - { - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), - new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), - new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential") - }); - } - } - - public static IEnumerable SubClientFactoryMethodTestCases - { - get - { - yield return new TestCaseData(InputFactory.Client(TestClientName), true); - yield return new TestCaseData(_animalClient, true); - yield return new TestCaseData(_dogClient, true); - yield return new TestCaseData(_huskyClient, false); - } - } - - public static IEnumerable BuildConstructorsTestCases - { - get - { - yield return new TestCaseData(new List - { - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client), - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - defaultValue: InputFactory.Constant.String("someValue"), - kind: InputOperationParameterKind.Client, - isEndpoint: true) - }); - // scenario where endpoint is required - yield return new TestCaseData(new List - { - InputFactory.Parameter( - KnownParameters.Endpoint.Name, - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client, - isRequired: true, - isEndpoint: true), - InputFactory.Parameter( - "optionalParam", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client) - }); - } - } - - private static IEnumerable EndpointParamInitializationValueTestCases() - { - // string primitive type - yield return new TestCaseData( - InputFactory.Parameter( - "param", - InputPrimitiveType.String, - location: RequestLocation.None, - kind: InputOperationParameterKind.Client, - isEndpoint: true, - defaultValue: InputFactory.Constant.String("mockValue")), - New.Instance(KnownParameters.Endpoint.Type, Literal("mockvalue"))); - } - - private record TestClientPipelineApi : ClientPipelineApi - { - private static ClientPipelineApi? _instance; - internal static ClientPipelineApi Instance => _instance ??= new TestClientPipelineApi(Empty); - - public TestClientPipelineApi(ValueExpression original) : base(typeof(string), original) - { - } - - public override CSharpType ClientPipelineType => typeof(string); - - public override CSharpType ClientPipelineOptionsType => typeof(string); - - public override CSharpType PipelinePolicyType => typeof(string); - - public override CSharpType? KeyCredentialType => null; - - public override CSharpType TokenCredentialType => typeof(TestTokenCredential); - - public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies) - => Original.Invoke("GetFakeCreate", [options, perRetryPolicies]); - - public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier) - => Original.Invoke("GetFakeCreateMessage", [requestOptions, responseClassifier]); - - public override ClientPipelineApi FromExpression(ValueExpression expression) - => new TestClientPipelineApi(expression); - - public override ValueExpression ConsumeKeyAuth(ValueExpression credential, ValueExpression headerName, ValueExpression? keyPrefix = null) - => throw new InvalidOperationException("ApiKey is not supported in this test"); - - public override ValueExpression ConsumeOAuth2Auth(ValueExpression credential, ValueExpression scopes) - => Original.Invoke("GetFakeTokenAuthorizationPolicy", [credential, scopes]); - - public override ClientPipelineApi ToExpression() => this; - - public override MethodBodyStatement[] ProcessMessage(HttpMessageApi message, HttpRequestOptionsApi options) - => [Original.Invoke("GetFakeProcessMessage", [message, options]).Terminate()]; - - public override MethodBodyStatement[] ProcessMessageAsync(HttpMessageApi message, HttpRequestOptionsApi options) - => [Original.Invoke("GetFakeProcessMessageAsync", [message, options]).Terminate()]; - } - - internal class TestTokenCredential { } - } + //public class ClientProviderOAuth2AuthTests + //{ + // private const string SubClientsCategory = "WithSubClients"; + // private const string TestClientName = "TestClient"; + // private static readonly InputClient _animalClient = new("animal", "AnimalClient description", [], [], TestClientName); + // private static readonly InputClient _dogClient = new("dog", "DogClient description", [], [], _animalClient.Name); + // private static readonly InputClient _huskyClient = new("husky", "HuskyClient description", [], [], _dogClient.Name); + + // [SetUp] + // public void SetUp() + // { + // var categories = TestContext.CurrentContext.Test?.Properties["Category"]; + // bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; + + // if (containsSubClients) + // { + // MockHelpers.LoadMockPlugin( + // oauth2Auth: () => new InputOAuth2Auth(["mock"]), + // clients: () => [_animalClient, _dogClient, _huskyClient], + // clientPipelineApi: TestClientPipelineApi.Instance); + // } + // else + // { + // MockHelpers.LoadMockPlugin( + // oauth2Auth: () => new InputOAuth2Auth(["mock"]), + // clientPipelineApi: TestClientPipelineApi.Instance); + // } + // } + + // [TestCaseSource(nameof(BuildFieldsTestCases))] + // public void TestBuildFields(List inputParameters, List expectedFields) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // AssertClientFields(clientProvider, expectedFields); + // } + + // // validates the fields are built correctly when a client has sub-clients + // [TestCaseSource(nameof(SubClientFieldsTestCases), Category = SubClientsCategory)] + // public void TestBuildFields_WithSubClients(InputClient client, List expectedFields) + // { + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // AssertClientFields(clientProvider, expectedFields); + // } + + // [TestCaseSource(nameof(BuildConstructorsTestCases))] + // public void TestBuildConstructors_PrimaryConstructor(List inputParameters) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + // Assert.AreEqual(3, constructors.Count); + + // var primaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // ValidatePrimaryConstructor(primaryPublicConstructor, inputParameters); + // } + + // [TestCaseSource(nameof(BuildConstructorsTestCases))] + // public void TestBuildConstructors_SecondaryConstructor(List inputParameters) + // { + // var client = InputFactory.Client(TestClientName, parameters: [.. inputParameters]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + + // Assert.AreEqual(3, constructors.Count); + // var primaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + + // Assert.IsNotNull(primaryPublicConstructor); + + // var secondaryPublicConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Initializer != null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // ValidateSecondaryConstructor(primaryPublicConstructor, secondaryPublicConstructor, inputParameters); + // } + + // [Test] + // public void TestBuildConstructors_ForSubClient() + // { + // var clientProvider = new ClientProvider(_animalClient); + + // Assert.IsNotNull(clientProvider); + + // var constructors = clientProvider.Constructors; + + // Assert.AreEqual(2, constructors.Count); + // var internalConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Modifiers == MethodSignatureModifiers.Internal); + // Assert.IsNotNull(internalConstructor); + // var ctorParams = internalConstructor?.Signature?.Parameters; + // Assert.AreEqual(3, ctorParams?.Count); + + // var mockingConstructor = constructors.FirstOrDefault( + // c => c.Signature?.Modifiers == MethodSignatureModifiers.Protected); + // Assert.IsNotNull(mockingConstructor); + // } + + // private static void ValidatePrimaryConstructor( + // ConstructorProvider? primaryPublicConstructor, + // List inputParameters) + // { + // Assert.IsNotNull(primaryPublicConstructor); + + // var primaryCtorParams = primaryPublicConstructor?.Signature?.Parameters; + // var expectedPrimaryCtorParamCount = 3; + + // Assert.AreEqual(expectedPrimaryCtorParamCount, primaryCtorParams?.Count); + + // // validate the order of the parameters (endpoint, credential, client options) + // var endpointParam = primaryCtorParams?[0]; + // Assert.AreEqual(KnownParameters.Endpoint.Name, endpointParam?.Name); + // Assert.AreEqual("tokenCredential", primaryCtorParams?[1].Name); + // Assert.AreEqual("options", primaryCtorParams?[2].Name); + + // if (endpointParam?.DefaultValue != null) + // { + // var inputEndpointParam = inputParameters.FirstOrDefault(p => p.IsEndpoint); + // var parsedValue = inputEndpointParam?.DefaultValue?.Value; + // Assert.AreEqual(Literal(parsedValue), endpointParam?.InitializationValue); + // } + + // // validate the body of the primary ctor + // var primaryCtorBody = primaryPublicConstructor?.BodyStatements; + // Assert.IsNotNull(primaryCtorBody); + // } + + // private void ValidateSecondaryConstructor( + // ConstructorProvider? primaryConstructor, + // ConstructorProvider? secondaryPublicConstructor, + // List inputParameters) + // { + // Assert.IsNotNull(secondaryPublicConstructor); + // var ctorParams = secondaryPublicConstructor?.Signature?.Parameters; + + // // secondary ctor should consist of all required parameters + auth parameter + // var requiredParams = inputParameters.Where(p => p.IsRequired).ToList(); + // Assert.AreEqual(requiredParams.Count + 1, ctorParams?.Count); + // var endpointParam = ctorParams?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); + + // if (requiredParams.Count == 0) + // { + // // auth should be the only parameter if endpoint is optional + // Assert.AreEqual("tokenCredential", ctorParams?[0].Name); + // } + // else + // { + // // otherwise, it should only consist of the auth parameter + // Assert.AreEqual(KnownParameters.Endpoint.Name, ctorParams?[0].Name); + // Assert.AreEqual("tokenCredential", ctorParams?[1].Name); + // } + + // Assert.AreEqual(MethodBodyStatement.Empty, secondaryPublicConstructor?.BodyStatements); + + // // validate the initializer + // var initializer = secondaryPublicConstructor?.Signature?.Initializer; + // Assert.AreEqual(primaryConstructor?.Signature?.Parameters?.Count, initializer?.Arguments?.Count); + // } + + // [TestCaseSource(nameof(EndpointParamInitializationValueTestCases))] + // public void EndpointInitializationValue(InputParameter endpointParameter, ValueExpression? expectedValue) + // { + // var client = InputFactory.Client(TestClientName, parameters: [endpointParameter]); + // var clientProvider = new ClientProvider(client); + + // Assert.IsNotNull(clientProvider); + // // find the endpoint parameter from the primary constructor + // var primaryConstructor = clientProvider.Constructors.FirstOrDefault( + // c => c.Signature?.Initializer == null && c.Signature?.Modifiers == MethodSignatureModifiers.Public); + // var endpoint = primaryConstructor?.Signature?.Parameters?.FirstOrDefault(p => p.Name == KnownParameters.Endpoint.Name); + + // Assert.IsNotNull(endpoint); + // Assert.AreEqual(expectedValue?.GetType(), endpoint?.InitializationValue?.GetType()); + // if (expectedValue != null) + // { + // Assert.IsTrue(endpoint?.InitializationValue is NewInstanceExpression); + // } + // } + + // [TestCaseSource(nameof(SubClientFactoryMethodTestCases), Category = SubClientsCategory)] + // public void TestSubClientAccessorFactoryMethods(InputClient client, bool hasSubClients) + // { + // var clientProvider = new ClientProvider(client); + // Assert.IsNotNull(clientProvider); + + // var methods = clientProvider.Methods; + // List subClientAccessorFactoryMethods = []; + // foreach (var method in methods) + // { + // var methodSignature = method.Signature; + // if (methodSignature != null && + // methodSignature.Name.StartsWith("Get") && + // methodSignature.Modifiers.HasFlag(MethodSignatureModifiers.Public | MethodSignatureModifiers.Virtual)) + // { + // subClientAccessorFactoryMethods.Add(method); + // } + // } + + // if (hasSubClients) + // { + // Assert.AreEqual(1, subClientAccessorFactoryMethods.Count); + // var factoryMethod = subClientAccessorFactoryMethods[0]; + // Assert.AreEqual(0, factoryMethod.Signature?.Parameters.Count); + + // // method body should not be empty + // Assert.AreNotEqual(MethodBodyStatement.Empty, factoryMethod.BodyStatements); + // } + // else + // { + // Assert.AreEqual(0, subClientAccessorFactoryMethods.Count); + // } + // } + + // public static IEnumerable BuildFieldsTestCases + // { + // get + // { + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location:RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }, + // new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalParam") + // } + // ); + // yield return new TestCaseData(new List + // { + // // have to explicitly set isRequired because we now call CreateParameter in buildFields + // InputFactory.Parameter( + // "optionalNullableParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isRequired: false), + // InputFactory.Parameter( + // "requiredParam2", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isRequired: true), + // InputFactory.Parameter( + // "requiredParam3", + // InputPrimitiveType.Int64, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.Int64(2), + // kind: InputOperationParameterKind.Client, + // isRequired: true), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: null, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }, + // new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), true), "_optionalNullableParam"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(string), false), "_requiredParam2"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(long), false), "_requiredParam3") + // }); + // } + // } + + // public static IEnumerable SubClientFieldsTestCases + // { + // get + // { + // yield return new TestCaseData(InputFactory.Client(TestClientName), new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Animal", "Sample", true), "_cachedAnimal"), + // }); + // yield return new TestCaseData(_animalClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Dog", "Sample", true), "_cachedDog"), + // }); + // yield return new TestCaseData(_dogClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential"), + // new(FieldModifiers.Private, new ExpectedCSharpType("Husky", "Sample", true), "_cachedHusky"), + // }); + // yield return new TestCaseData(_huskyClient, new List + // { + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(Uri)), "_endpoint"), + // new(FieldModifiers.Private | FieldModifiers.Const, new CSharpType(typeof(string[])), "AuthorizationScopes"), + // new(FieldModifiers.Private | FieldModifiers.ReadOnly, new CSharpType(typeof(TestTokenCredential)), "_tokenCredential") + // }); + // } + // } + + // public static IEnumerable SubClientFactoryMethodTestCases + // { + // get + // { + // yield return new TestCaseData(InputFactory.Client(TestClientName), true); + // yield return new TestCaseData(_animalClient, true); + // yield return new TestCaseData(_dogClient, true); + // yield return new TestCaseData(_huskyClient, false); + // } + // } + + // public static IEnumerable BuildConstructorsTestCases + // { + // get + // { + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client), + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // defaultValue: InputFactory.Constant.String("someValue"), + // kind: InputOperationParameterKind.Client, + // isEndpoint: true) + // }); + // // scenario where endpoint is required + // yield return new TestCaseData(new List + // { + // InputFactory.Parameter( + // KnownParameters.Endpoint.Name, + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isRequired: true, + // isEndpoint: true), + // InputFactory.Parameter( + // "optionalParam", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client) + // }); + // } + // } + + // private static IEnumerable EndpointParamInitializationValueTestCases() + // { + // // string primitive type + // yield return new TestCaseData( + // InputFactory.Parameter( + // "param", + // InputPrimitiveType.String, + // location: RequestLocation.None, + // kind: InputOperationParameterKind.Client, + // isEndpoint: true, + // defaultValue: InputFactory.Constant.String("mockValue")), + // New.Instance(KnownParameters.Endpoint.Type, Literal("mockvalue"))); + // } + + // private record TestClientPipelineApi : ClientPipelineApi + // { + // private static ClientPipelineApi? _instance; + // internal static ClientPipelineApi Instance => _instance ??= new TestClientPipelineApi(Empty); + + // public TestClientPipelineApi(ValueExpression original) : base(typeof(string), original) + // { + // } + + // public override CSharpType ClientPipelineType => typeof(string); + + // public override CSharpType ClientPipelineOptionsType => typeof(string); + + // public override CSharpType PipelinePolicyType => typeof(string); + + // public override CSharpType? KeyCredentialType => null; + + // public override CSharpType TokenCredentialType => typeof(TestTokenCredential); + + // public override ValueExpression Create(ValueExpression options, ValueExpression perRetryPolicies) + // => Original.Invoke("GetFakeCreate", [options, perRetryPolicies]); + + // public override ValueExpression CreateMessage(HttpRequestOptionsApi requestOptions, ValueExpression responseClassifier) + // => Original.Invoke("GetFakeCreateMessage", [requestOptions, responseClassifier]); + + // public override ClientPipelineApi FromExpression(ValueExpression expression) + // => new TestClientPipelineApi(expression); + + // public override ValueExpression ConsumeKeyAuth(ValueExpression credential, ValueExpression headerName, ValueExpression? keyPrefix = null) + // => throw new InvalidOperationException("ApiKey is not supported in this test"); + + // public override ValueExpression ConsumeOAuth2Auth(ValueExpression credential, ValueExpression scopes) + // => Original.Invoke("GetFakeTokenAuthorizationPolicy", [credential, scopes]); + + // public override ClientPipelineApi ToExpression() => this; + + // public override MethodBodyStatement[] ProcessMessage(HttpMessageApi message, HttpRequestOptionsApi options) + // => [Original.Invoke("GetFakeProcessMessage", [message, options]).Terminate()]; + + // public override MethodBodyStatement[] ProcessMessageAsync(HttpMessageApi message, HttpRequestOptionsApi options) + // => [Original.Invoke("GetFakeProcessMessageAsync", [message, options]).Terminate()]; + // } + + // internal class TestTokenCredential { } + //} } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs index 62f863574c..4f22943e05 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderTests.cs @@ -33,6 +33,23 @@ public class ClientProviderTests InputFactory.Property("p1", InputPrimitiveType.String, isRequired: true), ]); + [SetUp] + public void SetUp() + { + var categories = TestContext.CurrentContext.Test?.Properties["Category"]; + bool containsSubClients = categories?.Contains(SubClientsCategory) ?? false; + if (containsSubClients) + { + MockHelpers.LoadMockPlugin( + apiKeyAuth: () => new InputApiKeyAuth("mock", null), + clients: () => [_animalClient, _dogClient, _huskyClient]); + } + else + { + MockHelpers.LoadMockPlugin(apiKeyAuth: () => new InputApiKeyAuth("mock", null)); + } + } + [Test] public void TestBuildProperties() {