Skip to content

Commit 4a5614a

Browse files
robbkiddmterhar
authored andcommitted
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 7736d48 commit 4a5614a

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
@@ -1498,158 +1498,104 @@ func TestBuildRequestURL(t *testing.T) {
14981498
}
14991499
}
15001500

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

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

0 commit comments

Comments
 (0)