package main

import (
	"errors"
	"fmt"
	"io/fs"
	"strconv"
	"testing"
)

func TestLimitContract(t *testing.T) {
	if n, err := loadLimit("8"); n != 8 || err != nil {
		t.Fatal(n, err)
	}
	_, err := loadLimit("0")
	if !errors.Is(err, ErrPositive) {
		t.Fatal(err)
	}
	if fe, ok := errors.AsType[*FieldError](err); !ok || fe.Field != "limit" {
		t.Fatal(err)
	}
	_, err = loadLimit("many")
	if !errors.Is(err, strconv.ErrSyntax) {
		t.Fatal(err)
	}
}
func TestTreeAndFirstMatch(t *testing.T) {
	a := &FieldError{Field: "a", Err: ErrPositive}
	b := &FieldError{Field: "b", Err: fs.ErrPermission}
	err := fmt.Errorf("top: %w", errors.Join(a, b))
	var got *FieldError
	if !errors.As(err, &got) || got != a {
		t.Fatal(got)
	}
	if !errors.Is(err, ErrPositive) || !errors.Is(err, fs.ErrPermission) {
		t.Fatal(err)
	}
	if errors.Unwrap(errors.Join(a, b)) != nil {
		t.Fatal("Unwrap should not traverse []error")
	}
	if errors.Join(nil, nil) != nil {
		t.Fatal("nil join")
	}
}
func TestFinish(t *testing.T) {
	cases := []struct{ work, close error }{{nil, nil}, {ErrPositive, nil}, {nil, fs.ErrPermission}, {ErrPositive, fs.ErrPermission}}
	for _, tc := range cases {
		err := finish(func() error { return tc.work }, func() error { return tc.close })
		if (err == nil) != (tc.work == nil && tc.close == nil) {
			t.Fatal(err)
		}
		for _, want := range []error{tc.work, tc.close} {
			if want != nil && !errors.Is(err, want) {
				t.Fatal(err)
			}
		}
	}
}
func TestBoundary(t *testing.T) {
	if err := boundary(func() {}); err != nil {
		t.Fatal(err)
	}
	if err := boundary(func() { panic(ErrPositive) }); !errors.Is(err, ErrPositive) {
		t.Fatal(err)
	}
	if err := boundary(func() { panic("broken") }); err == nil || err.Error() != "task panicked: broken" {
		t.Fatal(err)
	}
}
