Skip to content

Commit 7472db9

Browse files
Merge pull request #1042 from microsoft/mk/add-license-spdx-identifier
Add license SPDX identifier
2 parents 509d53c + a1647d1 commit 7472db9

File tree

7 files changed

+108
-1
lines changed

7 files changed

+108
-1
lines changed

src/Microsoft.OpenApi.Readers/V3/OpenApiLicenseDeserializer.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ internal static partial class OpenApiV3Deserializer
2222
o.Name = n.GetScalarValue();
2323
}
2424
},
25+
{
26+
"identifier", (o, n) =>
27+
{
28+
o.Identifier = n.GetScalarValue();
29+
}
30+
},
2531
{
2632
"url", (o, n) =>
2733
{

src/Microsoft.OpenApi/Models/OpenApiConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ public static class OpenApiConstants
120120
/// </summary>
121121
public const string Name = "name";
122122

123+
/// <summary>
124+
/// Field: Identifier
125+
/// </summary>
126+
public const string Identifier = "identifier";
127+
123128
/// <summary>
124129
/// Field: Namespace
125130
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiLicense.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public class OpenApiLicense : IOpenApiSerializable, IOpenApiExtensible
1919
/// </summary>
2020
public string Name { get; set; }
2121

22+
/// <summary>
23+
/// An SPDX license expression for the API. The identifier field is mutually exclusive of the url field.
24+
/// </summary>
25+
public string Identifier { get; set; }
26+
2227
/// <summary>
2328
/// The URL pointing to the contact information. MUST be in the format of a URL.
2429
/// </summary>
@@ -40,6 +45,7 @@ public OpenApiLicense() {}
4045
public OpenApiLicense(OpenApiLicense license)
4146
{
4247
Name = license?.Name ?? Name;
48+
Identifier = license?.Identifier ?? Identifier;
4349
Url = license?.Url != null ? new Uri(license.Url.OriginalString) : null;
4450
Extensions = license?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(license.Extensions) : null;
4551
}
@@ -72,6 +78,9 @@ private void WriteInternal(IOpenApiWriter writer, OpenApiSpecVersion specVersion
7278
// name
7379
writer.WriteProperty(OpenApiConstants.Name, Name);
7480

81+
// identifier
82+
writer.WriteProperty(OpenApiConstants.Identifier, Identifier);
83+
7584
// url
7685
writer.WriteProperty(OpenApiConstants.Url, Url?.OriginalString);
7786

test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>net6.0</TargetFrameworks>
44
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
@@ -164,6 +164,9 @@
164164
<EmbeddedResource Include="V3Tests\Samples\OpenApiInfo\basicInfo.yaml">
165165
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
166166
</EmbeddedResource>
167+
<EmbeddedResource Include="V3Tests\Samples\OpenApiLicense\licenseWithSpdxIdentifier.yaml">
168+
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
169+
</EmbeddedResource>
167170
<EmbeddedResource Include="V3Tests\Samples\OpenApiInfo\minimalInfo.yaml">
168171
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
169172
</EmbeddedResource>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Models;
5+
using Microsoft.OpenApi.Readers.ParseNodes;
6+
using Microsoft.OpenApi.Readers.V3;
7+
using SharpYaml.Serialization;
8+
using System.IO;
9+
using Xunit;
10+
using System.Linq;
11+
using FluentAssertions;
12+
13+
namespace Microsoft.OpenApi.Readers.Tests.V3Tests
14+
{
15+
16+
public class OpenApiLicenseTests
17+
{
18+
private const string SampleFolderPath = "V3Tests/Samples/OpenApiLicense/";
19+
20+
[Fact]
21+
public void ParseLicenseWithSpdxIdentifierShouldSucceed()
22+
{
23+
using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "licenseWithSpdxIdentifier.yaml"));
24+
var yamlStream = new YamlStream();
25+
yamlStream.Load(new StreamReader(stream));
26+
var yamlNode = yamlStream.Documents.First().RootNode;
27+
28+
var diagnostic = new OpenApiDiagnostic();
29+
var context = new ParsingContext(diagnostic);
30+
31+
var node = new MapNode(context, (YamlMappingNode)yamlNode);
32+
33+
// Act
34+
var license = OpenApiV3Deserializer.LoadLicense(node);
35+
36+
// Assert
37+
license.Should().BeEquivalentTo(
38+
new OpenApiLicense
39+
{
40+
Name = "Apache 2.0",
41+
Identifier = "Apache-2.0"
42+
});
43+
}
44+
}
45+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
name: Apache 2.0
2+
identifier: Apache-2.0

test/Microsoft.OpenApi.Tests/Models/OpenApiLicenseTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public class OpenApiLicenseTests
3030
}
3131
};
3232

33+
public static OpenApiLicense LicenseWithIdentifier = new OpenApiLicense
34+
{
35+
Name = "Apache 2.0",
36+
Identifier = "Apache-2.0"
37+
};
38+
3339
[Theory]
3440
[InlineData(OpenApiSpecVersion.OpenApi3_0)]
3541
[InlineData(OpenApiSpecVersion.OpenApi2_0)]
@@ -123,5 +129,36 @@ public void ShouldCopyFromOriginalObjectWithoutMutating()
123129
Assert.NotEqual(AdvanceLicense.Name, licenseCopy.Name);
124130
Assert.NotEqual(AdvanceLicense.Url, licenseCopy.Url);
125131
}
132+
133+
[Fact]
134+
public void SerializeLicenseWithIdentifierAsJsonWorks()
135+
{
136+
// Arrange
137+
var expected =
138+
@"{
139+
""name"": ""Apache 2.0"",
140+
""identifier"": ""Apache-2.0""
141+
}";
142+
143+
// Act
144+
var actual = LicenseWithIdentifier.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0);
145+
146+
// Assert
147+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
148+
}
149+
150+
[Fact]
151+
public void SerializeLicenseWithIdentifierAsYamlWorks()
152+
{
153+
// Arrange
154+
var expected = @"name: Apache 2.0
155+
identifier: Apache-2.0";
156+
157+
// Act
158+
var actual = LicenseWithIdentifier.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0);
159+
160+
// Assert
161+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
162+
}
126163
}
127164
}

0 commit comments

Comments
 (0)