opentelemetry-dotnet/test/OpenTelemetry.Api.Tests/BaggageTests.cs

300 lines
8.1 KiB
C#

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
using Xunit;
namespace OpenTelemetry.Tests;
public class BaggageTests
{
private const string K1 = "Key1";
private const string K2 = "Key2";
private const string K3 = "Key3";
private const string V1 = "Value1";
private const string V2 = "Value2";
private const string V3 = "Value3";
[Fact]
public void EmptyTest()
{
Assert.Empty(Baggage.GetBaggage());
Assert.Empty(Baggage.Current.GetBaggage());
}
[Fact]
public void SetAndGetTest()
{
var list = new List<KeyValuePair<string, string>>(2)
{
new(K1, V1),
new(K2, V2),
};
Baggage.SetBaggage(K1, V1);
var baggage = Baggage.Current.SetBaggage(K2, V2);
Baggage.Current = baggage;
Assert.NotEmpty(Baggage.GetBaggage());
Assert.Equal(list, Baggage.GetBaggage(Baggage.Current));
Assert.Equal(V1, Baggage.GetBaggage(K1));
Assert.Equal(V1, Baggage.GetBaggage(K1.ToLower()));
Assert.Equal(V1, Baggage.GetBaggage(K1.ToUpper()));
Assert.Null(Baggage.GetBaggage("NO_KEY"));
Assert.Equal(V2, Baggage.Current.GetBaggage(K2));
Assert.Throws<ArgumentException>(() => Baggage.GetBaggage(null!));
}
[Fact]
public void SetExistingKeyTest()
{
var list = new List<KeyValuePair<string, string>>(2)
{
new(K1, V1),
};
Baggage.Current.SetBaggage(new KeyValuePair<string, string?>(K1, V1));
var baggage = Baggage.SetBaggage(K1, V1);
Baggage.SetBaggage(new Dictionary<string, string?> { [K1] = V1 }, baggage);
Assert.Equal(list, Baggage.GetBaggage());
}
[Fact]
public void SetNullValueTest()
{
var baggage = Baggage.Current;
baggage = Baggage.SetBaggage(K1, V1, baggage);
Assert.Equal(1, Baggage.Current.Count);
Assert.Equal(1, baggage.Count);
Baggage.Current.SetBaggage(K2, null);
Assert.Equal(1, Baggage.Current.Count);
Assert.Empty(Baggage.SetBaggage(K1, null).GetBaggage());
Baggage.SetBaggage(K1, V1);
Baggage.SetBaggage(new Dictionary<string, string?>
{
[K1] = null,
[K2] = V2,
});
Assert.Equal(1, Baggage.Current.Count);
Assert.Contains(Baggage.GetBaggage(), kvp => kvp.Key == K2);
}
[Fact]
public void RemoveTest()
{
var empty = Baggage.Current;
var empty2 = Baggage.RemoveBaggage(K1);
Assert.True(empty == empty2);
var baggage = Baggage.SetBaggage(new Dictionary<string, string?>
{
[K1] = V1,
[K2] = V2,
[K3] = V3,
});
var baggage2 = Baggage.RemoveBaggage(K1, baggage);
Assert.Equal(3, baggage.Count);
Assert.Equal(2, baggage2.Count);
Assert.DoesNotContain(new KeyValuePair<string, string>(K1, V1), baggage2.GetBaggage());
}
[Fact]
public void ClearTest()
{
var baggage = Baggage.SetBaggage(new Dictionary<string, string?>
{
[K1] = V1,
[K2] = V2,
[K3] = V3,
});
Assert.Equal(3, baggage.Count);
Baggage.ClearBaggage();
Assert.Equal(0, Baggage.Current.Count);
}
[Fact]
public void ContextFlowTest()
{
var baggage = Baggage.SetBaggage(K1, V1);
var baggage2 = Baggage.Current.SetBaggage(K2, V2);
Baggage.Current = baggage2;
var baggage3 = Baggage.SetBaggage(K3, V3);
Assert.Equal(1, baggage.Count);
Assert.Equal(2, baggage2.Count);
Assert.Equal(3, baggage3.Count);
Baggage.Current = baggage;
var baggage4 = Baggage.SetBaggage(K3, V3);
Assert.Equal(2, baggage4.Count);
Assert.DoesNotContain(new KeyValuePair<string, string>(K2, V2), baggage4.GetBaggage());
}
[Fact]
public void EnumeratorTest()
{
var list = new List<KeyValuePair<string, string>>(2)
{
new(K1, V1),
new(K2, V2),
};
var baggage = Baggage.SetBaggage(K1, V1);
baggage = Baggage.SetBaggage(K2, V2, baggage);
var enumerator = Baggage.GetEnumerator(baggage);
Assert.True(enumerator.MoveNext());
var tag1 = enumerator.Current;
Assert.True(enumerator.MoveNext());
var tag2 = enumerator.Current;
Assert.False(enumerator.MoveNext());
Assert.Equal(list, new List<KeyValuePair<string, string>> { tag1, tag2 });
Baggage.ClearBaggage();
enumerator = Baggage.GetEnumerator();
Assert.False(enumerator.MoveNext());
}
[Fact]
public void EqualsTest()
{
var bc1 = new Baggage(new Dictionary<string, string> { [K1] = V1, [K2] = V2 });
var bc2 = new Baggage(new Dictionary<string, string> { [K1] = V1, [K2] = V2 });
var bc3 = new Baggage(new Dictionary<string, string> { [K2] = V2, [K1] = V1 });
var bc4 = new Baggage(new Dictionary<string, string> { [K1] = V1, [K2] = V1 });
var bc5 = new Baggage(new Dictionary<string, string> { [K1] = V2, [K2] = V1 });
Assert.True(bc1.Equals(bc2));
Assert.False(bc1.Equals(bc3));
Assert.False(bc1.Equals(bc4));
Assert.False(bc2.Equals(bc4));
Assert.False(bc3.Equals(bc4));
Assert.False(bc5.Equals(bc4));
Assert.False(bc4.Equals(bc5));
}
[Fact]
public void CreateBaggageTest()
{
var baggage = Baggage.Create(null);
Assert.Equal(default, baggage);
baggage = Baggage.Create(new Dictionary<string, string>
{
[K1] = V1,
["key2"] = "value2",
["KEY2"] = "VALUE2",
["KEY3"] = "VALUE3",
["Key3"] = null!, // Note: This causes Key3 to be removed
});
Assert.Equal(2, baggage.Count);
Assert.Contains(baggage.GetBaggage(), kvp => kvp.Key == K1);
Assert.Equal("VALUE2", Baggage.GetBaggage("key2", baggage));
}
[Fact]
public void EqualityTests()
{
var emptyBaggage = Baggage.Create(null);
var baggage = Baggage.SetBaggage(K1, V1);
Assert.NotEqual(emptyBaggage, baggage);
Assert.True(emptyBaggage != baggage);
baggage = Baggage.ClearBaggage(baggage);
Assert.Equal(emptyBaggage, baggage);
baggage = Baggage.SetBaggage(K1, V1);
var baggage2 = Baggage.SetBaggage(null!);
Assert.Equal(baggage, baggage2);
Assert.False(baggage.Equals(this));
Assert.True(baggage.Equals((object)baggage2));
}
[Fact]
public void GetHashCodeTests()
{
var baggage = Baggage.Current;
var emptyBaggage = Baggage.Create(null);
Assert.Equal(emptyBaggage.GetHashCode(), baggage.GetHashCode());
baggage = Baggage.SetBaggage(K1, V1, baggage);
Assert.NotEqual(emptyBaggage.GetHashCode(), baggage.GetHashCode());
var expectedBaggage = Baggage.Create(new Dictionary<string, string> { [K1] = V1 });
Assert.Equal(expectedBaggage.GetHashCode(), baggage.GetHashCode());
}
[Fact]
public async Task AsyncLocalTests()
{
Baggage.SetBaggage("key1", "value1");
await InnerTask();
Baggage.SetBaggage("key4", "value4");
Assert.Equal(4, Baggage.Current.Count);
Assert.Equal("value1", Baggage.GetBaggage("key1"));
Assert.Equal("value2", Baggage.GetBaggage("key2"));
Assert.Equal("value3", Baggage.GetBaggage("key3"));
Assert.Equal("value4", Baggage.GetBaggage("key4"));
static async Task InnerTask()
{
Baggage.SetBaggage("key2", "value2");
await Task.Yield();
Baggage.SetBaggage("key3", "value3");
// key2 & key3 changes don't flow backward automatically
}
}
[Fact]
public void ThreadSafetyTest()
{
Baggage.SetBaggage("rootKey", "rootValue"); // Note: Required to establish a root ExecutionContext containing the BaggageHolder we use as a lock
Parallel.For(0, 100, (i) =>
{
Baggage.SetBaggage($"key{i}", $"value{i}");
});
Assert.Equal(101, Baggage.Current.Count);
}
}