First pass at data-driven conformance tests
These use the test files from https://github.com/cloudevents/conformance/tree/format-tests/format, which is included via a submodule called conformance. The XML tests are not included in this commit, as the C# XML formatter has not been reviewed yet. Signed-off-by: Jon Skeet <jonskeet@google.com>
This commit is contained in:
parent
8887ed21f9
commit
4dd0f93b55
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29001.49
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.32112.339
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents", "src\CloudNative.CloudEvents\CloudNative.CloudEvents.csproj", "{C5DC9F44-7C03-4A70-80EF-7A29696455EB}"
|
||||
EndProject
|
||||
|
@ -35,7 +35,42 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents.New
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents.SystemTextJson", "src\CloudNative.CloudEvents.SystemTextJson\CloudNative.CloudEvents.SystemTextJson.csproj", "{FACB3EF2-F078-479A-A91C-719894CB66BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CloudNative.CloudEvents.Protobuf", "src\CloudNative.CloudEvents.Protobuf\CloudNative.CloudEvents.Protobuf.csproj", "{9D82AC2B-0075-4161-AE0E-4A6629C9FF2A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CloudNative.CloudEvents.Protobuf", "src\CloudNative.CloudEvents.Protobuf\CloudNative.CloudEvents.Protobuf.csproj", "{9D82AC2B-0075-4161-AE0E-4A6629C9FF2A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "conformance", "conformance", "{8CCC98B3-1776-49FF-96D6-947A9E5DFB0A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "format", "format", "{A5906FBA-D73A-4A09-8539-CB10D7B586AE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
conformance\format\README.md = conformance\format\README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "json", "json", "{D8055631-E6BB-4CD2-8162-F674D6D30E76}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
conformance\format\json\invalid-batches.json = conformance\format\json\invalid-batches.json
|
||||
conformance\format\json\invalid-events.json = conformance\format\json\invalid-events.json
|
||||
conformance\format\json\README.md = conformance\format\json\README.md
|
||||
conformance\format\json\valid-batches.json = conformance\format\json\valid-batches.json
|
||||
conformance\format\json\valid-events.json = conformance\format\json\valid-events.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "protobuf", "protobuf", "{119AD438-878B-4383-BC9F-779F1605E711}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
conformance\format\protobuf\conformance_tests.proto = conformance\format\protobuf\conformance_tests.proto
|
||||
conformance\format\protobuf\invalid-batches.json = conformance\format\protobuf\invalid-batches.json
|
||||
conformance\format\protobuf\invalid-events.json = conformance\format\protobuf\invalid-events.json
|
||||
conformance\format\protobuf\README.md = conformance\format\protobuf\README.md
|
||||
conformance\format\protobuf\valid-batches.json = conformance\format\protobuf\valid-batches.json
|
||||
conformance\format\protobuf\valid-events.json = conformance\format\protobuf\valid-events.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "xml", "xml", "{4012C753-68DE-4737-936F-F5DBC485C51B}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
conformance\format\xml\invalid-batches.xml = conformance\format\xml\invalid-batches.xml
|
||||
conformance\format\xml\invalid-events.xml = conformance\format\xml\invalid-events.xml
|
||||
conformance\format\xml\README.md = conformance\format\xml\README.md
|
||||
conformance\format\xml\valid-batches.xml = conformance\format\xml\valid-batches.xml
|
||||
conformance\format\xml\valid-events.xml = conformance\format\xml\valid-events.xml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -207,6 +242,12 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{A5906FBA-D73A-4A09-8539-CB10D7B586AE} = {8CCC98B3-1776-49FF-96D6-947A9E5DFB0A}
|
||||
{D8055631-E6BB-4CD2-8162-F674D6D30E76} = {A5906FBA-D73A-4A09-8539-CB10D7B586AE}
|
||||
{119AD438-878B-4383-BC9F-779F1605E711} = {A5906FBA-D73A-4A09-8539-CB10D7B586AE}
|
||||
{4012C753-68DE-4737-936F-F5DBC485C51B} = {A5906FBA-D73A-4A09-8539-CB10D7B586AE}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F77A454C-CC17-4AD6-823A-64E1A94FDA0A}
|
||||
EndGlobalSection
|
||||
|
|
|
@ -63,5 +63,14 @@ $PROTOC \
|
|||
--csharp_opt=file_extension=.g.cs \
|
||||
test/CloudNative.CloudEvents.UnitTests/Protobuf/*.proto
|
||||
|
||||
# Conformance test protos
|
||||
$PROTOC \
|
||||
-I tmp/include \
|
||||
-I tmp/cloudevents \
|
||||
-I conformance/format/protobuf \
|
||||
--csharp_out=test/CloudNative.CloudEvents.UnitTests/Protobuf \
|
||||
--csharp_opt=file_extension=.g.cs \
|
||||
conformance/format/protobuf/*.proto
|
||||
|
||||
echo "Generated code."
|
||||
rm -rf tmp
|
||||
|
|
|
@ -95,7 +95,6 @@ namespace CloudNative.CloudEvents.AspNetCore.UnitTests
|
|||
|
||||
var parsed = new JsonEventFormatter().DecodeStructuredModeMessage(content, new ContentType(response.ContentType), extensionAttributes: null);
|
||||
AssertCloudEventsEqual(cloudEvent, parsed);
|
||||
Assert.Equal(cloudEvent.Data, parsed.Data);
|
||||
|
||||
// We populate headers even though we don't strictly need to; let's validate that.
|
||||
Assert.Equal("1.0", response.Headers["ce-specversion"]);
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
|
||||
public static class SampleBatches
|
||||
{
|
||||
private static ConcurrentDictionary<string, IReadOnlyList<CloudEvent>> batchesById = new ConcurrentDictionary<string, IReadOnlyList<CloudEvent>>();
|
||||
|
||||
private static readonly IReadOnlyList<CloudEvent> empty = Register("empty");
|
||||
private static readonly IReadOnlyList<CloudEvent> minimal = Register("minimal", SampleEvents.Minimal);
|
||||
private static readonly IReadOnlyList<CloudEvent> minimal2 = Register("minimal2", SampleEvents.Minimal, SampleEvents.Minimal);
|
||||
private static readonly IReadOnlyList<CloudEvent> minimalAndAllCore = Register("minimalAndAllCore", SampleEvents.Minimal, SampleEvents.AllCore);
|
||||
private static readonly IReadOnlyList<CloudEvent> minimalAndAllExtensionTypes =
|
||||
Register("minimalAndAllExtensionTypes", SampleEvents.Minimal, SampleEvents.AllExtensionTypes);
|
||||
|
||||
internal static IReadOnlyList<CloudEvent> Empty => Clone(empty);
|
||||
internal static IReadOnlyList<CloudEvent> Minimal => Clone(minimal);
|
||||
internal static IReadOnlyList<CloudEvent> Minimal2 => Clone(minimal2);
|
||||
internal static IReadOnlyList<CloudEvent> MinimalAndAllCore => Clone(minimalAndAllCore);
|
||||
internal static IReadOnlyList<CloudEvent> MinimalAndAllExtensionTypes => Clone(minimalAndAllExtensionTypes);
|
||||
|
||||
internal static IReadOnlyList<CloudEvent> FromId(string id) => batchesById.TryGetValue(id, out var batch)
|
||||
? Clone(batch)
|
||||
: throw new ArgumentException($"No such sample batch: '{id}'");
|
||||
|
||||
private static IReadOnlyList<CloudEvent> Clone(IReadOnlyList<CloudEvent> cloudEvents) =>
|
||||
cloudEvents.Select(SampleEvents.Clone).ToList().AsReadOnly();
|
||||
|
||||
private static IReadOnlyList<CloudEvent> Register(string id, params CloudEvent[] cloudEvents)
|
||||
{
|
||||
var list = new List<CloudEvent>(cloudEvents).AsReadOnly();
|
||||
batchesById[id] = list;
|
||||
return list;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
|
||||
internal static class SampleEvents
|
||||
{
|
||||
private static ConcurrentDictionary<string, CloudEvent> eventsById = new ConcurrentDictionary<string, CloudEvent>();
|
||||
|
||||
private static IReadOnlyList<CloudEventAttribute> allExtensionAttributes = new List<CloudEventAttribute>()
|
||||
{
|
||||
CloudEventAttribute.CreateExtension("extinteger", CloudEventAttributeType.Integer),
|
||||
CloudEventAttribute.CreateExtension("extboolean", CloudEventAttributeType.Boolean),
|
||||
CloudEventAttribute.CreateExtension("extstring", CloudEventAttributeType.String),
|
||||
CloudEventAttribute.CreateExtension("exttimestamp", CloudEventAttributeType.Timestamp),
|
||||
CloudEventAttribute.CreateExtension("exturi", CloudEventAttributeType.Uri),
|
||||
CloudEventAttribute.CreateExtension("exturiref", CloudEventAttributeType.UriReference),
|
||||
CloudEventAttribute.CreateExtension("extbinary", CloudEventAttributeType.Binary),
|
||||
}.AsReadOnly();
|
||||
|
||||
private static readonly CloudEvent minimal = new CloudEvent
|
||||
{
|
||||
Id = "minimal",
|
||||
Type = "io.cloudevents.test",
|
||||
Source = new Uri("https://cloudevents.io")
|
||||
}.Register();
|
||||
|
||||
private static readonly CloudEvent allCore = minimal.With(evt =>
|
||||
{
|
||||
evt.Id = "allCore";
|
||||
evt.DataContentType = "text/plain";
|
||||
evt.DataSchema = new Uri("https://cloudevents.io/dataschema");
|
||||
evt.Subject = "tests";
|
||||
evt.Time = new DateTimeOffset(2018, 4, 5, 17, 31, 0, TimeSpan.Zero);
|
||||
}).Register();
|
||||
|
||||
private static readonly CloudEvent minimalWithTime = minimal.With(evt =>
|
||||
{
|
||||
evt.Id = "minimalWithTime";
|
||||
evt.Time = new DateTimeOffset(2018, 4, 5, 17, 31, 0, TimeSpan.Zero);
|
||||
}).Register();
|
||||
|
||||
private static readonly CloudEvent minimalWithRelativeSource = minimal.With(evt =>
|
||||
{
|
||||
evt.Id = "minimalWithRelativeSource";
|
||||
evt.Source = new Uri("#fragment", UriKind.RelativeOrAbsolute);
|
||||
}).Register();
|
||||
|
||||
private static readonly CloudEvent simpleTextData = minimal.With(evt =>
|
||||
{
|
||||
evt.Id = "simpleTextData";
|
||||
evt.Data = "Simple text";
|
||||
evt.DataContentType = "text/plain";
|
||||
}).Register();
|
||||
|
||||
private static readonly CloudEvent allExtensionTypes = minimal.WithSampleExtensionAttributes().With(evt =>
|
||||
{
|
||||
evt.Id = "allExtensionTypes";
|
||||
|
||||
evt["extinteger"] = 10;
|
||||
evt["extboolean"] = true;
|
||||
evt["extstring"] = "text";
|
||||
evt["extbinary"] = new byte[] { 77, 97 };
|
||||
evt["exttimestamp"] = new DateTimeOffset(2023, 3, 31, 15, 12, 0, TimeSpan.Zero);
|
||||
evt["exturi"] = new Uri("https://cloudevents.io");
|
||||
evt["exturiref"] = new Uri("//authority/path", UriKind.RelativeOrAbsolute);
|
||||
}).Register();
|
||||
|
||||
internal static CloudEvent Minimal => Clone(minimal);
|
||||
internal static CloudEvent AllCore => Clone(allCore);
|
||||
internal static CloudEvent MinimalWithTime => Clone(minimalWithTime);
|
||||
internal static CloudEvent MinimalWithRelativeSource => Clone(minimalWithRelativeSource);
|
||||
internal static CloudEvent SimpleTextData => Clone(simpleTextData);
|
||||
internal static CloudEvent AllExtensionTypes => Clone(allExtensionTypes);
|
||||
internal static IReadOnlyList<CloudEventAttribute> SampleExtensionAttributes => allExtensionAttributes;
|
||||
|
||||
internal static CloudEvent FromId(string id) => eventsById.TryGetValue(id, out var evt)
|
||||
? Clone(evt)
|
||||
: throw new ArgumentException($"No such sample event: '{id}'");
|
||||
|
||||
// TODO: Make this available somewhere else?
|
||||
internal static CloudEvent Clone(CloudEvent evt)
|
||||
{
|
||||
var clone = new CloudEvent(evt.SpecVersion, evt.ExtensionAttributes);
|
||||
foreach (var attr in evt.GetPopulatedAttributes())
|
||||
{
|
||||
clone[attr.Key] = attr.Value;
|
||||
}
|
||||
// TODO: Deep copy where appropriate?
|
||||
clone.Data = evt.Data;
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static CloudEvent With(this CloudEvent evt, Action<CloudEvent> action)
|
||||
{
|
||||
var clone = Clone(evt);
|
||||
action(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clone of the given CloudEvent, with all attributes in <see cref="allExtensionAttributes"/>
|
||||
/// registered but without values.
|
||||
/// </summary>
|
||||
private static CloudEvent WithSampleExtensionAttributes(this CloudEvent evt) => evt.With(clone =>
|
||||
{
|
||||
foreach (var attribute in allExtensionAttributes)
|
||||
{
|
||||
clone[attribute] = null;
|
||||
}
|
||||
});
|
||||
|
||||
private static CloudEvent Register(this CloudEvent evt)
|
||||
{
|
||||
eventsById[evt.Id ?? throw new InvalidOperationException("No ID in sample event")] = evt;
|
||||
return evt;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
|
||||
internal class TestDataProvider
|
||||
{
|
||||
private static readonly string ConformanceTestDataRoot = Path.Combine(FindRepoRoot(), "conformance", "format");
|
||||
|
||||
public static TestDataProvider Json { get; } = new TestDataProvider("json", "*.json");
|
||||
public static TestDataProvider Protobuf { get; } = new TestDataProvider("protobuf", "*.json");
|
||||
public static TestDataProvider Xml { get; } = new TestDataProvider("xml", "*.xml");
|
||||
|
||||
|
||||
private readonly string testDataDirectory;
|
||||
private readonly string searchPattern;
|
||||
|
||||
private TestDataProvider(string relativeDirectory, string searchPattern)
|
||||
{
|
||||
testDataDirectory = Path.Combine(ConformanceTestDataRoot, relativeDirectory);
|
||||
this.searchPattern = searchPattern;
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListTestFiles() => Directory.EnumerateFiles(testDataDirectory, searchPattern);
|
||||
|
||||
/// <summary>
|
||||
/// Loads all tests, assuming multiple tests per file, to be loaded based on textual file content.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFile">The deserialized test file type.</typeparam>
|
||||
/// <typeparam name="TTest">The deserialized test type.</typeparam>
|
||||
/// <param name="fileParser">A function to parse the content of the file (provided as a string) to a test file.</param>
|
||||
/// <param name="testExtractor">A function to extract all the tests within the given test file.</param>
|
||||
public IReadOnlyList<TTest> LoadTests<TFile, TTest>(Func<string, TFile> fileParser, Func<TFile, IEnumerable<TTest>> testExtractor) =>
|
||||
ListTestFiles()
|
||||
.Select(file => fileParser(File.ReadAllText(file)))
|
||||
.SelectMany(testExtractor)
|
||||
.ToList()
|
||||
.AsReadOnly();
|
||||
|
||||
private static string FindRepoRoot()
|
||||
{
|
||||
var currentDirectory = Path.GetFullPath(".");
|
||||
var directory = new DirectoryInfo(currentDirectory);
|
||||
while (directory != null &&
|
||||
(!File.Exists(Path.Combine(directory.FullName, "LICENSE"))
|
||||
|| !File.Exists(Path.Combine(directory.FullName, "CloudEvents.sln"))))
|
||||
{
|
||||
directory = directory.Parent;
|
||||
}
|
||||
if (directory == null)
|
||||
{
|
||||
throw new Exception("Unable to determine root directory. Please run within the sdk-csharp repository.");
|
||||
}
|
||||
return directory.FullName;
|
||||
}
|
||||
}
|
|
@ -260,7 +260,6 @@ namespace CloudNative.CloudEvents.Http.UnitTests
|
|||
|
||||
var parsed = new JsonEventFormatter().DecodeStructuredModeMessage(bytes, MimeUtilities.ToContentType(content.Headers.ContentType), extensionAttributes: null);
|
||||
AssertCloudEventsEqual(cloudEvent, parsed);
|
||||
Assert.Equal(cloudEvent.Data, parsed.Data);
|
||||
|
||||
// We populate headers even though we don't strictly need to; let's validate that.
|
||||
Assert.Equal("1.0", response.Headers.GetValues("ce-specversion").Single());
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using CloudNative.CloudEvents.UnitTests;
|
||||
using CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace CloudNative.CloudEvents.NewtonsoftJson.UnitTests;
|
||||
|
||||
public class ConformanceTest
|
||||
{
|
||||
private static readonly IReadOnlyList<JsonConformanceTest> allTests =
|
||||
TestDataProvider.Json.LoadTests(ConformanceTestFile.FromJson, file => file.Tests);
|
||||
|
||||
private static JsonConformanceTest GetTestById(string id) => allTests.Single(test => test.Id == id);
|
||||
private static IEnumerable<object[]> SelectTestIds(ConformanceTestType type) =>
|
||||
allTests
|
||||
.Where(test => test.TestType == type)
|
||||
.Select(test => new object[] { test.Id });
|
||||
|
||||
public static IEnumerable<object[]> ValidEventTestIds => SelectTestIds(ConformanceTestType.ValidSingleEvent);
|
||||
public static IEnumerable<object[]> InvalidEventTestIds => SelectTestIds(ConformanceTestType.InvalidSingleEvent);
|
||||
public static IEnumerable<object[]> ValidBatchTestIds => SelectTestIds(ConformanceTestType.ValidBatch);
|
||||
public static IEnumerable<object[]> InvalidBatchTestIds => SelectTestIds(ConformanceTestType.InvalidBatch);
|
||||
|
||||
[Theory, MemberData(nameof(ValidEventTestIds))]
|
||||
public void ValidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
CloudEvent expected = SampleEvents.FromId(test.SampleId);
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
CloudEvent actual = new JsonEventFormatter().ConvertFromJObject(test.Event, extensions);
|
||||
TestHelpers.AssertCloudEventsEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidEventTestIds))]
|
||||
public void InvalidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new JsonEventFormatter();
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
Assert.Throws<ArgumentException>(() => formatter.ConvertFromJObject(test.Event, extensions));
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(ValidBatchTestIds))]
|
||||
public void ValidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
IReadOnlyList<CloudEvent> expected = SampleBatches.FromId(test.SampleId);
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
// We don't have a convenience method for batches, so serialize the array back to JSON.
|
||||
var json = test.Batch.ToString();
|
||||
var body = Encoding.UTF8.GetBytes(json);
|
||||
IReadOnlyList<CloudEvent> actual = new JsonEventFormatter().DecodeBatchModeMessage(body, contentType: null, extensions);
|
||||
TestHelpers.AssertBatchesEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidBatchTestIds))]
|
||||
public void InvalidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new JsonEventFormatter();
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
// We don't have a convenience method for batches, so serialize the array back to JSON.
|
||||
var json = test.Batch.ToString();
|
||||
var body = Encoding.UTF8.GetBytes(json);
|
||||
Assert.Throws<ArgumentException>(() => formatter.DecodeBatchModeMessage(body, contentType: null, extensions));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CloudNative.CloudEvents.NewtonsoftJson.UnitTests;
|
||||
|
||||
#nullable disable
|
||||
|
||||
public class ConformanceTestFile
|
||||
{
|
||||
private static readonly JsonSerializerSettings serializerSeettings = new() { DateParseHandling = DateParseHandling.None };
|
||||
|
||||
public ConformanceTestType? TestType { get; set; }
|
||||
public List<JsonConformanceTest> Tests { get; } = new List<JsonConformanceTest>();
|
||||
|
||||
public static ConformanceTestFile FromJson(string json)
|
||||
{
|
||||
var testFile = JsonConvert.DeserializeObject<ConformanceTestFile>(json, serializerSeettings) ?? throw new InvalidOperationException();
|
||||
foreach (var test in testFile.Tests)
|
||||
{
|
||||
test.TestType ??= testFile.TestType;
|
||||
}
|
||||
return testFile;
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonConformanceTest
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Description { get; set; }
|
||||
public ConformanceTestType? TestType { get; set; }
|
||||
public string SampleId { get; set; }
|
||||
public JObject Event { get; set; }
|
||||
public JArray Batch { get; set; }
|
||||
public bool RoundTrip { get; set; }
|
||||
public bool SampleExtensionAttributes { get; set; }
|
||||
public bool ExtensionConstraints { get; set; }
|
||||
}
|
||||
|
||||
public enum ConformanceTestType
|
||||
{
|
||||
ValidSingleEvent,
|
||||
ValidBatch,
|
||||
InvalidSingleEvent,
|
||||
InvalidBatch
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using CloudNative.CloudEvents.UnitTests;
|
||||
using CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
using Google.Protobuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace CloudNative.CloudEvents.Protobuf.UnitTests;
|
||||
|
||||
public class Conformance
|
||||
{
|
||||
private static readonly IReadOnlyList<ConformanceTest> allTests =
|
||||
TestDataProvider.Protobuf.LoadTests(ConformanceTestFile.FromJson, file => file.Tests);
|
||||
|
||||
private static ConformanceTest GetTestById(string id) => allTests.Single(test => test.Id == id);
|
||||
private static IEnumerable<object[]> SelectTestIds(ConformanceTest.EventOneofCase eventCase) =>
|
||||
allTests
|
||||
.Where(test => test.EventCase == eventCase)
|
||||
.Select(test => new object[] { test.Id });
|
||||
|
||||
public static IEnumerable<object[]> ValidEventTestIds => SelectTestIds(ConformanceTest.EventOneofCase.ValidSingle);
|
||||
public static IEnumerable<object[]> InvalidEventTestIds => SelectTestIds(ConformanceTest.EventOneofCase.InvalidSingle);
|
||||
public static IEnumerable<object[]> ValidBatchTestIds => SelectTestIds(ConformanceTest.EventOneofCase.ValidBatch);
|
||||
public static IEnumerable<object[]> InvalidBatchTestIds => SelectTestIds(ConformanceTest.EventOneofCase.InvalidBatch);
|
||||
|
||||
[Theory, MemberData(nameof(ValidEventTestIds))]
|
||||
public void ValidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
CloudEvent expected = SampleEvents.FromId(test.SampleId);
|
||||
CloudEvent actual = new ProtobufEventFormatter().ConvertFromProto(test.ValidSingle, null);
|
||||
TestHelpers.AssertCloudEventsEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidEventTestIds))]
|
||||
public void InvalidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new ProtobufEventFormatter();
|
||||
Assert.Throws<ArgumentException>(() => formatter.ConvertFromProto(test.InvalidSingle, null));
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(ValidBatchTestIds))]
|
||||
public void ValidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
IReadOnlyList<CloudEvent> expected = SampleBatches.FromId(test.SampleId);
|
||||
|
||||
// We don't have a convenience method for batches, so serialize batch back to binary.
|
||||
var body = test.ValidBatch.ToByteArray();
|
||||
IReadOnlyList<CloudEvent> actual = new ProtobufEventFormatter().DecodeBatchModeMessage(body, null, null);
|
||||
TestHelpers.AssertBatchesEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidBatchTestIds))]
|
||||
public void InvalidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new ProtobufEventFormatter();
|
||||
// We don't have a convenience method for batches, so serialize batch back to binary.
|
||||
var body = test.InvalidBatch.ToByteArray();
|
||||
Assert.Throws<ArgumentException>(() => formatter.DecodeBatchModeMessage(body, null, null));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.Reflection;
|
||||
|
||||
namespace CloudNative.CloudEvents.Protobuf.UnitTests;
|
||||
|
||||
public partial class ConformanceTestFile
|
||||
{
|
||||
private static readonly JsonParser jsonParser =
|
||||
new(JsonParser.Settings.Default.WithTypeRegistry(TypeRegistry.FromFiles(ConformanceTestsReflection.Descriptor)));
|
||||
|
||||
internal static ConformanceTestFile FromJson(string json) =>
|
||||
jsonParser.Parse<ConformanceTestFile>(json);
|
||||
}
|
|
@ -0,0 +1,964 @@
|
|||
// <auto-generated>
|
||||
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
// source: conformance_tests.proto
|
||||
// </auto-generated>
|
||||
#pragma warning disable 1591, 0612, 3021, 8981
|
||||
#region Designer generated code
|
||||
|
||||
using pb = global::Google.Protobuf;
|
||||
using pbc = global::Google.Protobuf.Collections;
|
||||
using pbr = global::Google.Protobuf.Reflection;
|
||||
using scg = global::System.Collections.Generic;
|
||||
namespace CloudNative.CloudEvents.Protobuf.UnitTests {
|
||||
|
||||
/// <summary>Holder for reflection information generated from conformance_tests.proto</summary>
|
||||
public static partial class ConformanceTestsReflection {
|
||||
|
||||
#region Descriptor
|
||||
/// <summary>File descriptor for conformance_tests.proto</summary>
|
||||
public static pbr::FileDescriptor Descriptor {
|
||||
get { return descriptor; }
|
||||
}
|
||||
private static pbr::FileDescriptor descriptor;
|
||||
|
||||
static ConformanceTestsReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"Chdjb25mb3JtYW5jZV90ZXN0cy5wcm90bxIRaW8uY2xvdWRldmVudHMudjEa",
|
||||
"EWNsb3VkZXZlbnRzLnByb3RvIkgKE0NvbmZvcm1hbmNlVGVzdEZpbGUSMQoF",
|
||||
"dGVzdHMYASADKAsyIi5pby5jbG91ZGV2ZW50cy52MS5Db25mb3JtYW5jZVRl",
|
||||
"c3QitgIKD0NvbmZvcm1hbmNlVGVzdBIKCgJpZBgBIAEoCRITCgtkZXNjcmlw",
|
||||
"dGlvbhgCIAEoCRIRCglzYW1wbGVfaWQYAyABKAkSNQoMdmFsaWRfc2luZ2xl",
|
||||
"GAQgASgLMh0uaW8uY2xvdWRldmVudHMudjEuQ2xvdWRFdmVudEgAEjkKC3Zh",
|
||||
"bGlkX2JhdGNoGAUgASgLMiIuaW8uY2xvdWRldmVudHMudjEuQ2xvdWRFdmVu",
|
||||
"dEJhdGNoSAASNwoOaW52YWxpZF9zaW5nbGUYBiABKAsyHS5pby5jbG91ZGV2",
|
||||
"ZW50cy52MS5DbG91ZEV2ZW50SAASOwoNaW52YWxpZF9iYXRjaBgHIAEoCzIi",
|
||||
"LmlvLmNsb3VkZXZlbnRzLnYxLkNsb3VkRXZlbnRCYXRjaEgAQgcKBWV2ZW50",
|
||||
"IioKGkNvbmZvcm1hbmNlVGVzdE1lc3NhZ2VEYXRhEgwKBHRleHQYASABKAlC",
|
||||
"LaoCKkNsb3VkTmF0aXZlLkNsb3VkRXZlbnRzLlByb3RvYnVmLlVuaXRUZXN0",
|
||||
"c2IGcHJvdG8z"));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { global::CloudNative.CloudEvents.V1.CloudeventsReflection.Descriptor, },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestFile), global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestFile.Parser, new[]{ "Tests" }, null, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest), global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest.Parser, new[]{ "Id", "Description", "SampleId", "ValidSingle", "ValidBatch", "InvalidSingle", "InvalidBatch" }, new[]{ "Event" }, null, null, null),
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestMessageData), global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestMessageData.Parser, new[]{ "Text" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#region Messages
|
||||
/// <summary>
|
||||
/// A simple container for conformance tests.
|
||||
/// </summary>
|
||||
public sealed partial class ConformanceTestFile : pb::IMessage<ConformanceTestFile>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<ConformanceTestFile> _parser = new pb::MessageParser<ConformanceTestFile>(() => new ConformanceTestFile());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pb::MessageParser<ConformanceTestFile> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestsReflection.Descriptor.MessageTypes[0]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestFile() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestFile(ConformanceTestFile other) : this() {
|
||||
tests_ = other.tests_.Clone();
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestFile Clone() {
|
||||
return new ConformanceTestFile(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "tests" field.</summary>
|
||||
public const int TestsFieldNumber = 1;
|
||||
private static readonly pb::FieldCodec<global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest> _repeated_tests_codec
|
||||
= pb::FieldCodec.ForMessage(10, global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest.Parser);
|
||||
private readonly pbc::RepeatedField<global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest> tests_ = new pbc::RepeatedField<global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest>();
|
||||
/// <summary>
|
||||
/// The tests within this file.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public pbc::RepeatedField<global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTest> Tests {
|
||||
get { return tests_; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as ConformanceTestFile);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool Equals(ConformanceTestFile other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if(!tests_.Equals(other.tests_)) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
hash ^= tests_.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
tests_.WriteTo(output, _repeated_tests_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
tests_.WriteTo(ref output, _repeated_tests_codec);
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
size += tests_.CalculateSize(_repeated_tests_codec);
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(ConformanceTestFile other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
tests_.Add(other.tests_);
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
tests_.AddEntriesFrom(input, _repeated_tests_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
tests_.AddEntriesFrom(ref input, _repeated_tests_codec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A single test in the conformance test suite.
|
||||
/// </summary>
|
||||
public sealed partial class ConformanceTest : pb::IMessage<ConformanceTest>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<ConformanceTest> _parser = new pb::MessageParser<ConformanceTest>(() => new ConformanceTest());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pb::MessageParser<ConformanceTest> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestsReflection.Descriptor.MessageTypes[1]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTest() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTest(ConformanceTest other) : this() {
|
||||
id_ = other.id_;
|
||||
description_ = other.description_;
|
||||
sampleId_ = other.sampleId_;
|
||||
switch (other.EventCase) {
|
||||
case EventOneofCase.ValidSingle:
|
||||
ValidSingle = other.ValidSingle.Clone();
|
||||
break;
|
||||
case EventOneofCase.ValidBatch:
|
||||
ValidBatch = other.ValidBatch.Clone();
|
||||
break;
|
||||
case EventOneofCase.InvalidSingle:
|
||||
InvalidSingle = other.InvalidSingle.Clone();
|
||||
break;
|
||||
case EventOneofCase.InvalidBatch:
|
||||
InvalidBatch = other.InvalidBatch.Clone();
|
||||
break;
|
||||
}
|
||||
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTest Clone() {
|
||||
return new ConformanceTest(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "id" field.</summary>
|
||||
public const int IdFieldNumber = 1;
|
||||
private string id_ = "";
|
||||
/// <summary>
|
||||
/// The ID of the test; must be unique across all protobuf conformance tests.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Id {
|
||||
get { return id_; }
|
||||
set {
|
||||
id_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "description" field.</summary>
|
||||
public const int DescriptionFieldNumber = 2;
|
||||
private string description_ = "";
|
||||
/// <summary>
|
||||
/// The description of the test.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Description {
|
||||
get { return description_; }
|
||||
set {
|
||||
description_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "sample_id" field.</summary>
|
||||
public const int SampleIdFieldNumber = 3;
|
||||
private string sampleId_ = "";
|
||||
/// <summary>
|
||||
/// For valid tests, the ID of the well-known sample event/batch that
|
||||
/// this test data should be equivalent to.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string SampleId {
|
||||
get { return sampleId_; }
|
||||
set {
|
||||
sampleId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "valid_single" field.</summary>
|
||||
public const int ValidSingleFieldNumber = 4;
|
||||
/// <summary>
|
||||
/// A single event that should be converted to an in-memory representation without error.
|
||||
/// sample_id indicates the sample event that the result should be equivalent to.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::CloudNative.CloudEvents.V1.CloudEvent ValidSingle {
|
||||
get { return eventCase_ == EventOneofCase.ValidSingle ? (global::CloudNative.CloudEvents.V1.CloudEvent) event_ : null; }
|
||||
set {
|
||||
event_ = value;
|
||||
eventCase_ = value == null ? EventOneofCase.None : EventOneofCase.ValidSingle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "valid_batch" field.</summary>
|
||||
public const int ValidBatchFieldNumber = 5;
|
||||
/// <summary>
|
||||
/// A batch of events that should be converted to an in-memory representation without error.
|
||||
/// sample_id indicates the sample batch that the result should be equivalent to.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::CloudNative.CloudEvents.V1.CloudEventBatch ValidBatch {
|
||||
get { return eventCase_ == EventOneofCase.ValidBatch ? (global::CloudNative.CloudEvents.V1.CloudEventBatch) event_ : null; }
|
||||
set {
|
||||
event_ = value;
|
||||
eventCase_ = value == null ? EventOneofCase.None : EventOneofCase.ValidBatch;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "invalid_single" field.</summary>
|
||||
public const int InvalidSingleFieldNumber = 6;
|
||||
/// <summary>
|
||||
/// A single event that should be rejected when converted to an in-memory representation.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::CloudNative.CloudEvents.V1.CloudEvent InvalidSingle {
|
||||
get { return eventCase_ == EventOneofCase.InvalidSingle ? (global::CloudNative.CloudEvents.V1.CloudEvent) event_ : null; }
|
||||
set {
|
||||
event_ = value;
|
||||
eventCase_ = value == null ? EventOneofCase.None : EventOneofCase.InvalidSingle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "invalid_batch" field.</summary>
|
||||
public const int InvalidBatchFieldNumber = 7;
|
||||
/// <summary>
|
||||
/// A batch of events that should be rejected when converted to an in-memory representation.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::CloudNative.CloudEvents.V1.CloudEventBatch InvalidBatch {
|
||||
get { return eventCase_ == EventOneofCase.InvalidBatch ? (global::CloudNative.CloudEvents.V1.CloudEventBatch) event_ : null; }
|
||||
set {
|
||||
event_ = value;
|
||||
eventCase_ = value == null ? EventOneofCase.None : EventOneofCase.InvalidBatch;
|
||||
}
|
||||
}
|
||||
|
||||
private object event_;
|
||||
/// <summary>Enum of possible cases for the "event" oneof.</summary>
|
||||
public enum EventOneofCase {
|
||||
None = 0,
|
||||
ValidSingle = 4,
|
||||
ValidBatch = 5,
|
||||
InvalidSingle = 6,
|
||||
InvalidBatch = 7,
|
||||
}
|
||||
private EventOneofCase eventCase_ = EventOneofCase.None;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public EventOneofCase EventCase {
|
||||
get { return eventCase_; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void ClearEvent() {
|
||||
eventCase_ = EventOneofCase.None;
|
||||
event_ = null;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as ConformanceTest);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool Equals(ConformanceTest other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Id != other.Id) return false;
|
||||
if (Description != other.Description) return false;
|
||||
if (SampleId != other.SampleId) return false;
|
||||
if (!object.Equals(ValidSingle, other.ValidSingle)) return false;
|
||||
if (!object.Equals(ValidBatch, other.ValidBatch)) return false;
|
||||
if (!object.Equals(InvalidSingle, other.InvalidSingle)) return false;
|
||||
if (!object.Equals(InvalidBatch, other.InvalidBatch)) return false;
|
||||
if (EventCase != other.EventCase) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (Id.Length != 0) hash ^= Id.GetHashCode();
|
||||
if (Description.Length != 0) hash ^= Description.GetHashCode();
|
||||
if (SampleId.Length != 0) hash ^= SampleId.GetHashCode();
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) hash ^= ValidSingle.GetHashCode();
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) hash ^= ValidBatch.GetHashCode();
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) hash ^= InvalidSingle.GetHashCode();
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) hash ^= InvalidBatch.GetHashCode();
|
||||
hash ^= (int) eventCase_;
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (Id.Length != 0) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Id);
|
||||
}
|
||||
if (Description.Length != 0) {
|
||||
output.WriteRawTag(18);
|
||||
output.WriteString(Description);
|
||||
}
|
||||
if (SampleId.Length != 0) {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(SampleId);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteMessage(ValidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteMessage(ValidBatch);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) {
|
||||
output.WriteRawTag(50);
|
||||
output.WriteMessage(InvalidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) {
|
||||
output.WriteRawTag(58);
|
||||
output.WriteMessage(InvalidBatch);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (Id.Length != 0) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Id);
|
||||
}
|
||||
if (Description.Length != 0) {
|
||||
output.WriteRawTag(18);
|
||||
output.WriteString(Description);
|
||||
}
|
||||
if (SampleId.Length != 0) {
|
||||
output.WriteRawTag(26);
|
||||
output.WriteString(SampleId);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) {
|
||||
output.WriteRawTag(34);
|
||||
output.WriteMessage(ValidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) {
|
||||
output.WriteRawTag(42);
|
||||
output.WriteMessage(ValidBatch);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) {
|
||||
output.WriteRawTag(50);
|
||||
output.WriteMessage(InvalidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) {
|
||||
output.WriteRawTag(58);
|
||||
output.WriteMessage(InvalidBatch);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (Id.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Id);
|
||||
}
|
||||
if (Description.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Description);
|
||||
}
|
||||
if (SampleId.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(SampleId);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ValidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeMessageSize(ValidBatch);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeMessageSize(InvalidSingle);
|
||||
}
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeMessageSize(InvalidBatch);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(ConformanceTest other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.Id.Length != 0) {
|
||||
Id = other.Id;
|
||||
}
|
||||
if (other.Description.Length != 0) {
|
||||
Description = other.Description;
|
||||
}
|
||||
if (other.SampleId.Length != 0) {
|
||||
SampleId = other.SampleId;
|
||||
}
|
||||
switch (other.EventCase) {
|
||||
case EventOneofCase.ValidSingle:
|
||||
if (ValidSingle == null) {
|
||||
ValidSingle = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
}
|
||||
ValidSingle.MergeFrom(other.ValidSingle);
|
||||
break;
|
||||
case EventOneofCase.ValidBatch:
|
||||
if (ValidBatch == null) {
|
||||
ValidBatch = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
}
|
||||
ValidBatch.MergeFrom(other.ValidBatch);
|
||||
break;
|
||||
case EventOneofCase.InvalidSingle:
|
||||
if (InvalidSingle == null) {
|
||||
InvalidSingle = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
}
|
||||
InvalidSingle.MergeFrom(other.InvalidSingle);
|
||||
break;
|
||||
case EventOneofCase.InvalidBatch:
|
||||
if (InvalidBatch == null) {
|
||||
InvalidBatch = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
}
|
||||
InvalidBatch.MergeFrom(other.InvalidBatch);
|
||||
break;
|
||||
}
|
||||
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
Id = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 18: {
|
||||
Description = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
SampleId = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEvent subBuilder = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) {
|
||||
subBuilder.MergeFrom(ValidSingle);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
ValidSingle = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEventBatch subBuilder = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) {
|
||||
subBuilder.MergeFrom(ValidBatch);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
ValidBatch = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 50: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEvent subBuilder = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) {
|
||||
subBuilder.MergeFrom(InvalidSingle);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
InvalidSingle = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEventBatch subBuilder = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) {
|
||||
subBuilder.MergeFrom(InvalidBatch);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
InvalidBatch = subBuilder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
Id = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 18: {
|
||||
Description = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 26: {
|
||||
SampleId = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 34: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEvent subBuilder = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
if (eventCase_ == EventOneofCase.ValidSingle) {
|
||||
subBuilder.MergeFrom(ValidSingle);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
ValidSingle = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 42: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEventBatch subBuilder = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
if (eventCase_ == EventOneofCase.ValidBatch) {
|
||||
subBuilder.MergeFrom(ValidBatch);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
ValidBatch = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 50: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEvent subBuilder = new global::CloudNative.CloudEvents.V1.CloudEvent();
|
||||
if (eventCase_ == EventOneofCase.InvalidSingle) {
|
||||
subBuilder.MergeFrom(InvalidSingle);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
InvalidSingle = subBuilder;
|
||||
break;
|
||||
}
|
||||
case 58: {
|
||||
global::CloudNative.CloudEvents.V1.CloudEventBatch subBuilder = new global::CloudNative.CloudEvents.V1.CloudEventBatch();
|
||||
if (eventCase_ == EventOneofCase.InvalidBatch) {
|
||||
subBuilder.MergeFrom(InvalidBatch);
|
||||
}
|
||||
input.ReadMessage(subBuilder);
|
||||
InvalidBatch = subBuilder;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A sample message for tests using CloudEvent.proto_data.
|
||||
/// </summary>
|
||||
public sealed partial class ConformanceTestMessageData : pb::IMessage<ConformanceTestMessageData>
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
, pb::IBufferMessage
|
||||
#endif
|
||||
{
|
||||
private static readonly pb::MessageParser<ConformanceTestMessageData> _parser = new pb::MessageParser<ConformanceTestMessageData>(() => new ConformanceTestMessageData());
|
||||
private pb::UnknownFieldSet _unknownFields;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pb::MessageParser<ConformanceTestMessageData> Parser { get { return _parser; } }
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public static pbr::MessageDescriptor Descriptor {
|
||||
get { return global::CloudNative.CloudEvents.Protobuf.UnitTests.ConformanceTestsReflection.Descriptor.MessageTypes[2]; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
pbr::MessageDescriptor pb::IMessage.Descriptor {
|
||||
get { return Descriptor; }
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestMessageData() {
|
||||
OnConstruction();
|
||||
}
|
||||
|
||||
partial void OnConstruction();
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestMessageData(ConformanceTestMessageData other) : this() {
|
||||
text_ = other.text_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public ConformanceTestMessageData Clone() {
|
||||
return new ConformanceTestMessageData(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "text" field.</summary>
|
||||
public const int TextFieldNumber = 1;
|
||||
private string text_ = "";
|
||||
/// <summary>
|
||||
/// Just some text data.
|
||||
/// </summary>
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string Text {
|
||||
get { return text_; }
|
||||
set {
|
||||
text_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
return Equals(other as ConformanceTestMessageData);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public bool Equals(ConformanceTestMessageData other) {
|
||||
if (ReferenceEquals(other, null)) {
|
||||
return false;
|
||||
}
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Text != other.Text) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (Text.Length != 0) hash ^= Text.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override string ToString() {
|
||||
return pb::JsonFormatter.ToDiagnosticString(this);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void WriteTo(pb::CodedOutputStream output) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (Text.Length != 0) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Text);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (Text.Length != 0) {
|
||||
output.WriteRawTag(10);
|
||||
output.WriteString(Text);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (Text.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(Text);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(ConformanceTestMessageData other) {
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.Text.Length != 0) {
|
||||
Text = other.Text;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public void MergeFrom(pb::CodedInputStream input) {
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
input.ReadRawMessage(this);
|
||||
#else
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 10: {
|
||||
Text = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
|
||||
uint tag;
|
||||
while ((tag = input.ReadTag()) != 0) {
|
||||
switch(tag) {
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 10: {
|
||||
Text = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
#endregion Designer generated code
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using CloudNative.CloudEvents.UnitTests;
|
||||
using CloudNative.CloudEvents.UnitTests.ConformanceTestData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace CloudNative.CloudEvents.SystemTextJson.UnitTests;
|
||||
|
||||
public class ConformanceTest
|
||||
{
|
||||
private static readonly IReadOnlyList<JsonConformanceTest> allTests =
|
||||
TestDataProvider.Json.LoadTests(ConformanceTestFile.FromJson, file => file.Tests);
|
||||
|
||||
private static JsonConformanceTest GetTestById(string id) => allTests.Single(test => test.Id == id);
|
||||
private static IEnumerable<object[]> SelectTestIds(ConformanceTestType type) =>
|
||||
allTests
|
||||
.Where(test => test.TestType == type)
|
||||
.Select(test => new object[] { test.Id });
|
||||
|
||||
public static IEnumerable<object[]> ValidEventTestIds => SelectTestIds(ConformanceTestType.ValidSingleEvent);
|
||||
public static IEnumerable<object[]> InvalidEventTestIds => SelectTestIds(ConformanceTestType.InvalidSingleEvent);
|
||||
public static IEnumerable<object[]> ValidBatchTestIds => SelectTestIds(ConformanceTestType.ValidBatch);
|
||||
public static IEnumerable<object[]> InvalidBatchTestIds => SelectTestIds(ConformanceTestType.InvalidBatch);
|
||||
|
||||
[Theory, MemberData(nameof(ValidEventTestIds))]
|
||||
public void ValidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
CloudEvent expected = SampleEvents.FromId(test.SampleId);
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
CloudEvent actual = new JsonEventFormatter().ConvertFromJsonElement(test.Event, extensions);
|
||||
TestHelpers.AssertCloudEventsEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidEventTestIds))]
|
||||
public void InvalidEvent(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new JsonEventFormatter();
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
// Hmm... we throw FormatException in some cases, when ArgumentException would be better.
|
||||
// Changing that would be "somewhat breaking"... it's unclear how much we should worry.
|
||||
Assert.ThrowsAny<Exception>(() => formatter.ConvertFromJsonElement(test.Event, extensions));
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(ValidBatchTestIds))]
|
||||
public void ValidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
IReadOnlyList<CloudEvent> expected = SampleBatches.FromId(test.SampleId);
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
// We don't have a convenience method for batches, so serialize the array back to JSON.
|
||||
var json = test.Batch.ToString();
|
||||
var body = Encoding.UTF8.GetBytes(json);
|
||||
IReadOnlyList<CloudEvent> actual = new JsonEventFormatter().DecodeBatchModeMessage(body, contentType: null, extensions);
|
||||
TestHelpers.AssertBatchesEqual(expected, actual, TestHelpers.InstantOnlyTimestampComparer);
|
||||
}
|
||||
|
||||
[Theory, MemberData(nameof(InvalidBatchTestIds))]
|
||||
public void InvalidBatch(string testId)
|
||||
{
|
||||
var test = GetTestById(testId);
|
||||
var formatter = new JsonEventFormatter();
|
||||
var extensions = test.SampleExtensionAttributes ? SampleEvents.SampleExtensionAttributes : null;
|
||||
// We don't have a convenience method for batches, so serialize the array back to JSON.
|
||||
var json = test.Batch.ToString();
|
||||
var body = Encoding.UTF8.GetBytes(json);
|
||||
// Hmm... we throw FormatException in some cases, when ArgumentException would be better.
|
||||
// Changing that would be "somewhat breaking"... it's unclear how much we should worry.
|
||||
Assert.ThrowsAny<Exception>(() => formatter.DecodeBatchModeMessage(body, contentType: null, extensions));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2023 Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace CloudNative.CloudEvents.SystemTextJson.UnitTests;
|
||||
|
||||
#nullable disable
|
||||
|
||||
public class ConformanceTestFile
|
||||
{
|
||||
private static readonly JsonSerializerOptions serializerOptions = new() { Converters = { new JsonStringEnumConverter() } };
|
||||
|
||||
[JsonPropertyName("testType")]
|
||||
public ConformanceTestType? TestType { get; set; }
|
||||
|
||||
// Note: we need a setter here; System.Text.Json doesn't support adding to an existing collection.
|
||||
// See https://github.com/dotnet/runtime/issues/30258
|
||||
[JsonPropertyName("tests")]
|
||||
public List<JsonConformanceTest> Tests { get; set; } = new List<JsonConformanceTest>();
|
||||
|
||||
public static ConformanceTestFile FromJson(string json)
|
||||
{
|
||||
var testFile = JsonSerializer.Deserialize<ConformanceTestFile>(json, serializerOptions) ?? throw new InvalidOperationException();
|
||||
foreach (var test in testFile.Tests)
|
||||
{
|
||||
test.TestType ??= testFile.TestType;
|
||||
}
|
||||
return testFile;
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonConformanceTest
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; }
|
||||
[JsonPropertyName("testType")]
|
||||
public ConformanceTestType? TestType { get; set; }
|
||||
[JsonPropertyName("sampleId")]
|
||||
public string SampleId { get; set; }
|
||||
[JsonPropertyName("event")]
|
||||
public JsonElement Event { get; set; }
|
||||
[JsonPropertyName("batch")]
|
||||
public JsonArray Batch { get; set; }
|
||||
[JsonPropertyName("sampleExtensionAttributes")]
|
||||
public bool SampleExtensionAttributes { get; set; }
|
||||
[JsonPropertyName("extensionConstraints")]
|
||||
public bool ExtensionConstraints { get; set; }
|
||||
}
|
||||
|
||||
public enum ConformanceTestType
|
||||
{
|
||||
ValidSingleEvent,
|
||||
ValidBatch,
|
||||
InvalidSingleEvent,
|
||||
InvalidBatch
|
||||
}
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
|
@ -15,6 +17,9 @@ namespace CloudNative.CloudEvents.UnitTests
|
|||
/// </summary>
|
||||
internal static class TestHelpers
|
||||
{
|
||||
internal static IEqualityComparer<DateTimeOffset> InstantOnlyTimestampComparer => EqualityComparer<DateTimeOffset>.Default;
|
||||
internal static IEqualityComparer<DateTimeOffset> StrictTimestampComparer => StrictTimestampComparerImpl.Instance;
|
||||
|
||||
internal static CloudEventAttribute[] EmptyExtensionArray { get; } = new CloudEventAttribute[0];
|
||||
internal static IEnumerable<CloudEventAttribute> EmptyExtensionSequence { get; } = new List<CloudEventAttribute>().AsReadOnly();
|
||||
|
||||
|
@ -44,7 +49,7 @@ namespace CloudNative.CloudEvents.UnitTests
|
|||
/// <summary>
|
||||
/// The base64 representation of <see cref="SampleBinaryData"/>.
|
||||
/// </summary>
|
||||
internal static string SampleBinaryDataBase64 { get; } = Convert.ToBase64String(SampleBinaryData);
|
||||
internal static string SampleBinaryDataBase64 { get; } = Convert.ToBase64String(SampleBinaryData); // AQID
|
||||
|
||||
/// <summary>
|
||||
/// Arbitrary timestamp to be used for testing.
|
||||
|
@ -154,8 +159,12 @@ namespace CloudNative.CloudEvents.UnitTests
|
|||
}
|
||||
|
||||
// TODO: Use this more widely
|
||||
internal static void AssertCloudEventsEqual(CloudEvent expected, CloudEvent actual)
|
||||
// TODO: Document handling of timestamps, and potentially parameterize it.
|
||||
internal static void AssertCloudEventsEqual(CloudEvent expected, CloudEvent actual,
|
||||
IEqualityComparer<DateTimeOffset>? timestampComparer = null,
|
||||
IEqualityComparer<object?>? dataComparer = null)
|
||||
{
|
||||
timestampComparer ??= StrictTimestampComparer;
|
||||
Assert.Equal(expected.SpecVersion, actual.SpecVersion);
|
||||
var expectedAttributes = expected.GetPopulatedAttributes().ToList();
|
||||
var actualAttributes = actual.GetPopulatedAttributes().ToList();
|
||||
|
@ -166,18 +175,62 @@ namespace CloudNative.CloudEvents.UnitTests
|
|||
var actualAttribute = actualAttributes.FirstOrDefault(actual => actual.Key.Name == expectedAttribute.Key.Name);
|
||||
Assert.NotNull(actualAttribute.Key);
|
||||
|
||||
Assert.Equal(actualAttribute.Key.Type, expectedAttribute.Key.Type);
|
||||
Assert.Equal(actualAttribute.Value, expectedAttribute.Value);
|
||||
Assert.Equal(expectedAttribute.Key.Type, actualAttribute.Key.Type);
|
||||
if (expectedAttribute.Value is DateTimeOffset expectedDto &&
|
||||
actualAttribute.Value is DateTimeOffset actualDto)
|
||||
{
|
||||
Assert.Equal(expectedDto, actualDto, timestampComparer);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Equal(expectedAttribute.Value, actualAttribute.Value);
|
||||
}
|
||||
}
|
||||
Assert.Equal(expected.Data, actual.Data, dataComparer ?? EqualityComparer<object?>.Default);
|
||||
}
|
||||
|
||||
internal static void AssertBatchesEqual(IReadOnlyList<CloudEvent> expectedBatch, IReadOnlyList<CloudEvent> actualBatch)
|
||||
internal static void AssertBatchesEqual(IReadOnlyList<CloudEvent> expectedBatch, IReadOnlyList<CloudEvent> actualBatch,
|
||||
IEqualityComparer<DateTimeOffset>? timestampComparer = null,
|
||||
IEqualityComparer<object?>? dataComparer = null)
|
||||
{
|
||||
Assert.Equal(expectedBatch.Count, actualBatch.Count);
|
||||
foreach (var pair in expectedBatch.Zip(actualBatch, (x, y) => (x, y)))
|
||||
{
|
||||
AssertCloudEventsEqual(pair.x, pair.y);
|
||||
AssertCloudEventsEqual(pair.x, pair.y, timestampComparer, dataComparer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the resource with the given name, copying it into a MemoryStream.
|
||||
/// (That's often easier to work with when debugging.)
|
||||
/// </summary>
|
||||
internal static MemoryStream LoadResource(string resource)
|
||||
{
|
||||
using var stream = typeof(TestHelpers).Assembly.GetManifestResourceStream(resource);
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentException($"Resource {resource} is missing. Known resources: {string.Join(", ", typeof(TestHelpers).Assembly.GetManifestResourceNames())}");
|
||||
}
|
||||
var output = new MemoryStream();
|
||||
stream.CopyTo(output);
|
||||
output.Position = 0;
|
||||
return output;
|
||||
}
|
||||
|
||||
private class StrictTimestampComparerImpl : IEqualityComparer<DateTimeOffset>
|
||||
{
|
||||
internal static StrictTimestampComparerImpl Instance { get; } = new StrictTimestampComparerImpl();
|
||||
|
||||
private StrictTimestampComparerImpl()
|
||||
{
|
||||
}
|
||||
|
||||
public bool Equals(DateTimeOffset x, DateTimeOffset y) =>
|
||||
x.UtcDateTime == y.UtcDateTime &&
|
||||
x.Offset == y.Offset;
|
||||
|
||||
public int GetHashCode([DisallowNull] DateTimeOffset obj) =>
|
||||
obj.UtcDateTime.GetHashCode() ^ obj.Offset.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue