Skip to content

Commit f0e3ee7

Browse files
committed
Add header propagation tests
1 parent 5bb0e88 commit f0e3ee7

File tree

2 files changed

+125
-1
lines changed

2 files changed

+125
-1
lines changed

libraries/Microsoft.Bot.Connector/HeaderPropagationEntryCollection.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,18 @@ public void Add(string key, StringValues value)
4949
/// <param name="value">The value to append for the specified key.</param>
5050
public void Append(string key, StringValues value)
5151
{
52+
StringValues newValue;
53+
54+
if (_entries.TryGetValue(key, out var entry))
55+
{
56+
// If the key already exists, append the new value to the existing one.
57+
newValue = StringValues.Concat(entry.Value, value);
58+
}
59+
5260
_entries[key] = new HeaderPropagationEntry
5361
{
5462
Key = key,
55-
Value = value,
63+
Value = !StringValues.IsNullOrEmpty(newValue) ? newValue : value,
5664
Action = HeaderPropagationEntryAction.Append
5765
};
5866
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using Microsoft.Extensions.Primitives;
6+
using Xunit;
7+
8+
namespace Microsoft.Bot.Connector.Tests
9+
{
10+
[Collection("Non-Parallel Collection")] // Ensure this test runs in a single-threaded context to avoid issues with static dictionary.
11+
public class HeaderPropagationTests
12+
{
13+
public HeaderPropagationTests()
14+
{
15+
HeaderPropagation.HeadersToPropagate = new Dictionary<string, StringValues>();
16+
}
17+
18+
[Fact]
19+
public void HeaderPropagationContext_ShouldFilterHeaders()
20+
{
21+
// Arrange
22+
HeaderPropagation.RequestHeaders = new Dictionary<string, StringValues>
23+
{
24+
{ "x-custom-header-1", new StringValues("Value-1") },
25+
{ "x-custom-header-2", new StringValues("Value-2") },
26+
{ "x-custom-header-3", new StringValues("Value-3") }
27+
};
28+
29+
var headersToPropagate = new HeaderPropagationEntryCollection();
30+
31+
headersToPropagate.Add("x-custom-header", "custom-value");
32+
headersToPropagate.Propagate("x-custom-header-1");
33+
headersToPropagate.Override("x-custom-header-2", "new-value");
34+
headersToPropagate.Append("x-custom-header-3", "extra-value");
35+
36+
// Act
37+
var filteredHeaders = HeaderPropagation.FilterHeaders(headersToPropagate);
38+
39+
// Assert
40+
Assert.Equal(4, filteredHeaders.Count);
41+
Assert.Equal("custom-value", filteredHeaders["x-custom-header"]);
42+
Assert.Equal("Value-1", filteredHeaders["x-custom-header-1"]);
43+
Assert.Equal("new-value", filteredHeaders["x-custom-header-2"]);
44+
Assert.Equal("Value-3,extra-value", filteredHeaders["x-custom-header-3"]);
45+
}
46+
47+
[Fact]
48+
public void HeaderPropagationContext_ShouldAppendMultipleValues()
49+
{
50+
// Arrange
51+
HeaderPropagation.RequestHeaders = new Dictionary<string, StringValues>
52+
{
53+
{ "User-Agent", new StringValues("Value-1") }
54+
};
55+
56+
var headersToPropagate = new HeaderPropagationEntryCollection();
57+
58+
headersToPropagate.Append("User-Agent", "extra-value-1");
59+
headersToPropagate.Append("User-Agent", "extra-value-2");
60+
61+
// Act
62+
var filteredHeaders = HeaderPropagation.FilterHeaders(headersToPropagate);
63+
64+
// Assert
65+
Assert.Single(filteredHeaders);
66+
Assert.Equal("Value-1,extra-value-1,extra-value-2", filteredHeaders["User-Agent"]);
67+
}
68+
69+
[Fact]
70+
public void HeaderPropagationContext_MultipleAdd_ShouldKeepLastValue()
71+
{
72+
// Arrange
73+
HeaderPropagation.RequestHeaders = new Dictionary<string, StringValues>();
74+
75+
var headersToPropagate = new HeaderPropagationEntryCollection();
76+
77+
headersToPropagate.Add("x-custom-header-1", "value-1");
78+
headersToPropagate.Add("x-custom-header-1", "value-2");
79+
80+
// Act
81+
var filteredHeaders = HeaderPropagation.FilterHeaders(headersToPropagate);
82+
83+
// Assert
84+
Assert.Single(filteredHeaders);
85+
Assert.Equal("value-2", filteredHeaders["x-custom-header-1"]);
86+
}
87+
88+
[Fact]
89+
public void HeaderPropagationContext_MultipleOverride_ShouldKeepLastValue()
90+
{
91+
// Arrange
92+
HeaderPropagation.RequestHeaders = new Dictionary<string, StringValues>
93+
{
94+
{ "x-custom-header-1", new StringValues("Value-1") }
95+
};
96+
97+
var headersToPropagate = new HeaderPropagationEntryCollection();
98+
headersToPropagate.Override("x-custom-header-1", "new-value-1");
99+
headersToPropagate.Override("x-custom-header-1", "new-value-2");
100+
101+
// Act
102+
var filteredHeaders = HeaderPropagation.FilterHeaders(headersToPropagate);
103+
104+
// Assert
105+
Assert.Single(filteredHeaders);
106+
Assert.Equal("new-value-2", filteredHeaders["x-custom-header-1"]);
107+
}
108+
}
109+
110+
[CollectionDefinition("Non-Parallel Collection", DisableParallelization = true)]
111+
#pragma warning disable SA1402 // File may only contain a single type
112+
public class NonParallelCollectionDefinition
113+
{
114+
}
115+
#pragma warning restore SA1402 // File may only contain a single type
116+
}

0 commit comments

Comments
 (0)