From 533cb75f3de1bdc7476f4dbc645cc52abda8ba15 Mon Sep 17 00:00:00 2001
From: Jorge Rangel <102122018+jorgerangel-msft@users.noreply.github.com>
Date: Tue, 1 Oct 2024 11:02:37 -0500
Subject: [PATCH] Add tests for adding custom client method (#4578)
This PR adds unit tests for adding custom client methods.
fixes: https://github.com/microsoft/typespec/issues/4262
---
.../ClientProviderCustomizationTests.cs | 118 ++++++++++++++++++
.../CanAddMethod/CanAddMethod.cs | 25 ++++
.../CanAddMethodSameName.cs | 22 ++++
.../CanAddMultipleMethods.cs | 32 +++++
.../test/TestHelpers/MockHelpers.cs | 6 +-
.../src/Providers/TypeProvider.cs | 2 +-
6 files changed, 203 insertions(+), 2 deletions(-)
create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderCustomizationTests.cs
create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethod/CanAddMethod.cs
create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethodSameName/CanAddMethodSameName.cs
create mode 100644 packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMultipleMethods/CanAddMultipleMethods.cs
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderCustomizationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderCustomizationTests.cs
new file mode 100644
index 0000000000..b4fae5cbc3
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderCustomizationTests.cs
@@ -0,0 +1,118 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System;
+using System.ClientModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Generator.CSharp.ClientModel.Providers;
+using Microsoft.Generator.CSharp.Input;
+using Microsoft.Generator.CSharp.Tests.Common;
+using NUnit.Framework;
+
+namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers.ClientProviders
+{
+ public class ClientProviderCustomizationTests
+ {
+ [Test]
+ public async Task CanAddMethod()
+ {
+ var inputOperation = InputFactory.Operation("HelloAgain", parameters:
+ [
+ InputFactory.Parameter("p1", InputFactory.Array(InputPrimitiveType.String))
+ ]);
+ var inputClient = InputFactory.Client("TestClient", operations: [inputOperation]);
+ var plugin = await MockHelpers.LoadMockPluginAsync(
+ clients: () => [inputClient],
+ compilation: async () => await Helpers.GetCompilationFromDirectoryAsync());
+
+ // Find the client provider
+ var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider);
+ Assert.IsNotNull(clientProvider);
+
+ var clientProviderMethods = clientProvider!.Methods;
+ Assert.AreEqual(4, clientProviderMethods.Count);
+ Assert.IsFalse(clientProviderMethods.Any(m => m.Signature.Name == "NewMethod"));
+
+ // The custom code view should contain the method
+ var customCodeView = clientProvider.CustomCodeView;
+ Assert.IsNotNull(customCodeView);
+ var customMethods = customCodeView!.Methods;
+ Assert.AreEqual(1, customMethods.Count);
+ Assert.AreEqual("NewMethod", customMethods[0].Signature.Name);
+ Assert.AreEqual(customMethods[0].Signature.Parameters.Count, 2);
+ Assert.IsNull(customMethods[0].BodyExpression);
+ Assert.AreEqual(string.Empty, customMethods[0].BodyStatements!.ToDisplayString());
+ }
+
+ [Test]
+ public async Task CanAddMultipleMethods()
+ {
+ var inputOperation = InputFactory.Operation("HelloAgain", parameters:
+ [
+ InputFactory.Parameter("p1", InputFactory.Array(InputPrimitiveType.String))
+ ]);
+ var inputClient = InputFactory.Client("TestClient", operations: [inputOperation]);
+ var plugin = await MockHelpers.LoadMockPluginAsync(
+ clients: () => [inputClient],
+ compilation: async () => await Helpers.GetCompilationFromDirectoryAsync());
+
+ // Find the client provider
+ var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider);
+ Assert.IsNotNull(clientProvider);
+
+ var clientProviderMethods = clientProvider!.Methods;
+ Assert.AreEqual(4, clientProviderMethods.Count);
+
+ // The custom code view should contain the method
+ var customCodeView = clientProvider.CustomCodeView;
+ Assert.IsNotNull(customCodeView);
+ var customMethods = customCodeView!.Methods;
+ Assert.AreEqual(4, customMethods.Count);
+ Assert.AreEqual("NewMethodOne", customMethods[0].Signature.Name);
+ Assert.AreEqual(customMethods[0].Signature.Parameters.Count, 2);
+ Assert.AreEqual("NewMethodTwo", customMethods[1].Signature.Name);
+ Assert.AreEqual(customMethods[1].Signature.Parameters.Count, 0);
+ Assert.AreEqual("NewMethodThree", customMethods[2].Signature.Name);
+ Assert.AreEqual(customMethods[2].Signature.Parameters.Count, 1);
+ Assert.AreEqual("NewMethodFour", customMethods[3].Signature.Name);
+ Assert.AreEqual(customMethods[3].Signature.Parameters.Count, 1);
+ }
+
+ // Validates that the custom method is added when the method has the same name as an existing method but different parameters
+ [Test]
+ public async Task CanAddMethodSameName()
+ {
+ var inputOperation = InputFactory.Operation("HelloAgain", parameters:
+ [
+ InputFactory.Parameter("p1", InputFactory.Array(InputPrimitiveType.String))
+ ]);
+ var inputClient = InputFactory.Client("TestClient", operations: [inputOperation]);
+ var plugin = await MockHelpers.LoadMockPluginAsync(
+ clients: () => [inputClient],
+ compilation: async () => await Helpers.GetCompilationFromDirectoryAsync());
+
+ // Find the client provider
+ var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider);
+ Assert.IsNotNull(clientProvider);
+
+ var clientProviderMethods = clientProvider!.Methods;
+ Assert.AreEqual(4, clientProviderMethods.Count);
+
+ var helloAgainMethod = clientProviderMethods.FirstOrDefault(m
+ => m.Signature.Name == "HelloAgain" && m.Signature.Parameters.Count > 0 && m.Signature.Parameters[0].Name == "p1");
+ Assert.IsNotNull(helloAgainMethod);
+ Assert.AreEqual(1, helloAgainMethod!.Signature.Parameters.Count);
+
+ // The custom code view should contain the method
+ var customCodeView = clientProvider.CustomCodeView;
+ Assert.IsNotNull(customCodeView);
+ var customMethods = customCodeView!.Methods;
+ Assert.AreEqual(1, customMethods.Count);
+ Assert.AreEqual("HelloAgain", customMethods[0].Signature.Name);
+ Assert.AreEqual(customMethods[0].Signature.Parameters.Count, 2);
+ Assert.IsNull(customMethods[0].BodyExpression);
+ Assert.AreEqual(string.Empty, customMethods[0].BodyStatements!.ToDisplayString());
+ }
+ }
+}
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethod/CanAddMethod.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethod/CanAddMethod.cs
new file mode 100644
index 0000000000..4bb20ab75f
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethod/CanAddMethod.cs
@@ -0,0 +1,25 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel;
+using System.ClientModel.Primitives;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Sample
+{
+ ///
+ public partial class TestClient
+ {
+ public virtual ClientResult NewMethod(BinaryContent content, RequestOptions options)
+ {
+ Argument.AssertNotNull(content, nameof(content));
+
+ using PipelineMessage message = CreateRequest(content, options);
+ return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options));
+ }
+ }
+}
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethodSameName/CanAddMethodSameName.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethodSameName/CanAddMethodSameName.cs
new file mode 100644
index 0000000000..750bbb18f1
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMethodSameName/CanAddMethodSameName.cs
@@ -0,0 +1,22 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel;
+using System.ClientModel.Primitives;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Sample
+{
+ ///
+ public partial class TestClient
+ {
+ public virtual ClientResult HelloAgain(string[] p1, RequestOptions options)
+ {
+
+ }
+ }
+}
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMultipleMethods/CanAddMultipleMethods.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMultipleMethods/CanAddMultipleMethods.cs
new file mode 100644
index 0000000000..17e0e7e9ff
--- /dev/null
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/TestData/ClientProviderCustomizationTests/CanAddMultipleMethods/CanAddMultipleMethods.cs
@@ -0,0 +1,32 @@
+//
+
+#nullable disable
+
+using System;
+using System.ClientModel;
+using System.ClientModel.Primitives;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Sample
+{
+ ///
+ public partial class TestClient
+ {
+ public virtual ClientResult NewMethodOne(BinaryContent content, RequestOptions options)
+ {
+ Argument.AssertNotNull(content, nameof(content));
+
+ using PipelineMessage message = CreateRequest(content, options);
+ return ClientResult.FromResponse(Pipeline.ProcessMessage(message, options));
+ }
+
+ public void NewMethodTwo() { }
+
+ public void NewMethodThree(CustomModel p1) { }
+ public bool NewMethodFour(CustomModel? p1) { return false; }
+ }
+
+ public class CustomModel { }
+}
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs
index a16c7c47e0..0c9c14cd5a 100644
--- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/TestHelpers/MockHelpers.cs
@@ -25,9 +25,13 @@ internal static class MockHelpers
public static async Task> LoadMockPluginAsync(
Func>? inputEnums = null,
Func>? inputModels = null,
+ Func>? clients = null,
Func>? compilation = null)
{
- var mockPlugin = LoadMockPlugin(inputEnums: inputEnums, inputModels: inputModels);
+ var mockPlugin = LoadMockPlugin(
+ inputEnums: inputEnums,
+ inputModels: inputModels,
+ clients: clients);
var compilationResult = compilation == null ? null : await compilation();
diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs
index 00f4b78510..d70019b3d3 100644
--- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs
+++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs
@@ -424,7 +424,7 @@ private static bool IsMatch(TypeProvider enclosingType, MethodSignatureBase sign
private static bool IsMatch(MethodSignatureBase customMethod, MethodSignatureBase method)
{
- if (customMethod.Parameters.Count != method.Parameters.Count)
+ if (customMethod.Parameters.Count != method.Parameters.Count || customMethod.Name != method.Name)
{
return false;
}