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

chore: expose SessionID #1793

Merged
merged 3 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions testcontainer.go
Original file line number Diff line number Diff line change
@@ -1 +1,28 @@
package testcontainers

import "github.com/testcontainers/testcontainers-go/internal/testcontainerssession"

// SessionID returns a unique session ID for the current test session. Because each Go package
// will be run in a separate process, we need a way to identify the current test session.
// By test session, we mean:
// - a single "go test" invocation (including flags)
// - a single "go test ./..." invocation (including flags)
// - the execution of a single test or a set of tests using the IDE
//
// As a consequence, with the sole goal of aggregating test execution across multiple
// packages, this variable will contain the value of the parent process ID (pid) of the current process
// and its creation date, to use it to generate a unique session ID. We are using the parent pid because
// the current process will be a child process of:
// - the process that is running the tests, e.g.: "go test";
// - the process that is running the application in development mode, e.g. "go run main.go -tags dev";
// - the process that is running the tests in the IDE, e.g.: "go test ./...".
//
// Finally, we will hash the combination of the "testcontainers-go:" string with the parent pid
// and the creation date of that parent process to generate a unique session ID.
//
// This sessionID will be used to:
// - identify the test session, aggregating the test execution of multiple packages in the same test session.
// - tag the containers created by testcontainers-go, adding a label to the container with the session ID.
func SessionID() string {
return testcontainerssession.SessionID()
}
85 changes: 85 additions & 0 deletions testcontainers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package testcontainers

import (
"fmt"
"os"
"os/exec"
"regexp"
"testing"
)

func TestSessionID(t *testing.T) {
t.Run("SessionID() returns a non-empty string", func(t *testing.T) {
sessionID := SessionID()
if sessionID == "" {
t.Error("SessionID() returned an empty string")
}
})

t.Run("Multiple calls to SessionID() return the same value", func(t *testing.T) {
sessionID1 := SessionID()
sessionID2 := SessionID()
if sessionID1 != sessionID2 {
t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2)
}
})

t.Run("Multiple calls to SessionID() in multiple goroutines return the same value", func(t *testing.T) {
sessionID1 := ""
sessionID2 := ""

done := make(chan bool)
go func() {
sessionID1 = SessionID()
done <- true
}()

go func() {
sessionID2 = SessionID()
done <- true
}()

<-done
<-done

if sessionID1 != sessionID2 {
t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2)
}
})

t.Run("SessionID() from different child processes returns the same value", func(t *testing.T) {
args := []string{"test", "./...", "-v", "-run", "TestSessionIDHelper"}
env := append(os.Environ(), "TESTCONTAINERS_SESSION_ID_HELPER=1")

re := regexp.MustCompile(">>>(.*)<<<")

cmd1 := exec.Command("go", args...)
cmd1.Env = env
stdoutStderr1, err := cmd1.CombinedOutput()
if err != nil {
t.Errorf("cmd1.Run() failed with %s", err)
}
sessionID1 := re.FindString(string(stdoutStderr1))

cmd2 := exec.Command("go", args...)
cmd2.Env = env
stdoutStderr2, err := cmd2.CombinedOutput()
if err != nil {
t.Errorf("cmd2.Run() failed with %s", err)
}
sessionID2 := re.FindString(string(stdoutStderr2))

if sessionID1 != sessionID2 {
t.Errorf("SessionID() returned different values: %s != %s", sessionID1, sessionID2)
}
})
}

// Not a real test, used to print out the session ID
func TestSessionIDHelper(t *testing.T) {
if os.Getenv("TESTCONTAINERS_SESSION_ID_HELPER") == "" {
t.Skip("Not a real test, used as a test helper")
}

fmt.Printf(">>>%s<<<\n", SessionID())
}