opentelemetry-dotnet/test/OpenTelemetry.Tests/Implementation/Context/Propagation/DistributedContextSerializa...

154 lines
5.4 KiB
C#

// <copyright file="DistributedContextSerializationTest.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using OpenTelemetry.Internal;
using Xunit;
namespace OpenTelemetry.Context.Propagation.Test
{
public class DistributedContextSerializationTest
{
private const string K1 = "k1";
private const string K2 = "k2";
private const string K3 = "k3";
private const string K4 = "k4";
private const string V1 = "v1";
private const string V2 = "v2";
private const string V3 = "v3";
private const string V4 = "v4";
private static readonly CorrelationContextEntry T1 = new CorrelationContextEntry(K1, V1);
private static readonly CorrelationContextEntry T2 = new CorrelationContextEntry(K2, V2);
private static readonly CorrelationContextEntry T3 = new CorrelationContextEntry(K3, V3);
private static readonly CorrelationContextEntry T4 = new CorrelationContextEntry(K4, V4);
private readonly DistributedContextBinarySerializer serializer;
public DistributedContextSerializationTest()
{
DistributedContext.Carrier = AsyncLocalDistributedContextCarrier.Instance;
this.serializer = new DistributedContextBinarySerializer();
}
[Fact]
public void TestSerializeDefault()
{
this.TestSerialize();
}
[Fact]
public void TestSerializeWithOneTag()
{
this.TestSerialize(T1);
}
[Fact]
public void TestSerializeWithMultipleTags()
{
this.TestSerialize(T1, T2, T3, T4);
}
[Fact]
public void TestSerializeTooLargeTagContext()
{
var list = new List<CorrelationContextEntry>();
for (var i = 0; i < (SerializationUtils.TagContextSerializedSizeLimit / 8) - 1; i++)
{
// Each tag will be with format {key : "0123", value : "0123"}, so the length of it is 8.
var str = i.ToString("0000");
list.Add(new CorrelationContextEntry(str, str));
}
// The last tag will be of size 9, so the total size of the TagContext (8193) will be one byte
// more than limit.
list.Add(new CorrelationContextEntry("last", "last1"));
var dc = DistributedContextBuilder.CreateContext(list);
Assert.Empty(this.serializer.ToByteArray(dc));
}
private static void EncodeString(string input, MemoryStream byteArrayOutPutStream)
{
VarInt.PutVarInt(input.Length, byteArrayOutPutStream);
var inpBytes = Encoding.UTF8.GetBytes(input);
byteArrayOutPutStream.Write(inpBytes, 0, inpBytes.Length);
}
private static void RotateRight(IList<CorrelationContextEntry> sequence, int count)
{
var tmp = sequence[count - 1];
sequence.RemoveAt(count - 1);
sequence.Insert(0, tmp);
}
private static IEnumerable<IList<CorrelationContextEntry>> Permutate(IList<CorrelationContextEntry> sequence, int count)
{
if (count == 0)
{
yield return sequence;
}
else
{
for (var i = 0; i < count; i++)
{
foreach (var perm in Permutate(sequence, count - 1))
{
yield return perm;
}
RotateRight(sequence, count);
}
}
}
private void TestSerialize(params CorrelationContextEntry[] tags)
{
var list = new List<CorrelationContextEntry>(tags);
var actual = this.serializer.ToByteArray(DistributedContextBuilder.CreateContext(list));
var tagsList = tags.ToList();
var tagPermutation = Permutate(tagsList, tagsList.Count);
ISet<string> possibleOutPuts = new HashSet<string>();
foreach (var distributedContextEntries in tagPermutation)
{
var l = (List<CorrelationContextEntry>)distributedContextEntries;
var expected = new MemoryStream();
expected.WriteByte(SerializationUtils.VersionId);
foreach (var tag in l)
{
expected.WriteByte(SerializationUtils.TagFieldId);
EncodeString(tag.Key, expected);
EncodeString(tag.Value, expected);
}
var bytes = expected.ToArray();
possibleOutPuts.Add(Encoding.UTF8.GetString(bytes));
}
var exp = Encoding.UTF8.GetString(actual);
Assert.Contains(exp, possibleOutPuts);
}
}
}