Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,55 @@
using Microsoft.TypeSpec.Generator.Input;
using Microsoft.TypeSpec.Generator.Primitives;
using Microsoft.TypeSpec.Generator.Providers;
using Microsoft.TypeSpec.Generator.Snippets;
using Microsoft.TypeSpec.Generator.Tests.Common;
using NUnit.Framework;

namespace Microsoft.TypeSpec.Generator.ClientModel.Tests.Providers.MrwSerializationTypeDefinitions
{
public class SerializationCustomizationTests
{
[Test]
public async Task BackCompat_RenamedPropertiesKeepSerializationParameters(
[Values(false, true)] bool useLastContract)
{
var inputEnum = InputFactory.StringEnum("DestinationKind", [("VirtualNetwork", "virtualNetwork")]);
var inputModel = InputFactory.Model("MockInputModel", properties: [
InputFactory.Property("isEnabled", InputPrimitiveType.Boolean, isRequired: true, serializedName: "enabled"),
InputFactory.Property("destinationType", inputEnum, isRequired: true, serializedName: "type"),
InputFactory.Property("enforcement", inputEnum)
],
usage: InputModelTypeUsage.Input | InputModelTypeUsage.Output | InputModelTypeUsage.Json);
var mockGenerator = await MockHelpers.LoadMockGeneratorAsync(
inputEnums: () => [inputEnum],
inputModels: () => [inputModel],
compilation: async () => await Helpers.GetCompilationFromDirectoryAsync("Custom"),
lastContractCompilation: useLastContract
? async () => await Helpers.GetCompilationFromDirectoryAsync("Previous")
: null);

var modelProvider = mockGenerator.Object.OutputLibrary.TypeProviders.OfType<ModelProvider>().Single();
var serializationProvider = modelProvider.SerializationProviders.Single(t => t is MrwSerializationTypeDefinition);
modelProvider.EnsureBuilt();
serializationProvider.EnsureBuilt();
modelProvider.ProcessTypeForBackCompatibility();

var publicConstructor = modelProvider.Constructors.Single(c =>
c.Signature.Modifiers.HasFlag(MethodSignatureModifiers.Public));
Assert.That(publicConstructor.Signature.Parameters.Select(p => p.Name),
Is.EqualTo(useLastContract ? new[] { "enabled", "type" } : new[] { "isEnabled", "destinationType" }));
Assert.That(publicConstructor.Signature.Parameters.Select(p => p.Property?.Name),
Is.EqualTo(new[] { "IsEnabled", "DestinationType" }));
Assert.That(modelProvider.FullConstructor.Signature.Parameters.Take(2).Select(p => p.Name),
Is.EqualTo(new[] { "isEnabled", "destinationType" }));
Assert.That(modelProvider.FullConstructor.Signature.Parameters.Take(2).Select(p => p.AsVariable().Declaration.RequestedName),
Is.EqualTo(new[] { "isEnabled", "destinationType" }));

var writer = new TypeProviderWriter(new FilteredMethodsTypeProvider(
serializationProvider, name => name is "DeserializeMockInputModel" or "JsonModelWriteCore"));
Assert.AreEqual(Helpers.GetExpectedFromFile(), writer.Write().Content);
Comment thread
jorgerangel-msft marked this conversation as resolved.
}

[Test]
public async Task CanChangePropertyName()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

namespace Sample.Models
{
public partial class MockInputModel
{
public bool Enabled
{
get => IsEnabled;
set => IsEnabled = value;
}

public DestinationKind Type
{
get => DestinationType;
set => DestinationType = value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;

namespace Sample.Models
{
public partial class MockInputModel
{
public MockInputModel(bool enabled, DestinationKind type)
{
IsEnabled = enabled;
DestinationType = type;
}

internal MockInputModel(bool enabled, DestinationKind type, DestinationKind? enforcement, IDictionary<string, BinaryData> additionalBinaryDataProperties)
{
IsEnabled = enabled;
DestinationType = type;
Enforcement = enforcement;
}

public bool IsEnabled { get; set; }
public bool Enabled
{
get => IsEnabled;
set => IsEnabled = value;
}

public DestinationKind DestinationType { get; set; }
public DestinationKind? Enforcement { get; set; }
public DestinationKind Type
{
get => DestinationType;
set => DestinationType = value;
}
}

public enum DestinationKind
{
VirtualNetwork
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// <auto-generated/>

#nullable disable

using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Text.Json;
using Sample.Models;

namespace Sample
{
public partial class MockInputModel
{
protected virtual void JsonModelWriteCore(global::System.Text.Json.Utf8JsonWriter writer, global::System.ClientModel.Primitives.ModelReaderWriterOptions options)
{
string format = (options.Format == "W") ? ((global::System.ClientModel.Primitives.IPersistableModel<global::Sample.Models.MockInputModel>)this).GetFormatFromOptions(options) : options.Format;
if ((format != "J"))
{
throw new global::System.FormatException($"The model {nameof(global::Sample.Models.MockInputModel)} does not support writing '{format}' format.");
}
writer.WritePropertyName("enabled"u8);
writer.WriteBooleanValue(IsEnabled);
writer.WritePropertyName("type"u8);
writer.WriteStringValue(DestinationType.ToSerialString());
if (global::Sample.Optional.IsDefined(Enforcement))
{
writer.WritePropertyName("enforcement"u8);
writer.WriteStringValue(Enforcement.Value.ToSerialString());
}
if (((options.Format != "W") && (_additionalBinaryDataProperties != null)))
{
foreach (var item in _additionalBinaryDataProperties)
{
writer.WritePropertyName(item.Key);
#if NET6_0_OR_GREATER
writer.WriteRawValue(item.Value);
#else
using (global::System.Text.Json.JsonDocument document = global::System.Text.Json.JsonDocument.Parse(item.Value))
{
global::System.Text.Json.JsonSerializer.Serialize(writer, document.RootElement);
}
#endif
}
}
}

internal static global::Sample.Models.MockInputModel DeserializeMockInputModel(global::System.Text.Json.JsonElement element, global::System.ClientModel.Primitives.ModelReaderWriterOptions options)
Comment thread
jorgerangel-msft marked this conversation as resolved.
{
if ((element.ValueKind == global::System.Text.Json.JsonValueKind.Null))
{
return null;
}
bool isEnabled = default;
global::Sample.Models.DestinationKind destinationType = default;
global::Sample.Models.DestinationKind? enforcement = default;
global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties = new global::Sample.ChangeTrackingDictionary<string, global::System.BinaryData>();
foreach (var prop in element.EnumerateObject())
{
if (prop.NameEquals("enabled"u8))
{
isEnabled = prop.Value.GetBoolean();
continue;
}
if (prop.NameEquals("type"u8))
{
destinationType = prop.Value.GetString().ToDestinationKind();
continue;
}
if (prop.NameEquals("enforcement"u8))
{
if ((prop.Value.ValueKind == global::System.Text.Json.JsonValueKind.Null))
{
continue;
}
enforcement = prop.Value.GetString().ToDestinationKind();
continue;
}
if ((options.Format != "W"))
{
additionalBinaryDataProperties.Add(prop.Name, prop.Value.GetUtf8Bytes());
}
}
return new global::Sample.Models.MockInputModel(isEnabled, destinationType, enforcement, additionalBinaryDataProperties);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ private ParameterProvider BuildInputVariant()
wireInfo: WireInfo,
validation: Validation)
{
_asVariable = _asVariable,
SpreadSource = SpreadSource,
InputParameter = InputParameter,
IsExactName = IsExactName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ public MockInputModel(string newName, int oldCount)
NewCount = oldCount;
}

internal MockInputModel(string newName, int oldCount, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal MockInputModel(string newName, int newCount, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
new_name = newName;
NewCount = oldCount;
NewCount = newCount;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public CasingModel(string vmwareSiteId)
VMwareSiteId = vmwareSiteId;
}

internal CasingModel(string vmwareSiteId, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal CasingModel(string vMwareSiteId, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
VMwareSiteId = vmwareSiteId;
VMwareSiteId = vMwareSiteId;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ public MockInputModel(string name, string vmName)
Name = vmName;
}

internal MockInputModel(string name, string vmName, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal MockInputModel(string skuName, string name, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
SkuName = name;
Name = vmName;
SkuName = skuName;
Name = name;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public DateTimeModel(global::System.DateTimeOffset startTime)
StartsOn = startTime;
}

internal DateTimeModel(global::System.DateTimeOffset startTime, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal DateTimeModel(global::System.DateTimeOffset startsOn, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
StartsOn = startTime;
StartsOn = startsOn;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ public MockInputModel(string unchanged, string oldName)
NewName = oldName;
}

internal MockInputModel(string unchanged, string oldName, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal MockInputModel(string unchanged, string newName, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
Unchanged = unchanged;
NewName = oldName;
NewName = newName;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public MockInputModel(string oldUnchanged, string newName)
new_name = newName;
}

internal MockInputModel(string oldUnchanged, string newName, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
internal MockInputModel(string unchanged, string newName, global::System.Collections.Generic.IDictionary<string, global::System.BinaryData> additionalBinaryDataProperties)
{
Unchanged = oldUnchanged;
Unchanged = unchanged;
new_name = newName;
_additionalBinaryDataProperties = additionalBinaryDataProperties;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public void IndependentlyCreatedParametersPreserveMetadata()
}

[Test]
public void PublicInputVariantPreservesVariableAndMetadata()
public void PublicInputVariantPreservesMetadataWithIndependentVariable()
{
MockHelpers.LoadMockGenerator();
var input = InputFactory.MethodParameter(
Expand All @@ -226,13 +226,20 @@ public void PublicInputVariantPreservesVariableAndMetadata()

Assert.AreEqual(parameter.Name, inputVariant.Name);
Assert.IsTrue(inputVariant.Type.Equals(typeof(IEnumerable<string>)));
Assert.AreSame(variable, inputVariant.AsVariable());
Assert.AreNotSame(variable, inputVariant.AsVariable());
Assert.AreEqual(inputVariant.Type, inputVariant.AsVariable().Type);
Assert.AreEqual(variable.Declaration.RequestedName, inputVariant.AsVariable().Declaration.RequestedName);
Assert.AreSame(input, inputVariant.InputParameter);
Assert.AreSame(parameter.WireInfo, inputVariant.WireInfo);
Assert.AreEqual(parameter.IsExactName, inputVariant.IsExactName);
Assert.AreEqual(parameter.DefaultValue, inputVariant.DefaultValue);
Assert.AreEqual(parameter.Validation, inputVariant.Validation);
Assert.AreSame(inputVariant, parameter.ToPublicInputParameter());

inputVariant.Update(name: "publishedIPv4Addresses");
Comment thread
jorgerangel-msft marked this conversation as resolved.
Assert.AreEqual("publishedIPv4Addresses", inputVariant.AsVariable().Declaration.RequestedName);
Assert.AreEqual("iPv4Addresses", parameter.Name);
Assert.AreEqual("iPv4Addresses", variable.Declaration.RequestedName);
}

private static IEnumerable<InputType> ValueInputTypes()
Expand Down Expand Up @@ -344,6 +351,23 @@ public void ToPublicInputParameterCopiesProperties()
Assert.AreEqual(parameter.Type.InputType, publicParameter.Type);
}

[Test]
public void ToPublicInputParameterDoesNotShareVariable()
{
var parameter = new ParameterProvider("isEnabled", $"Description", typeof(bool));
var variable = parameter.AsVariable();
var publicParameter = parameter.ToPublicInputParameter();
var publicVariable = publicParameter.AsVariable();

publicParameter.Update(name: "enabled");

Assert.AreEqual("isEnabled", parameter.Name);
Assert.AreEqual("isEnabled", variable.Declaration.RequestedName);
Assert.AreEqual("enabled", publicVariable.Declaration.RequestedName);
Assert.AreSame(variable, parameter.AsVariable());
Assert.AreSame(publicVariable, publicParameter.AsVariable());
}

[Test]
public void WithRefCopiesProperties()
{
Expand Down
Loading