From c0cbd6d2ceab6008fd6bb581950734654bbb1d50 Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Tue, 18 Nov 2025 09:25:01 +0100 Subject: [PATCH 1/3] implement DooD for startApp test first part --- Taskfile.yml | 4 + internal/e2e/startapp/helper.go | 356 ++++++++++++++++++++++++++ internal/e2e/startapp/start_test.go | 76 ++++++ internal/e2e/startapp/test.Dockerfile | 25 ++ 4 files changed, 461 insertions(+) create mode 100644 internal/e2e/startapp/helper.go create mode 100644 internal/e2e/startapp/start_test.go create mode 100644 internal/e2e/startapp/test.Dockerfile diff --git a/Taskfile.yml b/Taskfile.yml index 8f2e49c0..a0effb5b 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -57,6 +57,10 @@ tasks: test:update: cmds: - go test --timeout 30m -v ./internal/e2e/updatetest + #todo se funziona rimuovere e integrare con il comando qui sopra! + test:start: + cmds: + - go test --timeout 10m -v ./internal/e2e/startapp test:pkg: desc: Run only tests in the pkg directory diff --git a/internal/e2e/startapp/helper.go b/internal/e2e/startapp/helper.go new file mode 100644 index 00000000..bfc8dbea --- /dev/null +++ b/internal/e2e/startapp/helper.go @@ -0,0 +1,356 @@ +package startapp + +import ( + "bufio" + "bytes" + "context" + "encoding/json" + "fmt" + "iter" + "log" + "net" + "net/http" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func fetchDebPackageLatest(t *testing.T, path, repo string) string { + t.Helper() + + repo = fmt.Sprintf("github.com/arduino/%s", repo) + cmd := exec.Command( + "gh", "release", "list", + "--repo", repo, + "--exclude-pre-releases", + "--limit", "1", + ) + + output, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("command failed: %v\nOutput: %s", err, output) + } + + fmt.Println(string(output)) + + fields := strings.Fields(string(output)) + if len(fields) == 0 { + log.Fatal("could not parse tag from gh release list output") + } + tag := fields[0] + + fmt.Println("Detected tag:", tag) + cmd2 := exec.Command( + "gh", "release", "download", + tag, + "--repo", repo, + "--pattern", "*.deb", + "--dir", path, + ) + + out, err := cmd2.CombinedOutput() + if err != nil { + log.Fatalf("download failed: %v\nOutput: %s", err, out) + } + + return tag + +} + +func buildDebVersion(t *testing.T, storePath, tagVersion, arch string) { + t.Helper() + cwd, err := os.Getwd() + if err != nil { + panic(err) + } + outputDir := filepath.Join(cwd, storePath) + + tagVersion = fmt.Sprintf("VERSION=%s", tagVersion) + arch = fmt.Sprintf("ARCH=%s", arch) + outputDir = fmt.Sprintf("OUTPUT=%s", outputDir) + + cmd := exec.Command( + "go", "tool", "task", "build-deb", + tagVersion, + arch, + outputDir, + ) + + if err := cmd.Run(); err != nil { + log.Fatalf("failed to run build command: %v", err) + } +} + +func genMajorTag(t *testing.T, tag string) string { + t.Helper() + + parts := strings.Split(tag, ".") + last := parts[len(parts)-1] + + lastNum, _ := strconv.Atoi(strings.TrimPrefix(last, "v")) + lastNum++ + + parts[len(parts)-1] = strconv.Itoa(lastNum) + newTag := strings.Join(parts, ".") + + return newTag +} + +func genMinorTag(t *testing.T, tag string) string { + t.Helper() + + parts := strings.Split(tag, ".") + last := parts[len(parts)-1] + + lastNum, _ := strconv.Atoi(strings.TrimPrefix(last, "v")) + if lastNum > 0 { + lastNum-- + } + + parts[len(parts)-1] = strconv.Itoa(lastNum) + newTag := strings.Join(parts, ".") + + if !strings.HasPrefix(newTag, "v") { + newTag = "v" + newTag + } + return newTag +} + +func buildDockerImage(t *testing.T, dockerfile, name, arch, dockerGid string) { + t.Helper() + + archArg := fmt.Sprintf("ARCH=%s", arch) + gidArg := fmt.Sprintf("DOCKER_GID=%s", dockerGid) + + cmd := exec.Command("docker", "build", + "--build-arg", archArg, + "--build-arg", gidArg, + "-t", name, "-f", dockerfile, ".") + // Capture both stdout and stderr + var out bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + fmt.Printf("❌ Docker build failed: %v\n", err) + fmt.Printf("---- STDERR ----\n%s\n", stderr.String()) + fmt.Printf("---- STDOUT ----\n%s\n", out.String()) + return + } + + fmt.Println("✅ Docker build succeeded!") +} + +func startDockerContainer(t *testing.T, containerName string, containerImageName string) { + t.Helper() + + cmd := exec.Command( + "docker", "run", "--rm", "-d", + "-p", "8800:8800", + "--privileged", + "--cgroupns=host", + //"--network", "host", + "-v", "/sys/fs/cgroup:/sys/fs/cgroup:rw", + "-v", "/var/run/docker.sock:/var/run/docker.sock", + "-e", "DOCKER_HOST=unix:///var/run/docker.sock", + "--name", containerName, + containerImageName, + ) + + if err := cmd.Run(); err != nil { + t.Fatalf("failed to run container: %v", err) + } + +} + +func getAppCliVersion(t *testing.T, containerName string) string { + t.Helper() + + cmd := exec.Command( + "docker", "exec", + "--user", "arduino", + containerName, + "arduino-app-cli", "version", "--format", "json", + ) + output, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("command failed: %v\nOutput: %s", err, output) + } + + var version struct { + Version string `json:"version"` + DaemonVersion string `json:"daemon_version"` + } + err = json.Unmarshal(output, &version) + require.NoError(t, err) + // TODO to enable after 0.6.7 + // require.Equal(t, version.Version, version.DaemonVersion, "client and daemon versions should match") + require.NotEmpty(t, version.Version) + return version.Version + +} + +func runSystemUpdate(t *testing.T, containerName string) { + t.Helper() + + cmd := exec.Command( + "docker", "exec", + "--user", "arduino", + containerName, + "arduino-app-cli", "system", "update", "--yes", + ) + output, err := cmd.CombinedOutput() + require.NoError(t, err, "system update failed: %s", output) + t.Logf("system update output: %s", output) +} + +func stopDockerContainer(t *testing.T, containerName string) { + t.Helper() + + cleanupCmd := exec.Command("docker", "rm", "-f", containerName) + + fmt.Println("🧹 Removing Docker container " + containerName) + if err := cleanupCmd.Run(); err != nil { + fmt.Printf("⚠️ Warning: could not remove container (might not exist): %v\n", err) + } + +} + +func putUpdateRequest(t *testing.T, host string) { + + t.Helper() + + url := fmt.Sprintf("http://%s/v1/system/update/apply", host) + + req, err := http.NewRequest(http.MethodPut, url, nil) + if err != nil { + log.Fatalf("Error creating request: %v", err) + } + + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + log.Fatalf("Error sending request: %v", err) + } + defer resp.Body.Close() + + require.Equal(t, 202, resp.StatusCode) + +} + +func NewSSEClient(ctx context.Context, method, url string) iter.Seq2[Event, error] { + return func(yield func(Event, error) bool) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + _ = yield(Event{}, err) + return + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + _ = yield(Event{}, err) + return + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + _ = yield(Event{}, fmt.Errorf("got response status code %d", resp.StatusCode)) + return + } + + reader := bufio.NewReader(resp.Body) + + evt := Event{} + for { + line, err := reader.ReadString('\n') + if err != nil { + _ = yield(Event{}, err) + return + } + switch { + case strings.HasPrefix(line, "data:"): + evt.Data = []byte(strings.TrimSpace(strings.TrimPrefix(line, "data:"))) + case strings.HasPrefix(line, "event:"): + evt.Event = strings.TrimSpace(strings.TrimPrefix(line, "event:")) + case strings.HasPrefix(line, "id:"): + evt.ID = strings.TrimSpace(strings.TrimPrefix(line, "id:")) + case strings.HasPrefix(line, "\n"): + if !yield(evt, nil) { + return + } + evt = Event{} + default: + _ = yield(Event{}, fmt.Errorf("unknown line: '%s'", line)) + return + } + } + } +} + +type Event struct { + ID string + Event string + Data []byte // json +} + +func waitForPort(t *testing.T, host string, timeout time.Duration) { // nolint:unparam + t.Helper() + deadline := time.Now().Add(timeout) + for time.Now().Before(deadline) { + conn, err := net.DialTimeout("tcp", host, 500*time.Millisecond) + if err == nil { + _ = conn.Close() + t.Logf("Server is up on %s", host) + return + } + time.Sleep(200 * time.Millisecond) + } + t.Fatalf("Server at %s did not start within %v", host, timeout) +} + +func runAppStart(t *testing.T, containerName, appName string) { + t.Helper() + appCommand := fmt.Sprintf("arduino-app-cli app start %s", appName) + + cmd := exec.Command( + "docker", "exec", + containerName, + "su", "-", "arduino", + "-c", appCommand, + ) + + output, err := cmd.CombinedOutput() + require.NoError(t, err, "start command filed: %s", output) + t.Logf("Output comando 'start': %s", output) +} + +func checkContainerRunningOnHost(t *testing.T, appContainerName string) bool { + t.Helper() + cmd := exec.Command( + "docker", "ps", + "--filter", "name=^/"+appContainerName+"$", + "--format", "{{.Names}}", + ) + + var stdout bytes.Buffer + cmd.Stdout = &stdout + + err := cmd.Run() + require.NoError(t, err, "fallito controllo 'docker ps' sull'host") + + return strings.TrimSpace(stdout.String()) == appContainerName +} +func stopAppContainer(t *testing.T, appContainerName string) { + t.Helper() + stopDockerContainer(t, appContainerName) +} diff --git a/internal/e2e/startapp/start_test.go b/internal/e2e/startapp/start_test.go new file mode 100644 index 00000000..646eb7be --- /dev/null +++ b/internal/e2e/startapp/start_test.go @@ -0,0 +1,76 @@ +package startapp + +import ( + "fmt" + "os" + "os/exec" + "runtime" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +var arch = runtime.GOARCH + +const ( + dockerFile = "test.Dockerfile" + daemonHost = "127.0.0.1:8800" + versionToTest = "v1.0.0" +) + +func TestStartApp(t *testing.T) { + fmt.Printf("***** ARCH %s ***** \n", arch) + + t.Cleanup(func() { os.RemoveAll("build") }) + + fmt.Printf("Building local deb version %s \n", versionToTest) + buildDebVersion(t, "build", versionToTest, arch) + + fmt.Println("Fetching 'arduino-router' dependency...") + fetchDebPackageLatest(t, "build", "arduino-router") + + cmd := exec.Command("stat", "-c", "%g", "/var/run/docker.sock") + outputBytes, err := cmd.Output() + require.NoError(t, err, "could not get docker socket GID: %v", err) + + dockerGid := strings.TrimSpace(string(outputBytes)) + fmt.Printf("**** Using Docker GID from Host: %s *****\n", dockerGid) + + const dockerImageName = "e2e-start-test-image" + fmt.Println("**** BUILD docker image (e2e-test-runner) *****") + buildDockerImage(t, dockerFile, dockerImageName, arch, dockerGid) + // TODO: aggiungere t.Cleanup per rimuovere l'immagine docker. da controllare se mi serve! + + t.Run("Test App Start Command", func(t *testing.T) { + + const containerA_Name = "e2e-test-runner" + const containerB_AppName = "examples:object-detection" + + //todo devo creare un app senza sketch, ma con qualche brick magari! oppure usare un esempio? + + t.Cleanup(func() { + stopDockerContainer(t, containerA_Name) + stopAppContainer(t, containerB_AppName) + }) + + fmt.Println("**** RUN docker image (board container) *****") + startDockerContainer(t, containerA_Name, dockerImageName) + + waitForPort(t, daemonHost, 20*time.Second) + + fmt.Printf("**** Telling e2e-test-runner to start app '%s' *****\n", containerB_AppName) + runAppStart(t, containerA_Name, containerB_AppName) + + fmt.Printf("**** Verifying on HOST if '%s' (Container B) is running *****\n", containerB_AppName) + + time.Sleep(1 * time.Second) + + isRunning := checkContainerRunningOnHost(t, containerB_AppName) + + require.True(t, isRunning, "Il container B (%s) not foud", containerB_AppName) + + fmt.Printf("Success: e2e-test-runner successfully launched Container B (%s) on host.\n", containerB_AppName) + }) +} diff --git a/internal/e2e/startapp/test.Dockerfile b/internal/e2e/startapp/test.Dockerfile new file mode 100644 index 00000000..6341ad24 --- /dev/null +++ b/internal/e2e/startapp/test.Dockerfile @@ -0,0 +1,25 @@ +FROM debian:trixie + +RUN apt update && \ + apt install -y systemd systemd-sysv dbus \ + sudo docker.io ca-certificates curl gnupg \ + dpkg-dev apt-utils adduser gzip && \ + rm -rf /var/lib/apt/lists/* + +ARG ARCH=amd64 + +COPY build/arduino-app-cli*_${ARCH}.deb /tmp/app.deb +COPY build/arduino-router*_${ARCH}.deb /tmp/router.deb + +RUN apt update && apt install -y /tmp/router.deb /tmp/app.deb \ + && rm /tmp/app.deb /tmp/router.deb + +RUN sed -i 's/--port 8800/--port 8800 --address 0.0.0.0/' /etc/systemd/system/arduino-app-cli.service + +RUN usermod -s /bin/bash arduino || true +RUN mkdir -p /home/arduino && chown -R arduino:arduino /home/arduino +RUN usermod -aG docker arduino + +EXPOSE 8800 + +CMD ["/sbin/init"] \ No newline at end of file From bd4fbe8ff0780acfbbe71d396e5baa7193605215 Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Tue, 18 Nov 2025 16:42:47 +0100 Subject: [PATCH 2/3] start app test dood part two --- internal/e2e/startapp/helper.go | 123 +++------------------------- internal/e2e/startapp/start_test.go | 11 +-- 2 files changed, 12 insertions(+), 122 deletions(-) diff --git a/internal/e2e/startapp/helper.go b/internal/e2e/startapp/helper.go index bfc8dbea..5f0685dd 100644 --- a/internal/e2e/startapp/helper.go +++ b/internal/e2e/startapp/helper.go @@ -4,7 +4,6 @@ import ( "bufio" "bytes" "context" - "encoding/json" "fmt" "iter" "log" @@ -13,7 +12,6 @@ import ( "os" "os/exec" "path/filepath" - "strconv" "strings" "testing" "time" @@ -87,50 +85,13 @@ func buildDebVersion(t *testing.T, storePath, tagVersion, arch string) { } } -func genMajorTag(t *testing.T, tag string) string { - t.Helper() - - parts := strings.Split(tag, ".") - last := parts[len(parts)-1] - - lastNum, _ := strconv.Atoi(strings.TrimPrefix(last, "v")) - lastNum++ - - parts[len(parts)-1] = strconv.Itoa(lastNum) - newTag := strings.Join(parts, ".") - - return newTag -} - -func genMinorTag(t *testing.T, tag string) string { - t.Helper() - - parts := strings.Split(tag, ".") - last := parts[len(parts)-1] - - lastNum, _ := strconv.Atoi(strings.TrimPrefix(last, "v")) - if lastNum > 0 { - lastNum-- - } - - parts[len(parts)-1] = strconv.Itoa(lastNum) - newTag := strings.Join(parts, ".") - - if !strings.HasPrefix(newTag, "v") { - newTag = "v" + newTag - } - return newTag -} - -func buildDockerImage(t *testing.T, dockerfile, name, arch, dockerGid string) { +func buildDockerImage(t *testing.T, dockerfile, name, arch string) { t.Helper() archArg := fmt.Sprintf("ARCH=%s", arch) - gidArg := fmt.Sprintf("DOCKER_GID=%s", dockerGid) cmd := exec.Command("docker", "build", "--build-arg", archArg, - "--build-arg", gidArg, "-t", name, "-f", dockerfile, ".") // Capture both stdout and stderr var out bytes.Buffer @@ -157,10 +118,9 @@ func startDockerContainer(t *testing.T, containerName string, containerImageName "-p", "8800:8800", "--privileged", "--cgroupns=host", - //"--network", "host", "-v", "/sys/fs/cgroup:/sys/fs/cgroup:rw", - "-v", "/var/run/docker.sock:/var/run/docker.sock", - "-e", "DOCKER_HOST=unix:///var/run/docker.sock", + "-v", "/var/run/docker.sock:/host/docker.sock", + "-e", "DOCKER_HOST=unix:///host/docker.sock", "--name", containerName, containerImageName, ) @@ -171,47 +131,6 @@ func startDockerContainer(t *testing.T, containerName string, containerImageName } -func getAppCliVersion(t *testing.T, containerName string) string { - t.Helper() - - cmd := exec.Command( - "docker", "exec", - "--user", "arduino", - containerName, - "arduino-app-cli", "version", "--format", "json", - ) - output, err := cmd.CombinedOutput() - if err != nil { - log.Fatalf("command failed: %v\nOutput: %s", err, output) - } - - var version struct { - Version string `json:"version"` - DaemonVersion string `json:"daemon_version"` - } - err = json.Unmarshal(output, &version) - require.NoError(t, err) - // TODO to enable after 0.6.7 - // require.Equal(t, version.Version, version.DaemonVersion, "client and daemon versions should match") - require.NotEmpty(t, version.Version) - return version.Version - -} - -func runSystemUpdate(t *testing.T, containerName string) { - t.Helper() - - cmd := exec.Command( - "docker", "exec", - "--user", "arduino", - containerName, - "arduino-app-cli", "system", "update", "--yes", - ) - output, err := cmd.CombinedOutput() - require.NoError(t, err, "system update failed: %s", output) - t.Logf("system update output: %s", output) -} - func stopDockerContainer(t *testing.T, containerName string) { t.Helper() @@ -224,30 +143,6 @@ func stopDockerContainer(t *testing.T, containerName string) { } -func putUpdateRequest(t *testing.T, host string) { - - t.Helper() - - url := fmt.Sprintf("http://%s/v1/system/update/apply", host) - - req, err := http.NewRequest(http.MethodPut, url, nil) - if err != nil { - log.Fatalf("Error creating request: %v", err) - } - - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - log.Fatalf("Error sending request: %v", err) - } - defer resp.Body.Close() - - require.Equal(t, 202, resp.StatusCode) - -} - func NewSSEClient(ctx context.Context, method, url string) iter.Seq2[Event, error] { return func(yield func(Event, error) bool) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) @@ -320,17 +215,21 @@ func waitForPort(t *testing.T, host string, timeout time.Duration) { // nolint:u func runAppStart(t *testing.T, containerName, appName string) { t.Helper() - appCommand := fmt.Sprintf("arduino-app-cli app start %s", appName) + fixCmd := exec.Command("docker", "exec", containerName, + "chmod", "666", "/host/docker.sock") + + outputFix, errFix := fixCmd.CombinedOutput() + require.NoError(t, errFix, "Failed to chmod docker socket: %s", outputFix) + appCommand := fmt.Sprintf("/usr/bin/arduino-app-cli app start %s", appName) cmd := exec.Command( "docker", "exec", containerName, - "su", "-", "arduino", - "-c", appCommand, + "su", "arduino", "-c", appCommand, ) output, err := cmd.CombinedOutput() - require.NoError(t, err, "start command filed: %s", output) + require.NoError(t, err, "Start command failed: %s", output) t.Logf("Output comando 'start': %s", output) } diff --git a/internal/e2e/startapp/start_test.go b/internal/e2e/startapp/start_test.go index 646eb7be..b2f51622 100644 --- a/internal/e2e/startapp/start_test.go +++ b/internal/e2e/startapp/start_test.go @@ -3,9 +3,7 @@ package startapp import ( "fmt" "os" - "os/exec" "runtime" - "strings" "testing" "time" @@ -31,16 +29,9 @@ func TestStartApp(t *testing.T) { fmt.Println("Fetching 'arduino-router' dependency...") fetchDebPackageLatest(t, "build", "arduino-router") - cmd := exec.Command("stat", "-c", "%g", "/var/run/docker.sock") - outputBytes, err := cmd.Output() - require.NoError(t, err, "could not get docker socket GID: %v", err) - - dockerGid := strings.TrimSpace(string(outputBytes)) - fmt.Printf("**** Using Docker GID from Host: %s *****\n", dockerGid) - const dockerImageName = "e2e-start-test-image" fmt.Println("**** BUILD docker image (e2e-test-runner) *****") - buildDockerImage(t, dockerFile, dockerImageName, arch, dockerGid) + buildDockerImage(t, dockerFile, dockerImageName, arch) // TODO: aggiungere t.Cleanup per rimuovere l'immagine docker. da controllare se mi serve! t.Run("Test App Start Command", func(t *testing.T) { From 6ffbe45a14568ba72b203c7f1dd74cf7e747679b Mon Sep 17 00:00:00 2001 From: mirkoCrobu Date: Wed, 19 Nov 2025 13:35:53 +0100 Subject: [PATCH 3/3] dood test e2e start app 3 part --- internal/e2e/startapp/create-mock-devices.sh | 16 +++++++++++++ internal/e2e/startapp/helper.go | 24 ++++++++++++++++++++ internal/e2e/startapp/start_test.go | 24 ++++++++++---------- internal/e2e/startapp/test.Dockerfile | 16 +++++++++---- 4 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 internal/e2e/startapp/create-mock-devices.sh diff --git a/internal/e2e/startapp/create-mock-devices.sh b/internal/e2e/startapp/create-mock-devices.sh new file mode 100644 index 00000000..7035d550 --- /dev/null +++ b/internal/e2e/startapp/create-mock-devices.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +# Mock GPU path +mkdir -p /dev/dri || true +if [ ! -e /dev/dri/renderD128 ]; then + mknod /dev/dri/renderD128 c 226 128 || true +fi + +# Mock camera +if [ ! -e /dev/video0 ]; then + mknod /dev/video0 c 81 0 || true +fi + +# Continue with the actual CMD +exec "$@" diff --git a/internal/e2e/startapp/helper.go b/internal/e2e/startapp/helper.go index 5f0685dd..ba0cdc89 100644 --- a/internal/e2e/startapp/helper.go +++ b/internal/e2e/startapp/helper.go @@ -5,6 +5,7 @@ import ( "bytes" "context" "fmt" + "io" "iter" "log" "net" @@ -118,6 +119,7 @@ func startDockerContainer(t *testing.T, containerName string, containerImageName "-p", "8800:8800", "--privileged", "--cgroupns=host", + "--network", "host", "-v", "/sys/fs/cgroup:/sys/fs/cgroup:rw", "-v", "/var/run/docker.sock:/host/docker.sock", "-e", "DOCKER_HOST=unix:///host/docker.sock", @@ -253,3 +255,25 @@ func stopAppContainer(t *testing.T, appContainerName string) { t.Helper() stopDockerContainer(t, appContainerName) } + +func postCreateApp(t *testing.T, host string) { + t.Helper() + + url := fmt.Sprintf("http://%s/v1/apps?skip-python=false&skip-sketch=true", host) + + payload := `{"name": "HelloWorld","description": "My HelloWorld description","icon": ""}` + req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(payload)) + require.NoError(t, err) + + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{Timeout: 5 * time.Second} + resp, err := client.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, 200, resp.StatusCode) + + body, _ := io.ReadAll(resp.Body) + t.Logf("Response body: %s", body) +} diff --git a/internal/e2e/startapp/start_test.go b/internal/e2e/startapp/start_test.go index b2f51622..a22e571f 100644 --- a/internal/e2e/startapp/start_test.go +++ b/internal/e2e/startapp/start_test.go @@ -32,18 +32,15 @@ func TestStartApp(t *testing.T) { const dockerImageName = "e2e-start-test-image" fmt.Println("**** BUILD docker image (e2e-test-runner) *****") buildDockerImage(t, dockerFile, dockerImageName, arch) - // TODO: aggiungere t.Cleanup per rimuovere l'immagine docker. da controllare se mi serve! t.Run("Test App Start Command", func(t *testing.T) { const containerA_Name = "e2e-test-runner" - const containerB_AppName = "examples:object-detection" - - //todo devo creare un app senza sketch, ma con qualche brick magari! oppure usare un esempio? + const appToStart = "user:helloworld" t.Cleanup(func() { - stopDockerContainer(t, containerA_Name) - stopAppContainer(t, containerB_AppName) + //stopDockerContainer(t, containerA_Name) + //stopAppContainer(t, appToStart) }) fmt.Println("**** RUN docker image (board container) *****") @@ -51,17 +48,20 @@ func TestStartApp(t *testing.T) { waitForPort(t, daemonHost, 20*time.Second) - fmt.Printf("**** Telling e2e-test-runner to start app '%s' *****\n", containerB_AppName) - runAppStart(t, containerA_Name, containerB_AppName) + fmt.Println("**** Creating user app 'user:helloworld' *****") + postCreateApp(t, daemonHost) + + fmt.Printf("**** Telling e2e-test-runner to start app '%s' *****\n", appToStart) + runAppStart(t, containerA_Name, appToStart) - fmt.Printf("**** Verifying on HOST if '%s' (Container B) is running *****\n", containerB_AppName) + fmt.Printf("**** Verifying on HOST if '%s' ( app to start) is running *****\n", appToStart) time.Sleep(1 * time.Second) - isRunning := checkContainerRunningOnHost(t, containerB_AppName) + isRunning := checkContainerRunningOnHost(t, appToStart) - require.True(t, isRunning, "Il container B (%s) not foud", containerB_AppName) + require.True(t, isRunning, "Il container B (%s) not foud", appToStart) - fmt.Printf("Success: e2e-test-runner successfully launched Container B (%s) on host.\n", containerB_AppName) + fmt.Printf("Success: e2e-test-runner successfully launched app to start (%s) on host.\n", appToStart) }) } diff --git a/internal/e2e/startapp/test.Dockerfile b/internal/e2e/startapp/test.Dockerfile index 6341ad24..690a1a30 100644 --- a/internal/e2e/startapp/test.Dockerfile +++ b/internal/e2e/startapp/test.Dockerfile @@ -1,9 +1,11 @@ FROM debian:trixie +# Install packages first RUN apt update && \ apt install -y systemd systemd-sysv dbus \ - sudo docker.io ca-certificates curl gnupg \ - dpkg-dev apt-utils adduser gzip && \ + sudo docker.io docker-compose \ + ca-certificates curl gnupg \ + dpkg-dev apt-utils adduser gzip && \ rm -rf /var/lib/apt/lists/* ARG ARCH=amd64 @@ -14,12 +16,16 @@ COPY build/arduino-router*_${ARCH}.deb /tmp/router.deb RUN apt update && apt install -y /tmp/router.deb /tmp/app.deb \ && rm /tmp/app.deb /tmp/router.deb -RUN sed -i 's/--port 8800/--port 8800 --address 0.0.0.0/' /etc/systemd/system/arduino-app-cli.service - RUN usermod -s /bin/bash arduino || true RUN mkdir -p /home/arduino && chown -R arduino:arduino /home/arduino RUN usermod -aG docker arduino +# Copy + enable mock devices script +COPY create-mock-devices.sh /usr/local/bin/create-mock-devices.sh +RUN chmod +x /usr/local/bin/create-mock-devices.sh + EXPOSE 8800 -CMD ["/sbin/init"] \ No newline at end of file +# ENTRYPOINT must remain last +ENTRYPOINT ["/usr/local/bin/create-mock-devices.sh"] +CMD ["/sbin/init"]