Skip to content

Commit

Permalink
Merge pull request #35 from treblereel/apache_issues_1647_tests
Browse files Browse the repository at this point in the history
tests
  • Loading branch information
treblereel authored Dec 5, 2024
2 parents 373d4fa + 648c487 commit fd5833f
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 8 deletions.
71 changes: 71 additions & 0 deletions packages/kn-plugin-workflow/e2e-tests/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package e2e_tests

import (
"bufio"
"bytes"
"fmt"
"io"
Expand All @@ -32,6 +33,7 @@ import (
"syscall"
"testing"

"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/command"
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/command/quarkus"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -63,6 +65,11 @@ func ExecuteKnWorkflowWithCmd(cmd *exec.Cmd, args ...string) (string, error) {
return executeCommandWithOutput(cmd, args...)
}

// ExecuteKnWorkflowWithCmdAndStopContainer executes the 'kn-workflow' CLI tool with the given arguments using the provided command and returns the containerID and possible error message.
func ExecuteKnWorkflowWithCmdAndStopContainer(cmd *exec.Cmd, args ...string) (string, error) {
return executeCommandWithOutputAndStopContainer(cmd, args...)
}

// ExecuteKnWorkflowQuarkusWithCmd executes the 'kn-workflow' CLI tool with 'quarkus' command with the given arguments using the provided command and returns the command's output and possible error message.
func ExecuteKnWorkflowQuarkusWithCmd(cmd *exec.Cmd, args ...string) (string, error) {
newArgs := append([]string{"quarkus"}, args...)
Expand All @@ -89,6 +96,70 @@ func executeCommandWithOutput(cmd *exec.Cmd, args ...string) (string, error) {
return stdout.String(), nil
}

func executeCommandWithOutputAndStopContainer(cmd *exec.Cmd, args ...string) (string, error) {
cmd.Args = append([]string{cmd.Path}, args...)

var containerId string
var stderr bytes.Buffer

stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
return "", fmt.Errorf("failed to create stdout pipe: %w", err)
}
defer stdoutPipe.Close()

stdinPipe, err := cmd.StdinPipe()
if err != nil {
return "", fmt.Errorf("failed to create stdin pipe: %w", err)
}
defer stdinPipe.Close()

cmd.Stderr = &stderr
errorCh := make(chan error, 1)

go func() {
defer close(errorCh)
scanner := bufio.NewScanner(stdoutPipe)
for scanner.Scan() {
line := scanner.Text()

if strings.HasPrefix(line, "Created container with ID ") {
id, ok := strings.CutPrefix(line, "Created container with ID ")
if !ok || id == "" {
errorCh <- fmt.Errorf("failed to parse container ID from output: %q", line)
return
}
containerId = id
}

if line == command.StopContainerMsg {
_, err := io.WriteString(stdinPipe, "any\n")
if err != nil {
errorCh <- fmt.Errorf("failed to write to stdin: %w", err)
return
}
}
}

if err := scanner.Err(); err != nil {
errorCh <- fmt.Errorf("error reading from stdout: %w", err)
return
}
}()

err = cmd.Run()
if err != nil {
return "", fmt.Errorf("command run error: %w (stderr: %s)", err, stderr.String())
}

readErr := <-errorCh
if readErr != nil {
return "", readErr
}

return containerId, nil
}

// VerifyFileContent verifies that the content of a file matches the expected content.
func VerifyFileContent(t *testing.T, filePath string, expected string) {
actual, err := os.ReadFile(filePath)
Expand Down
25 changes: 19 additions & 6 deletions packages/kn-plugin-workflow/e2e-tests/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (

"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/command"
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand All @@ -44,8 +45,8 @@ type cfgTestInputRun struct {
}

var cfgTestInputRun_Success = []cfgTestInputRun{
{input: command.RunCmdConfig{PortMapping: "8081", OpenDevUI: false, StopContainerOnUserInput: false}},
{input: command.RunCmdConfig{StopContainerOnUserInput: false}},
{input: command.RunCmdConfig{PortMapping: "8081", OpenDevUI: false}},
{input: command.RunCmdConfig{}},
}

func transformRunCmdCfgToArgs(cfg command.RunCmdConfig) []string {
Expand All @@ -56,9 +57,6 @@ func transformRunCmdCfgToArgs(cfg command.RunCmdConfig) []string {
if cfg.PortMapping != "" {
args = append(args, "--port", cfg.PortMapping)
}
if cfg.StopContainerOnUserInput {
args = append(args, "--stop-container-on-user-input=false")
}
return args
}

Expand All @@ -83,6 +81,7 @@ func TestRunCommand(t *testing.T) {

func RunRunTest(t *testing.T, cfgTestInputPrepareCreate CfgTestInputCreate, test cfgTestInputRun) string {
var err error
var containerId string

// Create the project
RunCreateTest(t, cfgTestInputPrepareCreate)
Expand All @@ -102,7 +101,8 @@ func RunRunTest(t *testing.T, cfgTestInputPrepareCreate CfgTestInputCreate, test
// Run the `run` command
go func() {
defer wg.Done()
_, err = ExecuteKnWorkflowWithCmd(cmd, transformRunCmdCfgToArgs(test.input)...)
containerId, err = ExecuteKnWorkflowWithCmdAndStopContainer(cmd, transformRunCmdCfgToArgs(test.input)...)
assert.NotNil(t, containerId, "Container ID is nil")
require.Truef(t, err == nil || IsSignalInterrupt(err), "Expected nil error or signal interrupt, got %v", err)
}()

Expand All @@ -123,5 +123,18 @@ func RunRunTest(t *testing.T, cfgTestInputPrepareCreate CfgTestInputCreate, test

wg.Wait()

stopped := make(chan bool)
t.Logf("Checking if container is stopped")
assert.NotNil(t, containerId, "Container ID is nil")
// Check if the container is stopped within a specified time limit.
go common.PollContainerStoppedCheck(containerId, pollInterval, stopped)
select {
case <-stopped:
fmt.Println("Project is stopped")
case <-time.After(timeout):
t.Fatalf("Test case timed out after %s. The project was not stopped within the specified time.", timeout)
cmd.Process.Signal(os.Interrupt)
}

return projectName
}
7 changes: 5 additions & 2 deletions packages/kn-plugin-workflow/pkg/command/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ type RunCmdConfig struct {
StopContainerOnUserInput bool
}

const StopContainerMsg = "Press any key to stop the container"


func NewRunCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "run",
Expand All @@ -64,7 +67,7 @@ func NewRunCommand() *cobra.Command {
`,
SuggestFor: []string{"rnu", "start"}, //nolint:misspell
PreRunE: common.BindEnv("port", "open-dev-ui"),
PreRunE: common.BindEnv("port", "open-dev-ui", "stop-container-on-user-input"),
}

cmd.RunE = func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -156,7 +159,7 @@ func runSWFProjectDevMode(containerTool string, cfg RunCmdConfig) (err error) {
}

func stopContainer(containerTool string) error {
fmt.Println("Press ENTER to stop the container")
fmt.Println(StopContainerMsg)

reader := bufio.NewReader(os.Stdin)

Expand Down
44 changes: 44 additions & 0 deletions packages/kn-plugin-workflow/pkg/common/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,47 @@ func processOutputDuringContainerExecution(cli *client.Client, ctx context.Conte

return nil
}


func PollContainerStoppedCheck(containerID string, interval time.Duration, ready chan<- bool) {
for {
running, err := IsContainerRunning(containerID)
if err != nil {
fmt.Printf("Error checking if container %s is running: %s", containerID, err)
ready <- false
return
}
if !running {
ready <- true
return
}
time.Sleep(interval)
}
}

func IsContainerRunning(containerID string) (bool, error) {
if errDocker := CheckDocker(); errDocker == nil {
cli, err := getDockerClient()
if err != nil {
return false, fmt.Errorf("unable to create docker client: %w", err)
}
containerJSON, err := cli.ContainerInspect(context.Background(), containerID)
if err != nil {
if client.IsErrNotFound(err) {
return false, nil
}
return false, fmt.Errorf("unable to inspect container %s with docker: %w", containerID, err)
}
return containerJSON.State.Running, nil

} else if errPodman := CheckPodman(); errPodman == nil {
cmd := exec.Command("podman", "inspect", containerID, "--format", "{{.State.Running}}")
output, err := cmd.Output()
if err != nil {
return false, fmt.Errorf("unable to inspect container %s with podman: %w", containerID, err)
}
return strings.TrimSpace(string(output)) == "true", nil
}

return false, fmt.Errorf("there is no docker or podman available")
}

0 comments on commit fd5833f

Please sign in to comment.