Skip to content

Commit 8a029e2

Browse files
committed
Adding ctor for init on function metadata
1 parent 88582e6 commit 8a029e2

File tree

2 files changed

+185
-0
lines changed

2 files changed

+185
-0
lines changed

dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunctionMetadata.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,37 @@ public KernelFunctionMetadata(string name)
3434
this.Name = name;
3535
}
3636

37+
/// <summary>Initializes the <see cref="KernelFunctionMetadata"/> with all properties.</summary>
38+
/// <param name="name">The name of the function.</param>
39+
/// <param name="pluginName">The name of the plugin containing the function.</param>
40+
/// <param name="description">The description of the function.</param>
41+
/// <param name="parameters">The metadata for the parameters to the function.</param>
42+
/// <param name="returnParameter">The metadata for the return parameter.</param>
43+
/// <param name="additionalProperties">Optional metadata in addition to the named properties.</param>
44+
/// <exception cref="ArgumentNullException">The <paramref name="name"/> was null.</exception>
45+
/// <exception cref="ArgumentException">An invalid name was supplied.</exception>
46+
public KernelFunctionMetadata(
47+
string name,
48+
string? pluginName = null,
49+
string? description = null,
50+
IReadOnlyList<KernelParameterMetadata>? parameters = null,
51+
KernelReturnParameterMetadata? returnParameter = null,
52+
ReadOnlyDictionary<string, object?>? additionalProperties = null)
53+
: this(name)
54+
{
55+
this.PluginName = pluginName;
56+
this.Description = description;
57+
this.Parameters = parameters ?? [];
58+
if (returnParameter is not null)
59+
{
60+
this.ReturnParameter = returnParameter;
61+
}
62+
if (additionalProperties is not null)
63+
{
64+
this.AdditionalProperties = additionalProperties;
65+
}
66+
}
67+
3768
/// <summary>Initializes a <see cref="KernelFunctionMetadata"/> as a copy of another <see cref="KernelFunctionMetadata"/>.</summary>
3869
/// <exception cref="ArgumentNullException">The <paramref name="metadata"/> was null.</exception>
3970
/// <remarks>

dotnet/src/SemanticKernel.UnitTests/Functions/KernelFunctionMetadataTests.cs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) Microsoft. All rights reserved.
22

3+
using System;
34
using System.Collections.Generic;
45
using System.Collections.ObjectModel;
56
using System.ComponentModel;
@@ -232,6 +233,159 @@ public void CopyConstructorCopiesPropertiesValues()
232233
Assert.Equal(original.ReturnParameter, copy.ReturnParameter);
233234
}
234235

