From 0ba790bc48463ea2de9776caa67b4c05aaac8787 Mon Sep 17 00:00:00 2001 From: TimLovellSmith Date: Fri, 20 May 2016 11:58:29 -0700 Subject: [PATCH 1/5] Fix Swagger SchemaResolver to allow for the fact that properties may be defined by chains of indirect references to some type which inherits from another compatible type - and that should be fine! --- .../AutoRest.Modeler.Swagger.Tests.csproj | 4 + .../Swagger/swagger-redis-sample.json | 683 ++++++++++++++++++ .../Swagger.Tests/SwaggerModelerRedisTests.cs | 35 + AutoRest/Modelers/Swagger/SchemaResolver.cs | 49 +- 4 files changed, 756 insertions(+), 15 deletions(-) create mode 100644 AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json create mode 100644 AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs diff --git a/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj b/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj index ea2b011b5341a..dda50548a36da 100644 --- a/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj +++ b/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj @@ -36,9 +36,13 @@ True Resources.resx + + + PreserveNewest + PreserveNewest diff --git a/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json b/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json new file mode 100644 index 0000000000000..bf80d0515b194 --- /dev/null +++ b/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json @@ -0,0 +1,683 @@ +{ + "swagger": "2.0", + "info": { + "title": "RedisManagementClient", + "description": "REST API for Azure Redis Cache Service", + "version": "2016-04-01" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json", + "text/json" + ], + "produces": [ + "application/json", + "text/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}": { + "put": { + "tags": [ + "Redis" + ], + "operationId": "Redis_CreateOrUpdate", + "description": "Create a redis cache, or replace (overwrite/recreate, with potential downtime) an existing cache", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RedisCreateOrUpdateParameters" + }, + "description": "Parameters supplied to the CreateOrUpdate redis operation." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/RedisResourceWithAccessKey" + } + }, + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/RedisResourceWithAccessKey" + } + } + } + }, + "delete": { + "tags": [ + "Redis" + ], + "operationId": "Redis_Delete", + "description": "Deletes a redis cache. This operation takes a while to complete.", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "" + }, + "204": { + "description": "" + } + } + }, + "get": { + "tags": [ + "Redis" + ], + "operationId": "Redis_Get", + "description": "Gets a redis cache (resource description).", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/RedisResource" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/": { + "get": { + "tags": [ + "Redis" + ], + "operationId": "Redis_ListByResourceGroup", + "description": "Gets all redis caches in a resource group.", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/RedisListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Cache/Redis/": { + "get": { + "tags": [ + "Redis" + ], + "operationId": "Redis_List", + "description": "Gets all redis caches in the specified subscription.", + "parameters": [ + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/RedisListResult" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/listKeys": { + "post": { + "tags": [ + "Redis" + ], + "operationId": "Redis_ListKeys", + "description": "Retrieve a redis cache's access keys. This operation requires write permission to the cache resource.", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Lists the keys for Redis Cache", + "schema": { + "$ref": "#/definitions/RedisListKeysResult" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/regenerateKey": { + "post": { + "tags": [ + "Redis" + ], + "operationId": "Redis_RegenerateKey", + "description": "Regenerate redis cache's access keys. This operation requires write permission to the cache resource.", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RedisRegenerateKeyParameters" + }, + "description": "Specifies which key to reset." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Lists the regenerated keys for Redis Cache", + "schema": { + "$ref": "#/definitions/RedisListKeysResult" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/forceReboot": { + "post": { + "tags": [ + "Redis" + ], + "operationId": "Redis_ForceReboot", + "description": "Reboot specified redis node(s). This operation requires write permission to the cache resource. There can be potential data loss.", + "parameters": [ + { + "name": "resourceGroupName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the resource group." + }, + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "The name of the redis cache." + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RedisRebootParameters" + }, + "description": "Specifies which redis node(s) to reboot." + }, + { + "$ref": "#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "" + }, + "204": { + "description": "" + } + } + } + } + }, + "definitions": { + "Sku": { + "properties": { + "name": { + "type": "string", + "description": "What type of redis cache to deploy. Valid values: (Basic, Standard, Premium)", + "enum": [ + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": true + } + }, + "family": { + "type": "string", + "description": "Which family to use. Valid values: (C, P)", + "enum": [ + "C", + "P" + ], + "x-ms-enum": { + "name": "SkuFamily", + "modelAsString": true + } + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "What size of redis cache to deploy. Valid values: for C family (0, 1, 2, 3, 4, 5, 6), for P family (1, 2, 3, 4)" + } + }, + "required": [ + "name", + "family", + "capacity" + ], + "description": "Sku parameters supplied to the create redis operation." + }, + "RedisProperties": { + "properties": { + "redisVersion": { + "type": "string", + "description": "RedisVersion parameter has been deprecated. As such, it is no longer necessary to provide this parameter and any value specified is ignored." + }, + "sku": { + "$ref": "#/definitions/Sku", + "description": "What sku of redis cache to deploy." + }, + "redisConfiguration": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc." + }, + "enableNonSslPort": { + "type": "boolean", + "description": "If the value is true, then the non-ssl redis server port (6379) will be enabled." + }, + "tenantSettings": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "tenantSettings" + }, + "shardCount": { + "type": "integer", + "format": "int32", + "description": "The number of shards to be created on a Premium Cluster Cache." + }, + "subnetId": { + "type": "string", + "description": "The full resource ID of a subnet in a virtual network to deploy the redis cache in. Example format: /subscriptions/{subid}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1" + }, + "staticIP": { + "type": "string", + "description": "Required when deploying a redis cache inside an existing Azure Virtual Network." + } + }, + "required": [ + "sku" + ], + "description": "Parameters supplied to CreateOrUpdate redis operation." + }, + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + }, + "location": { + "type": "string", + "description": "Resource location" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags" + } + }, + "required": [ + "location" + ], + "x-ms-azure-resource": true + }, + "RedisCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisProperties", + "description": "Redis cache properties." + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "Parameters supplied to the CreateOrUpdate Redis operation." + }, + "RedisAccessKeys": { + "properties": { + "primaryKey": { + "type": "string", + "description": "The current primary key that clients can use to authenticate with redis cache." + }, + "secondaryKey": { + "type": "string", + "description": "The current secondary key that clients can use to authenticate with redis cache." + } + }, + "description": "Redis cache access keys." + }, + "RedisReadableProperties": { + "properties": { + "provisioningState": { + "type": "string", + "description": "Redis instance provisioning status" + }, + "hostName": { + "type": "string", + "description": "Redis host name" + }, + "port": { + "type": "integer", + "format": "int32", + "description": "Redis non-ssl port" + }, + "sslPort": { + "type": "integer", + "format": "int32", + "description": "Redis ssl port" + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisProperties" + } + ], + "description": "Parameters describing a redis instance" + }, + "RedisReadablePropertiesWithAccessKey": { + "properties": { + "accessKeys": { + "$ref": "#/definitions/RedisAccessKeys", + "description": "Redis cache access keys." + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisReadableProperties" + } + ], + "description": "Properties generated only in response to CreateOrUpdate redis operation." + }, + "RedisResourceWithAccessKey": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisReadablePropertiesWithAccessKey", + "description": "Redis cache properties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisResource" + } + ], + "description": "A redis item in CreateOrUpdate Operation response." + }, + "RedisResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisReadableProperties", + "description": "Redis cache properties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "A single redis item in List or Get Operation." + }, + "RedisListResult": { + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/RedisResource" + }, + "description": "Results of the list operation" + }, + "nextLink": { + "type": "string", + "description": "Link for next set of locations." + } + }, + "description": "The response of list redis operation." + }, + "RedisListKeysResult": { + "properties": { + "primaryKey": { + "type": "string", + "description": "The current primary key that clients can use to authenticate with redis cache." + }, + "secondaryKey": { + "type": "string", + "description": "The current secondary key that clients can use to authenticate with redis cache." + } + }, + "description": "The response of redis list keys operation." + }, + "RedisRegenerateKeyParameters": { + "properties": { + "keyType": { + "type": "string", + "description": "Which redis access key to reset", + "enum": [ + "Primary", + "Secondary" + ], + "x-ms-enum": { + "name": "RedisKeyType", + "modelAsString": false + } + } + }, + "required": [ + "keyType" + ], + "description": "Specifies which redis access keys to reset." + }, + "RedisRebootParameters": { + "properties": { + "rebootType": { + "type": "string", + "description": "Which redis node(s) to reboot. Depending on this value data loss is possible.", + "enum": [ + "PrimaryNode", + "SecondaryNode", + "AllNodes" + ], + "x-ms-enum": { + "name": "RebootType", + "modelAsString": false + } + }, + "shardId": { + "type": "integer", + "format": "int32", + "description": "In case of cluster cache, this specifies shard id which should be rebooted." + } + }, + "required": [ + "rebootType" + ], + "description": "Specifies which redis node(s) to reboot." + } + }, + "parameters": { + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "Gets subscription credentials which uniquely identify Microsoft Azure subscription. The subscription ID forms part of the URI for every service call." + }, + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "required": true, + "type": "string", + "description": "Client Api Version." + } + } +} \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs new file mode 100644 index 0000000000000..e19bd34e90a5f --- /dev/null +++ b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Net; +using Microsoft.Rest.Generator; +using Microsoft.Rest.Generator.ClientModel; +using Microsoft.Rest.Generator.CSharp; +using Microsoft.Rest.Generator.Extensibility; +using Microsoft.Rest.Generator.Utilities; +using Xunit; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Rest.Modeler.Swagger.Tests +{ + [Collection("AutoRest Tests")] + public class SwaggerModelerRedisTests + { + [Fact] + public void RedisResponseWithAccessKeys_IsAssignableTo_RedisResponse() + { + Generator.Modeler modeler = new SwaggerModeler(new Settings + { + Namespace = "Test", + Input = Path.Combine("Swagger", "swagger-redis-sample.json") + }); + var clientModel = modeler.Build(); + var redisResponseModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResource"); + var redisResponseWithAccessKeyModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResourceWithAccessKey"); + Assert.Equal(redisResponseModel, redisResponseWithAccessKeyModel.BaseModelType); + } + } +} \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger/SchemaResolver.cs b/AutoRest/Modelers/Swagger/SchemaResolver.cs index 092a8c145f6d4..6fbf3603c69ec 100644 --- a/AutoRest/Modelers/Swagger/SchemaResolver.cs +++ b/AutoRest/Modelers/Swagger/SchemaResolver.cs @@ -18,7 +18,6 @@ public class SchemaResolver : ICloneable private const int MaximumReferenceDepth = 40; private readonly SwaggerModeler _modeler; private readonly ServiceDefinition _serviceDefinition; - private readonly List _visitedReferences; /// /// Create a new schema resolver in the context of the given swagger spec @@ -33,7 +32,6 @@ public SchemaResolver(SwaggerModeler modeler) _modeler = modeler; _serviceDefinition = modeler.ServiceDefinition; - _visitedReferences = new List(); } /// @@ -44,11 +42,6 @@ public SchemaResolver(SwaggerModeler modeler) public object Clone() { var resolver = new SchemaResolver(_modeler); - foreach (string reference in _visitedReferences) - { - resolver._visitedReferences.Add(reference); - } - return resolver; } @@ -201,12 +194,32 @@ private bool SchemaTypesAreEquivalent(Schema parentProperty, if ((parentProperty.Type == null || parentProperty.Type == DataType.Object) && (unwrappedProperty.Type == null || unwrappedProperty.Type == DataType.Object)) { - if (!string.IsNullOrEmpty(parentProperty.Reference) || - !string.IsNullOrEmpty(unwrappedProperty.Reference)) + var parentPropertyToCompare = parentProperty; + var unwrappedPropertyToCompare = unwrappedProperty; + if (!string.IsNullOrEmpty(parentProperty.Reference)) + { + parentPropertyToCompare = Dereference(parentProperty.Reference); + } + if (!string.IsNullOrEmpty(unwrappedProperty.Reference)) { - return parentProperty.Reference == unwrappedProperty.Reference; + unwrappedPropertyToCompare = Dereference(unwrappedProperty.Reference); } - // do not compare inline schemas + + if (parentPropertyToCompare == unwrappedPropertyToCompare) + { + return true; // when fully dereferenced, they can refer to the same thing + } + + // or they can refer to different things... but there can be an inheritance relation... + while (unwrappedPropertyToCompare != null && unwrappedPropertyToCompare.Extends != null) + { + unwrappedPropertyToCompare = Dereference(unwrappedPropertyToCompare.Extends); + if (unwrappedPropertyToCompare == parentPropertyToCompare) + { + return true; + } + } + return false; } if (parentProperty.Type == DataType.Array && @@ -252,6 +265,12 @@ private Schema FindParentProperty(string parentReference, string propertyName) /// The schema reference to dereference. /// The dereferenced schema. private Schema Dereference(string referencePath) + { + var vistedReferences = new List(); + return DereferenceInner(referencePath, vistedReferences); + } + + private Schema DereferenceInner(string referencePath, List visitedReferences) { // Check if external reference string[] splitReference = referencePath.Split(new[] {'#'}, StringSplitOptions.RemoveEmptyEntries); @@ -260,17 +279,17 @@ private Schema Dereference(string referencePath) referencePath = "#" + splitReference[1]; } - if (_visitedReferences.Contains(referencePath.ToLower(CultureInfo.InvariantCulture))) + if (visitedReferences.Contains(referencePath.ToLower(CultureInfo.InvariantCulture))) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Properties.Resources.CircularReference, referencePath)); } - if (_visitedReferences.Count >= MaximumReferenceDepth) + if (visitedReferences.Count >= MaximumReferenceDepth) { throw new ArgumentException(Properties.Resources.ExceededMaximumReferenceDepth, referencePath); } - _visitedReferences.Add(referencePath.ToLower(CultureInfo.InvariantCulture)); + visitedReferences.Add(referencePath.ToLower(CultureInfo.InvariantCulture)); var definitions = _serviceDefinition.Definitions; if (definitions == null || !definitions.ContainsKey(referencePath.StripDefinitionPath())) { @@ -282,7 +301,7 @@ private Schema Dereference(string referencePath) var schema = _serviceDefinition.Definitions[referencePath.StripDefinitionPath()]; if (schema.Reference != null) { - schema = Dereference(schema.Reference); + schema = DereferenceInner(schema.Reference, visitedReferences); } return schema; From 5f974470281be5a91231c8c5571462df829174d1 Mon Sep 17 00:00:00 2001 From: TimLovellSmith Date: Mon, 23 May 2016 11:01:27 -0700 Subject: [PATCH 2/5] Modify the circular detection logic for circular 'allOf' inheritance so that there can again be a passing test 'ClientModelWithCircularDependencyThrowsError'. --- .../Swagger.Tests/SwaggerModelerTests.cs | 4 ++- .../Swagger/Properties/Resources.Designer.cs | 9 ++++++ .../Swagger/Properties/Resources.resx | 3 ++ AutoRest/Modelers/Swagger/SchemaResolver.cs | 31 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs index 0aac57a71e45f..8c7af5c952207 100644 --- a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs +++ b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs @@ -185,7 +185,9 @@ public void ClientModelWithCircularDependencyThrowsError() Namespace = "Test", Input = Path.Combine("Swagger", "swagger-allOf-circular.json") }); - Assert.Throws(() => modeler.Build()); + var ex = Assert.Throws(() => modeler.Build()); + Assert.Contains("circular", ex.Message, StringComparison.InvariantCultureIgnoreCase); + Assert.Contains("siamese", ex.Message, StringComparison.InvariantCultureIgnoreCase); } [Fact] diff --git a/AutoRest/Modelers/Swagger/Properties/Resources.Designer.cs b/AutoRest/Modelers/Swagger/Properties/Resources.Designer.cs index e2335bc14a76a..bb600eb0be9a3 100644 --- a/AutoRest/Modelers/Swagger/Properties/Resources.Designer.cs +++ b/AutoRest/Modelers/Swagger/Properties/Resources.Designer.cs @@ -60,6 +60,15 @@ internal Resources() { } } + /// + /// Looks up a localized string similar to Found a type set '{0}' which is circularly defined.. + /// + internal static string CircularBaseSchemaSet { + get { + return ResourceManager.GetString("CircularBaseSchemaSet", resourceCulture); + } + } + /// /// Looks up a localized string similar to Circular reference detected: {0}. /// diff --git a/AutoRest/Modelers/Swagger/Properties/Resources.resx b/AutoRest/Modelers/Swagger/Properties/Resources.resx index 057ff414a1b2e..18588c7695845 100644 --- a/AutoRest/Modelers/Swagger/Properties/Resources.resx +++ b/AutoRest/Modelers/Swagger/Properties/Resources.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Found a type set '{0}' which is circularly defined. + Circular reference detected: {0} diff --git a/AutoRest/Modelers/Swagger/SchemaResolver.cs b/AutoRest/Modelers/Swagger/SchemaResolver.cs index 6fbf3603c69ec..562b51e737d12 100644 --- a/AutoRest/Modelers/Swagger/SchemaResolver.cs +++ b/AutoRest/Modelers/Swagger/SchemaResolver.cs @@ -82,7 +82,9 @@ public void ExpandAllOf(Schema schema) if (schema.AllOf != null) { + CheckCircularAllOf(schema, null, null); var references = schema.AllOf.Where(s => s.Reference != null).ToList(); + if (references.Count == 1) { if (schema.Extends != null) @@ -101,6 +103,7 @@ public void ExpandAllOf(Schema schema) Properties = schema.Properties }; + var schemaList = new List().Concat(schema.AllOf) .Concat(new List {propertiesOnlySchema}); @@ -170,6 +173,34 @@ public void ExpandAllOf(Schema schema) } } + void CheckCircularAllOf(Schema schema, HashSet visited, Stack referenceChain) + { + visited = visited ?? new HashSet(); + referenceChain = referenceChain ?? new Stack(); + if (!visited.Add(schema)) // was already present in the set + { + var setDescription = "(" + String.Join(", ", referenceChain) + ")"; + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, + Properties.Resources.CircularBaseSchemaSet, setDescription)); + } + + if (schema.AllOf != null) + { + foreach (var reference in schema.AllOf.Select(s => s.Reference).Where(r => r != null)) + { + referenceChain.Push(reference); + + var deref = Dereference(reference); + CheckCircularAllOf(deref, visited, referenceChain); + + Debug.Assert(reference == referenceChain.Peek()); + referenceChain.Pop(); + } + } + visited.Remove(schema); + } + /// /// Determine equivalence between the types described by two schemas. /// Limit the comparison to exclude comparison of complexe inline schemas. From 2707593a16e43c22af12afcaf50a8ead0c80f0bb Mon Sep 17 00:00:00 2001 From: TimLovellSmith Date: Tue, 24 May 2016 13:48:17 -0700 Subject: [PATCH 3/5] Fix code analysis warnings from using ToLower(CultureInfo.InvariantCulture). --- AutoRest/Modelers/Swagger/SchemaResolver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutoRest/Modelers/Swagger/SchemaResolver.cs b/AutoRest/Modelers/Swagger/SchemaResolver.cs index 562b51e737d12..7504d33141065 100644 --- a/AutoRest/Modelers/Swagger/SchemaResolver.cs +++ b/AutoRest/Modelers/Swagger/SchemaResolver.cs @@ -310,7 +310,7 @@ private Schema DereferenceInner(string referencePath, List visitedRefere referencePath = "#" + splitReference[1]; } - if (visitedReferences.Contains(referencePath.ToLower(CultureInfo.InvariantCulture))) + if (visitedReferences.Contains(referencePath.ToUpperInvariant())) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Properties.Resources.CircularReference, referencePath)); @@ -320,7 +320,7 @@ private Schema DereferenceInner(string referencePath, List visitedRefere { throw new ArgumentException(Properties.Resources.ExceededMaximumReferenceDepth, referencePath); } - visitedReferences.Add(referencePath.ToLower(CultureInfo.InvariantCulture)); + visitedReferences.Add(referencePath.ToUpperInvariant()); var definitions = _serviceDefinition.Definitions; if (definitions == null || !definitions.ContainsKey(referencePath.StripDefinitionPath())) { From b403b9a006061eec5524734e1fb55511295dfbe8 Mon Sep 17 00:00:00 2001 From: TimLovellSmith Date: Wed, 25 May 2016 12:52:56 -0700 Subject: [PATCH 4/5] Simplify the unit test for verifying redis swagger modelling inheritance scenarios. --- .../AutoRest.Modeler.Swagger.Tests.csproj | 3 +- .../Swagger/swagger-redis-sample.json | 683 ------------------ .../swagger-ref-allOf-inheritance.json | 280 +++++++ .../Swagger.Tests/SwaggerModelerRedisTests.cs | 35 - .../Swagger.Tests/SwaggerModelerTests.cs | 34 + 5 files changed, 315 insertions(+), 720 deletions(-) delete mode 100644 AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json create mode 100644 AutoRest/Modelers/Swagger.Tests/Swagger/swagger-ref-allOf-inheritance.json delete mode 100644 AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs diff --git a/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj b/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj index dda50548a36da..76cdda60224ff 100644 --- a/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj +++ b/AutoRest/Modelers/Swagger.Tests/AutoRest.Modeler.Swagger.Tests.csproj @@ -36,11 +36,10 @@ True Resources.resx - - + PreserveNewest diff --git a/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json b/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json deleted file mode 100644 index bf80d0515b194..0000000000000 --- a/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-redis-sample.json +++ /dev/null @@ -1,683 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "title": "RedisManagementClient", - "description": "REST API for Azure Redis Cache Service", - "version": "2016-04-01" - }, - "host": "management.azure.com", - "schemes": [ - "https" - ], - "consumes": [ - "application/json", - "text/json" - ], - "produces": [ - "application/json", - "text/json" - ], - "security": [ - { - "azure_auth": [ - "user_impersonation" - ] - } - ], - "securityDefinitions": { - "azure_auth": { - "type": "oauth2", - "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", - "flow": "implicit", - "description": "Azure Active Directory OAuth2 Flow", - "scopes": { - "user_impersonation": "impersonate your user account" - } - } - }, - "paths": { - "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}": { - "put": { - "tags": [ - "Redis" - ], - "operationId": "Redis_CreateOrUpdate", - "description": "Create a redis cache, or replace (overwrite/recreate, with potential downtime) an existing cache", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "name": "parameters", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/RedisCreateOrUpdateParameters" - }, - "description": "Parameters supplied to the CreateOrUpdate redis operation." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "201": { - "description": "", - "schema": { - "$ref": "#/definitions/RedisResourceWithAccessKey" - } - }, - "200": { - "description": "", - "schema": { - "$ref": "#/definitions/RedisResourceWithAccessKey" - } - } - } - }, - "delete": { - "tags": [ - "Redis" - ], - "operationId": "Redis_Delete", - "description": "Deletes a redis cache. This operation takes a while to complete.", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "" - }, - "204": { - "description": "" - } - } - }, - "get": { - "tags": [ - "Redis" - ], - "operationId": "Redis_Get", - "description": "Gets a redis cache (resource description).", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "", - "schema": { - "$ref": "#/definitions/RedisResource" - } - } - } - } - }, - "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/": { - "get": { - "tags": [ - "Redis" - ], - "operationId": "Redis_ListByResourceGroup", - "description": "Gets all redis caches in a resource group.", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "", - "schema": { - "$ref": "#/definitions/RedisListResult" - } - } - }, - "x-ms-pageable": { - "nextLinkName": "nextLink" - } - } - }, - "/subscriptions/{subscriptionId}/providers/Microsoft.Cache/Redis/": { - "get": { - "tags": [ - "Redis" - ], - "operationId": "Redis_List", - "description": "Gets all redis caches in the specified subscription.", - "parameters": [ - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "", - "schema": { - "$ref": "#/definitions/RedisListResult" - } - } - }, - "x-ms-pageable": { - "nextLinkName": "nextLink" - } - } - }, - "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/listKeys": { - "post": { - "tags": [ - "Redis" - ], - "operationId": "Redis_ListKeys", - "description": "Retrieve a redis cache's access keys. This operation requires write permission to the cache resource.", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "Lists the keys for Redis Cache", - "schema": { - "$ref": "#/definitions/RedisListKeysResult" - } - } - } - } - }, - "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/regenerateKey": { - "post": { - "tags": [ - "Redis" - ], - "operationId": "Redis_RegenerateKey", - "description": "Regenerate redis cache's access keys. This operation requires write permission to the cache resource.", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "name": "parameters", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/RedisRegenerateKeyParameters" - }, - "description": "Specifies which key to reset." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "Lists the regenerated keys for Redis Cache", - "schema": { - "$ref": "#/definitions/RedisListKeysResult" - } - } - } - } - }, - "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Cache/Redis/{name}/forceReboot": { - "post": { - "tags": [ - "Redis" - ], - "operationId": "Redis_ForceReboot", - "description": "Reboot specified redis node(s). This operation requires write permission to the cache resource. There can be potential data loss.", - "parameters": [ - { - "name": "resourceGroupName", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the resource group." - }, - { - "name": "name", - "in": "path", - "required": true, - "type": "string", - "description": "The name of the redis cache." - }, - { - "name": "parameters", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/RedisRebootParameters" - }, - "description": "Specifies which redis node(s) to reboot." - }, - { - "$ref": "#/parameters/ApiVersionParameter" - }, - { - "$ref": "#/parameters/SubscriptionIdParameter" - } - ], - "responses": { - "200": { - "description": "" - }, - "204": { - "description": "" - } - } - } - } - }, - "definitions": { - "Sku": { - "properties": { - "name": { - "type": "string", - "description": "What type of redis cache to deploy. Valid values: (Basic, Standard, Premium)", - "enum": [ - "Basic", - "Standard", - "Premium" - ], - "x-ms-enum": { - "name": "SkuName", - "modelAsString": true - } - }, - "family": { - "type": "string", - "description": "Which family to use. Valid values: (C, P)", - "enum": [ - "C", - "P" - ], - "x-ms-enum": { - "name": "SkuFamily", - "modelAsString": true - } - }, - "capacity": { - "type": "integer", - "format": "int32", - "description": "What size of redis cache to deploy. Valid values: for C family (0, 1, 2, 3, 4, 5, 6), for P family (1, 2, 3, 4)" - } - }, - "required": [ - "name", - "family", - "capacity" - ], - "description": "Sku parameters supplied to the create redis operation." - }, - "RedisProperties": { - "properties": { - "redisVersion": { - "type": "string", - "description": "RedisVersion parameter has been deprecated. As such, it is no longer necessary to provide this parameter and any value specified is ignored." - }, - "sku": { - "$ref": "#/definitions/Sku", - "description": "What sku of redis cache to deploy." - }, - "redisConfiguration": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "All Redis Settings. Few possible keys: rdb-backup-enabled,rdb-storage-connection-string,rdb-backup-frequency,maxmemory-delta,maxmemory-policy,notify-keyspace-events,maxmemory-samples,slowlog-log-slower-than,slowlog-max-len,list-max-ziplist-entries,list-max-ziplist-value,hash-max-ziplist-entries,hash-max-ziplist-value,set-max-intset-entries,zset-max-ziplist-entries,zset-max-ziplist-value etc." - }, - "enableNonSslPort": { - "type": "boolean", - "description": "If the value is true, then the non-ssl redis server port (6379) will be enabled." - }, - "tenantSettings": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "tenantSettings" - }, - "shardCount": { - "type": "integer", - "format": "int32", - "description": "The number of shards to be created on a Premium Cluster Cache." - }, - "subnetId": { - "type": "string", - "description": "The full resource ID of a subnet in a virtual network to deploy the redis cache in. Example format: /subscriptions/{subid}/resourceGroups/{resourceGroupName}/Microsoft.{Network|ClassicNetwork}/VirtualNetworks/vnet1/subnets/subnet1" - }, - "staticIP": { - "type": "string", - "description": "Required when deploying a redis cache inside an existing Azure Virtual Network." - } - }, - "required": [ - "sku" - ], - "description": "Parameters supplied to CreateOrUpdate redis operation." - }, - "Resource": { - "properties": { - "id": { - "readOnly": true, - "type": "string", - "description": "Resource Id" - }, - "name": { - "readOnly": true, - "type": "string", - "description": "Resource name" - }, - "type": { - "readOnly": true, - "type": "string", - "description": "Resource type" - }, - "location": { - "type": "string", - "description": "Resource location" - }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Resource tags" - } - }, - "required": [ - "location" - ], - "x-ms-azure-resource": true - }, - "RedisCreateOrUpdateParameters": { - "properties": { - "properties": { - "x-ms-client-flatten": true, - "$ref": "#/definitions/RedisProperties", - "description": "Redis cache properties." - } - }, - "required": [ - "properties" - ], - "allOf": [ - { - "$ref": "#/definitions/Resource" - } - ], - "description": "Parameters supplied to the CreateOrUpdate Redis operation." - }, - "RedisAccessKeys": { - "properties": { - "primaryKey": { - "type": "string", - "description": "The current primary key that clients can use to authenticate with redis cache." - }, - "secondaryKey": { - "type": "string", - "description": "The current secondary key that clients can use to authenticate with redis cache." - } - }, - "description": "Redis cache access keys." - }, - "RedisReadableProperties": { - "properties": { - "provisioningState": { - "type": "string", - "description": "Redis instance provisioning status" - }, - "hostName": { - "type": "string", - "description": "Redis host name" - }, - "port": { - "type": "integer", - "format": "int32", - "description": "Redis non-ssl port" - }, - "sslPort": { - "type": "integer", - "format": "int32", - "description": "Redis ssl port" - } - }, - "allOf": [ - { - "$ref": "#/definitions/RedisProperties" - } - ], - "description": "Parameters describing a redis instance" - }, - "RedisReadablePropertiesWithAccessKey": { - "properties": { - "accessKeys": { - "$ref": "#/definitions/RedisAccessKeys", - "description": "Redis cache access keys." - } - }, - "allOf": [ - { - "$ref": "#/definitions/RedisReadableProperties" - } - ], - "description": "Properties generated only in response to CreateOrUpdate redis operation." - }, - "RedisResourceWithAccessKey": { - "properties": { - "properties": { - "x-ms-client-flatten": true, - "$ref": "#/definitions/RedisReadablePropertiesWithAccessKey", - "description": "Redis cache properties" - } - }, - "allOf": [ - { - "$ref": "#/definitions/RedisResource" - } - ], - "description": "A redis item in CreateOrUpdate Operation response." - }, - "RedisResource": { - "properties": { - "properties": { - "x-ms-client-flatten": true, - "$ref": "#/definitions/RedisReadableProperties", - "description": "Redis cache properties" - } - }, - "allOf": [ - { - "$ref": "#/definitions/Resource" - } - ], - "description": "A single redis item in List or Get Operation." - }, - "RedisListResult": { - "properties": { - "value": { - "type": "array", - "items": { - "$ref": "#/definitions/RedisResource" - }, - "description": "Results of the list operation" - }, - "nextLink": { - "type": "string", - "description": "Link for next set of locations." - } - }, - "description": "The response of list redis operation." - }, - "RedisListKeysResult": { - "properties": { - "primaryKey": { - "type": "string", - "description": "The current primary key that clients can use to authenticate with redis cache." - }, - "secondaryKey": { - "type": "string", - "description": "The current secondary key that clients can use to authenticate with redis cache." - } - }, - "description": "The response of redis list keys operation." - }, - "RedisRegenerateKeyParameters": { - "properties": { - "keyType": { - "type": "string", - "description": "Which redis access key to reset", - "enum": [ - "Primary", - "Secondary" - ], - "x-ms-enum": { - "name": "RedisKeyType", - "modelAsString": false - } - } - }, - "required": [ - "keyType" - ], - "description": "Specifies which redis access keys to reset." - }, - "RedisRebootParameters": { - "properties": { - "rebootType": { - "type": "string", - "description": "Which redis node(s) to reboot. Depending on this value data loss is possible.", - "enum": [ - "PrimaryNode", - "SecondaryNode", - "AllNodes" - ], - "x-ms-enum": { - "name": "RebootType", - "modelAsString": false - } - }, - "shardId": { - "type": "integer", - "format": "int32", - "description": "In case of cluster cache, this specifies shard id which should be rebooted." - } - }, - "required": [ - "rebootType" - ], - "description": "Specifies which redis node(s) to reboot." - } - }, - "parameters": { - "SubscriptionIdParameter": { - "name": "subscriptionId", - "in": "path", - "required": true, - "type": "string", - "description": "Gets subscription credentials which uniquely identify Microsoft Azure subscription. The subscription ID forms part of the URI for every service call." - }, - "ApiVersionParameter": { - "name": "api-version", - "in": "query", - "required": true, - "type": "string", - "description": "Client Api Version." - } - } -} \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-ref-allOf-inheritance.json b/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-ref-allOf-inheritance.json new file mode 100644 index 0000000000000..a72247c6fb389 --- /dev/null +++ b/AutoRest/Modelers/Swagger.Tests/Swagger/swagger-ref-allOf-inheritance.json @@ -0,0 +1,280 @@ +{ + "swagger": "2.0", + "info": { + "title": "RedisManagementClient", + "description": "A sample model for testing that swagger references and allOf gets understood by the modeler properly", + "version": "1.0.0" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json", + "text/json" + ], + "produces": [ + "application/json", + "text/json" + ], + "securityDefinitions": { }, + "security": [ ], + "tags": [ ], + "paths": { + "providers/Microsoft.Cache/Redis/{name}": { + "put": { + "operationId": "Redis_CreateOrUpdate", + "description": "Create or update a redis cache", + "parameters": [ + { + "name": "name", + "in": "path", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "parameters", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RedisCreateOrUpdateParameters" + }, + "description": "Parameters supplied to the CreateOrUpdate redis operation." + } + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/Resource" + } + } + } + } + } + }, + "definitions": { + "Sku": { + "properties": { + "name": { + "type": "string", + "description": "", + "enum": [ + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuName", + "modelAsString": true + } + }, + "family": { + "type": "string", + "description": "", + "enum": [ + "C", + "P" + ], + "x-ms-enum": { + "name": "SkuFamily", + "modelAsString": true + } + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "" + } + }, + "required": [ + "name", + "family", + "capacity" + ], + "description": "Sku parameters supplied to the create redis operation." + }, + "RedisProperties": { + "properties": { + "sku": { + "$ref": "#/definitions/Sku", + "description": "" + }, + "redisConfiguration": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "" + }, + "enableNonSslPort": { + "type": "boolean", + "description": "" + }, + "tenantSettings": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "" + }, + "shardCount": { + "type": "integer", + "format": "int32", + "description": "" + }, + "subnetId": { + "type": "string", + "description": "" + }, + "staticIP": { + "type": "string", + "description": "" + } + }, + "required": [ + "sku" + ], + "description": "'RedisProperties' - Parameters supplied to CreateOrUpdate redis operation." + }, + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Resource Id" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "Resource name" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "Resource type" + }, + "location": { + "type": "string", + "description": "Resource location" + }, + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags" + } + }, + "description": "''Resource' - common resource information", + "required": [ + "location" + ], + "x-ms-azure-resource": true + }, + "RedisCreateOrUpdateParameters": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisProperties", + "description": "'RedisCreateOrUpdateParameters.properties' - Redis cache properties." + } + }, + "required": [ + "properties" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "'RedisCreateOrUpdateParameters' - Parameters supplied to the CreateOrUpdate Redis operation." + }, + "RedisAccessKeys": { + "properties": { + "primaryKey": { + "type": "string", + "description": "" + }, + "secondaryKey": { + "type": "string", + "description": "" + } + }, + "description": "'RedisAccessKeys' - Redis cache access keys." + }, + "RedisReadableProperties": { + "properties": { + "provisioningState": { + "type": "string", + "description": "provisioning status" + }, + "hostName": { + "type": "string", + "description": "" + }, + "port": { + "type": "integer", + "format": "int32", + "description": "" + }, + "sslPort": { + "type": "integer", + "format": "int32", + "description": "" + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisProperties" + } + ], + "description": "'RedisReadableProperties' - Parameters describing a redis instance" + }, + "RedisReadablePropertiesWithAccessKey": { + "properties": { + "accessKeys": { + "$ref": "#/definitions/RedisAccessKeys", + "description": "Redis cache access keys." + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisReadableProperties" + } + ], + "description": "'RedisReadablePropertiesWithAccessKey' - Access Keys in addition to RedisReadableProperties" + }, + "RedisResourceWithAccessKey": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisReadablePropertiesWithAccessKey", + "description": "'RedisResourceWithAccessKey.properties' Redis cache properties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/RedisResource" + } + ], + "description": "'RedisResourceWithAccessKey' - A redis item in CreateOrUpdate Operation response." + }, + "RedisResource": { + "properties": { + "properties": { + "x-ms-client-flatten": true, + "$ref": "#/definitions/RedisReadableProperties", + "description": "'RedisResource.properties' - Redis cache properties" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "description": "'RedisResource' - A redis resource" + } + } +} \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs deleted file mode 100644 index e19bd34e90a5f..0000000000000 --- a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerRedisTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.IO; -using System.Linq; -using System.Net; -using Microsoft.Rest.Generator; -using Microsoft.Rest.Generator.ClientModel; -using Microsoft.Rest.Generator.CSharp; -using Microsoft.Rest.Generator.Extensibility; -using Microsoft.Rest.Generator.Utilities; -using Xunit; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Rest.Modeler.Swagger.Tests -{ - [Collection("AutoRest Tests")] - public class SwaggerModelerRedisTests - { - [Fact] - public void RedisResponseWithAccessKeys_IsAssignableTo_RedisResponse() - { - Generator.Modeler modeler = new SwaggerModeler(new Settings - { - Namespace = "Test", - Input = Path.Combine("Swagger", "swagger-redis-sample.json") - }); - var clientModel = modeler.Build(); - var redisResponseModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResource"); - var redisResponseWithAccessKeyModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResourceWithAccessKey"); - Assert.Equal(redisResponseModel, redisResponseWithAccessKeyModel.BaseModelType); - } - } -} \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs index 8c7af5c952207..42e20619bf07d 100644 --- a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs +++ b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs @@ -206,6 +206,40 @@ public void TestClientModelWithRecursiveTypes() Assert.Equal("String", clientModel.ModelTypes.First(m => m.Name == "Product").Properties[0].Type.ToString()); } + [Fact] + public void TestClientModel_AliasedAndInheritedTypes_SuccessfullyResolveIntoBaseModelRelationships() + { + Generator.Modeler modeler = new SwaggerModeler(new Settings + { + Namespace = "Test", + Input = Path.Combine("Swagger", "swagger-ref-allOf-inheritance.json") + }); + var clientModel = modeler.Build(); + + // This model has a few base type relationships which should be observed: + // RedisResource is a Resource + var resourceModel = clientModel.ModelTypes.Single(x => x.Name == "Resource"); + var redisResourceModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResource"); + Assert.Equal(resourceModel, redisResourceModel.BaseModelType); + + // RedisResourceWithAccessKey is a RedisResource + var redisResponseWithAccessKeyModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResourceWithAccessKey"); + Assert.Equal(redisResourceModel, redisResponseWithAccessKeyModel.BaseModelType); + + // RedisCreateOrUpdateParameters is a Resource + var redisCreateUpdateParametersModel = clientModel.ModelTypes.Single(x => x.Name == "RedisCreateOrUpdateParameters"); + Assert.Equal(resourceModel, redisCreateUpdateParametersModel.BaseModelType); + + // RedisReadableProperties is a RedisProperties + var redisPropertiesModel = clientModel.ModelTypes.Single(x => x.Name == "RedisProperties"); + var redisReadablePropertieModel = clientModel.ModelTypes.Single(x => x.Name == "RedisReadableProperties"); + Assert.Equal(redisPropertiesModel, redisReadablePropertieModel.BaseModelType); + + // RedisReadablePropertiesWithAccessKey is a RedisReadableProperties + var redisReadablePropertiesWithAccessKeysModel = clientModel.ModelTypes.Single(x => x.Name == "RedisReadablePropertiesWithAccessKey"); + Assert.Equal(redisReadablePropertieModel, redisReadablePropertiesWithAccessKeysModel.BaseModelType); + } + [Fact] public void TestClientModelWithNoContent() { From 7954a99bb2b07f99284cf407e5e2fad948e3a4b9 Mon Sep 17 00:00:00 2001 From: TimLovellSmith Date: Wed, 25 May 2016 13:22:04 -0700 Subject: [PATCH 5/5] Turn off CA1822 for test projects, warnings about performance of non-static unit test methods are a waste of time! --- .../Azure.CSharp.Tests/GlobalSuppressions.cs | 7 ----- .../CSharp/CSharp.Tests/GlobalSuppressions.cs | 18 ------------- .../GlobalSuppressions.cs | 26 ------------------- .../Extensions.Tests/GlobalSuppressions.cs | 10 ------- .../GlobalSuppressions.cs | 11 +------- .../Swagger.Tests/GlobalSuppressions.cs | 24 ----------------- .../Swagger.Tests/SwaggerModelerTests.cs | 11 ++++---- Tools/TestRules.ruleset | 4 ++- 8 files changed, 9 insertions(+), 102 deletions(-) diff --git a/AutoRest/Generators/CSharp/Azure.CSharp.Tests/GlobalSuppressions.cs b/AutoRest/Generators/CSharp/Azure.CSharp.Tests/GlobalSuppressions.cs index 725603fb1ce52..113846cb0d13a 100644 --- a/AutoRest/Generators/CSharp/Azure.CSharp.Tests/GlobalSuppressions.cs +++ b/AutoRest/Generators/CSharp/Azure.CSharp.Tests/GlobalSuppressions.cs @@ -8,10 +8,6 @@ // "In Suppression File". // You do not need to add suppressions to this file manually. -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", -Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.AcceptanceTests.#ResourceFlatteningGenerationTest()", Justification="Non-static test classes allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", -Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.AcceptanceTests.#EnsureStatusCode`1(System.Net.HttpStatusCode,System.Func`1>>)", Justification="Non-static test classes allow fixtures")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.AcceptanceTests.#LroSadPathTests()", Justification="Test code is straighforward")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", @@ -24,10 +20,7 @@ Target = "Fixtures.Azure.AcceptanceTestsLro.Models.SubProduct.#ProvisioningStateValues", Justification="Necessary for read-only properties in serialization types")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.AcceptanceTests.#XmsRequestClientIdTest()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.AcceptanceTests.#AzureODataTests()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.CSharpAzureCodeNamingFrameworkTests.#ConvertsPageResultsToPageTypeTest()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope = "type", Target = "Fixtures.Azure.AcceptanceTestsPaging.Models.Page`1")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.PageJsonTest.#TestNullPageDeSerialization()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.PageJsonTest.#TestNextLinkDeSerialization()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Fixtures.Azure.AcceptanceTestsLro.Models.Resource.#Id")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Fixtures.Azure.AcceptanceTestsLro.Models.Resource.#Type")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "Fixtures.Azure.AcceptanceTestsLro.Models.Resource.#Name")] diff --git a/AutoRest/Generators/CSharp/CSharp.Tests/GlobalSuppressions.cs b/AutoRest/Generators/CSharp/CSharp.Tests/GlobalSuppressions.cs index dd1260862d26d..85ac07db86656 100644 --- a/AutoRest/Generators/CSharp/CSharp.Tests/GlobalSuppressions.cs +++ b/AutoRest/Generators/CSharp/CSharp.Tests/GlobalSuppressions.cs @@ -16,23 +16,6 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1809:AvoidExcessiveLocals", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#ArrayTests()", Justification = "Fixture values for serialization")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1809:AvoidExcessiveLocals", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#DictionaryTests()", Justification = "Fixture values for serialization")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1809:AvoidExcessiveLocals", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#ComplexTests()", Justification = "Fixture values for serialization")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#TypeNormalizationTest()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#TypeNormalizationWithComplexTypesTest()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#VerifyMethodRenaming()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#NameCollisionTestWithoutNamespace()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#NameCollisionTestWithNamespace()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#SequenceWithRenamedComplexType()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#EnsureStatusCode`1(System.Net.HttpStatusCode,System.Func`1>>)", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#CanRoundTripSequences()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#CanRoundtripPolymorphicTypes()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#CanRoundtripFilledOutNestedTypesWithoutRecursion()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#CanRoundtripFilledOutNestedTypesWithoutRecursion2()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.ProcessOutputListener.#ScrubAndWriteValue(System.String,System.String)", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#CanSerializeAndDeserializePrimitiveTypes()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.MirrorTests.#UrlIsCorrectWhenBaseUriContainsSegment()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#VerifyInputMappingsForFlattening()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#VerifyInputMappingsForGrouping()", Justification = "Test classes must be non-static to allow fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.CSharpCodeNamingFrameworkTests.#VerifyInputMappingsForResources()", Justification = "Test classes must be non-static to allow fixtures")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Fixtures.AcceptanceTestsRequiredOptional.Models.ArrayWrapper.#Validate()", Justification="Validation exceptions types are being changed")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Fixtures.AcceptanceTestsRequiredOptional.Models.ClassWrapper.#Validate()", Justification="Validation exceptions types are being changed")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly", Scope = "member", Target = "Fixtures.MirrorSequences.Models.ErrorModel.#Validate()", Justification="Validation exceptions types are being changed")] @@ -50,4 +33,3 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "npm", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.ServiceController.#StartServiceProcess()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1057:StringUriOverloadsCallSystemUriOverloads", Scope = "member", Target = "Fixtures.AcceptanceTestsUrl.AutoRestUrlTestService.#.ctor(System.String,System.Net.Http.DelegatingHandler[])", Justification = "Invalid in the current context.")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1809:AvoidExcessiveLocals", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#TestDictionaryPrimitiveTypes(Fixtures.AcceptanceTestsBodyDictionary.AutoRestSwaggerBATdictionaryService)")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Tests.AcceptanceTests.#EnsureStatusCode`2(System.Net.HttpStatusCode,System.Func`1>>)")] diff --git a/AutoRest/Generators/Extensions/Azure.Extensions.Tests/GlobalSuppressions.cs b/AutoRest/Generators/Extensions/Azure.Extensions.Tests/GlobalSuppressions.cs index 314fda5322cc4..91b9c621e2bc2 100644 --- a/AutoRest/Generators/Extensions/Azure.Extensions.Tests/GlobalSuppressions.cs +++ b/AutoRest/Generators/Extensions/Azure.Extensions.Tests/GlobalSuppressions.cs @@ -8,31 +8,5 @@ // "In Suppression File". // You do not need to add suppressions to this file manually. -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#ResourceIsFlattenedForSimpleResource()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#ResourceIsFlattenedForComplexResource()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#SwaggerODataSpecParsingTest()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#SwaggerResourceExternalFalseTest()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#AzureParameterTest()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#PageableTest()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#ExternalResourceTypeIsNullSafe()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", - Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#ResourceIsFlattenedForConflictingResource()", - Justification = "Test methods must not be static to allow suite-level fixtures")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Azure.Extensions.Tests.AzureServiceClientNormalizerTests.#FlatteningTest()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.CSharpAzureCodeNamingFrameworkTests.#ConvertsPageResultsToPageTypeTest()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Scope = "member", Target = "Microsoft.Rest.Generator.CSharp.Azure.Tests.CSharpAzureCodeNamingFrameworkTests.#ConvertsPageResultsToPageTypeTest()")] diff --git a/AutoRest/Generators/Extensions/Extensions.Tests/GlobalSuppressions.cs b/AutoRest/Generators/Extensions/Extensions.Tests/GlobalSuppressions.cs index a628d38cbf3bc..46ddf026866e7 100644 --- a/AutoRest/Generators/Extensions/Extensions.Tests/GlobalSuppressions.cs +++ b/AutoRest/Generators/Extensions/Extensions.Tests/GlobalSuppressions.cs @@ -1,14 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientModelWithPayloadFlattening()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.MappingExtensionsTests.#TestInputMapping()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientModelWithPayloadFlatteningViaXMSClientFlatten()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientModelWithPayloadFlatteningViaXMSClientFlatten()")] - -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientModelClientName()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientNameCSharpNormalization()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientNameJavaNormalization()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientNameNodeJSNormalization()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientNamePythonNormalization()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Generator.Tests.ExtensionsTests.#TestClientNameRubyNormalization()")] diff --git a/AutoRest/Modelers/CompositeSwagger.Tests/GlobalSuppressions.cs b/AutoRest/Modelers/CompositeSwagger.Tests/GlobalSuppressions.cs index fbc8ea7cbdbcd..5f282702bb03e 100644 --- a/AutoRest/Modelers/CompositeSwagger.Tests/GlobalSuppressions.cs +++ b/AutoRest/Modelers/CompositeSwagger.Tests/GlobalSuppressions.cs @@ -1,10 +1 @@ -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeSwaggerWithTwoModels()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeSwaggerWithOneModel()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithEmptyInfo()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithEmptyDocuments()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithConflictInSettings()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithConflictInModel()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithConflictInMethod()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeModelWithConflictInGlobalParam()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.CompositeSwagger.Tests.CompositeSwaggerModelerTests.#CompositeSwaggerWithSameModels()")] - + \ No newline at end of file diff --git a/AutoRest/Modelers/Swagger.Tests/GlobalSuppressions.cs b/AutoRest/Modelers/Swagger.Tests/GlobalSuppressions.cs index 003d12bb4dc19..d7540fb6b412e 100644 --- a/AutoRest/Modelers/Swagger.Tests/GlobalSuppressions.cs +++ b/AutoRest/Modelers/Swagger.Tests/GlobalSuppressions.cs @@ -11,28 +11,4 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerSpecHelper.#RunTests`1(System.String,System.String,System.String,Microsoft.Rest.Generator.Settings)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerSpecHelper.#RunTests`1(Microsoft.Rest.Generator.Settings,System.String)")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestDataTypes()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelFromSimpleSwagger()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestExternalReferences()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestExternalReferencesWithAllOf()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestExternalReferencesWithReferencesInProperties()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestExternalReferencesWithExtension()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithInheritance()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelPolymorhism()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#ClientModelWithCircularDependencyThrowsError()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithRecursiveTypes()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithNoContent()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithDifferentReturnsTypesBasedOnStatusCode()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#DefaultReturnsCorrectType()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#GlobalResponsesReference()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithStreamAndByteArray()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithMethodGroups()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestDataTypes()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientWithValidation()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithPayloadFlattening()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestClientModelWithResponseHeaders()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestCustomPaths()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestSettingsFromSwagger()")] [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "client", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestSettingsFromSwagger()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestConstants()")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Scope = "member", Target = "Microsoft.Rest.Modeler.Swagger.Tests.SwaggerModelerTests.#TestCompositeConstants()")] - diff --git a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs index 42e20619bf07d..6083741a77c62 100644 --- a/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs +++ b/AutoRest/Modelers/Swagger.Tests/SwaggerModelerTests.cs @@ -186,8 +186,8 @@ public void ClientModelWithCircularDependencyThrowsError() Input = Path.Combine("Swagger", "swagger-allOf-circular.json") }); var ex = Assert.Throws(() => modeler.Build()); - Assert.Contains("circular", ex.Message, StringComparison.InvariantCultureIgnoreCase); - Assert.Contains("siamese", ex.Message, StringComparison.InvariantCultureIgnoreCase); + Assert.Contains("circular", ex.Message, StringComparison.OrdinalIgnoreCase); + Assert.Contains("siamese", ex.Message, StringComparison.OrdinalIgnoreCase); } [Fact] @@ -207,16 +207,16 @@ public void TestClientModelWithRecursiveTypes() } [Fact] - public void TestClientModel_AliasedAndInheritedTypes_SuccessfullyResolveIntoBaseModelRelationships() + public void TestClientModelWithManyAllOfRelationships() { - Generator.Modeler modeler = new SwaggerModeler(new Settings + var modeler = new SwaggerModeler(new Settings { Namespace = "Test", Input = Path.Combine("Swagger", "swagger-ref-allOf-inheritance.json") }); var clientModel = modeler.Build(); - // This model has a few base type relationships which should be observed: + // the model has a few base type relationships which should be observed: // RedisResource is a Resource var resourceModel = clientModel.ModelTypes.Single(x => x.Name == "Resource"); var redisResourceModel = clientModel.ModelTypes.Single(x => x.Name == "RedisResource"); @@ -596,7 +596,6 @@ public void TestSettingsFromSwagger() Assert.Equal(true, codeGenerator.InternalConstructors); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] [Fact] public void TestParameterizedHostFromSwagger() { diff --git a/Tools/TestRules.ruleset b/Tools/TestRules.ruleset index 6c0755dd13d58..15f831c090a89 100644 --- a/Tools/TestRules.ruleset +++ b/Tools/TestRules.ruleset @@ -1,4 +1,4 @@ - + @@ -35,6 +35,8 @@ + +