Skip to content

Commit 2d6117e

Browse files
authored
chore: maybe improved integration test for additional headers? (#1773)
## Which problem is this PR solving? I was playing with the tests to get to know the changes in #1771. The result is mostly the same, but I propose we maintain this version. ## Short description of the changes The multiple commits show my fiddling, but the major changes are: * a single table-driven test * the lock for synchronizing the captured headers is hidden by using an atomic type
1 parent 50cf847 commit 2d6117e

File tree

1 file changed

+97
-151
lines changed

1 file changed

+97
-151
lines changed

transmit/direct_transmit_test.go

Lines changed: 97 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,158 +1508,104 @@ func TestBuildRequestURL(t *testing.T) {
15081508
}
15091509
}
15101510

1511-
func TestDirectTransmitAdditionalHeaders(t *testing.T) {
1512-
// Create test server that captures headers
1513-
var capturedHeaders http.Header
1514-
var headerMutex sync.Mutex
1515-
1516-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1517-
headerMutex.Lock()
1518-
capturedHeaders = r.Header.Clone()
1519-
headerMutex.Unlock()
1520-
1521-
// Read and discard body
1522-
io.ReadAll(r.Body)
1523-
r.Body.Close()
1524-
1525-
// Send proper response
1526-
w.Header().Set("Content-Type", "application/json")
1527-
w.WriteHeader(http.StatusOK)
1528-
w.Write([]byte(`[{"status": 202}]`))
1529-
}))
1530-
defer server.Close()
1531-
1532-
// Create DirectTransmission with additional headers
1533-
additionalHeaders := map[string]string{
1534-
"FORWARD_TO_URL": "https://proxy.example.com",
1535-
"X-Custom-Header": "custom-value",
1536-
}
1537-
1538-
mockMetrics := &metrics.MockMetrics{}
1539-
mockMetrics.Start()
1540-
mockLogger := &logger.MockLogger{}
1541-
1542-
dt := NewDirectTransmission(
1543-
types.TransmitTypeUpstream,
1544-
http.DefaultTransport.(*http.Transport),
1545-
10,
1546-
100*time.Millisecond,
1547-
10*time.Second,
1548-
false, // no compression to simplify test
1549-
additionalHeaders,
1550-
)
1551-
dt.Logger = mockLogger
1552-
dt.Version = "test-version"
1553-
dt.Metrics = mockMetrics
1554-
1555-
err := dt.Start()
1556-
require.NoError(t, err)
1557-
defer dt.Stop()
1558-
1559-
// Send a test event
1560-
mockCfg := &config.MockConfig{}
1561-
eventData := types.NewPayload(mockCfg, map[string]any{"test": "value"})
1562-
eventData.ExtractMetadata()
1563-
1564-
event := &types.Event{
1565-
Context: context.Background(),
1566-
APIHost: server.URL,
1567-
APIKey: "test-api-key",
1568-
Dataset: "test-dataset",
1569-
SampleRate: 1,
1570-
Timestamp: time.Now().UTC(),
1571-
Data: eventData,
1511+
// TestDirectTransmission_AdditionalHeaders validates that additional headers configured
1512+
// in Network.AdditionalHeaders are properly sent with HTTP requests.
1513+
// Config-level validation (reserved headers, etc.) is tested in config/config_test.go
1514+
func TestDirectTransmission_AdditionalHeaders(t *testing.T) {
1515+
testCases := []struct {
1516+
desc string
1517+
additionalHeaders map[string]string
1518+
}{
1519+
{
1520+
desc: "with-additional-headers",
1521+
additionalHeaders: map[string]string{
1522+
"FORWARD_TO_URL": "https://proxy.example.com",
1523+
"X-Custom-Header": "custom-value",
1524+
},
1525+
},
1526+
{
1527+
desc: "with-empty-additional-headers",
1528+
additionalHeaders: map[string]string{},
1529+
},
1530+
{
1531+
desc: "with-nil-additional-headers",
1532+
additionalHeaders: nil,
1533+
},
15721534
}
1573-
dt.EnqueueEvent(event)
1574-
1575-
// Wait for the event to be sent
1576-
require.Eventually(t, func() bool {
1577-
headerMutex.Lock()
1578-
defer headerMutex.Unlock()
1579-
return capturedHeaders != nil
1580-
}, 5*time.Second, 50*time.Millisecond, "headers should be captured")
1581-
1582-
// Verify custom headers were sent
1583-
headerMutex.Lock()
1584-
defer headerMutex.Unlock()
1585-
assert.Equal(t, "https://proxy.example.com", capturedHeaders.Get("FORWARD_TO_URL"))
1586-
assert.Equal(t, "custom-value", capturedHeaders.Get("X-Custom-Header"))
1587-
1588-
// Verify standard Honeycomb headers are also present
1589-
assert.Equal(t, "test-api-key", capturedHeaders.Get("X-Honeycomb-Team"))
1590-
assert.Equal(t, "application/msgpack", capturedHeaders.Get("Content-Type"))
1591-
}
1592-
1593-
func TestDirectTransmitNoAdditionalHeaders(t *testing.T) {
1594-
// Create test server that captures headers
1595-
var capturedHeaders http.Header
1596-
var headerMutex sync.Mutex
1597-
1598-
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1599-
headerMutex.Lock()
1600-
capturedHeaders = r.Header.Clone()
1601-
headerMutex.Unlock()
1602-
1603-
io.ReadAll(r.Body)
1604-
r.Body.Close()
1605-
1606-
w.Header().Set("Content-Type", "application/json")
1607-
w.WriteHeader(http.StatusOK)
1608-
w.Write([]byte(`[{"status": 202}]`))
1609-
}))
1610-
defer server.Close()
1611-
1612-
// Create DirectTransmission without additional headers (nil)
1613-
mockMetrics := &metrics.MockMetrics{}
1614-
mockMetrics.Start()
1615-
mockLogger := &logger.MockLogger{}
1616-
1617-
dt := NewDirectTransmission(
1618-
types.TransmitTypeUpstream,
1619-
http.DefaultTransport.(*http.Transport),
1620-
10,
1621-
100*time.Millisecond,
1622-
10*time.Second,
1623-
false,
1624-
nil, // No additional headers
1625-
)
1626-
dt.Logger = mockLogger
1627-
dt.Version = "test-version"
1628-
dt.Metrics = mockMetrics
1629-
1630-
err := dt.Start()
1631-
require.NoError(t, err)
1632-
defer dt.Stop()
1633-
1634-
// Send a test event
1635-
mockCfg := &config.MockConfig{}
1636-
eventData := types.NewPayload(mockCfg, map[string]any{"test": "value"})
1637-
eventData.ExtractMetadata()
1535+
for _, tC := range testCases {
1536+
t.Run(tC.desc, func(t *testing.T) {
1537+
t.Parallel()
1538+
1539+
mockMetrics := &metrics.MockMetrics{}
1540+
mockMetrics.Start()
1541+
t.Cleanup(mockMetrics.Stop)
1542+
1543+
dt := NewDirectTransmission(
1544+
types.TransmitTypeUpstream,
1545+
http.DefaultTransport.(*http.Transport),
1546+
10,
1547+
100*time.Millisecond,
1548+
10*time.Second,
1549+
false, // no compression to simplify test
1550+
tC.additionalHeaders,
1551+
)
1552+
dt.Logger = &logger.MockLogger{}
1553+
dt.Metrics = mockMetrics
1554+
dt.Version = tC.desc + "-test"
1555+
1556+
// Store http.Header(s) received for validation outside handler
1557+
var receivedHeaders atomic.Value
1558+
1559+
capturingHeadersServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1560+
receivedHeaders.Store(r.Header.Clone())
1561+
1562+
// Read and discard body
1563+
_, _ = io.ReadAll(r.Body)
1564+
r.Body.Close()
1565+
1566+
// Send proper response
1567+
w.Header().Set("Content-Type", "application/json")
1568+
w.WriteHeader(http.StatusOK)
1569+
w.Write([]byte(`[{"status": 202}]`))
1570+
}))
1571+
t.Cleanup(capturingHeadersServer.Close)
16381572

