package subprocess

import (
	"bytes"
	"context"
	"errors"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestExec(t *testing.T) {
	t.Run("Success", func(t *testing.T) {
		var stdout, stderr bytes.Buffer
		res := Exec(ExecOptions{
			Ctx:    context.Background(),
			Bin:    "sh",
			Args:   []string{"-c", "echo out; echo err 1>&2"},
			Stdout: &stdout,
			Stderr: &stderr,
		})
		require.NoError(t, res.Err)
		assert.Contains(t, stdout.String(), "out")
		assert.Contains(t, stderr.String(), "err")
		assert.NotContains(t, stdout.String(), "err")
	})

	t.Run("NonZeroExit", func(t *testing.T) {
		res := Exec(ExecOptions{
			Ctx:  context.Background(),
			Bin:  "sh",
			Args: []string{"-c", "echo boom 1>&2; exit 42"},
		})
		assert.Error(t, res.Err)
		var se *Error
		require.ErrorAs(t, res.Err, &se)
		assert.Equal(t, 42, se.Code)
		assert.Contains(t, res.Stderr, "boom")
	})

	t.Run("BinNotFound", func(t *testing.T) {
		res := Exec(ExecOptions{
			Ctx: context.Background(),
			Bin: "no-such-bin-xyz",
		})
		assert.Error(t, res.Err)
		var se *Error
		assert.False(t, errors.As(res.Err, &se), "Err should NOT be *Error for missing binary")
		assert.Contains(t, res.Err.Error(), "executable file not found")
	})

	t.Run("NilMirrors", func(t *testing.T) {
		res := Exec(ExecOptions{
			Ctx:  context.Background(),
			Bin:  "sh",
			Args: []string{"-c", "echo visible"},
		})
		require.NoError(t, res.Err)
		assert.Contains(t, res.Stdout, "visible")
	})
}
