|
1 | 1 | package write
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "bytes" |
4 | 5 | "context"
|
5 | 6 | "errors"
|
| 7 | + "io" |
6 | 8 | "net/http"
|
7 | 9 | "net/http/httptest"
|
| 10 | + "net/url" |
8 | 11 | "sync"
|
9 | 12 | "testing"
|
10 | 13 | "time"
|
@@ -253,3 +256,77 @@ func TestBadAlloyConfig(t *testing.T) {
|
253 | 256 | err := syntax.Unmarshal([]byte(exampleAlloyConfig), &args)
|
254 | 257 | require.ErrorContains(t, err, "at most one of basic_auth, authorization, oauth2, bearer_token & bearer_token_file must be configured")
|
255 | 258 | }
|
| 259 | + |
| 260 | +func Test_Write_AppendIngest(t *testing.T) { |
| 261 | + var ( |
| 262 | + export Exports |
| 263 | + argument = DefaultArguments() |
| 264 | + appendCount = atomic.NewInt32(0) |
| 265 | + serverCount = int32(3) |
| 266 | + servers = make([]*httptest.Server, serverCount) |
| 267 | + endpoints = make([]*EndpointOptions, 0, serverCount) |
| 268 | + ) |
| 269 | + |
| 270 | + testData := []byte("test-profile-data") |
| 271 | + |
| 272 | + handlerFn := func(expectedPath, expectedQuery string) http.HandlerFunc { |
| 273 | + return func(w http.ResponseWriter, r *http.Request) { |
| 274 | + appendCount.Inc() |
| 275 | + require.Equal(t, expectedPath, r.URL.Path, "Unexpected path") |
| 276 | + require.Equal(t, expectedQuery, r.URL.RawQuery, "Unexpected query") |
| 277 | + require.Equal(t, "test-value", r.Header.Get("X-Test-Header"), "Unexpected header value") |
| 278 | + body, err := io.ReadAll(r.Body) |
| 279 | + require.NoError(t, err, "Failed to read request body") |
| 280 | + require.Equal(t, testData, body, "Unexpected body content") |
| 281 | + w.WriteHeader(http.StatusOK) |
| 282 | + } |
| 283 | + } |
| 284 | + |
| 285 | + for i := int32(0); i < serverCount; i++ { |
| 286 | + servers[i] = httptest.NewServer(handlerFn("/ingest", "key=value")) |
| 287 | + endpoints = append(endpoints, &EndpointOptions{ |
| 288 | + URL: servers[i].URL, |
| 289 | + RemoteTimeout: GetDefaultEndpointOptions().RemoteTimeout, |
| 290 | + Headers: map[string]string{ |
| 291 | + "X-Test-Header": "test-value", |
| 292 | + }, |
| 293 | + }) |
| 294 | + } |
| 295 | + defer func() { |
| 296 | + for _, s := range servers { |
| 297 | + s.Close() |
| 298 | + } |
| 299 | + }() |
| 300 | + |
| 301 | + argument.Endpoints = endpoints |
| 302 | + |
| 303 | + // Create the receiver |
| 304 | + var wg sync.WaitGroup |
| 305 | + wg.Add(1) |
| 306 | + c, err := New(component.Options{ |
| 307 | + ID: "test-write", |
| 308 | + Logger: util.TestAlloyLogger(t), |
| 309 | + Registerer: prometheus.NewRegistry(), |
| 310 | + OnStateChange: func(e component.Exports) { |
| 311 | + defer wg.Done() |
| 312 | + export = e.(Exports) |
| 313 | + }, |
| 314 | + }, argument) |
| 315 | + require.NoError(t, err, "Failed to create component") |
| 316 | + |
| 317 | + ctx, cancel := context.WithCancel(context.Background()) |
| 318 | + defer cancel() |
| 319 | + go c.Run(ctx) |
| 320 | + wg.Wait() // wait for the state change to happen |
| 321 | + require.NotNil(t, export.Receiver, "Receiver is nil") |
| 322 | + |
| 323 | + incomingProfile := &pyroscope.IncomingProfile{ |
| 324 | + Body: io.NopCloser(bytes.NewReader(testData)), |
| 325 | + Headers: http.Header{"Content-Type": []string{"application/octet-stream"}}, |
| 326 | + URL: &url.URL{Path: "/ingest", RawQuery: "key=value"}, |
| 327 | + } |
| 328 | + |
| 329 | + err = export.Receiver.Appender().AppendIngest(context.Background(), incomingProfile) |
| 330 | + require.NoError(t, err) |
| 331 | + require.Equal(t, serverCount, appendCount.Load()) |
| 332 | +} |
0 commit comments