Skip to content

Commit

Permalink
introduce mrw feature for resourcemanager, and add a shared test case…
Browse files Browse the repository at this point in the history
… to validate the mrw pattern (Azure#41133)
  • Loading branch information
ArcturusZhang authored Jan 11, 2024
1 parent 8a70af0 commit 9ed6951
Show file tree
Hide file tree
Showing 219 changed files with 14,779 additions and 583 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;

namespace Azure.ResourceManager.TestFramework
{
public sealed partial class ModelReaderWriterImplementationValidation
{
private string[] ExceptionList { get; set; }

private const string ModelNamespaceSuffix = ".Models";
private const string AssemblyPrefix = "Azure.ResourceManager.";
private const string ResourceManagerAssemblyName = "Azure.ResourceManager";
private const string TestAssemblySuffix = ".Tests";

[Test]
public void ValidateModelReaderWriterPattern()
{
var testAssembly = Assembly.GetExecutingAssembly();
var assemblyName = testAssembly.GetName().Name;
Assert.IsTrue(assemblyName.EndsWith(TestAssemblySuffix), $"The test assembly should end with {TestAssemblySuffix}");
var rpNamespace = assemblyName.Substring(0, assemblyName.Length - TestAssemblySuffix.Length);

TestContext.WriteLine($"Testing assembly {rpNamespace}");

if (!rpNamespace.StartsWith(AssemblyPrefix) && rpNamespace != ResourceManagerAssemblyName)
{
// this is not a MPG project
return;
}

// find the SDK assembly by filtering the assemblies in the current domain, or load it if not found (when there is no test case)
var sdkAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == rpNamespace) ?? Assembly.Load(rpNamespace);

Assert.IsNotNull(sdkAssembly, $"The SDK assembly {rpNamespace} not found");

List<Type> violatedTypes = new();
var exceptionList = ExceptionList == null ? new HashSet<string>() : new HashSet<string>(ExceptionList);
foreach (var type in sdkAssembly.GetTypes())
{
if (IsModelType(type, exceptionList))
{
TestContext.WriteLine($"Verifying class {type}");
CheckModelType(type, violatedTypes);
}
}

if (violatedTypes.Count > 0)
{
var builder = new StringBuilder();
builder.AppendLine($"The following type should either implement {typeof(IJsonModel<>)} or {typeof(IPersistableModel<>)}:");
foreach (var type in violatedTypes)
{
builder.AppendLine(type.ToString());
}
Assert.Fail(builder.ToString());
}
}

private static bool IsModelType(Type type, HashSet<string> exceptionList)
{
if (!type.IsPublic || type.IsInterface || IsStaticType(type) || !type.IsClass)
return false;

if (exceptionList.Contains($"{type.Namespace}.{type.Name}"))
return false;

// if the type is in the Models namespace, it is a model
if (type.Namespace.EndsWith(ModelNamespaceSuffix))
return true;

return false;
}

private static void CheckModelType(Type type, List<Type> violatedTypes)
{
var interfaces = type.GetInterfaces();
var iJsonModelType = typeof(IJsonModel<>).MakeGenericType(type);
var iPersistableModelType = typeof(IPersistableModel<>).MakeGenericType(type);
// check the type implements the IJsonModel<T> interface
if (interfaces.Contains(iJsonModelType))
return;
// if not, it should implements the IPersistableModel<T> interface
if (interfaces.Contains(iPersistableModelType))
return;

violatedTypes.Add(type);
}

private static bool IsStaticType(Type type) => type.IsSealed && type.IsAbstract; // CLR uses sealed and abstract to represent static classes
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{4E159B41-7
docs\Sample3_CreatingAVirtualNetwork.md = docs\Sample3_CreatingAVirtualNetwork.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core", "..\..\core\Azure.Core\src\Azure.Core.csproj", "{E0F3952A-D1C7-4CE4-B2A8-5C34945EBED8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ResourceManager.Perf", "perf\Azure.ResourceManager.Perf.csproj", "{138A2FF1-F1AB-480A-9588-136FB875026E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Test.Perf", "..\..\..\common\Perf\Azure.Test.Perf\Azure.Test.Perf.csproj", "{AD397048-D114-4A32-8F35-64E5C72A4697}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.ResourceManager.Samples", "samples\Azure.ResourceManager.Samples.csproj", "{0D3137B9-8FB5-46E3-9033-84EF6DBE8D1E}"
EndProject
Global
Expand Down
Loading

0 comments on commit 9ed6951

Please sign in to comment.