From 78b0ade526775553a0d155c2f86d24c584359bb1 Mon Sep 17 00:00:00 2001
From: Victor Yves Crispim <rotcivyves@hotmail.com>
Date: Wed, 15 Nov 2023 16:18:03 -0300
Subject: [PATCH] test: remove Rust binary dependency

So far, tests of the Service struct assumed that the "cartesi-rollups-graphql-server" binary had been built already and then used it internally. This commit creates a "fake-service" binary for this purpose, eliminating the dependency.

Also adds new tests for Service.
---
 .gitignore                        |   7 +-
 internal/services/service.go      |   4 +-
 internal/services/service_test.go | 124 +++++++++++++++++++++++++-----
 test/fakeservice/main.go          |  10 +++
 4 files changed, 120 insertions(+), 25 deletions(-)
 create mode 100644 test/fakeservice/main.go

diff --git a/.gitignore b/.gitignore
index f22a3ae7c..cc73ca4cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
-.vscode
-.env
+**/.idea/
 .DS_Store
+.env
+.vscode
 build/deployments
-**/.idea/
+build/fake-service
diff --git a/internal/services/service.go b/internal/services/service.go
index a57148f28..8bc873d07 100644
--- a/internal/services/service.go
+++ b/internal/services/service.go
@@ -46,8 +46,8 @@ func (s Service) Start(ctx context.Context) error {
 		<-ctx.Done()
 		logger.Debug.Printf("%v: %v\n", s.String(), ctx.Err())
 		if err := cmd.Process.Signal(syscall.SIGTERM); err != nil {
-			msg := "%v: failed to send SIGTERM to %v\n"
-			logger.Error.Printf(msg, s.String(), s.name)
+			msg := "failed to send SIGTERM to %v: %v"
+			logger.Warning.Printf(msg, s.name, err)
 		}
 	}()
 
diff --git a/internal/services/service_test.go b/internal/services/service_test.go
index 8ef7a9fa5..06220e071 100644
--- a/internal/services/service_test.go
+++ b/internal/services/service_test.go
@@ -5,10 +5,10 @@ package services
 
 import (
 	"context"
+	"fmt"
 	"os"
 	"os/exec"
 	"path/filepath"
-	"syscall"
 	"testing"
 	"time"
 
@@ -16,45 +16,129 @@ import (
 )
 
 func setup() {
-	logger.Init("warning", false)
-	setRustBinariesPath()
+	logger.Init("debug", false)
+	buildFakeService()
 }
 
 func TestService(t *testing.T) {
+	setup()
 
 	t.Run("it stops when the context is cancelled", func(t *testing.T) {
-		setup()
 		service := Service{
-			name:       "graphql-server",
-			binaryName: "cartesi-rollups-graphql-server",
+			name:       "fake-service",
+			binaryName: "fake-service",
 		}
 		ctx, cancel := context.WithCancel(context.Background())
-		exit := make(chan error)
+		defer cancel()
 
+		startErr := make(chan error)
+		success := make(chan struct{})
 		go func() {
 			if err := service.Start(ctx); err != nil {
-				exit <- err
+				startErr <- err
 			}
+			success <- struct{}{}
 		}()
 
 		<-time.After(100 * time.Millisecond)
 		cancel()
 
-		err := <-exit
-		exitError, ok := err.(*exec.ExitError)
-		if !ok || !assertExitErrorWasCausedBy(exitError, syscall.SIGTERM) {
-			t.Logf("service exited for the wrong reason: %v", err)
-			t.FailNow()
+		select {
+		case err := <-startErr:
+			t.Errorf("service exited for the wrong reason: %v", err)
+		case <-success:
+			return
+		}
+	})
+
+	t.Run("it stops when timeout is reached and it isn't ready yet", func(t *testing.T) {
+		service := Service{
+			name:            "fake-service",
+			binaryName:      "fake-service",
+			healthcheckPort: "0000", //wrong port
+		}
+		ctx, cancel := context.WithCancel(context.Background())
+		defer cancel()
+
+		startErr := make(chan error, 1)
+		go func() {
+			if err := service.Start(ctx); err != nil {
+				startErr <- err
+			}
+		}()
+
+		readyErr := make(chan error, 1)
+		success := make(chan struct{}, 1)
+		timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 1*time.Second)
+		defer timeoutCancel()
+		go func() {
+			if err := service.Ready(timeoutCtx); err == nil {
+				readyErr <- fmt.Errorf("expected service to timeout")
+			}
+			success <- struct{}{}
+		}()
+
+		select {
+		case err := <-startErr:
+			t.Errorf("service failed to start: %v", err)
+		case err := <-readyErr:
+			t.Error(err)
+		case <-success:
+			return
 		}
 	})
-}
 
-func setRustBinariesPath() {
-	rustBinPath, _ := filepath.Abs("../../offchain/target/debug")
-	os.Setenv("PATH", os.Getenv("PATH")+":"+rustBinPath)
+	t.Run("it becomes ready soon after being started", func(t *testing.T) {
+		service := Service{
+			name:            "fake-service",
+			binaryName:      "fake-service",
+			healthcheckPort: "8090",
+		}
+		ctx, cancel := context.WithCancel(context.Background())
+		defer cancel()
+
+		startErr := make(chan error, 1)
+		go func() {
+			if err := service.Start(ctx); err != nil {
+				startErr <- err
+			}
+		}()
+
+		readyErr := make(chan error, 1)
+		success := make(chan struct{}, 1)
+		timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 5*time.Second)
+		defer timeoutCancel()
+		go func() {
+			if err := service.Ready(timeoutCtx); err != nil {
+				readyErr <- err
+			}
+			success <- struct{}{}
+		}()
+
+		select {
+		case err := <-startErr:
+			t.Errorf("service failed to start: %v", err)
+		case err := <-readyErr:
+			t.Errorf("service wasn't ready in time. %v", err)
+		case <-success:
+			return
+		}
+	})
 }
 
-func assertExitErrorWasCausedBy(err *exec.ExitError, signal syscall.Signal) bool {
-	status := err.Sys().(syscall.WaitStatus)
-	return status.Signal() == signal
+// Builds the fake-service binary and adds it to PATH
+func buildFakeService() {
+	rootDir, err := filepath.Abs("../../")
+	if err != nil {
+		panic(err)
+	}
+
+	cmd := exec.Command("go", "build", "-o", "build/fake-service", "test/fakeservice/main.go")
+	cmd.Dir = rootDir
+	if err := cmd.Run(); err != nil {
+		panic(err)
+	}
+
+	execPath := filepath.Join(rootDir, "build")
+	os.Setenv("PATH", os.Getenv("PATH")+":"+execPath)
 }
diff --git a/test/fakeservice/main.go b/test/fakeservice/main.go
new file mode 100644
index 000000000..95756d545
--- /dev/null
+++ b/test/fakeservice/main.go
@@ -0,0 +1,10 @@
+// This file creates a dummy webserver with the sole pupose of being used
+// as a binary to test the services.Service struct
+package main
+
+import "net/http"
+
+func main() {
+	err := http.ListenAndServe(":8090", nil)
+	panic(err)
+}