236+
[Fact]
237+
public void ItCanBeConstructedWithAllParameters()
238+
{
239+
// Test the new constructor that accepts all parameters
240+
var parameters = new List<KernelParameterMetadata>
241+
{
242+
new("param1", "First parameter", "default1", true, typeof(string)),
243+
new("param2", "Second parameter", 42, false, typeof(int))
244+
};
245+
var returnParameter = new KernelReturnParameterMetadata("Return description", typeof(bool));
246+
var additionalProperties = new ReadOnlyDictionary<string, object?>(new Dictionary<string, object?>
247+
{
248+
{ "method", "GET" },
249+
{ "endpoint", "/test" }
250+
});
251+
252+
var metadata = new KernelFunctionMetadata(
253+
name: "TestFunction",
254+
pluginName: "TestPlugin",
255+
description: "Test function description",
256+
parameters: parameters,
257+
returnParameter: returnParameter,
258+
additionalProperties: additionalProperties);
259+
260+
Assert.Equal("TestFunction", metadata.Name);
261+
Assert.Equal("TestPlugin", metadata.PluginName);
262+
Assert.Equal("Test function description", metadata.Description);
263+
Assert.Equal(parameters, metadata.Parameters);
264+
Assert.Equal(returnParameter, metadata.ReturnParameter);
265+
Assert.Equal(additionalProperties, metadata.AdditionalProperties);
266+
}
267+
268+
[Fact]
269+
public void ItUsesDefaultValuesInNewConstructor()
270+
{
271+
// Test that optional parameters have correct default values
272+
var metadata = new KernelFunctionMetadata("TestFunction");
273+
274+
Assert.Equal("TestFunction", metadata.Name);
275+
Assert.Null(metadata.PluginName);
276+
Assert.Empty(metadata.Description);
277+
Assert.Empty(metadata.Parameters);
278+
Assert.NotNull(metadata.ReturnParameter); // Should be default empty instance
279+
Assert.Empty(metadata.AdditionalProperties);
280+
}
281+
282+
[Fact]
283+
public void ItThrowsForInvalidNameInNewConstructor()
284+
{
285+
// Test that the new constructor still validates the name parameter
286+
Assert.Throws<ArgumentNullException>(() => new KernelFunctionMetadata(null!, "plugin"));
287+
Assert.Throws<ArgumentException>(() => new KernelFunctionMetadata("", "plugin"));
288+
Assert.Throws<ArgumentException>(() => new KernelFunctionMetadata(" ", "plugin"));
289+
Assert.Throws<ArgumentException>(() => new KernelFunctionMetadata("invalid-name!", "plugin"));
290+
}
291+
292+
[Fact]
293+
public void ItHandlesNullDescriptionInNewConstructor()
294+
{
295+
// Test that null description is handled correctly
296+
var metadata = new KernelFunctionMetadata(
297+
name: "TestFunction",
298+
pluginName: "TestPlugin",
299+
description: null);
300+
301+
Assert.Equal("TestFunction", metadata.Name);
302+
Assert.Equal("TestPlugin", metadata.PluginName);
303+
Assert.Empty(metadata.Description); // null description should become empty string
304+
}
305+
306+
[Fact]
307+
public void ItHandlesNullParametersInNewConstructor()
308+
{
309+
// Test that null parameters list is handled correctly
310+
var metadata = new KernelFunctionMetadata(
311+
name: "TestFunction",
312+
parameters: null);
313+
314+
Assert.Equal("TestFunction", metadata.Name);
315+
Assert.Empty(metadata.Parameters); // null parameters should become empty list
316+
}
317+
318+
[Fact]
319+
public void ItHandlesNullReturnParameterInNewConstructor()
320+
{
321+
// Test that null return parameter is handled correctly
322+
var metadata = new KernelFunctionMetadata(
323+
name: "TestFunction",
324+
returnParameter: null);
325+
326+
Assert.Equal("TestFunction", metadata.Name);
327+
Assert.NotNull(metadata.ReturnParameter); // Should use default empty instance
328+
Assert.Empty(metadata.ReturnParameter.Description);
329+
}
330+
331+
[Fact]
332+
public void ItHandlesNullAdditionalPropertiesInNewConstructor()
333+
{
334+
// Test that null additional properties is handled correctly
335+
var metadata = new KernelFunctionMetadata(
336+
name: "TestFunction",
337+
additionalProperties: null);
338+
339+
Assert.Equal("TestFunction", metadata.Name);
340+
Assert.Empty(metadata.AdditionalProperties); // Should use default empty dictionary
341+
}
342+
343+
[Fact]
344+
public void ItCanBeConstructedWithOnlyNameAndDescription()
345+
{
346+
// Test constructor with only name and description
347+
var metadata = new KernelFunctionMetadata(
348+
name: "TestFunction",
349+
description: "Test description");
350+
351+
Assert.Equal("TestFunction", metadata.Name);
352+
Assert.Null(metadata.PluginName);
353+
Assert.Equal("Test description", metadata.Description);
354+
Assert.Empty(metadata.Parameters);
355+
Assert.NotNull(metadata.ReturnParameter);
356+
Assert.Empty(metadata.AdditionalProperties);
357+
}
358+
359+
[Fact]
360+
public void ItCanBeConstructedWithNameAndPluginName()
361+
{
362+
// Test constructor with name and plugin name
363+
var metadata = new KernelFunctionMetadata(
364+
name: "TestFunction",
365+
pluginName: "TestPlugin");
366+
367+
Assert.Equal("TestFunction", metadata.Name);
368+
Assert.Equal("TestPlugin", metadata.PluginName);
369+
Assert.Empty(metadata.Description);
370+
Assert.Empty(metadata.Parameters);
371+
Assert.NotNull(metadata.ReturnParameter);
372+
Assert.Empty(metadata.AdditionalProperties);
373+
}
374+
375+
[Fact]
376+
public void ItCanBeConstructedWithEmptyParametersList()
377+
{
378+
// Test constructor with explicitly empty parameters list
379+
var emptyParameters = new List<KernelParameterMetadata>();
380+
var metadata = new KernelFunctionMetadata(
381+
name: "TestFunction",
382+
parameters: emptyParameters);
383+
384+
Assert.Equal("TestFunction", metadata.Name);
385+
Assert.Empty(metadata.Parameters);
386+
Assert.Same(emptyParameters, metadata.Parameters);
387+
}
388+
235389
private static void ValidFunctionName() { }
236390
private static async Task ValidFunctionNameAsync()
237391
{

0 commit comments

Comments
 (0)