Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Kafka doesn't work with t.Parallel() #1038

Closed
karelbilek opened this issue May 7, 2024 · 4 comments
Closed

Bug: Kafka doesn't work with t.Parallel() #1038

karelbilek opened this issue May 7, 2024 · 4 comments

Comments

@karelbilek
Copy link
Contributor

karelbilek commented May 7, 2024

Describe the bug
Kafka doesn't work with t.Parallel

Not only does it not work when I do t.Parallel in more tests, that set up and teardown docker. It also doesn't work if I use same preset in multiple packages (I need to use -p 1 in that case, which makes all test run on 1 core)

Other presets do work, so it's strange that this one doesn't

To Reproduce

package wut

import (
	"fmt"
	"os"
	"testing"

	"github.com/orlangure/gnomock"
	"github.com/orlangure/gnomock/preset/kafka"
	"github.com/stretchr/testify/require"
)

func TestXxx(t *testing.T) {
	t.Parallel()
	for i := 0; i < 10; i++ {
		t.Run(fmt.Sprintf("test %d", i), func(t *testing.T) {
			t.Parallel()

			p := kafka.Preset(
				kafka.WithTopics("topic-1", "topic-2"),
			)

			container, err := gnomock.Start(
				p,
				gnomock.WithDebugMode(), gnomock.WithLogWriter(os.Stdout),
			)
			require.NoError(t, err)

			defer func() { require.NoError(t, gnomock.Stop(container)) }()
		})
	}
}

This starts 10 tests, all start kafka, and then tear it down. All in parallel. Most of them will fail.

Expected behavior
Test will work.

System (please complete the following information):

  • OS: macOS
  • Version 14.4.1
  • Docker version
Client:
 Cloud integration: v1.0.35+desktop.13
 Version:           26.0.0
 API version:       1.45
 Go version:        go1.21.8
 Git commit:        2ae903e
 Built:             Wed Mar 20 15:14:46 2024
 OS/Arch:           darwin/arm64
 Context:           desktop-linux

Server: Docker Desktop 4.29.0 (145265)
 Engine:
  Version:          26.0.0
  API version:      1.45 (minimum version 1.24)
  Go version:       go1.21.8
  Git commit:       8b79278
  Built:            Wed Mar 20 15:18:02 2024
  OS/Arch:          linux/arm64
  Experimental:     false
 containerd:
  Version:          1.6.28
  GitCommit:        ae07eda36dd25f8a1b98dfbf587313b99c0190bb
 runc:
  Version:          1.1.12
  GitCommit:        v1.1.12-0-g51d5e94
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
@karelbilek
Copy link
Contributor Author

Ah, that's because the port is set explicitly in NamedPort; which is needed, because Kafka needs to have the same port outside as inside for some reason.

I have fixed it in a local fork by holding a global map with ports in kafka preset, which is changed at the time of running kafka.Preset(); so each kafka.Preset() has a different port; and also added a new function func (p *P) FreePort() which I call explicitly from test after closing the docker; it feels like a hacky solution, but only one that works for me.

I have a local fork because of other kafka issues (see other PRs) so it's fine for now for me

@karelbilek
Copy link
Contributor Author

The code:

var portMap *sync.Map = &sync.Map{}

func Preset(opts ...Option) gnomock.Preset {
	p := &P{}

	for _, opt := range opts {
		opt(p)
	}

	// this is a little dumb but it works...
	for i := brokerPortMin; i <= brokerPortMax; i++ {
		_, loaded := portMap.LoadOrStore(i, true)
		if !loaded {
			p.BrokerPort = i
			break
		}
	}
	if p.BrokerPort == 0 {
		panic("wrong broker port")
	}

	return p
}

func (p *P) FreePort() {
	portMap.Delete(p.BrokerPort)
}

FreePort needs to be run manually

karelbilek added a commit to karelbilek/gnomock that referenced this issue May 7, 2024
@orlangure
Copy link
Owner

Thanks for reporting this @karelbilek. Yes it's a limitation of the Kafka preset. I think your solution is nice, and if more people would like to run kafka presets in parallel, it would be great to have it merged. Closing this for now.

@karelbilek
Copy link
Contributor Author

karelbilek commented May 15, 2024

I was thinking how to do this in a nice, non-hacky way.

The only thing I thought about is to make a different Docker image than the one you use, which would start some small HTTP service (or some other way to pass data there - unix signal? files?), we would send the service the external port after the Docker is started (because we do know the port at that point), and only then would it start Kafka (it would set the env var and actually start the thing)

It would mean writing our own Docker for kafka, based on the existing one but with this additional delay. (Or, maybe it would be possible to use the one that is there and somehow in a hacky way start this HTTP server/bash script/something there.... will experiment later.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants