package main

import (
	"context"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

func TestChildFailures(t *testing.T) {
	path := filepath.Join(t.TempDir(), "lab")
	if out, err := exec.Command("go", "build", "-o", path, ".").CombinedOutput(); err != nil {
		t.Fatalf("build %v %s", err, out)
	}
	for _, mode := range []string{"pool", "memory", "goroutine", "fd", "deadlock"} {
		t.Run(mode, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
			defer cancel()
			out, err := exec.CommandContext(ctx, path, mode).CombinedOutput()
			if ctx.Err() != nil {
				t.Fatalf("child exceeded limit: %s", out)
			}
			if mode == "deadlock" {
				if err == nil || !strings.Contains(string(out), "all goroutines are asleep - deadlock!") {
					t.Fatalf("unexpected deadlock: %v %s", err, out)
				}
			} else if err != nil {
				t.Fatalf("%v %s", err, out)
			}
			t.Log(strings.TrimSpace(string(out)))
		})
	}
}

func TestInProcessSafeCases(t *testing.T) {
	for _, f := range []func() error{pool, memory, goroutines} {
		if err := f(); err != nil {
			t.Fatal(err)
		}
	}
}
