Initial extensions test coverage. Completed extensions
Signed-off-by: clemensv <clemensv@microsoft.com>
This commit is contained in:
parent
df4f79d40a
commit
f0cfdd6322
|
|
@ -8,6 +8,9 @@ namespace CloudNative.CloudEvents
|
|||
using System.Collections.Generic;
|
||||
using System.Net.Mime;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a CloudEvent
|
||||
/// </summary>
|
||||
public class CloudEvent
|
||||
{
|
||||
public const string MediaType = "application/cloudevents";
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ namespace CloudNative.CloudEvents
|
|||
using System.Globalization;
|
||||
using System.Net.Mime;
|
||||
|
||||
/// <summary>
|
||||
/// The CloudEvents attributes
|
||||
/// </summary>
|
||||
public class CloudEventAttributes : IDictionary<string, object>
|
||||
{
|
||||
public const string ContentTypeAttributeName = "contenttype";
|
||||
|
|
@ -32,7 +35,7 @@ namespace CloudNative.CloudEvents
|
|||
|
||||
IEnumerable<ICloudEventExtension> extensions;
|
||||
|
||||
public CloudEventAttributes(IEnumerable<ICloudEventExtension> extensions)
|
||||
internal CloudEventAttributes(IEnumerable<ICloudEventExtension> extensions)
|
||||
{
|
||||
this.extensions = extensions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,21 @@ namespace CloudNative.CloudEvents
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// This class is for use with `HttpClient` and constructs content and headers for
|
||||
/// a HTTP request from a CloudEvent.
|
||||
/// </summary>
|
||||
public class CloudEventContent : HttpContent
|
||||
{
|
||||
IInnerContent inner;
|
||||
static JsonEventFormatter jsonFormatter = new JsonEventFormatter();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="cloudEvent">CloudEvent</param>
|
||||
/// <param name="contentMode">Content mode. Structured or binary.</param>
|
||||
/// <param name="formatter">Event formatter</param>
|
||||
public CloudEventContent(CloudEvent cloudEvent, ContentMode contentMode, ICloudEventFormatter formatter)
|
||||
{
|
||||
if (contentMode == ContentMode.Structured)
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@ namespace CloudNative.CloudEvents
|
|||
/// </summary>
|
||||
public enum ContentMode
|
||||
{
|
||||
// Structured mode. The complete CloudEvent is contained in the transport body
|
||||
/// <summary>
|
||||
/// Structured mode. The complete CloudEvent is contained in the transport body
|
||||
/// </summary>
|
||||
Structured,
|
||||
// Binary mode. The CloudEvent is projected onto the transport frame
|
||||
/// <summary>
|
||||
/// Binary mode. The CloudEvent is projected onto the transport frame
|
||||
/// </summary>
|
||||
Binary
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ namespace CloudNative.CloudEvents.Extensions
|
|||
|
||||
IDictionary<string, object> attributes = new Dictionary<string, object>();
|
||||
|
||||
public DistributedTracingExtension(string traceParent)
|
||||
public DistributedTracingExtension(string traceParent = null)
|
||||
{
|
||||
this.TraceParent = traceParent;
|
||||
}
|
||||
|
|
@ -43,9 +43,11 @@ namespace CloudNative.CloudEvents.Extensions
|
|||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
eventAttributes[attr.Key] = attr.Value;
|
||||
}
|
||||
|
||||
if (attr.Value != null)
|
||||
{
|
||||
eventAttributes[attr.Key] = attr.Value;
|
||||
}
|
||||
}
|
||||
attributes = eventAttributes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace CloudNative.CloudEvents.Extensions
|
||||
{
|
||||
public class IntegerSequenceExtension : SequenceExtension
|
||||
{
|
||||
public IntegerSequenceExtension(int? sequenceValue = null) : base()
|
||||
{
|
||||
base.SequenceType = "Integer";
|
||||
this.Sequence = sequenceValue;
|
||||
}
|
||||
|
||||
public new int? Sequence
|
||||
{
|
||||
get
|
||||
{
|
||||
var s = base.Sequence;
|
||||
if (s != null)
|
||||
{
|
||||
return int.Parse(s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Sequence = value?.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public new string SequenceType
|
||||
{
|
||||
get => base.SequenceType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace CloudNative.CloudEvents.Extensions
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class SamplingExtension : ICloudEventExtension
|
||||
{
|
||||
public const string SampledRateAttributeName = "sampledrate";
|
||||
|
||||
IDictionary<string, object> attributes = new Dictionary<string, object>();
|
||||
|
||||
public SamplingExtension(int sampledRate = 0)
|
||||
{
|
||||
this.SampledRate = sampledRate;
|
||||
}
|
||||
|
||||
public int? SampledRate
|
||||
{
|
||||
get => (int?)this.attributes[SampledRateAttributeName];
|
||||
set => attributes[SampledRateAttributeName] = value;
|
||||
}
|
||||
|
||||
public Type GetAttributeType(string name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case SampledRateAttributeName:
|
||||
return typeof(int?);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void ICloudEventExtension.Attach(CloudEvent cloudEvent)
|
||||
{
|
||||
var eventAttributes = cloudEvent.GetAttributes();
|
||||
if (attributes == eventAttributes)
|
||||
{
|
||||
// already done
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
eventAttributes[attr.Key] = attr.Value;
|
||||
}
|
||||
|
||||
attributes = eventAttributes;
|
||||
}
|
||||
|
||||
bool ICloudEventExtension.ValidateAndNormalize(string key, ref object value)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case SampledRateAttributeName:
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (value is string)
|
||||
{
|
||||
if (int.TryParse((string)value, out var i))
|
||||
{
|
||||
value = (int?)i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (value is int)
|
||||
{
|
||||
value = (int?)value;
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(Strings.ErrorSampledRateValueIsaNotAnInteger);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace CloudNative.CloudEvents.Extensions
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class SequenceExtension : ICloudEventExtension
|
||||
{
|
||||
public const string SequenceAttributeName = "sequence";
|
||||
|
||||
public const string SequenceTypeAttributeName = "sequencetype";
|
||||
|
||||
IDictionary<string, object> attributes = new Dictionary<string, object>();
|
||||
|
||||
public SequenceExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public string Sequence
|
||||
{
|
||||
get => attributes[SequenceAttributeName] as string;
|
||||
set => attributes[SequenceAttributeName] = value;
|
||||
}
|
||||
|
||||
public string SequenceType
|
||||
{
|
||||
get => attributes[SequenceTypeAttributeName] as string;
|
||||
set => attributes[SequenceTypeAttributeName] = value;
|
||||
}
|
||||
|
||||
public Type GetAttributeType(string name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case SequenceAttributeName:
|
||||
case SequenceTypeAttributeName:
|
||||
return typeof(string);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void ICloudEventExtension.Attach(CloudEvent cloudEvent)
|
||||
{
|
||||
var eventAttributes = cloudEvent.GetAttributes();
|
||||
if (attributes == eventAttributes)
|
||||
{
|
||||
// already done
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var attr in attributes)
|
||||
{
|
||||
eventAttributes[attr.Key] = attr.Value;
|
||||
}
|
||||
|
||||
attributes = eventAttributes;
|
||||
}
|
||||
|
||||
bool ICloudEventExtension.ValidateAndNormalize(string key, ref object value)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case SequenceAttributeName:
|
||||
if (value == null || value is string)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(Strings.ErrorSequenceValueIsaNotAString);
|
||||
case SequenceTypeAttributeName:
|
||||
if (value == null || value is string)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(Strings.ErrorSequenceTypeValueIsaNotAString);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,14 @@ namespace CloudNative.CloudEvents
|
|||
const string SpecVersionHttpHeader = HttpHeaderPrefix + "specversion";
|
||||
static JsonEventFormatter jsonFormatter = new JsonEventFormatter();
|
||||
|
||||
/// <summary>
|
||||
/// Copies the CloudEvent into this HttpListenerResponse instance
|
||||
/// </summary>
|
||||
/// <param name="httpListenerResponse">this</param>
|
||||
/// <param name="cloudEvent">CloudEvent to copy</param>
|
||||
/// <param name="contentMode">Content mode (structured or binary)</param>
|
||||
/// <param name="formatter">Formatter</param>
|
||||
/// <returns>Task</returns>
|
||||
public static Task CopyFromAsync(this HttpListenerResponse httpListenerResponse, CloudEvent cloudEvent,
|
||||
ContentMode contentMode, ICloudEventFormatter formatter)
|
||||
{
|
||||
|
|
@ -39,6 +47,14 @@ namespace CloudNative.CloudEvents
|
|||
return stream.CopyToAsync(httpListenerResponse.OutputStream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the CloudEvent into this HttpWebRequest instance
|
||||
/// </summary>
|
||||
/// <param name="httpWebRequest">this</param>
|
||||
/// <param name="cloudEvent">CloudEvent to copy</param>
|
||||
/// <param name="contentMode">Content mode (structured or binary)</param>
|
||||
/// <param name="formatter">Formatter</param>
|
||||
/// <returns>Task</returns>
|
||||
public static async Task CopyFromAsync(this HttpWebRequest httpWebRequest, CloudEvent cloudEvent,
|
||||
ContentMode contentMode, ICloudEventFormatter formatter)
|
||||
{
|
||||
|
|
@ -58,6 +74,11 @@ namespace CloudNative.CloudEvents
|
|||
await stream.CopyToAsync(httpWebRequest.GetRequestStream());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this HttpResponseMessage holds a CloudEvent
|
||||
/// </summary>
|
||||
/// <param name="httpResponseMessage"></param>
|
||||
/// <returns>true, if the response is a CloudEvent</returns>
|
||||
public static bool IsCloudEvent(this HttpResponseMessage httpResponseMessage)
|
||||
{
|
||||
return ((httpResponseMessage.Content.Headers.ContentType != null &&
|
||||
|
|
@ -65,6 +86,9 @@ namespace CloudNative.CloudEvents
|
|||
httpResponseMessage.Headers.Contains(SpecVersionHttpHeader));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this HttpListenerRequest holds a CloudEvent
|
||||
/// </summary>
|
||||
public static bool IsCloudEvent(this HttpListenerRequest httpListenerRequest)
|
||||
{
|
||||
return ((httpListenerRequest.Headers["content-type"] != null &&
|
||||
|
|
@ -72,24 +96,52 @@ namespace CloudNative.CloudEvents
|
|||
httpListenerRequest.Headers.AllKeys.Contains(SpecVersionHttpHeader));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this response message into a CloudEvent object, with the given extensions.
|
||||
/// </summary>
|
||||
/// <param name="httpResponseMessage">Response message</param>
|
||||
/// <param name="extensions">List of extension instances</param>
|
||||
/// <returns>A CloudEvent instance or 'null' if the response message doesn't hold a CloudEvent</returns>
|
||||
public static CloudEvent ToCloudEvent(this HttpResponseMessage httpResponseMessage,
|
||||
params ICloudEventExtension[] extensions)
|
||||
{
|
||||
return ToCloudEventInternal(httpResponseMessage, null, extensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this response message into a CloudEvent object, with the given extensions and
|
||||
/// overriding the default formatter.
|
||||
/// </summary>
|
||||
/// <param name="httpResponseMessage">Response message</param>
|
||||
/// <param name="formatter"></param>
|
||||
/// <param name="extensions">List of extension instances</param>
|
||||
/// <returns>A CloudEvent instance or 'null' if the response message doesn't hold a CloudEvent</returns>
|
||||
public static CloudEvent ToCloudEvent(this HttpResponseMessage httpResponseMessage,
|
||||
ICloudEventFormatter formatter, params ICloudEventExtension[] extensions)
|
||||
{
|
||||
return ToCloudEventInternal(httpResponseMessage, formatter, extensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this listener request into a CloudEvent object, with the given extensions.
|
||||
/// </summary>
|
||||
/// <param name="httpListenerRequest">Listener request</param>
|
||||
/// <param name="extensions">List of extension instances</param>
|
||||
/// <returns>A CloudEvent instance or 'null' if the response message doesn't hold a CloudEvent</returns>
|
||||
public static CloudEvent ToCloudEvent(this HttpListenerRequest httpListenerRequest,
|
||||
params ICloudEventExtension[] extensions)
|
||||
{
|
||||
return ToCloudEvent(httpListenerRequest, null, extensions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this listener request into a CloudEvent object, with the given extensions,
|
||||
/// overriding the formatter.
|
||||
/// </summary>
|
||||
/// <param name="httpListenerRequest">Listener request</param>
|
||||
/// <param name="formatter"></param>
|
||||
/// <param name="extensions">List of extension instances</param>
|
||||
/// <returns>A CloudEvent instance or 'null' if the response message doesn't hold a CloudEvent</returns>
|
||||
public static CloudEvent ToCloudEvent(this HttpListenerRequest httpListenerRequest,
|
||||
ICloudEventFormatter formatter = null,
|
||||
params ICloudEventExtension[] extensions)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ namespace CloudNative.CloudEvents
|
|||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Implemented for extension objects that reflect CloudEvent extension specifications.
|
||||
/// </summary>
|
||||
public interface ICloudEventExtension
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -9,12 +9,47 @@ namespace CloudNative.CloudEvents
|
|||
using System.Net.Mime;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Implemented by formatters
|
||||
/// </summary>
|
||||
public interface ICloudEventFormatter
|
||||
{
|
||||
/// <summary>
|
||||
/// Decode a structured event from a stream
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="extensions"></param>
|
||||
/// <returns></returns>
|
||||
CloudEvent DecodeStructuredEvent(Stream data, IEnumerable<ICloudEventExtension> extensions);
|
||||
/// <summary>
|
||||
/// Decode a structured event from a byte array
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="extensions"></param>
|
||||
/// <returns></returns>
|
||||
CloudEvent DecodeStructuredEvent(byte[] data, IEnumerable<ICloudEventExtension> extensions);
|
||||
/// <summary>
|
||||
/// Encode an structured event into a byte array
|
||||
/// </summary>
|
||||
/// <param name="cloudEvent"></param>
|
||||
/// <param name="contentType"></param>
|
||||
/// <returns></returns>
|
||||
byte[] EncodeStructuredEvent(CloudEvent cloudEvent, out ContentType contentType);
|
||||
/// <summary>
|
||||
/// Decode an attribute from a byte array
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="extensions"></param>
|
||||
/// <returns></returns>
|
||||
object DecodeAttribute(string name, byte[] data, IEnumerable<ICloudEventExtension> extensions);
|
||||
/// <summary>
|
||||
/// Encode an attribute into a byte array
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="extensions"></param>
|
||||
/// <returns></returns>
|
||||
byte[] EncodeAttribute(string name, object value, IEnumerable<ICloudEventExtension> extensions);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,9 @@ namespace CloudNative.CloudEvents
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// Formatter that implements the JSON Event Format
|
||||
/// </summary>
|
||||
public class JsonEventFormatter : ICloudEventFormatter
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,15 @@ namespace CloudNative.CloudEvents {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The 'sampledrate' attribute value must be an integer.
|
||||
/// </summary>
|
||||
internal static string ErrorSampledRateValueIsaNotAnInteger {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorSampledRateValueIsaNotAnInteger", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The 'schemaurl' attribute value must be a valid absolute or relative URI.
|
||||
/// </summary>
|
||||
|
|
@ -87,6 +96,24 @@ namespace CloudNative.CloudEvents {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The 'sequencetype' attribute value must be an integer.
|
||||
/// </summary>
|
||||
internal static string ErrorSequenceTypeValueIsaNotAString {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorSequenceTypeValueIsaNotAString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The 'sequence' attribute value must be an integer.
|
||||
/// </summary>
|
||||
internal static string ErrorSequenceValueIsaNotAString {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorSequenceValueIsaNotAString", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The 'source' attribute value must be a valid absolute or relative URI.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -123,9 +123,18 @@
|
|||
<data name="ErrorIdValueIsNotAString" xml:space="preserve">
|
||||
<value>The 'id' attribute value must be a string</value>
|
||||
</data>
|
||||
<data name="ErrorSampledRateValueIsaNotAnInteger" xml:space="preserve">
|
||||
<value>The 'sampledrate' attribute value must be an integer</value>
|
||||
</data>
|
||||
<data name="ErrorSchemaUrlIsNotAUri" xml:space="preserve">
|
||||
<value>The 'schemaurl' attribute value must be a valid absolute or relative URI</value>
|
||||
</data>
|
||||
<data name="ErrorSequenceTypeValueIsaNotAString" xml:space="preserve">
|
||||
<value>The 'sequencetype' attribute value must be an integer</value>
|
||||
</data>
|
||||
<data name="ErrorSequenceValueIsaNotAString" xml:space="preserve">
|
||||
<value>The 'sequence' attribute value must be an integer</value>
|
||||
</data>
|
||||
<data name="ErrorSourceValueIsNotAUri" xml:space="preserve">
|
||||
<value>The 'source' attribute value must be a valid absolute or relative URI</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
// Copyright (c) Cloud Native Foundation.
|
||||
// Licensed under the Apache 2.0 license.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace CloudNative.CloudEvents.UnitTests
|
||||
{
|
||||
using System;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
using CloudNative.CloudEvents.Extensions;
|
||||
using Xunit;
|
||||
|
||||
public class ExtensionsTest
|
||||
{
|
||||
const string jsonDistTrace =
|
||||
"{\n" +
|
||||
" \"specversion\" : \"0.2\",\n" +
|
||||
" \"type\" : \"com.github.pull.create\",\n" +
|
||||
" \"source\" : \"https://github.com/cloudevents/spec/pull/123\",\n" +
|
||||
" \"id\" : \"A234-1234-1234\",\n" +
|
||||
" \"time\" : \"2018-04-05T17:31:00Z\",\n" +
|
||||
" \"traceparent\" : \"00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01\",\n" +
|
||||
" \"tracestate\" : \"rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4=\",\n" +
|
||||
" \"contenttype\" : \"text/plain\",\n" +
|
||||
" \"data\" : \"test\"\n" +
|
||||
"}";
|
||||
|
||||
const string jsonSequence =
|
||||
"{\n" +
|
||||
" \"specversion\" : \"0.2\",\n" +
|
||||
" \"type\" : \"com.github.pull.create\",\n" +
|
||||
" \"source\" : \"https://github.com/cloudevents/spec/pull/123\",\n" +
|
||||
" \"id\" : \"A234-1234-1234\",\n" +
|
||||
" \"time\" : \"2018-04-05T17:31:00Z\",\n" +
|
||||
" \"sequencetype\" : \"Integer\",\n" +
|
||||
" \"sequence\" : \"25\",\n" +
|
||||
" \"contenttype\" : \"text/plain\",\n" +
|
||||
" \"data\" : \"test\"\n" +
|
||||
"}";
|
||||
|
||||
const string jsonSampledRate =
|
||||
"{\n" +
|
||||
" \"specversion\" : \"0.2\",\n" +
|
||||
" \"type\" : \"com.github.pull.create\",\n" +
|
||||
" \"source\" : \"https://github.com/cloudevents/spec/pull/123\",\n" +
|
||||
" \"id\" : \"A234-1234-1234\",\n" +
|
||||
" \"time\" : \"2018-04-05T17:31:00Z\",\n" +
|
||||
" \"sampledrate\" : \"1\",\n" +
|
||||
" \"contenttype\" : \"text/plain\",\n" +
|
||||
" \"data\" : \"test\"\n" +
|
||||
"}";
|
||||
|
||||
[Fact]
|
||||
public void DistTraceParse()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonDistTrace), new DistributedTracingExtension());
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", cloudEvent.Extension<DistributedTracingExtension>().TraceParent);
|
||||
Assert.Equal("rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4=", cloudEvent.Extension<DistributedTracingExtension>().TraceState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DistTraceJsonTranscode()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent1 = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonDistTrace));
|
||||
var jsonData = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(jsonData, new DistributedTracingExtension());
|
||||
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", cloudEvent.Extension<DistributedTracingExtension>().TraceParent);
|
||||
Assert.Equal("rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4=", cloudEvent.Extension<DistributedTracingExtension>().TraceState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SequenceParse()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSequence), new SequenceExtension());
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal("Integer", cloudEvent.Extension<SequenceExtension>().SequenceType);
|
||||
Assert.Equal("25", cloudEvent.Extension<SequenceExtension>().Sequence);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SequenceJsonTranscode()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent1 = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSequence));
|
||||
var jsonData = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(jsonData, new SequenceExtension());
|
||||
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal("Integer", cloudEvent.Extension<SequenceExtension>().SequenceType);
|
||||
Assert.Equal("25", cloudEvent.Extension<SequenceExtension>().Sequence);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IntegerSequenceParse()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSequence), new IntegerSequenceExtension());
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal(25, cloudEvent.Extension<IntegerSequenceExtension>().Sequence);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IntegerSequenceJsonTranscode()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent1 = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSequence));
|
||||
var jsonData = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(jsonData, new IntegerSequenceExtension());
|
||||
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal(25, cloudEvent.Extension<IntegerSequenceExtension>().Sequence);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SamplingParse()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSampledRate), new SamplingExtension());
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal(1, cloudEvent.Extension<SamplingExtension>().SampledRate.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SamplingJsonTranscode()
|
||||
{
|
||||
var jsonFormatter = new JsonEventFormatter();
|
||||
var cloudEvent1 = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSampledRate));
|
||||
var jsonData = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
|
||||
var cloudEvent = jsonFormatter.DecodeStructuredEvent(jsonData, new SamplingExtension());
|
||||
|
||||
Assert.Equal("0.2", cloudEvent.SpecVersion);
|
||||
Assert.Equal("com.github.pull.create", cloudEvent.Type);
|
||||
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
|
||||
Assert.Equal("A234-1234-1234", cloudEvent.Id);
|
||||
Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
|
||||
cloudEvent.Time.Value.ToUniversalTime());
|
||||
|
||||
Assert.Equal(1, cloudEvent.Extension<SamplingExtension>().SampledRate.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue