diff --git a/src/Microsoft.OpenApi.Readers/Interface/ILog.cs b/src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs
similarity index 57%
rename from src/Microsoft.OpenApi.Readers/Interface/ILog.cs
rename to src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs
index dd9df7c4c..d01b8dbc9 100644
--- a/src/Microsoft.OpenApi.Readers/Interface/ILog.cs
+++ b/src/Microsoft.OpenApi.Readers/Interface/IDiagnostic.cs
@@ -3,19 +3,12 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
-using System.Collections.Generic;
-
namespace Microsoft.OpenApi.Readers.Interface
{
///
- /// Interface for the log
+ /// Interface for the entity containing diagnostic information from the reading process.
///
- /// Type of recorded errors
- public interface ILog
+ public interface IDiagnostic
{
- ///
- /// List of recorded errors.
- ///
- IList Errors { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs b/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs
index d718c3e90..6f0274552 100644
--- a/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs
+++ b/src/Microsoft.OpenApi.Readers/Interface/IOpenApiReader.cs
@@ -3,24 +3,21 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------
-using SharpYaml.Serialization.Logging;
-
namespace Microsoft.OpenApi.Readers.Interface
{
///
- /// Interface for open API readers.
+ /// Interface for Open API readers.
///
/// The type of input to read from.
- /// The type of log for information from reading process.
- /// The type of the recorded error from the reading process.
- public interface IOpenApiReader where TLog : ILog
+ /// The type of diagnostic for information from reading process.
+ public interface IOpenApiReader where TDiagnostic : IDiagnostic
{
///
/// Reads the input and parses it into an Open API document.
///
/// The input to read from.
- /// The log or context containing information from the reading process.
+ /// The diagnostic entity containing information from the reading process.
/// The Open API document.
- OpenApiDocument Read(TInput input, out TLog log);
+ OpenApiDocument Read(TInput input, out TDiagnostic diagnostic);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ListNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ListNode.cs
deleted file mode 100644
index 7e833d8bb..000000000
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/ListNode.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using SharpYaml.Serialization;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Microsoft.OpenApi.Readers.YamlReaders
-{
- internal class ListNode : ParseNode, IEnumerable
- {
- YamlSequenceNode nodeList;
- ParsingContext context;
- public ListNode(ParsingContext ctx, YamlSequenceNode sequenceNode) : base(ctx)
- {
- this.context = ctx;
- nodeList = sequenceNode;
- }
-
- public override List CreateList(Func map)
- {
- var yamlSequence = nodeList as YamlSequenceNode;
- if (yamlSequence == null) throw new OpenApiException($"Expected list at line {nodeList.Start.Line} while parsing {typeof(T).Name}");
-
- return yamlSequence.Select(n => map(new MapNode(this.context,n as YamlMappingNode))).Where(i => i != null).ToList();
- }
-
- public override List CreateSimpleList(Func map)
- {
- var yamlSequence = this.nodeList as YamlSequenceNode;
- if (yamlSequence == null) throw new OpenApiException($"Expected list at line {nodeList.Start.Line} while parsing {typeof(T).Name}");
-
- return yamlSequence.Select(n => map(new ValueNode(this.Context,(YamlScalarNode)n))).ToList();
- }
-
- public IEnumerator GetEnumerator()
- {
- return nodeList.Select(n => YamlHelper.Create(this.Context,n)).ToList().GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.GetEnumerator();
- }
- }
-
-
-}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/MapNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/MapNode.cs
deleted file mode 100644
index 88737a140..000000000
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/MapNode.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-using SharpYaml.Schemas;
-using SharpYaml.Serialization;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace Microsoft.OpenApi.Readers.YamlReaders
-{
- ///
- /// Abstraction of a Map to isolate semantic parsing from details of
- ///
- internal class MapNode : ParseNode, IEnumerable
- {
- YamlMappingNode node;
- private List nodes;
-
- public static MapNode Create(string yaml)
- {
-
- var parsingContent = new ParsingContext();
- return new MapNode(parsingContent, (YamlMappingNode)YamlHelper.ParseYaml(yaml));
- }
-
- public MapNode(ParsingContext ctx, YamlMappingNode node) : base(ctx)
- {
- if (node == null) throw new OpenApiException($"Expected map");
- this.node = node;
- nodes = this.node.Children.Select(kvp => new PropertyNode(Context, kvp.Key.GetScalarValue(), kvp.Value)).Cast().ToList();
- }
-
- public IEnumerator GetEnumerator()
- {
- return this.nodes.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return this.nodes.GetEnumerator();
- }
-
- public PropertyNode this[string key]
- {
- get
- {
- YamlNode node = null;
- if (this.node.Children.TryGetValue(new YamlScalarNode(key), out node))
- {
- return new PropertyNode(this.Context, key, this.node.Children[new YamlScalarNode(key)]);
- } else
- {
- return null;
- }
- }
- }
-
- public override string GetRaw()
- {
- var x = new Serializer(new SerializerSettings(new JsonSchema()) { EmitJsonComptible = true } );
- return x.Serialize(this.node);
-
- }
-
- public string GetScalarValue(ValueNode key)
- {
- var scalarNode = this.node.Children[new YamlScalarNode(key.GetScalarValue())] as YamlScalarNode;
- if (scalarNode == null) throw new OpenApiException($"Expected scalar at line {this.node.Start.Line} for key {key.GetScalarValue()}");
-
- return scalarNode.Value;
- }
-
- public T GetReferencedObject(string refPointer) where T : IOpenApiReference
- {
- return (T)this.Context.GetReferencedObject(refPointer);
- }
- public T CreateOrReferenceDomainObject(Func factory) where T: IOpenApiReference
- {
- T domainObject;
- var refPointer = GetReferencePointer(); // What should the DOM of a reference look like?
- // Duplicated object - poor perf/more memory/unsynchronized changes
- // Intermediate object - require common base class/client code has to explicitly code for it.
- // Delegating object - lot of setup work/maintenance/ require full interfaces
- // **current favourite***Shared object - marker to indicate its a reference/serialization code must serialize as reference everywhere except components.
- if (refPointer != null)
- {
- domainObject = (T)this.Context.GetReferencedObject(refPointer);
-
- }
- else
- {
- domainObject = factory();
- }
-
- return domainObject;
- }
-
- public override Dictionary CreateMap(Func map)
- {
- var yamlMap = this.node;
- if (yamlMap == null) throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
- var nodes = yamlMap.Select(n => new { key = n.Key.GetScalarValue(), value = map(new MapNode(this.Context,n.Value as YamlMappingNode)) });
- return nodes.ToDictionary(k => k.key, v => v.value);
- }
-
- public override Dictionary CreateMapWithReference(string refpointerbase, Func map)
- {
-
- var yamlMap = this.node;
- if (yamlMap == null) throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
- var nodes = yamlMap.Select(n => new { key = n.Key.GetScalarValue(),
- value = this.GetReferencedObject(refpointerbase + n.Key.GetScalarValue())
- ?? map(new MapNode(this.Context, (YamlMappingNode)n.Value))
- });
- return nodes.ToDictionary(k => k.key, v => v.value);
- }
-
- public override Dictionary CreateSimpleMap(Func map)
- {
- var yamlMap = this.node;
- if (yamlMap == null) throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
- var nodes = yamlMap.Select(n => new { key = n.Key.GetScalarValue(), value = map(new ValueNode(this.Context, (YamlScalarNode)n.Value)) });
- return nodes.ToDictionary(k => k.key, v => v.value);
- }
-
- public string GetReferencePointer()
- {
- YamlNode refNode;
-
- if (!this.node.Children.TryGetValue(new YamlScalarNode("$ref"), out refNode))
- {
- return null;
- }
- return refNode.GetScalarValue();
- }
- }
-
-
-}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiDiagnostic.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiDiagnostic.cs
new file mode 100644
index 000000000..0c40644b3
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiDiagnostic.cs
@@ -0,0 +1,15 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System.Collections.Generic;
+using Microsoft.OpenApi.Readers.Interface;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders
+{
+ public class OpenApiDiagnostic : IDiagnostic
+ {
+ public IList Errors { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiError.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiError.cs
index 06433d45e..fb78ceeb3 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiError.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiError.cs
@@ -1,17 +1,21 @@
-using Microsoft.OpenApi.Readers.Interface;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
namespace Microsoft.OpenApi.Readers.YamlReaders
{
public class OpenApiError
{
- string pointer;
- string message;
+ private readonly string message;
+ private readonly string pointer;
- public OpenApiError(OpenApiException ex)
+ public OpenApiError(OpenApiException exception)
{
- this.message = ex.Message;
- this.pointer = ex.Pointer;
+ message = exception.Message;
+ pointer = exception.Pointer;
}
+
public OpenApiError(string pointer, string message)
{
this.pointer = pointer;
@@ -20,7 +24,7 @@ public OpenApiError(string pointer, string message)
public override string ToString()
{
- return this.message + (!string.IsNullOrEmpty(this.pointer) ? " at " + this.pointer : "");
+ return message + (!string.IsNullOrEmpty(pointer) ? " at " + pointer : "");
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStreamReader.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStreamReader.cs
index 1488ac041..779902be9 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStreamReader.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStreamReader.cs
@@ -6,6 +6,7 @@
using System.IO;
using System.Linq;
using Microsoft.OpenApi.Readers.Interface;
+using Microsoft.OpenApi.Readers.YamlReaders.ParseNodes;
using SharpYaml;
using SharpYaml.Serialization;
@@ -14,7 +15,7 @@ namespace Microsoft.OpenApi.Readers.YamlReaders
///
/// Service class for converting streams into OpenApiDocument instances
///
- public class OpenApiStreamReader : IOpenApiReader
+ public class OpenApiStreamReader : IOpenApiReader
{
///
/// Gets the version of the Open API document.
@@ -22,46 +23,42 @@ public class OpenApiStreamReader : IOpenApiReader
/// Reads the stream input and parses it into an Open API document.
///
- public OpenApiDocument Read(Stream input, out ParsingContext context)
+ public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
{
RootNode rootNode;
- context = new ParsingContext();
-
+ var context = new ParsingContext();
+ diagnostic = new OpenApiDiagnostic();
+
try
{
using (var streamReader = new StreamReader(input))
{
-
var yamlStream = new YamlStream();
yamlStream.Load(streamReader);
var yamlDocument = yamlStream.Documents.First();
- rootNode = new RootNode(context, yamlDocument);
+ rootNode = new RootNode(context, diagnostic, yamlDocument);
}
}
catch (SyntaxErrorException ex)
{
- context.Errors.Add(new OpenApiError(string.Empty, ex.Message));
- context.OpenApiDocument = new OpenApiDocument(); // Could leave this null?
+ diagnostic.Errors.Add(new OpenApiError(string.Empty, ex.Message));
- return context.OpenApiDocument;
+ return new OpenApiDocument();
}
var inputVersion = GetVersion(rootNode);
@@ -70,25 +67,24 @@ public OpenApiDocument Read(Stream input, out ParsingContext context)
{
case "2.0":
context.SetReferenceService(
- new ReferenceService(rootNode)
+ new OpenApiReferenceService(rootNode)
{
- loadReference = OpenApiV2Builder.LoadReference,
- parseReference = p => OpenApiV2Builder.ParseReference(p)
+ loadReference = OpenApiV2Deserializer.LoadReference,
+ parseReference = p => OpenApiV2Deserializer.ParseReference(p)
});
- context.OpenApiDocument = OpenApiV2Builder.LoadOpenApi(rootNode);
- break;
+
+ return OpenApiV2Deserializer.LoadOpenApi(rootNode);
+
default:
context.SetReferenceService(
- new ReferenceService(rootNode)
+ new OpenApiReferenceService(rootNode)
{
- loadReference = OpenApiV3Builder.LoadReference,
+ loadReference = OpenApiV3Deserializer.LoadReference,
parseReference = p => new OpenApiReference(p)
});
- context.OpenApiDocument = OpenApiV3Builder.LoadOpenApi(rootNode);
- break;
- }
- return context.OpenApiDocument;
+ return OpenApiV3Deserializer.LoadOpenApi(rootNode);
+ }
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStringReader.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStringReader.cs
index d5ff05905..a06625d2d 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStringReader.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiStringReader.cs
@@ -11,12 +11,12 @@ namespace Microsoft.OpenApi.Readers.YamlReaders
///
/// Service class for converting strings into OpenApiDocument instances
///
- public class OpenApiStringReader : IOpenApiReader
+ public class OpenApiStringReader : IOpenApiReader
{
///
/// Reads the string input and parses it into an Open API document.
///
- public OpenApiDocument Read(string input, out ParsingContext context)
+ public OpenApiDocument Read(string input, out OpenApiDiagnostic diagnostic)
{
using (var memoryStream = new MemoryStream())
{
@@ -25,7 +25,7 @@ public OpenApiDocument Read(string input, out ParsingContext context)
writer.Flush();
memoryStream.Position = 0;
- return new OpenApiStreamReader().Read(memoryStream, out context);
+ return new OpenApiStreamReader().Read(memoryStream, out diagnostic);
}
}
}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Builder.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs
similarity index 95%
rename from src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Builder.cs
rename to src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs
index eeee13a6a..f852cae9c 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Builder.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV2Deserializer.cs
@@ -1,12 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.OpenApi.Readers.YamlReaders.ParseNodes;
namespace Microsoft.OpenApi.Readers.YamlReaders
{
- internal static class OpenApiV2Builder
+ ///
+ /// Class containing logic to deserialize Open API V2 document into
+ /// runtime Open API object model.
+ ///
+ internal static class OpenApiV2Deserializer
{
#region OpenApiObject
+
public static FixedFieldMap OpenApiFixedFields = new FixedFieldMap {
{ "swagger", (o,n) => { /* Ignore it */} },
{ "info", (o,n) => o.Info = LoadInfo(n) },
@@ -23,9 +29,7 @@ internal static class OpenApiV2Builder
{ "security", (o,n) => o.SecurityRequirements = n.CreateList(LoadSecurityRequirement)},
{ "tags", (o,n) => o.Tags = n.CreateList(LoadTag)},
{ "externalDocs", (o,n) => o.ExternalDocs = LoadExternalDocs(n) }
- };
-
-
+ };
private static void MakeServers(IList servers, ParsingContext context)
{
@@ -163,7 +167,7 @@ internal static OpenApiLicense LoadLicense(ParseNode node)
public static PatternFieldMap PathsPatternFields = new PatternFieldMap
{
- { (s)=> s.StartsWith("/"), (o,k,n)=> o.Add(k, OpenApiV2Builder.LoadPathItem(n) ) },
+ { (s)=> s.StartsWith("/"), (o,k,n)=> o.Add(k, OpenApiV2Deserializer.LoadPathItem(n) ) },
{ (s)=> s.StartsWith("x-"), (o,k,n)=> o.Extensions.Add(k, new OpenApiString(n.GetScalarValue())) }
};
@@ -184,7 +188,7 @@ public static OpenApiPaths LoadPaths(ParseNode node)
private static FixedFieldMap PathItemFixedFields = new FixedFieldMap
{
{ "$ref", (o,n) => { /* Not supported yet */} },
- { "parameters", (o,n) => { o.Parameters = n.CreateList(OpenApiV2Builder.LoadParameter); } },
+ { "parameters", (o,n) => { o.Parameters = n.CreateList(OpenApiV2Deserializer.LoadParameter); } },
};
@@ -192,7 +196,7 @@ public static OpenApiPaths LoadPaths(ParseNode node)
{
{ (s)=> s.StartsWith("x-"), (o,k,n)=> o.Extensions.Add(k, new OpenApiString(n.GetScalarValue())) },
{ (s)=> "get,put,post,delete,patch,options,head,patch".Contains(s),
- (o,k,n)=> o.AddOperation(OperationTypeExtensions.ParseOperationType(k), OpenApiV2Builder.LoadOperation(n) ) }
+ (o,k,n)=> o.AddOperation(OperationTypeExtensions.ParseOperationType(k), OpenApiV2Deserializer.LoadOperation(n) ) }
};
@@ -213,14 +217,22 @@ public static OpenApiPathItem LoadPathItem(ParseNode node)
private static FixedFieldMap OperationFixedFields = new FixedFieldMap
{
- { "tags", (o,n) => o.Tags = n.CreateSimpleList((v) => ReferenceService.LoadTagByReference(v.Context,v.GetScalarValue()))},
+ { "tags", (o,n) => o.Tags = n.CreateSimpleList((valueNode) =>
+ OpenApiReferenceService.LoadTagByReference(
+ valueNode.Context,
+ valueNode.Diagnostic,
+ valueNode.GetScalarValue()))},
{ "summary", (o,n) => { o.Summary = n.GetScalarValue(); } },
{ "description", (o,n) => { o.Description = n.GetScalarValue(); } },
{ "externalDocs", (o,n) => { o.ExternalDocs = LoadExternalDocs(n); } },
{ "operationId", (o,n) => { o.OperationId = n.GetScalarValue(); } },
{ "parameters", (o,n) => { o.Parameters = n.CreateList(LoadParameter); } },
- { "consumes", (o,n) => n.Context.SetTempStorage("operationconsumes", n.CreateSimpleList((s) => s.GetScalarValue()))},
- { "produces", (o,n) => n.Context.SetTempStorage("operationproduces", n.CreateSimpleList((s) => s.GetScalarValue()))},
+ { "consumes", (o,n) => n.Context.SetTempStorage(
+ "operationconsumes",
+ n.CreateSimpleList((s) => s.GetScalarValue()))},
+ { "produces", (o,n) => n.Context.SetTempStorage(
+ "operationproduces",
+ n.CreateSimpleList((s) => s.GetScalarValue()))},
{ "responses", (o,n) => { o.Responses = n.CreateMap(LoadResponse); } },
{ "deprecated", (o,n) => { o.Deprecated = bool.Parse(n.GetScalarValue()); } },
{ "security", (o,n) => { o.Security = n.CreateList(LoadSecurityRequirement); } },
@@ -765,20 +777,19 @@ public static OpenApiOAuthFlow LoadOAuthFlow(ParseNode node)
#region SecurityRequirement
public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node)
{
-
var mapNode = node.CheckMapNode("security");
var obj = new OpenApiSecurityRequirement();
foreach (var property in mapNode)
{
- var scheme = ReferenceService.LoadSecuritySchemeByReference(mapNode.Context, property.Name);
+ var scheme = OpenApiReferenceService.LoadSecuritySchemeByReference(mapNode.Context, mapNode.Diagnostic, property.Name);
if (scheme != null)
{
obj.Schemes.Add(scheme, property.Value.CreateSimpleList(n2 => n2.GetScalarValue()));
} else
{
- node.Context.Errors.Add(new OpenApiError(node.Context.GetLocation(), $"Scheme {property.Name} is not found"));
+ node.Diagnostic.Errors.Add(new OpenApiError(node.Context.GetLocation(), $"Scheme {property.Name} is not found"));
}
}
return obj;
@@ -854,13 +865,13 @@ public static IOpenApiReference LoadReference(OpenApiReference reference, object
switch (reference.ReferenceType)
{
case ReferenceType.Schema:
- referencedObject = OpenApiV2Builder.LoadSchema(node);
+ referencedObject = LoadSchema(node);
break;
case ReferenceType.Parameter:
- referencedObject = OpenApiV2Builder.LoadParameter(node);
+ referencedObject = LoadParameter(node);
break;
case ReferenceType.SecurityScheme:
- referencedObject = OpenApiV2Builder.LoadSecurityScheme(node);
+ referencedObject = LoadSecurityScheme(node);
break;
case ReferenceType.Tags:
ListNode list = (ListNode)node;
@@ -868,7 +879,7 @@ public static IOpenApiReference LoadReference(OpenApiReference reference, object
{
foreach (var item in list)
{
- var tag = OpenApiV2Builder.LoadTag(item);
+ var tag = LoadTag(item);
if (tag.Name == reference.TypeName)
{
@@ -896,15 +907,15 @@ private static void ParseMap(MapNode mapNode, T domainObject, FixedFieldMap(domainObject, fixedFieldMap, patternFieldMap);
- if (requiredFields != null) requiredFields.Remove(propertyNode.Name);
+ requiredFields?.Remove(propertyNode.Name);
}
}
- private static void ReportMissing(ParseNode node, List required)
+ private static void ReportMissing(ParseNode node, IList required)
{
foreach ( var error in required.Select(r => new OpenApiError("", $"{r} is a required property")).ToList() )
{
- node.Context.Errors.Add(error);
+ node.Diagnostic.Errors.Add(error);
}
}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Builder.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs
similarity index 95%
rename from src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Builder.cs
rename to src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs
index 9dac8a643..d1793575c 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Builder.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/OpenApiV3Deserializer.cs
@@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.OpenApi.Readers.YamlReaders.ParseNodes;
namespace Microsoft.OpenApi.Readers.YamlReaders
{
- internal static class OpenApiV3Builder
+ ///
+ /// Class containing logic to deserialize Open API V3 document into
+ /// runtime Open API object model.
+ ///
+ internal static class OpenApiV3Deserializer
{
#region OpenApiObject
public static FixedFieldMap OpenApiFixedFields = new FixedFieldMap {
@@ -270,7 +275,8 @@ public static OpenApiPathItem LoadPathItem(ParseNode node)
private static FixedFieldMap OperationFixedFields = new FixedFieldMap
{
- { "tags", (o,n) => o.Tags = n.CreateSimpleList((v) => ReferenceService.LoadTagByReference(v.Context,v.GetScalarValue()))},
+ { "tags", (o,n) => o.Tags = n.CreateSimpleList((valueNode) =>
+ OpenApiReferenceService.LoadTagByReference(valueNode.Context, valueNode.Diagnostic, valueNode.GetScalarValue()))},
{ "summary", (o,n) => { o.Summary = n.GetScalarValue(); } },
{ "description", (o,n) => { o.Description = n.GetScalarValue(); } },
{ "externalDocs", (o,n) => { o.ExternalDocs = LoadExternalDocs(n); } },
@@ -677,11 +683,6 @@ internal static OpenApiTag LoadTag(ParseNode n)
{ (s)=> s.StartsWith("x-"), (o,k,n)=> o.Extensions.Add(k, new OpenApiString(n.GetScalarValue())) }
};
- public static OpenApiSchema LoadSchema(string schema)
- {
- return LoadSchema(MapNode.Create(schema));
- }
-
public static OpenApiSchema LoadSchema(ParseNode node)
{
@@ -807,7 +808,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node)
foreach (var property in mapNode)
{
- var scheme = ReferenceService.LoadSecuritySchemeByReference(mapNode.Context, property.Name);
+ var scheme = OpenApiReferenceService.LoadSecuritySchemeByReference(mapNode.Context, mapNode.Diagnostic, property.Name);
obj.Schemes.Add(scheme, property.Value.CreateSimpleList(n2 => n2.GetScalarValue()));
}
@@ -826,31 +827,36 @@ public static IOpenApiReference LoadReference(OpenApiReference pointer, object r
switch (pointer.ReferenceType)
{
case ReferenceType.Schema:
- referencedObject = OpenApiV3Builder.LoadSchema(node);
+ referencedObject = LoadSchema(node);
break;
- case ReferenceType.Parameter:
- referencedObject = OpenApiV3Builder.LoadParameter(node);
+ case ReferenceType.Parameter:
+ referencedObject = LoadParameter(node);
break;
+
case ReferenceType.Callback:
- referencedObject = OpenApiV3Builder.LoadCallback(node);
+ referencedObject = LoadCallback(node);
break;
+
case ReferenceType.SecurityScheme:
- referencedObject = OpenApiV3Builder.LoadSecurityScheme(node);
+ referencedObject = LoadSecurityScheme(node);
break;
+
case ReferenceType.Link:
- referencedObject = OpenApiV3Builder.LoadLink(node);
+ referencedObject = LoadLink(node);
break;
+
case ReferenceType.Example:
- referencedObject = OpenApiV3Builder.LoadExample(node);
+ referencedObject = LoadExample(node);
break;
+
case ReferenceType.Tags:
ListNode list = (ListNode)node;
if (list != null)
{
foreach (var item in list)
{
- var tag = OpenApiV3Builder.LoadTag(item);
+ var tag = OpenApiV3Deserializer.LoadTag(item);
if (tag.Name == pointer.TypeName)
{
@@ -864,10 +870,11 @@ public static IOpenApiReference LoadReference(OpenApiReference pointer, object r
}
break;
+
default:
throw new OpenApiException($"Unknown type of $ref {pointer.ReferenceType} at {pointer.ToString()}");
-
}
+
return referencedObject;
}
@@ -878,8 +885,9 @@ private static void ParseMap(MapNode mapNode, T domainObject, FixedFieldMap(domainObject, fixedFieldMap, patternFieldMap);
- if (requiredFields != null) requiredFields.Remove(propertyNode.Name);
+ requiredFields?.Remove(propertyNode.Name);
}
+
ReportMissing(mapNode, requiredFields);
}
@@ -888,14 +896,17 @@ private static RuntimeExpression LoadRuntimeExpression(ParseNode node)
var value = node.GetScalarValue();
return new RuntimeExpression(value);
}
- private static void ReportMissing(ParseNode node, List required)
+
+ private static void ReportMissing(ParseNode node, IList required)
{
- if (required != null && required.Count > 0)
+ if (required == null || !required.Any() )
{
- foreach ( var error in required.Select(r => new OpenApiError("", $"{r} is a required property of {node.Context.GetLocation()}")).ToList())
- {
- node.Context.Errors.Add(error);
- }
+ return;
+ }
+
+ foreach (var error in required.Select(r => new OpenApiError("", $"{r} is a required property of {node.Context.GetLocation()}")).ToList())
+ {
+ node.Diagnostic.Errors.Add(error);
}
}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/FixedFieldMap.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/FixedFieldMap.cs
new file mode 100644
index 000000000..3e7fcaf78
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/FixedFieldMap.cs
@@ -0,0 +1,14 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ internal class FixedFieldMap : Dictionary>
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ListNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ListNode.cs
new file mode 100644
index 000000000..1a2f09f6d
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ListNode.cs
@@ -0,0 +1,61 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using SharpYaml.Serialization;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ internal class ListNode : ParseNode, IEnumerable
+ {
+ private readonly YamlSequenceNode nodeList;
+
+ public ListNode(ParsingContext context, OpenApiDiagnostic diagnostic, YamlSequenceNode sequenceNode) : base(
+ context,
+ diagnostic)
+ {
+ nodeList = sequenceNode;
+ }
+
+ public override List CreateList(Func map)
+ {
+ var yamlSequence = nodeList;
+ if (yamlSequence == null)
+ {
+ throw new OpenApiException(
+ $"Expected list at line {nodeList.Start.Line} while parsing {typeof(T).Name}");
+ }
+
+ return yamlSequence.Select(n => map(new MapNode(Context, Diagnostic, n as YamlMappingNode)))
+ .Where(i => i != null)
+ .ToList();
+ }
+
+ public override List CreateSimpleList(Func map)
+ {
+ var yamlSequence = nodeList;
+ if (yamlSequence == null)
+ {
+ throw new OpenApiException(
+ $"Expected list at line {nodeList.Start.Line} while parsing {typeof(T).Name}");
+ }
+
+ return yamlSequence.Select(n => map(new ValueNode(Context, Diagnostic, (YamlScalarNode)n))).ToList();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return nodeList.Select(n => Create(Context, Diagnostic, n)).ToList().GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/MapNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/MapNode.cs
new file mode 100644
index 000000000..49fbd8e5f
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/MapNode.cs
@@ -0,0 +1,173 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using SharpYaml.Schemas;
+using SharpYaml.Serialization;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ ///
+ /// Abstraction of a Map to isolate semantic parsing from details of
+ ///
+ internal class MapNode : ParseNode, IEnumerable
+ {
+ private readonly YamlMappingNode node;
+ private readonly List nodes;
+
+ public MapNode(ParsingContext context, OpenApiDiagnostic diagnostic, string yamlString) :
+ this(context, diagnostic, (YamlMappingNode)YamlHelper.ParseYamlString(yamlString))
+ {
+ }
+
+ public MapNode(ParsingContext context, OpenApiDiagnostic diagnostic, YamlMappingNode node) : base(context, diagnostic)
+ {
+ if (node == null)
+ {
+ throw new OpenApiException($"Expected map");
+ }
+
+ this.node = node;
+
+ nodes = this.node.Children
+ .Select(kvp => new PropertyNode(Context, Diagnostic, kvp.Key.GetScalarValue(), kvp.Value))
+ .Cast()
+ .ToList();
+ }
+
+ public PropertyNode this[string key]
+ {
+ get
+ {
+ YamlNode node = null;
+ if (this.node.Children.TryGetValue(new YamlScalarNode(key), out node))
+ {
+ return new PropertyNode(Context, Diagnostic, key, this.node.Children[new YamlScalarNode(key)]);
+ }
+
+ return null;
+ }
+ }
+
+ public override Dictionary CreateMap(Func map)
+ {
+ var yamlMap = node;
+ if (yamlMap == null)
+ {
+ throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
+ }
+
+ var nodes = yamlMap.Select(
+ n => new
+ {
+ key = n.Key.GetScalarValue(),
+ value = map(new MapNode(Context, Diagnostic, n.Value as YamlMappingNode))
+ });
+ return nodes.ToDictionary(k => k.key, v => v.value);
+ }
+
+ public override Dictionary CreateMapWithReference(string refpointerbase, Func map)
+ {
+ var yamlMap = node;
+ if (yamlMap == null)
+ {
+ throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
+ }
+
+ var nodes = yamlMap.Select(
+ n => new
+ {
+ key = n.Key.GetScalarValue(),
+ value = GetReferencedObject(refpointerbase + n.Key.GetScalarValue()) ??
+ map(new MapNode(Context, Diagnostic, (YamlMappingNode)n.Value))
+ });
+ return nodes.ToDictionary(k => k.key, v => v.value);
+ }
+
+ public T CreateOrReferenceDomainObject(Func factory) where T : IOpenApiReference
+ {
+ T domainObject;
+ var refPointer = GetReferencePointer(); // What should the DOM of a reference look like?
+ // Duplicated object - poor perf/more memory/unsynchronized changes
+ // Intermediate object - require common base class/client code has to explicitly code for it.
+ // Delegating object - lot of setup work/maintenance/ require full interfaces
+ // **current favourite***Shared object - marker to indicate its a reference/serialization code must serialize as reference everywhere except components.
+ if (refPointer != null)
+ {
+ domainObject = (T)Context.GetReferencedObject(Diagnostic, refPointer);
+ }
+ else
+ {
+ domainObject = factory();
+ }
+
+ return domainObject;
+ }
+
+ public override Dictionary CreateSimpleMap(Func map)
+ {
+ var yamlMap = node;
+ if (yamlMap == null)
+ {
+ throw new OpenApiException($"Expected map at line {yamlMap.Start.Line} while parsing {typeof(T).Name}");
+ }
+
+ var nodes = yamlMap.Select(
+ n => new
+ {
+ key = n.Key.GetScalarValue(),
+ value = map(new ValueNode(Context, Diagnostic, (YamlScalarNode)n.Value))
+ });
+ return nodes.ToDictionary(k => k.key, v => v.value);
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return nodes.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return nodes.GetEnumerator();
+ }
+
+ public override string GetRaw()
+ {
+ var x = new Serializer(new SerializerSettings(new JsonSchema()) {EmitJsonComptible = true});
+ return x.Serialize(node);
+ }
+
+ public T GetReferencedObject(string refPointer) where T : IOpenApiReference
+ {
+ return (T)Context.GetReferencedObject(Diagnostic, refPointer);
+ }
+
+ public string GetReferencePointer()
+ {
+ YamlNode refNode;
+
+ if (!node.Children.TryGetValue(new YamlScalarNode("$ref"), out refNode))
+ {
+ return null;
+ }
+
+ return refNode.GetScalarValue();
+ }
+
+ public string GetScalarValue(ValueNode key)
+ {
+ var scalarNode = node.Children[new YamlScalarNode(key.GetScalarValue())] as YamlScalarNode;
+ if (scalarNode == null)
+ {
+ throw new OpenApiException($"Expected scalar at line {node.Start.Line} for key {key.GetScalarValue()}");
+ }
+
+ return scalarNode.Value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ParseNode.cs
similarity index 52%
rename from src/Microsoft.OpenApi.Readers/YamlReaders/ParseNode.cs
rename to src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ParseNode.cs
index 843f13acf..28a76538f 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNode.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ParseNode.cs
@@ -1,27 +1,27 @@
-using System;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
using System.Collections.Generic;
-using System.IO;
-using System.Linq;
using System.Text.RegularExpressions;
+using SharpYaml.Serialization;
-namespace Microsoft.OpenApi.Readers.YamlReaders
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
{
- internal class FixedFieldMap : Dictionary>
- {
- }
-
- internal class PatternFieldMap : Dictionary, Action>
+ internal abstract class ParseNode
{
- }
-
- internal abstract class ParseNode
- {
- public ParseNode(ParsingContext ctx)
+ protected ParseNode(ParsingContext parsingContext, OpenApiDiagnostic diagnostic)
{
- this.Context = ctx;
+ Context = parsingContext;
+ Diagnostic = diagnostic;
}
public ParsingContext Context { get; }
+
+ public OpenApiDiagnostic Diagnostic { get; }
+
public string DomainType { get; internal set; }
public MapNode CheckMapNode(string nodeName)
@@ -29,54 +29,76 @@ public MapNode CheckMapNode(string nodeName)
var mapNode = this as MapNode;
if (mapNode == null)
{
- this.Context.Errors.Add(new OpenApiError("", $"{nodeName} must be a map/object at " + this.Context.GetLocation() ));
+ Diagnostic.Errors.Add(
+ new OpenApiError("", $"{nodeName} must be a map/object at " + Context.GetLocation()));
}
return mapNode;
}
- public virtual string GetRaw()
+ internal string CheckRegex(string value, Regex versionRegex, string defaultValue)
{
- throw new OpenApiException("Cannot get raw value");
+ if (!versionRegex.IsMatch(value))
+ {
+ Diagnostic.Errors.Add(new OpenApiError("", "Value does not match regex: " + versionRegex));
+ return defaultValue;
+ }
+
+ return value;
}
-
- public virtual string GetScalarValue()
+
+ public static ParseNode Create(ParsingContext context, OpenApiDiagnostic diagnostic, YamlNode node)
{
- throw new OpenApiException("Cannot get scalar value");
+ var listNode = node as YamlSequenceNode;
+
+ if (listNode != null)
+ {
+ return new ListNode(context, diagnostic, listNode);
+ }
+
+ var mapNode = node as YamlMappingNode;
+ if (mapNode != null)
+ {
+ return new MapNode(context, diagnostic, mapNode);
+ }
+
+ return new ValueNode(context, diagnostic, node as YamlScalarNode);
+ }
+
+ public virtual List CreateList(Func map)
+ {
+ throw new OpenApiException("Cannot create list");
}
public virtual Dictionary CreateMap(Func map)
{
throw new OpenApiException("Cannot create map");
}
- public virtual Dictionary CreateMapWithReference(string refpointer, Func map) where T : class, IOpenApiReference
+
+ public virtual Dictionary CreateMapWithReference(string refpointer, Func map)
+ where T : class, IOpenApiReference
{
throw new OpenApiException("Cannot create map from reference");
}
- public virtual Dictionary CreateSimpleMap(Func map)
+
+ public virtual List CreateSimpleList(Func map)
{
- throw new OpenApiException("Cannot create simple map");
+ throw new OpenApiException("Cannot create simple list");
}
- public virtual List CreateList(Func map)
+ public virtual Dictionary CreateSimpleMap(Func map)
{
- throw new OpenApiException("Cannot create list");
-
+ throw new OpenApiException("Cannot create simple map");
}
- public virtual List CreateSimpleList(Func map)
+
+ public virtual string GetRaw()
{
- throw new OpenApiException("Cannot create simple list");
+ throw new OpenApiException("Cannot get raw value");
}
- internal string CheckRegex(string value, Regex versionRegex, string defaultValue)
+ public virtual string GetScalarValue()
{
- if (!versionRegex.IsMatch(value))
- {
- this.Context.Errors.Add(new OpenApiError("", "Value does not match regex: " + versionRegex.ToString()));
- return defaultValue;
- }
- return value;
+ throw new OpenApiException("Cannot get scalar value");
}
}
-
-}
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PatternFieldMap.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PatternFieldMap.cs
new file mode 100644
index 000000000..1fd238f68
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PatternFieldMap.cs
@@ -0,0 +1,14 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ internal class PatternFieldMap : Dictionary, Action>
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PropertyNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PropertyNode.cs
new file mode 100644
index 000000000..8489ba12b
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/PropertyNode.cs
@@ -0,0 +1,80 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using SharpYaml.Serialization;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ internal class PropertyNode : ParseNode
+ {
+ public PropertyNode(ParsingContext context, OpenApiDiagnostic diagnostic, string name, YamlNode node) : base(
+ context,
+ diagnostic)
+ {
+ Name = name;
+ Value = Create(context, diagnostic, node);
+ }
+
+ public string Name { get; set; }
+
+ public ParseNode Value { get; set; }
+
+ public void ParseField(
+ T parentInstance,
+ IDictionary> fixedFields,
+ IDictionary, Action> patternFields)
+ {
+ Action fixedFieldMap;
+ var found = fixedFields.TryGetValue(Name, out fixedFieldMap);
+
+ if (fixedFieldMap != null)
+ {
+ try
+ {
+ Context.StartObject(Name);
+ fixedFieldMap(parentInstance, Value);
+ }
+ catch (OpenApiException ex)
+ {
+ ex.Pointer = Context.GetLocation();
+ Diagnostic.Errors.Add(new OpenApiError(ex));
+ }
+ finally
+ {
+ Context.EndObject();
+ }
+ }
+ else
+ {
+ var map = patternFields.Where(p => p.Key(Name)).Select(p => p.Value).FirstOrDefault();
+ if (map != null)
+ {
+ try
+ {
+ Context.StartObject(Name);
+ map(parentInstance, Name, Value);
+ }
+ catch (OpenApiException ex)
+ {
+ ex.Pointer = Context.GetLocation();
+ Diagnostic.Errors.Add(new OpenApiError(ex));
+ }
+ finally
+ {
+ Context.EndObject();
+ }
+ }
+ else
+ {
+ Diagnostic.Errors.Add(
+ new OpenApiError("", $"{Name} is not a valid property at {Context.GetLocation()}"));
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/RootNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/RootNode.cs
similarity index 65%
rename from src/Microsoft.OpenApi.Readers/YamlReaders/RootNode.cs
rename to src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/RootNode.cs
index ae8e142ad..fedf2483d 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/RootNode.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/RootNode.cs
@@ -1,41 +1,51 @@
-using SharpYaml.Serialization;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System;
+using SharpYaml.Serialization;
-namespace Microsoft.OpenApi.Readers.YamlReaders
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
{
///
/// Wrapper class around YamlDocument to isolate semantic parsing from details of Yaml DOM.
///
internal class RootNode : ParseNode
{
- YamlDocument yamlDocument;
- public RootNode(ParsingContext ctx, YamlDocument yamlDocument) : base(ctx)
+ private readonly YamlDocument yamlDocument;
+
+ public RootNode(ParsingContext context, OpenApiDiagnostic diagnostic, YamlDocument yamlDocument) : base(context, diagnostic)
{
this.yamlDocument = yamlDocument;
}
- public MapNode GetMap()
+ public ParseNode Find(JsonPointer refPointer)
{
- return new MapNode(Context, (YamlMappingNode)yamlDocument.RootNode);
+ var yamlNode = refPointer.Find(yamlDocument.RootNode);
+ if (yamlNode == null)
+ {
+ return null;
+ }
+
+ return Create(Context, Diagnostic, yamlNode);
}
- public ParseNode Find(JsonPointer refPointer)
+ public MapNode GetMap()
{
- var yamlNode = refPointer.Find(this.yamlDocument.RootNode);
- if (yamlNode == null) return null;
- return YamlHelper.Create(this.Context, yamlNode);
+ return new MapNode(Context, Diagnostic, (YamlMappingNode)yamlDocument.RootNode);
}
}
public static class JsonPointerExtensions
{
-
public static YamlNode Find(this JsonPointer currentpointer, YamlNode sample)
{
if (currentpointer.Tokens.Length == 0)
{
return sample;
}
+
try
{
var pointer = sample;
@@ -58,6 +68,7 @@ public static YamlNode Find(this JsonPointer currentpointer, YamlNode sample)
}
}
}
+
return pointer;
}
catch (Exception ex)
@@ -65,6 +76,5 @@ public static YamlNode Find(this JsonPointer currentpointer, YamlNode sample)
throw new ArgumentException("Failed to dereference pointer", ex);
}
}
-
}
-}
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ValueNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ValueNode.cs
new file mode 100644
index 000000000..77d85c773
--- /dev/null
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParseNodes/ValueNode.cs
@@ -0,0 +1,31 @@
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using SharpYaml.Serialization;
+
+namespace Microsoft.OpenApi.Readers.YamlReaders.ParseNodes
+{
+ internal class ValueNode : ParseNode
+ {
+ private readonly YamlScalarNode node;
+
+ public ValueNode(ParsingContext context, OpenApiDiagnostic diagnostic, YamlScalarNode scalarNode) : base(context, diagnostic)
+ {
+ node = scalarNode;
+ }
+
+ public override string GetScalarValue()
+ {
+ var scalarNode = node;
+
+ if (scalarNode == null)
+ {
+ throw new OpenApiException($"Expected scalar at line {node.Start.Line}");
+ }
+
+ return scalarNode.Value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ParsingContext.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ParsingContext.cs
index 401491162..b5bd1a85b 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/ParsingContext.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ParsingContext.cs
@@ -5,11 +5,10 @@
using System.Collections.Generic;
using System.Linq;
-using Microsoft.OpenApi.Readers.Interface;
namespace Microsoft.OpenApi.Readers.YamlReaders
{
- public class ParsingContext : ILog
+ public class ParsingContext
{
private readonly Stack currentLocation = new Stack();
@@ -20,11 +19,7 @@ public class ParsingContext : ILog
private readonly Dictionary referenceStore = new Dictionary();
private readonly Dictionary tempStorage = new Dictionary();
-
- public OpenApiDocument OpenApiDocument { get; set; }
-
- public IList Errors { get; set; } = new List();
-
+
public string Version { get; set; }
public void EndObject()
@@ -37,13 +32,13 @@ public string GetLocation()
return "#/" + string.Join("/", currentLocation.Reverse().ToArray());
}
- public IOpenApiReference GetReferencedObject(string pointer)
+ public IOpenApiReference GetReferencedObject(OpenApiDiagnostic diagnostic, string pointer)
{
var reference = referenceService.ParseReference(pointer);
- return GetReferencedObject(reference);
+ return GetReferencedObject(diagnostic, reference);
}
- public IOpenApiReference GetReferencedObject(OpenApiReference reference)
+ public IOpenApiReference GetReferencedObject(OpenApiDiagnostic diagnostic, OpenApiReference reference)
{
IOpenApiReference returnValue = null;
referenceStore.TryGetValue(reference.ToString(), out returnValue);
@@ -58,6 +53,7 @@ public IOpenApiReference GetReferencedObject(OpenApiReference reference)
previousPointers.Push(reference.ToString());
returnValue = referenceService.LoadReference(reference);
previousPointers.Pop();
+
if (returnValue != null)
{
returnValue.Pointer = reference;
@@ -65,7 +61,7 @@ public IOpenApiReference GetReferencedObject(OpenApiReference reference)
}
else
{
- Errors.Add(new OpenApiError(GetLocation(), $"Cannot resolve $ref {reference}"));
+ diagnostic.Errors.Add(new OpenApiError(GetLocation(), $"Cannot resolve $ref {reference}"));
}
}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/PropertyNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/PropertyNode.cs
deleted file mode 100644
index 1742afa30..000000000
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/PropertyNode.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using SharpYaml.Serialization;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Microsoft.OpenApi.Readers.YamlReaders
-{
- internal class PropertyNode : ParseNode
- {
- public PropertyNode(ParsingContext ctx, string name, YamlNode node) : base(ctx)
- {
- this.Name = name;
- Value = YamlHelper.Create(ctx,node);
- }
-
-
- public string Name { get; set; }
- public ParseNode Value { get; set; }
-
-
- public void ParseField(
- T parentInstance,
- IDictionary> fixedFields,
- IDictionary, Action> patternFields
- )
- {
-
- Action fixedFieldMap;
- var found = fixedFields.TryGetValue(this.Name, out fixedFieldMap);
-
- if (fixedFieldMap != null)
- {
- try
- {
- this.Context.StartObject(this.Name);
- fixedFieldMap(parentInstance, this.Value);
- } catch (OpenApiException ex)
- {
- ex.Pointer = this.Context.GetLocation();
- this.Context.Errors.Add(new OpenApiError(ex));
- }
- finally
- {
- this.Context.EndObject();
- }
- }
- else
- {
- var map = patternFields.Where(p => p.Key(this.Name)).Select(p => p.Value).FirstOrDefault();
- if (map != null)
- {
- try
- {
- this.Context.StartObject(this.Name);
- map(parentInstance, this.Name, this.Value);
- }
- catch (OpenApiException ex)
- {
- ex.Pointer = this.Context.GetLocation();
- this.Context.Errors.Add(new OpenApiError(ex));
- }
- finally
- {
- this.Context.EndObject();
- }
- }
- else
- {
- this.Context.Errors.Add(new OpenApiError("", $"{this.Name} is not a valid property at {this.Context.GetLocation()}" ));
- }
- }
- }
-
- }
-
-
-}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ReferenceService.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ReferenceService.cs
index 0bef85fc7..15b5196f9 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/ReferenceService.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/ReferenceService.cs
@@ -3,17 +3,18 @@
namespace Microsoft.OpenApi.Readers.YamlReaders
{
- internal class ReferenceService : IOpenApiReferenceService
+ internal class OpenApiReferenceService : IOpenApiReferenceService
{
public Func loadReference { get; set; }
public Func parseReference { get; set; }
- private object rootNode;
+ private readonly object rootNode;
- public ReferenceService(object rootNode)
+ public OpenApiReferenceService(object rootNode)
{
this.rootNode = rootNode;
}
+
public IOpenApiReference LoadReference(OpenApiReference reference)
{
var referenceObject = this.loadReference(reference,this.rootNode);
@@ -21,6 +22,7 @@ public IOpenApiReference LoadReference(OpenApiReference reference)
{
throw new OpenApiException($"Cannot locate $ref {reference.ToString()}");
}
+
return referenceObject;
}
@@ -29,28 +31,36 @@ public OpenApiReference ParseReference(string pointer)
return this.parseReference(pointer);
}
- public static OpenApiSecurityScheme LoadSecuritySchemeByReference(ParsingContext context, string schemeName)
+ public static OpenApiSecurityScheme LoadSecuritySchemeByReference(
+ ParsingContext context,
+ OpenApiDiagnostic diagnostic,
+ string schemeName)
{
+ var securitySchemeObject = (OpenApiSecurityScheme)context.GetReferencedObject(
+ diagnostic,
+ new OpenApiReference()
+ {
+ ReferenceType = ReferenceType.SecurityScheme,
+ TypeName = schemeName
+ });
- var schemeObject = (OpenApiSecurityScheme)context.GetReferencedObject(new OpenApiReference()
- {
- ReferenceType = ReferenceType.SecurityScheme,
- TypeName = schemeName
- });
-
- return schemeObject;
+ return securitySchemeObject;
}
-
-
- public static OpenApiTag LoadTagByReference(ParsingContext context, string tagName)
+
+ public static OpenApiTag LoadTagByReference(
+ ParsingContext context,
+ OpenApiDiagnostic diagnostic,
+ string tagName)
{
-
- var tagObject = (OpenApiTag)context.GetReferencedObject($"#/tags/{tagName}");
+ var tagObject = (OpenApiTag)context.GetReferencedObject(
+ diagnostic,
+ $"#/tags/{tagName}");
if (tagObject == null)
{
tagObject = new OpenApiTag() { Name = tagName };
}
+
return tagObject;
}
}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/ValueNode.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/ValueNode.cs
deleted file mode 100644
index 31bf94fe8..000000000
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/ValueNode.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-
-using SharpYaml.Serialization;
-
-namespace Microsoft.OpenApi.Readers.YamlReaders
-{
- internal class ValueNode : ParseNode
- {
- YamlScalarNode node;
- public ValueNode(ParsingContext ctx, YamlScalarNode scalarNode) : base(ctx)
- {
- this.node = scalarNode;
- }
-
- public override string GetScalarValue()
- {
-
- var scalarNode = this.node as YamlScalarNode;
- if (scalarNode == null) throw new OpenApiException($"Expected scalar at line {node.Start.Line}");
-
- return scalarNode.Value;
- }
-
- }
-
-
-}
diff --git a/src/Microsoft.OpenApi.Readers/YamlReaders/YamlHelper.cs b/src/Microsoft.OpenApi.Readers/YamlReaders/YamlHelper.cs
index 692b4a01d..0f94ddbf6 100644
--- a/src/Microsoft.OpenApi.Readers/YamlReaders/YamlHelper.cs
+++ b/src/Microsoft.OpenApi.Readers/YamlReaders/YamlHelper.cs
@@ -11,23 +11,6 @@ namespace Microsoft.OpenApi.Readers.YamlReaders
{
internal static class YamlHelper
{
- public static ParseNode Create(ParsingContext context, YamlNode node)
- {
- var listNode = node as YamlSequenceNode;
- if (listNode != null)
- {
- return new ListNode(context, listNode);
- }
-
- var mapNode = node as YamlMappingNode;
- if (mapNode != null)
- {
- return new MapNode(context, mapNode);
- }
-
- return new ValueNode(context, node as YamlScalarNode);
- }
-
public static string GetScalarValue(this YamlNode node)
{
var scalarNode = node as YamlScalarNode;
@@ -39,9 +22,9 @@ public static string GetScalarValue(this YamlNode node)
return scalarNode.Value;
}
- public static YamlNode ParseYaml(string yaml)
+ public static YamlNode ParseYamlString(string yamlString)
{
- var reader = new StringReader(yaml);
+ var reader = new StringReader(yamlString);
var yamlStream = new YamlStream();
yamlStream.Load(reader);
var yamlDocument = yamlStream.Documents.First();
diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs
index c081c2f25..c64661efc 100644
--- a/src/Microsoft.OpenApi.Workbench/MainModel.cs
+++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs
@@ -75,43 +75,40 @@ protected void OnPropertyChanged(string name)
internal void Validate()
{
- try {
+ try
+ {
- MemoryStream stream = CreateStream(input);
+ MemoryStream stream = CreateStream(input);
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
- var stopwatch = new Stopwatch();
- stopwatch.Start();
-
+ var openApiDocument = new OpenApiStreamReader().Read(stream, out var context);
+ stopwatch.Stop();
+ ParseTime = $"{stopwatch.ElapsedMilliseconds} ms";
- var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
- stopwatch.Stop();
- ParseTime = $"{stopwatch.ElapsedMilliseconds} ms";
-
- if (context.Errors.Count == 0)
- {
- Errors = "OK";
+ if (context.Errors.Count == 0)
+ {
+ Errors = "OK";
- }
- else
- {
- var errorReport = new StringBuilder();
- foreach (var error in context.Errors)
+ }
+ else
{
- errorReport.AppendLine(error.ToString());
+ var errorReport = new StringBuilder();
+ foreach (var error in context.Errors)
+ {
+ errorReport.AppendLine(error.ToString());
+ }
+ Errors = errorReport.ToString();
}
- Errors = errorReport.ToString();
- }
-
- stopwatch.Reset();
- stopwatch.Start();
- Output = WriteContents(context.OpenApiDocument);
- stopwatch.Stop();
- RenderTime = $"{stopwatch.ElapsedMilliseconds} ms";
+ stopwatch.Reset();
+ stopwatch.Start();
+ Output = WriteContents(openApiDocument);
+ stopwatch.Stop();
-
- }
+ RenderTime = $"{stopwatch.ElapsedMilliseconds} ms";
+ }
catch (Exception ex)
{
Errors = "Failed to parse input: " + ex.Message;
@@ -119,11 +116,8 @@ internal void Validate()
// Verify output is valid JSON or YAML
//var dummy = YamlHelper.ParseYaml(Output);
-
}
-
-
-
+
private string WriteContents(OpenApiDocument doc)
{
Func writerFactory = s => (this.format == "Yaml" ? new OpenApiYamlWriter(new StreamWriter(s)) : (IOpenApiWriter)new OpenApiJsonWriter(new StreamWriter(s)));
diff --git a/src/Microsoft.OpenApi/Abstracts/IOpenApiElement.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Abstracts/IOpenApiElement.cs
rename to src/Microsoft.OpenApi/Interfaces/IOpenApiElement.cs
diff --git a/src/Microsoft.OpenApi/Abstracts/IOpenApiExtension.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiExtension.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Abstracts/IOpenApiExtension.cs
rename to src/Microsoft.OpenApi/Interfaces/IOpenApiExtension.cs
diff --git a/src/Microsoft.OpenApi/Abstracts/IOpenApiReference.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReference.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Abstracts/IOpenApiReference.cs
rename to src/Microsoft.OpenApi/Interfaces/IOpenApiReference.cs
diff --git a/src/Microsoft.OpenApi/Abstracts/IOpenApiReferenceService.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceService.cs
similarity index 99%
rename from src/Microsoft.OpenApi/Abstracts/IOpenApiReferenceService.cs
rename to src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceService.cs
index a0baea3a6..5cec663f5 100644
--- a/src/Microsoft.OpenApi/Abstracts/IOpenApiReferenceService.cs
+++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReferenceService.cs
@@ -9,6 +9,7 @@ namespace Microsoft.OpenApi
public interface IOpenApiReferenceService
{
IOpenApiReference LoadReference(OpenApiReference reference);
+
OpenApiReference ParseReference(string pointer);
}
}
diff --git a/src/Microsoft.OpenApi/Sevices/OpenAPIDiff.cs b/src/Microsoft.OpenApi/Services/OpenAPIDiff.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Sevices/OpenAPIDiff.cs
rename to src/Microsoft.OpenApi/Services/OpenAPIDiff.cs
diff --git a/src/Microsoft.OpenApi/Sevices/OpenApiValidator.cs b/src/Microsoft.OpenApi/Services/OpenApiValidator.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Sevices/OpenApiValidator.cs
rename to src/Microsoft.OpenApi/Services/OpenApiValidator.cs
diff --git a/src/Microsoft.OpenApi/Sevices/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Sevices/OpenApiVisitorBase.cs
rename to src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs
diff --git a/src/Microsoft.OpenApi/Sevices/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs
similarity index 100%
rename from src/Microsoft.OpenApi/Sevices/OpenApiWalker.cs
rename to src/Microsoft.OpenApi/Services/OpenApiWalker.cs
diff --git a/src/Microsoft.OpenApi/Writers/WriterExtensions.cs b/src/Microsoft.OpenApi/Writers/WriterExtensions.cs
index 772078d35..d5466fe4f 100644
--- a/src/Microsoft.OpenApi/Writers/WriterExtensions.cs
+++ b/src/Microsoft.OpenApi/Writers/WriterExtensions.cs
@@ -19,99 +19,114 @@ public static void Save(this OpenApiDocument doc, Stream stream, IOpenApiStructu
{
openApiWriter = new OpenApiV3Writer();
}
+
openApiWriter.Write(stream, doc);
}
public static void WriteObject(this IOpenApiWriter writer, string propertyName, T entity, Action parser)
{
- if (entity != null)
+ if (entity == null)
{
- writer.WritePropertyName(propertyName);
- parser(writer, entity);
+ return;
}
+ writer.WritePropertyName(propertyName);
+ parser(writer, entity);
}
public static void WriteList(this IOpenApiWriter writer, string propertyName, IList list, Action parser)
{
- if (list != null && list.Any())
+ if (list == null || !list.Any())
{
- writer.WritePropertyName(propertyName);
- writer.WriteStartArray();
- foreach (var item in list)
- {
- parser(writer,item);
- }
- writer.WriteEndArray();
+ return;
}
+ writer.WritePropertyName(propertyName);
+ writer.WriteStartArray();
+ foreach (var item in list)
+ {
+ parser(writer,item);
+ }
+
+ writer.WriteEndArray();
}
public static void WriteMap(this IOpenApiWriter writer, string propertyName, IDictionary list, Action parser)
{
- if (list != null && list.Count() > 0)
+ if (list == null || !list.Any())
+ {
+ return;
+ }
+
+ writer.WritePropertyName(propertyName);
+ writer.WriteStartObject();
+ foreach (var item in list)
{
- writer.WritePropertyName(propertyName);
- writer.WriteStartObject();
- foreach (var item in list)
+ writer.WritePropertyName(item.Key);
+ if (item.Value != null)
{
- writer.WritePropertyName(item.Key);
- if (item.Value != null)
- {
- parser(writer, item.Value);
- }
- else
- {
- writer.WriteNull();
- }
+ parser(writer, item.Value);
+ }
+ else
+ {
+ writer.WriteNull();
}
- writer.WriteEndObject();
}
-
+ writer.WriteEndObject();
}
public static void WriteStringProperty(this IOpenApiWriter writer, string name, string value)
{
- if (!String.IsNullOrEmpty(value))
+ if (string.IsNullOrEmpty(value))
{
- writer.WritePropertyName(name);
- writer.WriteValue(value);
+ return;
}
+
+ writer.WritePropertyName(name);
+ writer.WriteValue(value);
}
public static void WriteBoolProperty(this IOpenApiWriter writer, string name, bool value, bool? defaultValue = null)
{
- if (defaultValue == null || value != defaultValue)
+ if (defaultValue != null && value == defaultValue)
{
- writer.WritePropertyName(name);
- writer.WriteValue(value);
+ return;
}
+
+ writer.WritePropertyName(name);
+ writer.WriteValue(value);
}
public static void WriteNumberProperty(this IOpenApiWriter writer, string name, decimal value, decimal? defaultValue = null)
{
- if (defaultValue == null || value != defaultValue)
+ if (defaultValue != null && value == defaultValue)
{
- writer.WritePropertyName(name);
- writer.WriteValue(value);
+ return;
}
+
+ writer.WritePropertyName(name);
+ writer.WriteValue(value);
}
public static void WriteNumberProperty(this IOpenApiWriter writer, string name, int? value)
{
- if (value != null)
+ if (value == null)
{
- writer.WritePropertyName(name);
- writer.WriteValue((int)value);
+ return;
}
+
+ writer.WritePropertyName(name);
+ writer.WriteValue((int)value);
}
public static void WriteNumberProperty(this IOpenApiWriter writer, string name, decimal? value)
{
- if (value != null)
+ if (value == null)
{
- writer.WritePropertyName(name);
- writer.WriteValue((decimal)value);
+ return;
}
+
+ writer.WritePropertyName(name);
+ writer.WriteValue((decimal)value);
}
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs
index 3abb8befa..682b5e25f 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/BasicTests.cs
@@ -1,74 +1,26 @@
-using Microsoft.OpenApi.Readers;
-using SharpYaml.Serialization;
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.IO;
using System.Linq;
using System.Text;
-using System.Threading.Tasks;
using Microsoft.OpenApi.Readers.YamlReaders;
+using SharpYaml.Serialization;
using Xunit;
-using Microsoft.OpenApi.Readers.Interface;
namespace Microsoft.OpenApi.Readers.Tests
{
public class BasicTests
{
- [Fact]
- public void TestYamlBuilding()
- {
- var doc = new YamlDocument(new YamlMappingNode(
- new YamlScalarNode("a"), new YamlScalarNode("apple"),
- new YamlScalarNode("b"), new YamlScalarNode("banana"),
- new YamlScalarNode("c"), new YamlScalarNode("cherry")
- ));
-
- var s = new YamlStream();
- s.Documents.Add(doc);
- var sb = new StringBuilder();
- var writer = new StringWriter(sb);
- s.Save(writer);
- var output = sb.ToString();
- }
-
- [Fact]
- public void ParseSimplestOpenApiEver()
- {
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.Simplest.yaml");
-
- var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
-
- Assert.Equal("1.0.0", openApiDoc.Version);
- Assert.Empty(openApiDoc.Paths);
- Assert.Equal("The Api", openApiDoc.Info.Title);
- Assert.Equal("0.9.1", openApiDoc.Info.Version.ToString());
- Assert.Empty(context.Errors);
- }
-
- [Fact]
- public void ParseBrokenSimplest()
- {
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(BasicTests),"Samples.BrokenSimplest.yaml");
-
- var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
-
- Assert.Equal(2, context.Errors.Count);
- Assert.NotNull(context.Errors.Where(s=> s.ToString() == "`openapi` property does not match the required format major.minor.patch at #/openapi").FirstOrDefault());
- Assert.NotNull(context.Errors.Where(s => s.ToString() == "title is a required property of #/info").FirstOrDefault());
-
- }
-
[Fact]
public void CheckOpenAPIVersion()
{
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.petstore30.yaml");
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.petstore30.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
Assert.Equal("3.0.0", openApiDoc.Version);
-
}
[Fact]
@@ -90,9 +42,59 @@ public void InlineExample()
out var parsingContext);
Assert.Equal("3.0.0", openApiDoc.Version);
+ }
+
+ [Fact]
+ public void ParseBrokenSimplest()
+ {
+ var stream = GetType()
+ .Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.BrokenSimplest.yaml");
+
+ var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
+
+ Assert.Equal(2, context.Errors.Count);
+ Assert.NotNull(
+ context.Errors.Where(
+ s => s.ToString() ==
+ "`openapi` property does not match the required format major.minor.patch at #/openapi")
+ .FirstOrDefault());
+ Assert.NotNull(
+ context.Errors.Where(s => s.ToString() == "title is a required property of #/info").FirstOrDefault());
+ }
+
+ [Fact]
+ public void ParseSimplestOpenApiEver()
+ {
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(BasicTests), "Samples.Simplest.yaml");
+
+ var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
+ Assert.Equal("1.0.0", openApiDoc.Version);
+ Assert.Empty(openApiDoc.Paths);
+ Assert.Equal("The Api", openApiDoc.Info.Title);
+ Assert.Equal("0.9.1", openApiDoc.Info.Version.ToString());
+ Assert.Empty(context.Errors);
}
+ [Fact]
+ public void TestYamlBuilding()
+ {
+ var doc = new YamlDocument(
+ new YamlMappingNode(
+ new YamlScalarNode("a"),
+ new YamlScalarNode("apple"),
+ new YamlScalarNode("b"),
+ new YamlScalarNode("banana"),
+ new YamlScalarNode("c"),
+ new YamlScalarNode("cherry")
+ ));
+ var s = new YamlStream();
+ s.Documents.Add(doc);
+ var sb = new StringBuilder();
+ var writer = new StringWriter(sb);
+ s.Save(writer);
+ var output = sb.ToString();
+ }
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/CallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/CallbackTests.cs
index 4e463f99f..170984636 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/CallbackTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/CallbackTests.cs
@@ -1,41 +1,38 @@
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.OpenApi;
-using Xunit;
-using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Readers.YamlReaders;
+using Xunit;
namespace Microsoft.OpenApi.Readers.Tests
{
-
public class CallbackTests
{
[Fact]
public void LoadSimpleCallback()
{
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(CallbackTests),"Samples.CallbackSample.yaml");
+ var stream = GetType()
+ .Assembly.GetManifestResourceStream(typeof(CallbackTests), "Samples.CallbackSample.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
- OpenApiPathItem path = openApiDoc.Paths.First().Value;
- OpenApiOperation subscribeOperation = path.Operations["post"];
+ var path = openApiDoc.Paths.First().Value;
+ var subscribeOperation = path.Operations["post"];
var callback = subscribeOperation.Callbacks["mainHook"];
var pathItem = callback.PathItems.First().Value;
var operation = pathItem.Operations["post"];
Assert.NotNull(operation);
-
}
[Fact]
public void LoadSimpleCallbackWithRefs()
{
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(CallbackTests), "Samples.CallbackSampleWithRef.yaml");
+ var stream = GetType()
+ .Assembly.GetManifestResourceStream(typeof(CallbackTests), "Samples.CallbackSampleWithRef.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
@@ -45,19 +42,17 @@ public void LoadSimpleCallbackWithRefs()
var callbackPair = operation.Callbacks.First();
Assert.Equal("simplehook", callbackPair.Key);
- OpenApiCallback callback = callbackPair.Value;
+ var callback = callbackPair.Value;
var pathItemPair = callback.PathItems.First();
Assert.Equal("$request.body(/url)", pathItemPair.Key.Expression);
- OpenApiPathItem pathItem = pathItemPair.Value;
+ var pathItem = pathItemPair.Value;
var operationPair = pathItem.Operations.First();
- OpenApiOperation cboperation = operationPair.Value;
+ var cboperation = operationPair.Value;
Assert.Equal("post", operationPair.Key);
Assert.NotNull(callback);
-
}
-
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs
index bbf6a3aba..f4be19a69 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/DownGradeTests.cs
@@ -1,56 +1,62 @@
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.OpenApi;
-using Xunit;
-using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Readers.YamlReaders;
using Microsoft.OpenApi.Writers;
+using Newtonsoft.Json.Linq;
+using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
- public class DownGradeTests
+ public class DowngradeTests
{
- public void SimpleTest()
- {
- var stream = this.GetType().Assembly.GetManifestResourceStream("OpenApiTests.Samples.Simplest.yaml");
-
- var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
-
- var outputStream = new MemoryStream();
- openApiDoc.Save(outputStream, new OpenApiV2Writer());
- }
-
[Fact]
public void EmptyTest()
{
var openApiDoc = new OpenApiDocument();
- JObject jObject = ExportV2ToJObject(openApiDoc);
+ var jObject = ExportV2ToJObject(openApiDoc);
Assert.Equal("2.0", jObject["swagger"]);
Assert.NotNull(jObject["info"]);
-
}
+ private static JObject ExportV2ToJObject(OpenApiDocument openApiDoc)
+ {
+ var outputStream = new MemoryStream();
+ openApiDoc.Save(outputStream, new OpenApiV2Writer(s => new OpenApiJsonWriter(new StreamWriter(s))));
+ outputStream.Position = 0;
+ var json = new StreamReader(outputStream).ReadToEnd();
+ var jObject = JObject.Parse(json);
+ return jObject;
+ }
[Fact]
public void HostTest()
{
var openApiDoc = new OpenApiDocument();
- openApiDoc.Servers.Add(new OpenApiServer() { Url = "http://example.org/api" });
- openApiDoc.Servers.Add(new OpenApiServer() { Url = "https://example.org/api" });
+ openApiDoc.Servers.Add(new OpenApiServer {Url = "http://example.org/api"});
+ openApiDoc.Servers.Add(new OpenApiServer {Url = "https://example.org/api"});
- JObject jObject = ExportV2ToJObject(openApiDoc);
+ var jObject = ExportV2ToJObject(openApiDoc);
Assert.Equal("example.org", (string)jObject["host"]);
Assert.Equal("/api", (string)jObject["basePath"]);
+ }
+ [Fact]
+ public void SimpleTest()
+ {
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(DowngradeTests), "Samples.Simplest.yaml");
+
+ var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
+
+ var outputStream = new MemoryStream();
+ openApiDoc.Save(outputStream, new OpenApiV2Writer());
}
[Fact]
@@ -62,60 +68,68 @@ public void TestConsumes()
{
RequestBody = new OpenApiRequestBody
{
- Content = new Dictionary() {
- { "application/vnd.collection+json", new OpenApiMediaType
- {
- }
+ Content = new Dictionary
+ {
+ {
+ "application/vnd.collection+json", new OpenApiMediaType()
+ }
+ }
+ },
+ Responses = new Dictionary
+ {
+ {
+ "200", new OpenApiResponse
+ {
+ Description = "Success"
}
}
- },
- Responses = new Dictionary { { "200", new OpenApiResponse() {
- Description = "Success"
- } } }
+ }
};
pathItem.AddOperation(OperationType.Get, operation);
openApiDoc.Paths.Add("/resource", pathItem);
- JObject jObject = ExportV2ToJObject(openApiDoc);
-
- Assert.Equal("application/vnd.collection+json", (string)jObject["paths"]["/resource"]["get"]["consumes"][0]);
+ var jObject = ExportV2ToJObject(openApiDoc);
+ Assert.Equal(
+ "application/vnd.collection+json",
+ (string)jObject["paths"]["/resource"]["get"]["consumes"][0]);
}
[Fact]
- public void TestRequestBody()
+ public void TestParameter()
{
var openApiDoc = new OpenApiDocument();
var pathItem = new OpenApiPathItem();
var operation = new OpenApiOperation
{
- RequestBody = new OpenApiRequestBody
+ Parameters = new List
{
- Content = new Dictionary() {
- { "application/vnd.collection+json", new OpenApiMediaType
- {
- Schema = new OpenApiSchema
- {
- Type = "string",
- MaxLength = 100
- }
- }
+ new OpenApiParameter
+ {
+ Name = "param1",
+ In = ParameterLocation.query,
+ Schema = new OpenApiSchema
+ {
+ Type = "string"
}
}
},
- Responses = new Dictionary { { "200", new OpenApiResponse() {
- Description = "Success"
- } } }
+ Responses = new Dictionary
+ {
+ {
+ "200", new OpenApiResponse
+ {
+ Description = "Success"
+ }
+ }
+ }
};
- pathItem.AddOperation(OperationType.Post, operation);
+ pathItem.AddOperation(OperationType.Get, operation);
openApiDoc.Paths.Add("/resource", pathItem);
- JObject jObject = ExportV2ToJObject(openApiDoc);
+ var jObject = ExportV2ToJObject(openApiDoc);
- var bodyparam = jObject["paths"]["/resource"]["post"]["parameters"][0];
- Assert.Equal("body", (string)bodyparam["in"]);
- Assert.Equal("string", (string)bodyparam["schema"]["type"]);
- Assert.Equal("100", (string)bodyparam["schema"]["maxLength"]);
+ Assert.Equal("string", (string)jObject["paths"]["/resource"]["get"]["parameters"][0]["type"]);
}
[Fact]
@@ -125,69 +139,76 @@ public void TestProduces()
var pathItem = new OpenApiPathItem();
var operation = new OpenApiOperation
{
- Responses = new Dictionary { { "200", new OpenApiResponse() {
- Description = "Success",
- Content = new Dictionary() {
- { "application/vnd.collection+json", new OpenApiMediaType
+ Responses = new Dictionary
+ {
+ {
+ "200", new OpenApiResponse
+ {
+ Description = "Success",
+ Content = new Dictionary
+ {
{
- }
- },
- { "text/plain", null }
+ "application/vnd.collection+json", new OpenApiMediaType()
+ },
+ {"text/plain", null}
+ }
+ }
}
-
- } } }
+ }
};
pathItem.AddOperation(OperationType.Get, operation);
openApiDoc.Paths.Add("/resource", pathItem);
- JObject jObject = ExportV2ToJObject(openApiDoc);
+ var jObject = ExportV2ToJObject(openApiDoc);
- Assert.Equal("application/vnd.collection+json", (string)jObject["paths"]["/resource"]["get"]["produces"][0]);
+ Assert.Equal(
+ "application/vnd.collection+json",
+ (string)jObject["paths"]["/resource"]["get"]["produces"][0]);
Assert.Equal("text/plain", (string)jObject["paths"]["/resource"]["get"]["produces"][1]);
-
-
}
[Fact]
- public void TestParameter()
+ public void TestRequestBody()
{
var openApiDoc = new OpenApiDocument();
var pathItem = new OpenApiPathItem();
var operation = new OpenApiOperation
{
- Parameters = new List {
- new OpenApiParameter {
- Name = "param1",
- In = ParameterLocation.query,
- Schema = new OpenApiSchema
+ RequestBody = new OpenApiRequestBody
+ {
+ Content = new Dictionary
{
- Type = "string"
+ {
+ "application/vnd.collection+json", new OpenApiMediaType
+ {
+ Schema = new OpenApiSchema
+ {
+ Type = "string",
+ MaxLength = 100
+ }
+ }
+ }
}
-
- } },
- Responses = new Dictionary { { "200", new OpenApiResponse() {
- Description = "Success"
- } } }
+ },
+ Responses = new Dictionary
+ {
+ {
+ "200", new OpenApiResponse
+ {
+ Description = "Success"
+ }
+ }
+ }
};
- pathItem.AddOperation(OperationType.Get, operation);
+ pathItem.AddOperation(OperationType.Post, operation);
openApiDoc.Paths.Add("/resource", pathItem);
- JObject jObject = ExportV2ToJObject(openApiDoc);
-
- Assert.Equal("string", (string)jObject["paths"]["/resource"]["get"]["parameters"][0]["type"]);
-
- }
+ var jObject = ExportV2ToJObject(openApiDoc);
- private static JObject ExportV2ToJObject(OpenApiDocument openApiDoc)
- {
- var outputStream = new MemoryStream();
- openApiDoc.Save(outputStream, new OpenApiV2Writer((s) => new OpenApiJsonWriter(new StreamWriter(s))));
- outputStream.Position = 0;
- var json = new StreamReader(outputStream).ReadToEnd();
- var jObject = JObject.Parse(json);
- return jObject;
+ var bodyparam = jObject["paths"]["/resource"]["post"]["parameters"][0];
+ Assert.Equal("body", (string)bodyparam["in"]);
+ Assert.Equal("string", (string)bodyparam["schema"]["type"]);
+ Assert.Equal("100", (string)bodyparam["schema"]["maxLength"]);
}
-
-
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/FixtureTests.cs b/test/Microsoft.OpenApi.Readers.Tests/FixtureTests.cs
index 85b1a34c0..0a5d9bb41 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/FixtureTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/FixtureTests.cs
@@ -1,79 +1,79 @@
-using Microsoft.OpenApi.Readers;
-using Microsoft.OpenApi.Services;
-using SharpYaml.Serialization;
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.IO;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.OpenApi.Readers.YamlReaders;
+using Microsoft.OpenApi.Readers.YamlReaders.ParseNodes;
+using SharpYaml.Serialization;
using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
public class FixtureTests
{
+ private YamlNode LoadNode(string filePath)
+ {
+ using (var stream = new FileStream(filePath, FileMode.Open))
+ {
+ var yamlStream = new YamlStream();
+ yamlStream.Load(new StreamReader(stream));
+ return yamlStream.Documents.First().RootNode;
+ }
+ }
// Load json,yaml for both 2.0 and 3.0. Ensure resulting DOM is not empty and equivalent?
// Load files from ../../fixtures/(v3.0|v2.0|v1.0 ???)/(json|yaml)/general/basicInfoObject.json
[Fact]
public void TestBasicInfoObject()
{
-
var yamlNode = LoadNode("../../../../fixtures/v3.0/json/general/basicInfoObject.json");
- var ctx = new ParsingContext();
- var node = new MapNode(ctx, (YamlMappingNode)yamlNode);
- var info = OpenApiV3Builder.LoadInfo(node);
+ var context = new ParsingContext();
+ var diagnostic = new OpenApiDiagnostic();
+
+ var node = new MapNode(context, diagnostic, (YamlMappingNode)yamlNode);
+ var info = OpenApiV3Deserializer.LoadInfo(node);
Assert.NotNull(info);
Assert.Equal("Swagger Sample App", info.Title);
Assert.Equal("1.0.1", info.Version.ToString());
Assert.Equal("support@swagger.io", info.Contact.Email);
- Assert.Empty(ctx.Errors);
+ Assert.Empty(diagnostic.Errors);
}
[Fact]
public void TestMinimalInfoObject()
{
-
var yamlNode = LoadNode("../../../../fixtures/v3.0/json/general/minimalInfoObject.json");
- var ctx = new ParsingContext();
- var node = new MapNode(ctx, (YamlMappingNode)yamlNode);
- var info = OpenApiV3Builder.LoadInfo(node);
+ var context = new ParsingContext();
+ var diagnostic = new OpenApiDiagnostic();
+
+ var node = new MapNode(context, diagnostic, (YamlMappingNode)yamlNode);
+ var info = OpenApiV3Deserializer.LoadInfo(node);
Assert.NotNull(info);
Assert.Equal("Swagger Sample App", info.Title);
Assert.Equal("1.0.1", info.Version.ToString());
- Assert.Empty(ctx.Errors);
+ Assert.Empty(diagnostic.Errors);
}
[Fact]
public void TestNegativeInfoObject()
{
-
var yamlNode = LoadNode("../../../../fixtures/v3.0/json/general/negative/negativeInfoObject.json");
- var ctx = new ParsingContext();
- var node = new MapNode(ctx, (YamlMappingNode)yamlNode);
- var info = OpenApiV3Builder.LoadInfo(node);
+ var context = new ParsingContext();
+ var diagnostic = new OpenApiDiagnostic();
- Assert.NotNull(info);
- Assert.Equal(2, ctx.Errors.Count);
- }
+ var node = new MapNode(context, diagnostic, (YamlMappingNode)yamlNode);
+ var info = OpenApiV3Deserializer.LoadInfo(node);
- private YamlNode LoadNode(string filePath)
- {
- using (var stream = new FileStream(filePath, FileMode.Open))
- {
-
- var yamlStream = new YamlStream();
- yamlStream.Load(new StreamReader(stream));
- return yamlStream.Documents.First().RootNode;
- }
+ Assert.NotNull(info);
+ Assert.Equal(2, diagnostic.Errors.Count);
}
}
-}
-
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs
index 24b85002a..7ffb2d9fb 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/InfoTests.cs
@@ -1,9 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Xunit;
-using Microsoft.OpenApi.Readers;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using Microsoft.OpenApi.Readers.YamlReaders;
+using Xunit;
namespace Microsoft.OpenApi.Readers.Tests
{
@@ -12,20 +13,22 @@ public class InfoTests
[Fact]
public void CheckPetStoreApiInfo()
{
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(InfoTests), "Samples.petstore30.yaml");
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(InfoTests), "Samples.petstore30.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
var info = openApiDoc.Info;
Assert.Equal("Swagger Petstore (Simple)", openApiDoc.Info.Title);
- Assert.Equal("A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", info.Description);
+ Assert.Equal(
+ "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
+ info.Description);
Assert.Equal("1.0.0", info.Version.ToString());
}
-
+
[Fact]
public void ParseCompleteHeaderOpenApi()
{
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(InfoTests), "Samples.CompleteHeader.yaml");
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(InfoTests), "Samples.CompleteHeader.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
@@ -37,8 +40,7 @@ public void ParseCompleteHeaderOpenApi()
Assert.Equal("This is an api", openApiDoc.Info.Description);
Assert.Equal("http://example.org/Dowhatyouwant", openApiDoc.Info.TermsOfService);
Assert.Equal("Darrel Miller", openApiDoc.Info.Contact.Name);
- // Assert.Equal("@darrel_miller", openApiDoc.Info.Contact.Extensions["x-twitter"].GetValueNode().GetScalarValue());
+ // Assert.Equal("@darrel_miller", openApiDoc.Info.Contact.Extensions["x-twitter"].GetValueNode().GetScalarValue());
}
-
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/JsonWriterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/JsonWriterTests.cs
index d1b24616c..11115121f 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/JsonWriterTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/JsonWriterTests.cs
@@ -1,35 +1,17 @@
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.OpenApi;
-using Xunit;
using Microsoft.OpenApi.Writers;
+using Newtonsoft.Json.Linq;
+using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
public class JsonWriterTests
{
- [Fact]
- public void WriteMap()
- {
- var outputString = new StringWriter();
- var writer = new OpenApiJsonWriter(outputString);
- writer.WriteStartObject();
- writer.WriteStringProperty("hello","world");
- writer.WriteStringProperty("good", "bye");
- writer.WriteEndObject();
- writer.Flush();
-
-
- var jObject = JObject.Parse(outputString.GetStringBuilder().ToString());
-
- Assert.Equal("world", jObject["hello"]);
- }
-
[Fact]
public void WriteList()
{
@@ -47,27 +29,19 @@ public void WriteList()
}
[Fact]
- public void WriteNestedMap()
+ public void WriteMap()
{
var outputString = new StringWriter();
var writer = new OpenApiJsonWriter(outputString);
- writer.WriteStartObject();
- writer.WritePropertyName("intro");
- writer.WriteStartObject();
- writer.WriteStringProperty("hello", "world");
- writer.WriteEndObject();
-
- writer.WritePropertyName("outro");
- writer.WriteStartObject();
- writer.WriteStringProperty("good", "bye");
- writer.WriteEndObject();
-
- writer.WriteEndObject();
+ writer.WriteStartObject();
+ writer.WriteStringProperty("hello", "world");
+ writer.WriteStringProperty("good", "bye");
+ writer.WriteEndObject();
writer.Flush();
var jObject = JObject.Parse(outputString.GetStringBuilder().ToString());
- Assert.Equal("world", jObject["intro"]["hello"]);
+ Assert.Equal("world", jObject["hello"]);
}
[Fact]
@@ -94,5 +68,28 @@ public void WriteNestedEmptyMap()
Assert.Equal("bye", jObject["outro"]["good"]);
}
+ [Fact]
+ public void WriteNestedMap()
+ {
+ var outputString = new StringWriter();
+ var writer = new OpenApiJsonWriter(outputString);
+ writer.WriteStartObject();
+ writer.WritePropertyName("intro");
+ writer.WriteStartObject();
+ writer.WriteStringProperty("hello", "world");
+ writer.WriteEndObject();
+
+ writer.WritePropertyName("outro");
+ writer.WriteStartObject();
+ writer.WriteStringProperty("good", "bye");
+ writer.WriteEndObject();
+
+ writer.WriteEndObject();
+ writer.Flush();
+
+ var jObject = JObject.Parse(outputString.GetStringBuilder().ToString());
+
+ Assert.Equal("world", jObject["intro"]["hello"]);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
index e447c2449..50493bc79 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
+++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
@@ -65,10 +65,10 @@
-
+
-
+
diff --git a/test/Microsoft.OpenApi.Readers.Tests/OAIExampleTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiExampleTests.cs
similarity index 68%
rename from test/Microsoft.OpenApi.Readers.Tests/OAIExampleTests.cs
rename to test/Microsoft.OpenApi.Readers.Tests/OpenApiExampleTests.cs
index 479b3a19e..6c3fb2298 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/OAIExampleTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiExampleTests.cs
@@ -1,59 +1,61 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
+using System;
using System.Net.Http;
-using System.Text;
using System.Threading.Tasks;
-using Microsoft.OpenApi;
-using Xunit;
-using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Readers.YamlReaders;
+using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
- public class OAIExampleTests
+ public class OpenApiExampleTests
{
- HttpClient client;
- public OAIExampleTests()
+ private readonly HttpClient client;
+
+ public OpenApiExampleTests()
{
client = new HttpClient();
- client.BaseAddress = new Uri("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/OpenAPI.next/examples/v3.0/");
+ client.BaseAddress = new Uri(
+ "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/OpenAPI.next/examples/v3.0/");
}
- [Fact]
- public async Task SimplePetStore()
+
+ [Fact(Skip = "Example is not updated yet")]
+ public async Task ApiWithExamples()
{
- var stream = await client.GetStreamAsync("petstore.yaml");
+ var stream = await client.GetStreamAsync("api-with-examples.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
Assert.Empty(context.Errors);
}
[Fact]
- public async Task UberExample()
+ public async Task PetStoreExpandedExample()
{
- var stream = await client.GetStreamAsync("uber.yaml");
+ var stream = await client.GetStreamAsync("petstore-expanded.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
Assert.Empty(context.Errors);
}
[Fact]
- public async Task PetStoreExpandedExample()
+ public async Task SimplePetStore()
{
- var stream = await client.GetStreamAsync("petstore-expanded.yaml");
+ var stream = await client.GetStreamAsync("petstore.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
Assert.Empty(context.Errors);
}
- [Fact(Skip = "Example is not updated yet")]
- public async Task ApiWithExamples()
+ [Fact]
+ public async Task UberExample()
{
- var stream = await client.GetStreamAsync("api-with-examples.yaml");
+ var stream = await client.GetStreamAsync("uber.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
Assert.Empty(context.Errors);
}
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReferenceTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReferenceTests.cs
index 58d2ac4ca..14a665f1a 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReferenceTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReferenceTests.cs
@@ -1,27 +1,32 @@
-
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
using Microsoft.OpenApi.Readers.YamlReaders;
+using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Microsoft.OpenApi;
- using Xunit;
- using Microsoft.OpenApi.Readers;
-
public class OpenApiReferenceTests
{
+ [Fact]
+ public void ParseExternalHeaderReference()
+ {
+ var reference = new OpenApiReference("externalschema.json#/components/headers/blah");
+
+ Assert.Equal(ReferenceType.Header, reference.ReferenceType);
+ Assert.Equal("externalschema.json", reference.ExternalFilePath);
+ Assert.Equal("blah", reference.TypeName);
+ }
+
[Fact]
public void ParseLocalParameterReference()
{
var reference = new OpenApiReference("#/components/parameters/foobar");
Assert.Equal(ReferenceType.Parameter, reference.ReferenceType);
- Assert.Equal(String.Empty, reference.ExternalFilePath);
+ Assert.Equal(string.Empty, reference.ExternalFilePath);
Assert.Equal("foobar", reference.TypeName);
}
@@ -31,36 +36,24 @@ public void ParseLocalSchemaReference()
var reference = new OpenApiReference("foobar");
Assert.Equal(ReferenceType.Schema, reference.ReferenceType);
- Assert.Equal(String.Empty, reference.ExternalFilePath);
+ Assert.Equal(string.Empty, reference.ExternalFilePath);
Assert.Equal("foobar", reference.TypeName);
}
[Fact]
- public void ParseExternalHeaderReference()
- {
- var reference = new OpenApiReference("externalschema.json#/components/headers/blah");
-
- Assert.Equal(ReferenceType.Header, reference.ReferenceType);
- Assert.Equal("externalschema.json", reference.ExternalFilePath);
- Assert.Equal("blah", reference.TypeName);
- }
-
- [Fact]
- public void TranslateV2Reference()
+ public void TranslateV2ExternalReference()
{
-
- var reference = OpenApiV2Builder.ParseReference("#/definitions/blahblah");
+ var reference = OpenApiV2Deserializer.ParseReference("swagger.json#/parameters/blahblah");
- Assert.Equal(ReferenceType.Schema, reference.ReferenceType);
- Assert.Equal(string.Empty, reference.ExternalFilePath);
+ Assert.Equal(ReferenceType.Parameter, reference.ReferenceType);
+ Assert.Equal("swagger.json", reference.ExternalFilePath);
Assert.Equal("blahblah", reference.TypeName);
}
[Fact]
public void TranslateV2LocalReference()
{
-
- var reference = OpenApiV2Builder.ParseReference("blahblah");
+ var reference = OpenApiV2Deserializer.ParseReference("blahblah");
Assert.Equal(ReferenceType.Schema, reference.ReferenceType);
Assert.Equal(string.Empty, reference.ExternalFilePath);
@@ -68,14 +61,13 @@ public void TranslateV2LocalReference()
}
[Fact]
- public void TranslateV2ExternalReference()
+ public void TranslateV2Reference()
{
+ var reference = OpenApiV2Deserializer.ParseReference("#/definitions/blahblah");
- var reference = OpenApiV2Builder.ParseReference("swagger.json#/parameters/blahblah");
-
- Assert.Equal(ReferenceType.Parameter, reference.ReferenceType);
- Assert.Equal("swagger.json", reference.ExternalFilePath);
+ Assert.Equal(ReferenceType.Schema, reference.ReferenceType);
+ Assert.Equal(string.Empty, reference.ExternalFilePath);
Assert.Equal("blahblah", reference.TypeName);
}
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/OperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OperationTests.cs
index 2bbb467e7..fd6623111 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/OperationTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/OperationTests.cs
@@ -1,24 +1,23 @@
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.OpenApi;
-using Xunit;
-using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Readers.YamlReaders;
+using Xunit;
namespace Microsoft.OpenApi.Readers.Tests
{
public class OperationTests
{
- private OpenApiDocument _PetStoreDoc;
- // private Operation _PostOperation;
+ private readonly OpenApiDocument _PetStoreDoc;
+ // private Operation _PostOperation;
public OperationTests()
{
-
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(OperationTests), "Samples.petstore30.yaml");
+ var stream = GetType()
+ .Assembly.GetManifestResourceStream(typeof(OperationTests), "Samples.petstore30.yaml");
_PetStoreDoc = new OpenApiStreamReader().Read(stream, out var context);
//_PostOperation = _PetStoreDoc.Paths.PathMap.Where(pm=>pm.Key == "/pets").Value
// .Operations.Where()
@@ -37,7 +36,6 @@ public void CheckPetStoreFirstOperation()
[Fact]
public void CheckPetStoreFirstOperationParameters()
{
-
var firstPath = _PetStoreDoc.Paths.First().Value;
var firstOperation = firstPath.Operations.First().Value;
var firstParameter = firstOperation.Parameters.First();
@@ -50,25 +48,28 @@ public void CheckPetStoreFirstOperationParameters()
[Fact]
public void CheckPetStoreFirstOperationRequest()
{
-
var firstPath = _PetStoreDoc.Paths.First().Value;
var firstOperation = firstPath.Operations.First().Value;
var requestBody = firstOperation.RequestBody;
-
Assert.Null(firstOperation.RequestBody);
}
[Fact]
- public void GetPostOperation()
+ public void DoesAPathExist()
{
+ Assert.Equal(2, _PetStoreDoc.Paths.Count());
+ Assert.NotNull(_PetStoreDoc.Paths["/pets"]);
+ }
+ [Fact]
+ public void GetPostOperation()
+ {
var postOperation = _PetStoreDoc.Paths["/pets"].Operations["post"];
Assert.Equal("addPet", postOperation.OperationId);
Assert.NotNull(postOperation);
-
}
[Fact]
@@ -77,24 +78,12 @@ public void GetResponses()
var getOperation = _PetStoreDoc.Paths["/pets"].Operations["get"];
var responses = getOperation.Responses;
-
+
Assert.Equal(2, responses["200"].Content.Values.Count());
var response = getOperation.Responses["200"];
var content = response.Content["application/json"];
Assert.NotNull(content.Schema);
}
-
-
-
-
- [Fact]
- public void DoesAPathExist()
- {
-
- Assert.Equal(2, _PetStoreDoc.Paths.Count());
- Assert.NotNull(_PetStoreDoc.Paths["/pets"]);
- }
-
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/ParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/ParameterTests.cs
index 5d90e736b..e971aba30 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/ParameterTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/ParameterTests.cs
@@ -1,70 +1,130 @@
-using Microsoft.OpenApi;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Threading.Tasks;
using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
public class ParameterTests
{
+ private const string _UriReservedSymbols = ":/?#[]@!$&'()*+,;=";
+ private const string _UriUnreservedSymbols = "-._~";
- [Theory,
- InlineData("foo","foo")]
- public void SerializeStrings(string value, string expected)
+ private static readonly char[] HexDigits =
{
- var parameter = new OpenApiParameter() {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F'
+ };
- };
+ private static string Encode(string p, bool allowReserved)
+ {
+ var result = new StringBuilder();
+ foreach (var c in p)
+ {
+ if ((c >= 'A' && c <= 'z') //Alpha
+ ||
+ (c >= '0' && c <= '9') // Digit
+ ||
+ _UriUnreservedSymbols.IndexOf(c) !=
+ -1 // Unreserved symbols - These should never be percent encoded
+ ||
+ (allowReserved && _UriReservedSymbols.IndexOf(c) != -1)
+ ) // Reserved symbols - should be included if requested (+)
+ {
+ result.Append(c);
+ }
+ else
+ {
+ var bytes = Encoding.UTF8.GetBytes(new[] {c});
+ foreach (var abyte in bytes)
+ {
+ result.Append(HexEscape(abyte));
+ }
+ }
+ }
- var actual = SerializeParameterValue(parameter,value);
- Assert.Equal(expected, actual);
+ return result.ToString();
}
- [Theory,
- InlineData("://foo/bar?", "://foo/bar?"),
- InlineData("foo bar", "foo%20bar")]
- public void SerializeEscapedStrings(string value, string expected)
+ public static string HexEscape(byte i)
{
- var parameter = new OpenApiParameter()
- {
- AllowReserved = false
- };
+ var esc = new char[3];
+ esc[0] = '%';
+ esc[1] = HexDigits[((i & 240) >> 4)];
+ esc[2] = HexDigits[(i & 15)];
+ return new string(esc);
+ }
- var actual = SerializeParameterValue(parameter, value);
- Assert.Equal(expected, actual);
+ public static string HexEscape(char c)
+ {
+ var esc = new char[3];
+ esc[0] = '%';
+ esc[1] = HexDigits[((c & 240) >> 4)];
+ esc[2] = HexDigits[(c & 15)];
+ return new string(esc);
+ }
+
+ private bool IsArray(object value)
+ {
+ return value is IEnumerable;
}
- [Theory,
- InlineData("label","yo", ".yo"),
- InlineData("matrix", "x", ";foo=x"),
- InlineData("matrix", "", ";foo")]
- public void SerializePrefixedStrings(string style,string value, string expected)
+ private bool IsMap(object value)
{
- var parameter = new OpenApiParameter()
+ return value is IDictionary;
+ }
+
+ private bool IsSimple(object value)
+ {
+ return value is string;
+ }
+
+ [Theory]
+ [InlineData("matrix", new[] {"a", "b"}, ";bar=a,b")]
+ [InlineData("exploded-matrix", new[] {"a", "b"}, ";bar=a;bar=b")]
+ [InlineData("label", new[] {"a", "b"}, ".a.b")]
+ [InlineData("exploded-label", new[] {"a", "b"}, ".a.b")]
+ public void SerializeArrays(string style, string[] value, string expected)
+ {
+ var parameter = new OpenApiParameter
{
- Name = "foo",
+ Name = "bar",
Style = style
};
-
+
var actual = SerializeParameterValue(parameter, value);
Assert.Equal(expected, actual);
}
- [Theory,
- InlineData("matrix",new[] { "a", "b" }, ";bar=a,b"),
- InlineData("exploded-matrix", new[] { "a", "b" }, ";bar=a;bar=b"),
- InlineData("label", new[] { "a", "b" }, ".a.b"),
- InlineData("exploded-label", new[] { "a", "b" }, ".a.b")]
- public void SerializeArrays(string style, string[] value, string expected)
+ [Theory]
+ [InlineData("://foo/bar?", "://foo/bar?")]
+ [InlineData("foo bar", "foo%20bar")]
+ public void SerializeEscapedStrings(string value, string expected)
{
- var parameter = new OpenApiParameter()
+ var parameter = new OpenApiParameter
{
- Name = "bar",
- Style = style
+ AllowReserved = false
};
var actual = SerializeParameterValue(parameter, value);
@@ -74,17 +134,15 @@ public void SerializeArrays(string style, string[] value, string expected)
// format="space-delimited" type="array" explode=false bar=a b
// format="space-delimited" type="array" explode=true bar=a bar=b
-
-
- [Theory,
- InlineData("matrix", ";bar=a,1,b,2"),
- InlineData("exploded-matrix", ";a=1;b=2"),
- InlineData("label", ".a.1.b.2"),
- InlineData("exploded-label", ".a=1.b=2")]
+ [Theory]
+ [InlineData("matrix", ";bar=a,1,b,2")]
+ [InlineData("exploded-matrix", ";a=1;b=2")]
+ [InlineData("label", ".a.1.b.2")]
+ [InlineData("exploded-label", ".a=1.b=2")]
public void SerializeMaps(string style, string expected)
{
- var value = new Dictionary { { "a", "1" }, { "b", "2" } };
- var parameter = new OpenApiParameter()
+ var value = new Dictionary {{"a", "1"}, {"b", "2"}};
+ var parameter = new OpenApiParameter
{
Name = "bar",
Style = style
@@ -93,44 +151,107 @@ public void SerializeMaps(string style, string expected)
var actual = SerializeParameterValue(parameter, value);
Assert.Equal(expected, actual);
}
+
// Is it possible to write code based on the information in Parameter
// to serialize the value like RFC6570 does!
- private string SerializeParameterValue(OpenApiParameter parameter, object value )
+ private string SerializeParameterValue(OpenApiParameter parameter, object value)
{
string output;
-
+
switch (parameter.Style)
{
- case "matrix": // Matrix
- output = SerializeValues(parameter.Name, false,parameter.AllowReserved,value, (n,v,m) => ";" + n + (string.IsNullOrEmpty(v) ? "" : "=") + v, ",");
+ case "matrix": // Matrix
+ output = SerializeValues(
+ parameter.Name,
+ false,
+ parameter.AllowReserved,
+ value,
+ (n, v, m) => ";" + n + (string.IsNullOrEmpty(v) ? "" : "=") + v,
+ ",");
break;
- case "exploded-matrix": // Matrix
- output = SerializeValues(parameter.Name, true, parameter.AllowReserved, value, (n, v, m) => ";" + n + (string.IsNullOrEmpty(v) ? "" : "=") + v, ",");
+ case "exploded-matrix": // Matrix
+ output = SerializeValues(
+ parameter.Name,
+ true,
+ parameter.AllowReserved,
+ value,
+ (n, v, m) => ";" + n + (string.IsNullOrEmpty(v) ? "" : "=") + v,
+ ",");
break;
- case "label": // Label
- output = SerializeValues(parameter.Name,false, parameter.AllowReserved, value, (n,v,m) => "." + ( m ? n + "=" : "") + v , ".");
+ case "label": // Label
+ output = SerializeValues(
+ parameter.Name,
+ false,
+ parameter.AllowReserved,
+ value,
+ (n, v, m) => "." + (m ? n + "=" : "") + v,
+ ".");
break;
- case "exploded-label": // Label
- output = SerializeValues(parameter.Name, true, parameter.AllowReserved, value, (n, v, m) => "." + (m ? n + "=" : "") + v, ".");
+ case "exploded-label": // Label
+ output = SerializeValues(
+ parameter.Name,
+ true,
+ parameter.AllowReserved,
+ value,
+ (n, v, m) => "." + (m ? n + "=" : "") + v,
+ ".");
break;
default: // Simple
- output = SerializeValues(parameter.Name, false, parameter.AllowReserved, value, (n, v,m) => v, ",");
+ output = SerializeValues(
+ parameter.Name,
+ false,
+ parameter.AllowReserved,
+ value,
+ (n, v, m) => v,
+ ",");
break;
-
}
+
return output;
}
- private string SerializeValues(string name, bool explode, bool allowReserved, object value, Func renderValue, string seperator)
+ [Theory]
+ [InlineData("label", "yo", ".yo")]
+ [InlineData("matrix", "x", ";foo=x")]
+ [InlineData("matrix", "", ";foo")]
+ public void SerializePrefixedStrings(string style, string value, string expected)
+ {
+ var parameter = new OpenApiParameter
+ {
+ Name = "foo",
+ Style = style
+ };
+
+ var actual = SerializeParameterValue(parameter, value);
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineData("foo", "foo")]
+ public void SerializeStrings(string value, string expected)
+ {
+ var parameter = new OpenApiParameter();
+
+ var actual = SerializeParameterValue(parameter, value);
+ Assert.Equal(expected, actual);
+ }
+
+ private string SerializeValues(
+ string name,
+ bool explode,
+ bool allowReserved,
+ object value,
+ Func renderValue,
+ string seperator)
{
string output = null;
if (IsSimple(value))
{
var stringValue = (string)value;
- output = renderValue(name, stringValue,false);
+ output = renderValue(name, stringValue, false);
}
else if (IsMap(value))
{
@@ -139,97 +260,36 @@ private string SerializeValues(string name, bool explode, bool allowReserved, ob
{
foreach (var item in mapValue)
{
- output += renderValue(item.Key, item.Value,true);
+ output += renderValue(item.Key, item.Value, true);
}
}
else
{
- output = renderValue(name, string.Join(seperator, mapValue.Select(kvp => kvp.Key + (explode ? "=" : seperator) + kvp.Value).ToList()),false);
+ output = renderValue(
+ name,
+ string.Join(
+ seperator,
+ mapValue.Select(kvp => kvp.Key + (explode ? "=" : seperator) + kvp.Value).ToList()),
+ false);
}
}
- else if (IsArray(value)) {
+ else if (IsArray(value))
+ {
var arrayValue = (string[])value;
- if (explode) {
- foreach(var itemValue in arrayValue)
+ if (explode)
+ {
+ foreach (var itemValue in arrayValue)
{
- output += renderValue(name, itemValue,false);
+ output += renderValue(name, itemValue, false);
}
}
else
{
- output = renderValue(name, string.Join(seperator, arrayValue),false);
+ output = renderValue(name, string.Join(seperator, arrayValue), false);
}
}
return Encode(output, !allowReserved);
-
- }
-
- private bool IsMap(object value)
- {
- return value is IDictionary;
- }
-
- private bool IsArray(object value)
- {
- return value is IEnumerable;
- }
-
- private bool IsSimple(object value)
- {
- return value is string;
- }
-
-
- private const string _UriReservedSymbols = ":/?#[]@!$&'()*+,;=";
- private const string _UriUnreservedSymbols = "-._~";
- private static string Encode(string p, bool allowReserved)
- {
-
- var result = new StringBuilder();
- foreach (char c in p)
- {
- if ((c >= 'A' && c <= 'z') //Alpha
- || (c >= '0' && c <= '9') // Digit
- || _UriUnreservedSymbols.IndexOf(c) != -1 // Unreserved symbols - These should never be percent encoded
- || (allowReserved && _UriReservedSymbols.IndexOf(c) != -1)) // Reserved symbols - should be included if requested (+)
- {
- result.Append(c);
- }
- else
- {
- var bytes = Encoding.UTF8.GetBytes(new[] { c });
- foreach (var abyte in bytes)
- {
- result.Append(HexEscape(abyte));
- }
-
- }
- }
-
- return result.ToString();
-
-
- }
-
- public static string HexEscape(byte i)
- {
- var esc = new char[3];
- esc[0] = '%';
- esc[1] = HexDigits[((i & 240) >> 4)];
- esc[2] = HexDigits[(i & 15)];
- return new string(esc);
}
- public static string HexEscape(char c)
- {
- var esc = new char[3];
- esc[0] = '%';
- esc[1] = HexDigits[(((int)c & 240) >> 4)];
- esc[2] = HexDigits[((int)c & 15)];
- return new string(esc);
- }
- private static readonly char[] HexDigits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/SchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/SchemaTests.cs
index f59e5d58b..3aa4c738f 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/SchemaTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/SchemaTests.cs
@@ -1,31 +1,26 @@
-using SharpYaml.Serialization;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.OpenApi;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using Microsoft.OpenApi.Readers.YamlReaders;
+using Microsoft.OpenApi.Readers.YamlReaders.ParseNodes;
using Xunit;
-
namespace Microsoft.OpenApi.Readers.Tests
{
public class SchemaTests
{
-
[Fact]
public void CheckPetStoreApiInfo()
{
- var stream = this.GetType().Assembly.GetManifestResourceStream(typeof(SchemaTests), "Samples.petstore30.yaml");
+ var stream = GetType().Assembly.GetManifestResourceStream(typeof(SchemaTests), "Samples.petstore30.yaml");
var openApiDoc = new OpenApiStreamReader().Read(stream, out var context);
var operation = openApiDoc.Paths["/pets"].Operations["get"];
var schema = operation.Responses["200"].Content["application/json"].Schema;
Assert.NotNull(schema);
-
}
[Fact]
@@ -33,12 +28,15 @@ public void CreateSchemaFromInlineJsonSchema()
{
var jsonSchema = " { \"type\" : \"int\" } ";
- var mapNode = MapNode.Create(jsonSchema);
+ var context = new ParsingContext();
+ var diagnostic = new OpenApiDiagnostic();
+
+ var mapNode = new MapNode(context, diagnostic, jsonSchema);
- var schema = OpenApiV3Builder.LoadSchema(mapNode);
+ var schema = OpenApiV3Deserializer.LoadSchema(mapNode);
Assert.NotNull(schema);
Assert.Equal("int", schema.Type);
}
}
-}
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.Readers.Tests/YamlWriterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/YamlWriterTests.cs
index fcde38f13..c6ab44d5e 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/YamlWriterTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/YamlWriterTests.cs
@@ -1,46 +1,42 @@
-using Microsoft.OpenApi;
-using Microsoft.OpenApi.Writers;
-using System;
-using System.Collections.Generic;
+// ------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
+// ------------------------------------------------------------
+
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Microsoft.OpenApi.Writers;
using Xunit;
-namespace OpenApiTests
+namespace Microsoft.OpenApi.Readers.Tests
{
public class YamlWriterTests
{
[Fact]
- public void WriteMap()
+ public void WriteList()
{
var outputString = new StringWriter();
var writer = new OpenApiYamlWriter(outputString);
+ writer.WriteStartArray();
writer.WriteStartObject();
writer.WriteEndObject();
-
+ writer.WriteEndArray();
//Assert.Equal(0, debug.StackState.Count);
//Assert.Equal("", debug.Indent);
}
[Fact]
- public void WriteList()
+ public void WriteMap()
{
var outputString = new StringWriter();
var writer = new OpenApiYamlWriter(outputString);
- writer.WriteStartArray();
writer.WriteStartObject();
writer.WriteEndObject();
- writer.WriteEndArray();
//Assert.Equal(0, debug.StackState.Count);
//Assert.Equal("", debug.Indent);
}
-
-
- }
}
+}
\ No newline at end of file