Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update reference types and add unit tests to validate #21031

Merged
merged 4 commits into from
May 12, 2021
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 @@ -9,12 +9,12 @@ namespace Azure.ResourceManager.Core
/// An attribute class indicating the constructor to use for initialization.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor)]
public class InitializationConstructor : Attribute
public class InitializationConstructorAttribute : Attribute
{
/// <summary>
/// Instatiate a new InitializationConstructor attribute.
/// </summary>
public InitializationConstructor()
public InitializationConstructorAttribute()
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected Resource() { }
/// <param name="name"> The name of the resource. </param>
/// <param name="type"> The <see cref="ResourceType"/> of the resource. </param>
[SerializationConstructor]
protected Resource(TIdentifier id, string name, ResourceType type)
protected internal Resource(TIdentifier id, string name, ResourceType type)
{
Id = id;
Name = name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace Azure.ResourceManager.Core
/// An attribute class indicating the constructor to use for serialization.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor)]
public class SerializationConstructor : Attribute
public class SerializationConstructorAttribute : Attribute
{
/// <summary>
/// Instatiate a new SerializationConstructor attribute.
/// </summary>
public SerializationConstructor()
public SerializationConstructorAttribute()
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ public partial class SubResource
/// Initializes an empty instance of <see cref="SubResource"/> for mocking.
/// </summary>
[InitializationConstructor]
protected SubResource()
public SubResource()
{
}

/// <summary> Initializes a new instance of SubResource. </summary>
/// <param name="id"> ARM resource Id. </param>
[SerializationConstructor]
internal SubResource(string id)
protected internal SubResource(string id)
{
Id = id;
}

/// <summary>
/// ARM resource identifier.
/// Gets the ARM resource identifier.
/// </summary>
/// <value></value>
public virtual ResourceIdentifier Id { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public SubResourceWritable()
/// <summary> Initializes a new instance of SubResourceReadOnly. </summary>
/// <param name="id"> ARM resource Id. </param>
[SerializationConstructor]
internal SubResourceWritable(string id)
protected internal SubResourceWritable(string id)
{
Id = id;
}

/// <summary>
/// ARM resource identifier (read-only).
/// Gets or sets the ARM resource identifier.
/// </summary>
/// <value></value>
public virtual ResourceIdentifier Id { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected TrackedResource(LocationData location)
/// <param name="tags"> The tags for the resource. </param>
/// <param name="location"> The location of the resource. </param>
[SerializationConstructor]
protected TrackedResource(TIdentifier id, string name, ResourceType type, LocationData location, IDictionary<string, string> tags)
protected internal TrackedResource(TIdentifier id, string name, ResourceType type, LocationData location, IDictionary<string, string> tags)
: base(id, name, type)
{
Tags = tags ?? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using NUnit.Framework;

namespace Azure.ResourceManager.Core.Tests
{
public class ReferenceTypeTests
{
private static readonly Type ReferenceAttribute = typeof(ReferenceTypeAttribute);
private static readonly Type SerializationConstructor = typeof(SerializationConstructorAttribute);
private static readonly Type InitializationConstructor = typeof(InitializationConstructorAttribute);
private static readonly IEnumerable<Type> AssemblyTypes = typeof(ArmClient).Assembly.GetTypes();

[Test]
public void ValidateSerializationConstructor()
{
foreach (var refType in AssemblyTypes.Where(t => HasAttribute(t.GetCustomAttributes<Attribute>(false), ReferenceAttribute)))
{
var serializationCtor = refType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(c => HasAttribute(c.GetCustomAttributes<Attribute>(false), SerializationConstructor)).FirstOrDefault();
Assert.IsNotNull(serializationCtor);
Assert.IsTrue(serializationCtor.IsFamilyOrAssembly, $"Serialization ctor for {refType.Name} should be protected internal");
Assert.IsFalse(serializationCtor.IsPublic, $"Serialization ctor for {refType.Name} should not be public");
}
}

[Test]
public void ValidateInitializationConstructor()
{
foreach (var refType in AssemblyTypes.Where(t => HasAttribute(t.GetCustomAttributes<Attribute>(false), ReferenceAttribute)))
{
var initializationCtor = refType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(c => HasAttribute(c.GetCustomAttributes<Attribute>(false), InitializationConstructor)).FirstOrDefault();
Assert.IsNotNull(initializationCtor);
Assert.IsTrue(refType.IsAbstract == initializationCtor.IsFamily, $"If {refType.Name} is abstract then its initialization ctor should be protected");
Assert.IsTrue(refType.IsAbstract != initializationCtor.IsPublic, $"If {refType.Name} is abstract then its initialization ctor should be public");
Assert.IsFalse(initializationCtor.IsAssembly, $"Initialization ctor for {refType.Name} should not be internal");
}
}

public bool HasAttribute(IEnumerable<Attribute> list, Type attributeType)
{
return list.FirstOrDefault(a => a.GetType() == attributeType) is not null;
}
}
}