1639-
event := &types.Event{
1640-
Context: context.Background(),
1641-
APIHost: server.URL,
1642-
APIKey: "test-api-key",
1643-
Dataset: "test-dataset",
1644-
SampleRate: 1,
1645-
Timestamp: time.Now().UTC(),
1646-
Data: eventData,
1573+
// Start the test DirectTransmission
1574+
err := dt.Start()
1575+
require.NoError(t, err)
1576+
t.Cleanup(func() { dt.Stop() })
1577+
1578+
// Send a test event
1579+
eventData := types.NewPayload(&config.MockConfig{}, map[string]any{"test": "value"})
1580+
eventData.ExtractMetadata()
1581+
1582+
event := &types.Event{
1583+
Context: context.Background(),
1584+
APIHost: capturingHeadersServer.URL,
1585+
APIKey: "test-additional-headers",
1586+
Dataset: "test-dataset",
1587+
SampleRate: 1,
1588+
Timestamp: time.Now().UTC(),
1589+
Data: eventData,
1590+
}
1591+
dt.EnqueueEvent(event)
1592+
1593+
// Wait for the server to receive the request
1594+
require.Eventually(t, func() bool {
1595+
return receivedHeaders.Load() != nil
1596+
}, 5*time.Second, 50*time.Millisecond, "request with headers should have been received")
1597+
1598+
// Validate headers
1599+
headers := receivedHeaders.Load().(http.Header)
1600+
if len(tC.additionalHeaders) > 0 {
1601+
for customHeaderName, customHeaderValue := range tC.additionalHeaders {
1602+
assert.Equal(t, customHeaderValue, headers.Get(customHeaderName),
1603+
"Additional header '%s' has unexpected value", customHeaderName)
1604+
}
1605+
}
1606+
assert.Equal(t, "test-additional-headers", headers.Get("X-Honeycomb-Team"))
1607+
assert.Equal(t, "application/msgpack", headers.Get("Content-Type"))
1608+
assert.Contains(t, headers.Get("User-Agent"), tC.desc+"-test")
1609+
})
16471610
}
1648-
dt.EnqueueEvent(event)
1649-
1650-
// Wait for the event to be sent
1651-
require.Eventually(t, func() bool {
1652-
headerMutex.Lock()
1653-
defer headerMutex.Unlock()
1654-
return capturedHeaders != nil
1655-
}, 5*time.Second, 50*time.Millisecond, "headers should be captured")
1656-
1657-
// Verify standard Honeycomb headers are present
1658-
headerMutex.Lock()
1659-
defer headerMutex.Unlock()
1660-
assert.Equal(t, "test-api-key", capturedHeaders.Get("X-Honeycomb-Team"))
1661-
assert.Equal(t, "application/msgpack", capturedHeaders.Get("Content-Type"))
1662-
1663-
// Custom headers should not be present
1664-
assert.Empty(t, capturedHeaders.Get("FORWARD_TO_URL"))
16651611
}

0 commit comments

Comments
 (0)