Files
imgproxy/integration/test_utils.go
Victor Sokolov aa91342686 IMG-33: adds simple integration tests for image.Load() (#1462)
* Load() integration test

* Added test-images as submodule
2025-07-23 19:09:49 +02:00

138 lines
4.0 KiB
Go

//go:build integration
// +build integration
// Integration test helpers for imgproxy.
// We use regular `go build` instead of Docker to make sure
// tests run in the same environment as other tests,
// including in CI, where everything runs in a custom Docker image
// against the different libvips versions.
package integration
import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/require"
)
const (
buildContext = ".." // Source code folder
binPath = "/tmp/imgproxy-test" // Path to the built imgproxy binary
bindPort = 9090 // Port to bind imgproxy to
bindHost = "127.0.0.1" // Host to bind imgproxy to
)
var (
buildCmd = []string{"build", "-v", "-ldflags=-s -w", "-o", binPath} // imgproxy build command
)
// waitForPort tries to connect to host:port until successful or timeout
func waitForPort(host string, port int, timeout time.Duration) error {
var address string
if net.ParseIP(host) != nil && net.ParseIP(host).To4() == nil {
// IPv6 address, wrap in brackets
address = fmt.Sprintf("[%s]:%d", host, port)
} else {
address = fmt.Sprintf("%s:%d", host, port)
}
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", address, 500*time.Millisecond)
if err == nil {
conn.Close()
return nil // port is open
}
time.Sleep(200 * time.Millisecond)
}
return fmt.Errorf("timeout waiting for port %s", address)
}
func startImgproxy(t *testing.T, ctx context.Context, testImagesPath string) string {
// Build the imgproxy binary
buildCmd := exec.Command("go", buildCmd...)
buildCmd.Dir = buildContext
buildCmd.Env = os.Environ()
buildOut, err := buildCmd.CombinedOutput()
require.NoError(t, err, "failed to build imgproxy: %v\n%s", err, string(buildOut))
// Start imgproxy in the background
cmd := exec.CommandContext(ctx, binPath)
// Set environment variables for imgproxy
cmd.Env = append(os.Environ(), "IMGPROXY_BIND=:"+fmt.Sprintf("%d", bindPort))
cmd.Env = append(cmd.Env, "IMGPROXY_LOCAL_FILESYSTEM_ROOT="+testImagesPath)
cmd.Env = append(cmd.Env, "IMGPROXY_MAX_ANIMATION_FRAMES=999")
cmd.Env = append(cmd.Env, "IMGPROXY_VIPS_LEAK_CHECK=true")
cmd.Env = append(cmd.Env, "IMGPROXY_LOG_MEM_STATS=true")
cmd.Env = append(cmd.Env, "IMGPROXY_DEVELOPMENT_ERRORS_MODE=true")
// That one is for the build logs
stdout, _ := os.CreateTemp("", "imgproxy-stdout-*")
stderr, _ := os.CreateTemp("", "imgproxy-stderr-*")
cmd.Stdout = stdout
cmd.Stderr = stderr
err = cmd.Start()
require.NoError(t, err, "failed to start imgproxy: %v", err)
// Wait for port 8090 to be available
err = waitForPort(bindHost, bindPort, 5*time.Second)
if err != nil {
cmd.Process.Kill()
require.NoError(t, err, "imgproxy did not start in time")
}
// Return a dummy container (nil) and connection string
t.Cleanup(func() {
cmd.Process.Kill()
stdout.Close()
stderr.Close()
os.Remove(stdout.Name())
os.Remove(stderr.Name())
os.Remove(binPath)
})
return fmt.Sprintf("%s:%d", bindHost, bindPort)
}
// fetchImage fetches an image from the imgproxy server
func fetchImage(t *testing.T, cs string, path string) []byte {
url := fmt.Sprintf("http://%s/%s", cs, path)
resp, err := http.Get(url)
require.NoError(t, err, "Failed to fetch image from %s", url)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode, "Expected status code 200 OK, got %d, url: %s", resp.StatusCode, url)
bytes, err := io.ReadAll(resp.Body)
require.NoError(t, err, "Failed to read response body from %s", url)
return bytes
}
// testImagesPath returns the absolute path to the test images directory
func testImagesPath(t *testing.T) (string, error) {
// Get current working directory
dir, err := os.Getwd()
require.NoError(t, err)
// Convert to absolute path (if it's not already)
absPath, err := filepath.Abs(dir)
require.NoError(t, err)
return path.Join(absPath, "../testdata/test-images"), nil
}