test(integration): extract test setup logic
This commit is contained in:
parent
7edb975b8e
commit
cddcb0eb4d
@ -29,9 +29,6 @@ func TestIntegration(t *testing.T) {
|
|||||||
ctx, cancel := context.WithTimeout(t.Context(), 10*time.Minute)
|
ctx, cancel := context.WithTimeout(t.Context(), 10*time.Minute)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
configService, err := config.NewDefaultService()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
destServer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
destServer, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||||
ContainerRequest: testcontainers.ContainerRequest{
|
ContainerRequest: testcontainers.ContainerRequest{
|
||||||
Image: "bluenviron/mediamtx:latest",
|
Image: "bluenviron/mediamtx:latest",
|
||||||
@ -51,60 +48,7 @@ func TestIntegration(t *testing.T) {
|
|||||||
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv)
|
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Fetching the screen contents is tricky at this level of the test pyramid,
|
screen, screenCaptureC, getContents := setupSimulationScreen(t)
|
||||||
// because we need to:
|
|
||||||
//
|
|
||||||
// 1. Somehow capture the screen contents, which is only available via the
|
|
||||||
// tcell.SimulationScreen, and...
|
|
||||||
// 2. Do so without triggering data races.
|
|
||||||
//
|
|
||||||
// We can achieve this by passing a channel into the terminal actor, which
|
|
||||||
// will send screen captures after each render. This can be stored locally
|
|
||||||
// and asserted against when needed.
|
|
||||||
var (
|
|
||||||
screenCells []tcell.SimCell
|
|
||||||
screenWidth int
|
|
||||||
screenMu sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
getContents := func() []string {
|
|
||||||
screenMu.Lock()
|
|
||||||
defer screenMu.Unlock()
|
|
||||||
|
|
||||||
var lines []string
|
|
||||||
for n, _ := range screenCells {
|
|
||||||
y := n / screenWidth
|
|
||||||
|
|
||||||
if y > len(lines)-1 {
|
|
||||||
lines = append(lines, "")
|
|
||||||
}
|
|
||||||
lines[y] += string(screenCells[n].Runes[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if t.Failed() {
|
|
||||||
printScreen(getContents, "After failing")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
screen := tcell.NewSimulationScreen("")
|
|
||||||
screenCaptureC := make(chan terminal.ScreenCapture, 1)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case capture := <-screenCaptureC:
|
|
||||||
screenMu.Lock()
|
|
||||||
screenCells = capture.Cells
|
|
||||||
screenWidth = capture.Width
|
|
||||||
screenMu.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/60740997/62871
|
// https://stackoverflow.com/a/60740997/62871
|
||||||
if runtime.GOOS != "linux" {
|
if runtime.GOOS != "linux" {
|
||||||
@ -114,18 +58,11 @@ func TestIntegration(t *testing.T) {
|
|||||||
|
|
||||||
destURL1 := fmt.Sprintf("rtmp://%s:%d/live/dest1", destHost, destServerPort.Int())
|
destURL1 := fmt.Sprintf("rtmp://%s:%d/live/dest1", destHost, destServerPort.Int())
|
||||||
destURL2 := fmt.Sprintf("rtmp://%s:%d/live/dest2", destHost, destServerPort.Int())
|
destURL2 := fmt.Sprintf("rtmp://%s:%d/live/dest2", destHost, destServerPort.Int())
|
||||||
cfg := config.Config{
|
configService := setupConfigService(t, config.Config{
|
||||||
Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true, StreamKey: "live"}},
|
Sources: config.Sources{RTMP: config.RTMPSource{Enabled: true, StreamKey: "live"}},
|
||||||
// Load one destination from config, add the other in-app.
|
// Load one destination from config, add the other in-app.
|
||||||
Destinations: []config.Destination{{Name: "Local server 1", URL: destURL1}},
|
Destinations: []config.Destination{{Name: "Local server 1", URL: destURL1}},
|
||||||
}
|
})
|
||||||
|
|
||||||
tmpDir, err := os.MkdirTemp("", "octoplex-app-test-integration")
|
|
||||||
require.NoError(t, err)
|
|
||||||
t.Cleanup(func() { os.RemoveAll(tmpDir) })
|
|
||||||
configService, err = config.NewService(func() (string, error) { return tmpDir, nil }, 1)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NoError(t, configService.SetConfig(cfg))
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
@ -147,7 +84,6 @@ func TestIntegration(t *testing.T) {
|
|||||||
done <- struct{}{}
|
done <- struct{}{}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
require.EventuallyWithT(
|
require.EventuallyWithT(
|
||||||
t,
|
t,
|
||||||
func(t *assert.CollectT) {
|
func(t *assert.CollectT) {
|
||||||
@ -304,6 +240,76 @@ func TestIntegration(t *testing.T) {
|
|||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupSimulationScreen(t *testing.T) (tcell.SimulationScreen, chan<- terminal.ScreenCapture, func() []string) {
|
||||||
|
// Fetching the screen contents is tricky at this level of the test pyramid,
|
||||||
|
// because we need to:
|
||||||
|
//
|
||||||
|
// 1. Somehow capture the screen contents, which is only available via the
|
||||||
|
// tcell.SimulationScreen, and...
|
||||||
|
// 2. Do so without triggering data races.
|
||||||
|
//
|
||||||
|
// We can achieve this by passing a channel into the terminal actor, which
|
||||||
|
// will send screen captures after each render. This can be stored locally
|
||||||
|
// and asserted against when needed.
|
||||||
|
var (
|
||||||
|
screenCells []tcell.SimCell
|
||||||
|
screenWidth int
|
||||||
|
screenMu sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
getContents := func() []string {
|
||||||
|
screenMu.Lock()
|
||||||
|
defer screenMu.Unlock()
|
||||||
|
|
||||||
|
var lines []string
|
||||||
|
for n, _ := range screenCells {
|
||||||
|
y := n / screenWidth
|
||||||
|
|
||||||
|
if y > len(lines)-1 {
|
||||||
|
lines = append(lines, "")
|
||||||
|
}
|
||||||
|
lines[y] += string(screenCells[n].Runes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
if t.Failed() {
|
||||||
|
printScreen(getContents, "After failing")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
screen := tcell.NewSimulationScreen("")
|
||||||
|
screenCaptureC := make(chan terminal.ScreenCapture, 1)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.Context().Done():
|
||||||
|
return
|
||||||
|
case capture := <-screenCaptureC:
|
||||||
|
screenMu.Lock()
|
||||||
|
screenCells = capture.Cells
|
||||||
|
screenWidth = capture.Width
|
||||||
|
screenMu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return screen, screenCaptureC, getContents
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupConfigService(t *testing.T, cfg config.Config) *config.Service {
|
||||||
|
tmpDir, err := os.MkdirTemp("", "octoplex_"+t.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Cleanup(func() { os.RemoveAll(tmpDir) })
|
||||||
|
configService, err := config.NewService(func() (string, error) { return tmpDir, nil }, 1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, configService.SetConfig(cfg))
|
||||||
|
|
||||||
|
return configService
|
||||||
|
}
|
||||||
|
|
||||||
func printScreen(getContents func() []string, label string) {
|
func printScreen(getContents func() []string, label string) {
|
||||||
fmt.Println(label + ":")
|
fmt.Println(label + ":")
|
||||||
for _, line := range getContents() {
|
for _, line := range getContents() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user