Skip to content

Commit a9092e5

Browse files
authored
[TT-14596] Investigate flaky amqp integration tests (#7019)
### **User description** <details open> <summary><a href="https://tyktech.atlassian.net/browse/TT-14596" title="TT-14596" target="_blank">TT-14596</a></summary> <br /> <table> <tr> <th>Summary</th> <td>Investigate flaky amqp integration tests</td> </tr> <tr> <th>Type</th> <td> <img alt="Task" src="https://tyktech.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium" /> Task </td> </tr> <tr> <th>Status</th> <td>In Dev</td> </tr> <tr> <th>Points</th> <td>N/A</td> </tr> <tr> <th>Labels</th> <td>-</td> </tr> </table> </details> <!-- do not remove this marker as it will break jira-lint's functionality. added_by_jira_lint --> --- This PR adds an aliveness check to be sure RabbitMQ is running and ready to accept connections before running the integration tests. ___ ### **PR Type** - Enhancement ___ ### **Description** - Add aliveness check function for RabbitMQ health verification - Define new constants and response struct for aliveness endpoint - Update TestAMQP to employ the new health check before tests ___ ### **Changes walkthrough** 📝 <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table> <tr> <td> <details> <summary><strong>mw_streaming_amqp_test.go</strong><dd><code>Introduce health check and update test connection flow</code>&nbsp; &nbsp; &nbsp; </dd></summary> <hr> gateway/mw_streaming_amqp_test.go <li>Introduced constants: AlivenessCheckPath, DefaultVirtualHost, <br>RabbitmqAdminUsername, RabbitmqAdminPassword<br> <li> Added struct alivenessCheckResponse for JSON parsing of health <br>response<br> <li> Created checkRabbitMQAliveness function with retries to ensure <br>readiness<br> <li> Modified TestAMQP to utilize the new function instead of hardcoded <br>credentials </details> </td> <td><a href="https://github.com/TykTechnologies/tyk/pull/7019/files#diff-3599fefd35a5eddd4f464208edce54054fc3e5045d1694473367e834c331f9dc">+69/-2</a>&nbsp; &nbsp; </td> </tr> </table></td></tr></tr></tbody></table> ___ > <details> <summary> Need help?</summary><li>Type <code>/help how to ...</code> in the comments thread for any questions about PR-Agent usage.</li><li>Check out the <a href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a> for more information.</li></details>
1 parent 0fce23c commit a9092e5

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

gateway/mw_streaming_amqp_test.go

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
amqp1 "github.com/Azure/go-amqp"
1818
"github.com/TykTechnologies/tyk/apidef/oas"
1919
"github.com/TykTechnologies/tyk/config"
20+
"github.com/TykTechnologies/tyk/test"
2021
"github.com/google/uuid"
2122
"github.com/gorilla/websocket"
2223
"github.com/rabbitmq/amqp091-go"
@@ -26,6 +27,11 @@ import (
2627
"github.com/testcontainers/testcontainers-go/modules/rabbitmq"
2728
)
2829

30+
const (
31+
RabbitmqAdminUsername = "guest"
32+
RabbitmqAdminPassword = "guest"
33+
)
34+
2935
type amqpTestContext struct {
3036
t *testing.T
3137
ts *Test
@@ -358,19 +364,67 @@ func (t *amqpTestContext) testTykStreamAMQPIntegration() {
358364
}
359365
}
360366

367+
// checkRabbitMQAliveness verifies the RabbitMQ container is alive and accepting connections within a specified duration.
368+
func checkRabbitMQAliveness(t *testing.T, rabbitmqContainer *rabbitmq.RabbitMQContainer) {
369+
amqpURL, err := rabbitmqContainer.AmqpURL(context.Background())
370+
require.NoError(t, err)
371+
372+
const interval = 250 * time.Millisecond
373+
duration, err := time.ParseDuration("60s")
374+
require.NoError(t, err)
375+
376+
checkAliveness := func() bool {
377+
var alive bool
378+
// Dial method may return an established TCP connection even if dialErr is not nil.
379+
conn, dialErr := amqp091.Dial(amqpURL)
380+
if dialErr == nil {
381+
alive = true
382+
}
383+
if dialErr != nil {
384+
t.Logf("Failed to connect to RabbitMQ: %v", dialErr)
385+
}
386+
if conn != nil {
387+
closeErr := conn.Close()
388+
if closeErr != nil {
389+
t.Logf("Failed to close RabbitMQ connection: %v", closeErr)
390+
}
391+
}
392+
return alive
393+
}
394+
395+
maxAttempts := int(duration.Milliseconds() / interval.Milliseconds())
396+
for attempt := 0; attempt < maxAttempts; attempt++ {
397+
if rabbitmqContainer.IsRunning() && checkAliveness() {
398+
// It's alive, let's start running the integration tests.
399+
t.Logf("RabbitMQ is alive after %d attempts", attempt+1)
400+
return
401+
}
402+
t.Logf("RabbitMQ is not ready to accept requests, attempt %d/%d", attempt+1, maxAttempts)
403+
time.Sleep(interval)
404+
}
405+
require.Fail(t, "RabbitMQ is not alive after %d attempts", maxAttempts)
406+
}
407+
361408
func TestAMQP(t *testing.T) {
409+
// Marking AMQP tests flaky because RabbitMQ refuses connections time to time
410+
// on GitHub Actions environment. We could not find any way to fix that problem.
411+
// Here is the error message:
412+
// Failed to connect to RabbitMQ: Exception (501) Reason: "read tcp [::1]:46712->[::1]:32773: read: connection reset by peer"
413+
test.Flaky(t)
362414
ctx := context.Background()
363415
rabbitmqContainer, err := rabbitmq.Run(ctx,
364416
"rabbitmq:4.0.8-management-alpine",
365-
rabbitmq.WithAdminUsername("guest"),
366-
rabbitmq.WithAdminPassword("guest"),
417+
rabbitmq.WithAdminUsername(RabbitmqAdminUsername),
418+
rabbitmq.WithAdminPassword(RabbitmqAdminPassword),
367419
)
368420
defer func() {
369421
terminateErr := testcontainers.TerminateContainer(rabbitmqContainer)
370422
require.NoError(t, terminateErr)
371423
}()
372424
require.NoError(t, err)
373425

426+
checkRabbitMQAliveness(t, rabbitmqContainer)
427+
374428
amqpURL, err := rabbitmqContainer.AmqpURL(ctx)
375429
require.NoError(t, err)
376430

0 commit comments

Comments
 (0)