Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit e11a59a

Browse files
authored
Enable running ITs against Quesma with debugger (#1479)
<!-- A note on testing your PR --> <!-- Basic unit test run is executed against each commit in the PR. If you want to run a full integration test suite, you can trigger it by commenting with '/run-integration-tests' or '/run-it' -->
1 parent fb0c361 commit e11a59a

File tree

6 files changed

+225
-14
lines changed

6 files changed

+225
-14
lines changed

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
ci/it/configs/*.yml
22
elasticsearch-data
3-
.idea
3+
.idea/*
4+
!.idea/runConfigurations/
5+
!.idea/runConfigurations/*.xml
6+
# User-specific IDEA files
7+
.idea/workspace.xml
8+
.idea/tasks.xml
9+
.idea/usage.statistics.xml
10+
.idea/dictionaries/
411
__pycache__
512
mitmproxy/requests/*.txt
613
mitmproxy/requests/*.mitm

.idea/runConfigurations/Debug_Quesma_ITs.xml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ci/it/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Quesma Integration Tests
2+
========================
3+
4+
This directory contains integration tests for Quesma.
5+
These are simple, end-to-end tests that verify the functionality of Quesma using [Testcontainers library](https://testcontainers.com).
6+
7+
8+
9+
10+
How to debug
11+
============
12+
13+
There is a way to run these tests agains a local Quesma instance with debugger attached.
14+
15+
1. Set up a breakpoint in Quesma codebase.
16+
2. Change the `debugQuesmaDuringTestRun` flag to `true` in `ci/it/testcases/utils.go`
17+
3. Start an integration test (either with CLI or in your IDE using play button next to the test declaration).
18+
...Test case execution will block and wait until you start Quesma manually in IDE in debug mode)
19+
4. Start Quesma in Debug mode using `Debug Quesma ITs` Run Configuration in your IDE.

ci/it/testcases/base.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ func (tc *IntegrationTestcaseBase) Cleanup(ctx context.Context, t *testing.T) {
4343
}
4444

4545
func (tc *IntegrationTestcaseBase) getQuesmaEndpoint() string {
46+
if debugQuesmaDuringTestRun { // If debug mode is enabled, return a hardcoded endpoint for Quesma
47+
return "http://localhost:8080"
48+
}
4649
ctx := context.Background()
4750
q := *tc.Containers.Quesma
4851
p, _ := q.MappedPort(ctx, "8080/tcp")

ci/it/testcases/container_utils.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
// Copyright Quesma, licensed under the Elastic License 2.0.
2+
// SPDX-License-Identifier: Elastic-2.0
3+
4+
package testcases
5+
6+
import (
7+
"context"
8+
"github.com/docker/docker/api/types"
9+
"github.com/docker/go-connections/nat"
10+
"github.com/testcontainers/testcontainers-go"
11+
"github.com/testcontainers/testcontainers-go/exec"
12+
"io"
13+
"time"
14+
)
15+
16+
func NewManuallyCreatedContainer() *ManuallyCreatedContainer {
17+
return &ManuallyCreatedContainer{}
18+
}
19+
20+
type ManuallyCreatedContainer struct{}
21+
22+
func (c ManuallyCreatedContainer) GetContainerID() string {
23+
panic("implement me")
24+
}
25+
26+
func (c ManuallyCreatedContainer) Endpoint(ctx context.Context, s string) (string, error) {
27+
panic("implement me")
28+
}
29+
30+
func (c ManuallyCreatedContainer) PortEndpoint(ctx context.Context, port nat.Port, s string) (string, error) {
31+
panic("implement me")
32+
}
33+
34+
func (c ManuallyCreatedContainer) Host(ctx context.Context) (string, error) {
35+
panic("implement me")
36+
}
37+
38+
func (c ManuallyCreatedContainer) Inspect(ctx context.Context) (*types.ContainerJSON, error) {
39+
panic("implement me")
40+
}
41+
42+
func (c ManuallyCreatedContainer) MappedPort(ctx context.Context, port nat.Port) (nat.Port, error) {
43+
return "8080/tcp", nil
44+
}
45+
46+
func (c ManuallyCreatedContainer) Ports(ctx context.Context) (nat.PortMap, error) {
47+
panic("implement me")
48+
}
49+
50+
func (c ManuallyCreatedContainer) SessionID() string {
51+
panic("implement me")
52+
}
53+
54+
func (c ManuallyCreatedContainer) IsRunning() bool {
55+
panic("implement me")
56+
}
57+
58+
func (c ManuallyCreatedContainer) Start(ctx context.Context) error {
59+
panic("implement me")
60+
}
61+
62+
func (c ManuallyCreatedContainer) Stop(ctx context.Context, duration *time.Duration) error {
63+
panic("implement me")
64+
}
65+
66+
func (c ManuallyCreatedContainer) Terminate(ctx context.Context) error {
67+
panic("implement me")
68+
}
69+
70+
func (c ManuallyCreatedContainer) Logs(ctx context.Context) (io.ReadCloser, error) {
71+
panic("implement me")
72+
}
73+
74+
func (c ManuallyCreatedContainer) FollowOutput(consumer testcontainers.LogConsumer) {
75+
panic("implement me")
76+
}
77+
78+
func (c ManuallyCreatedContainer) StartLogProducer(ctx context.Context, option ...testcontainers.LogProductionOption) error {
79+
panic("implement me")
80+
}
81+
82+
func (c ManuallyCreatedContainer) StopLogProducer() error {
83+
panic("implement me")
84+
}
85+
86+
func (c ManuallyCreatedContainer) Name(ctx context.Context) (string, error) {
87+
panic("implement me")
88+
}
89+
90+
func (c ManuallyCreatedContainer) State(ctx context.Context) (*types.ContainerState, error) {
91+
panic("implement me")
92+
}
93+
94+
func (c ManuallyCreatedContainer) Networks(ctx context.Context) ([]string, error) {
95+
panic("implement me")
96+
}
97+
98+
func (c ManuallyCreatedContainer) NetworkAliases(ctx context.Context) (map[string][]string, error) {
99+
panic("implement me")
100+
}
101+
102+
func (c ManuallyCreatedContainer) Exec(ctx context.Context, cmd []string, options ...exec.ProcessOption) (int, io.Reader, error) {
103+
panic("implement me")
104+
}
105+
106+
func (c ManuallyCreatedContainer) ContainerIP(ctx context.Context) (string, error) {
107+
panic("implement me")
108+
}
109+
110+
func (c ManuallyCreatedContainer) ContainerIPs(ctx context.Context) ([]string, error) {
111+
panic("implement me")
112+
}
113+
114+
func (c ManuallyCreatedContainer) CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error {
115+
panic("implement me")
116+
}
117+
118+
func (c ManuallyCreatedContainer) CopyDirToContainer(ctx context.Context, hostDirPath string, containerParentPath string, fileMode int64) error {
119+
panic("implement me")
120+
}
121+
122+
func (c ManuallyCreatedContainer) CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error {
123+
panic("implement me")
124+
}
125+
126+
func (c ManuallyCreatedContainer) CopyFileFromContainer(ctx context.Context, filePath string) (io.ReadCloser, error) {
127+
panic("implement me")
128+
}
129+
130+
func (c ManuallyCreatedContainer) GetLogProductionErrorChannel() <-chan error {
131+
panic("implement me")
132+
}

ci/it/testcases/utils.go

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/testcontainers/testcontainers-go/wait"
1414
"io"
1515
"log"
16+
"net/http"
1617
"os"
1718
"path/filepath"
1819
"strings"
@@ -21,12 +22,21 @@ import (
2122
"time"
2223
)
2324

25+
const (
26+
// debugQuesmaDuringTestRun should be set to `true` if you would like to run Quesma in IDE with debugger on
27+
// during the integration test run.
28+
debugQuesmaDuringTestRun = false
29+
)
30+
2431
const configTemplatesDir = "configs"
2532

2633
func GetInternalDockerHost() string {
2734
if check := os.Getenv("EXECUTING_ON_GITHUB_CI"); check != "" {
2835
return "localhost-for-github-ci"
2936
}
37+
if debugQuesmaDuringTestRun {
38+
return "localhost"
39+
}
3040
return "host.docker.internal" // `host.testcontainers.internal` doesn't work for Docker Desktop for Mac.
3141
}
3242

@@ -264,26 +274,27 @@ func setupClickHouse(ctx context.Context) (testcontainers.Container, error) {
264274
})
265275
}
266276

267-
func RenderQuesmaConfig(configTemplate string, data map[string]string) error {
277+
func RenderQuesmaConfig(configTemplate string, data map[string]string) (string, error) {
268278
absPath, err := filepath.Abs(filepath.Join(".", configTemplatesDir, configTemplate))
269279
content, err := os.ReadFile(absPath)
270280
if err != nil {
271-
return fmt.Errorf("error reading YAML file: %v", err)
281+
return "", fmt.Errorf("error reading YAML file: %v", err)
272282
}
273283
tmpl, err := template.New("yamlTemplate").Parse(string(content))
274284
if err != nil {
275-
return fmt.Errorf("error creating template: %v", err)
285+
return "", fmt.Errorf("error creating template: %v", err)
276286
}
277287
var renderedContent bytes.Buffer
278288
err = tmpl.Execute(&renderedContent, data)
279289
if err != nil {
280-
return fmt.Errorf("error executing template: %v", err)
290+
return "", fmt.Errorf("error executing template: %v", err)
281291
}
282-
err = os.WriteFile(strings.TrimSuffix(absPath, ".template"), renderedContent.Bytes(), 0644)
292+
configPath := strings.TrimSuffix(absPath, ".template")
293+
err = os.WriteFile(configPath, renderedContent.Bytes(), 0644)
283294
if err != nil {
284-
return fmt.Errorf("error writing rendered YAML file: %v", err)
295+
return "", fmt.Errorf("error writing rendered YAML file: %v", err)
285296
}
286-
return nil
297+
return configPath, nil
287298
}
288299

289300
func setupContainersForTransparentProxy(ctx context.Context, quesmaConfigTemplate string) (*Containers, error) {
@@ -300,7 +311,7 @@ func setupContainersForTransparentProxy(ctx context.Context, quesmaConfigTemplat
300311
"elasticsearch_host": GetInternalDockerHost(),
301312
"elasticsearch_port": esPort.Port(),
302313
}
303-
if err := RenderQuesmaConfig(quesmaConfigTemplate, data); err != nil {
314+
if _, err := RenderQuesmaConfig(quesmaConfigTemplate, data); err != nil {
304315
return &containers, fmt.Errorf("failed to render Quesma config: %v", err)
305316
}
306317

@@ -344,14 +355,39 @@ func setupAllContainersWithCh(ctx context.Context, quesmaConfigTemplate string)
344355
"clickhouse_host": GetInternalDockerHost(),
345356
"clickhouse_port": chPort.Port(),
346357
}
347-
if err := RenderQuesmaConfig(quesmaConfigTemplate, data); err != nil {
358+
configPath, err := RenderQuesmaConfig(quesmaConfigTemplate, data)
359+
if err != nil {
348360
return &containers, fmt.Errorf("failed to render Quesma config: %v", err)
349361
}
350362

351-
quesma, err := setupQuesma(ctx, quesmaConfigTemplate)
352-
containers.Quesma = &quesma
353-
if err != nil {
354-
return &containers, fmt.Errorf("failed to start Quesma, %v", err)
363+
var quesma testcontainers.Container
364+
if debugQuesmaDuringTestRun {
365+
debuggerQuesmaConfig := filepath.Join(filepath.Dir(configPath), "quesma-with-debugger.yml")
366+
content, err := os.ReadFile(configPath)
367+
if err != nil {
368+
return &containers, fmt.Errorf("failed to read rendered Quesma config: %v", err)
369+
}
370+
if err := os.WriteFile(debuggerQuesmaConfig, content, 0644); err != nil {
371+
return &containers, fmt.Errorf("failed to write quesma-with-debugger.yml: %v", err)
372+
}
373+
log.Printf("Quesma config rendered to: %s", debuggerQuesmaConfig)
374+
375+
log.Printf("Waiting for you to start Quesma form your IDE using `Debug Quesma IT` configuration")
376+
for {
377+
if resp, err := http.Get("http://localhost:8080"); err == nil {
378+
resp.Body.Close()
379+
break
380+
}
381+
log.Printf("Waiting for Quesma HTTP server at port 8080...")
382+
time.Sleep(1 * time.Second)
383+
quesma = NewManuallyCreatedContainer()
384+
}
385+
} else {
386+
quesma, err = setupQuesma(ctx, quesmaConfigTemplate)
387+
if err != nil {
388+
return &containers, fmt.Errorf("failed to start Quesma: %v", err)
389+
}
390+
containers.Quesma = &quesma
355391
}
356392

357393
kibana, err := setupKibana(ctx, quesma)

0 commit comments

Comments
 (0)