package examples_test

import (
	"context"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/pingcap/log"
	"golang.org/x/sync/errgroup"

	. "github.com/pingcap/endless/pkg/util"
)

var _ = Describe("FastFail", func() {
	doSomething := func(ctx context.Context, sleep time.Duration) error {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(sleep):
		}
		return nil
	}

	// Since this test case always fails, we mark it as pending.
	// You can try this example by yourself.
	PIt("should fail imediatelly if one of the goroutine fails", func() {
		g, ctx := errgroup.WithContext(context.Background())

		// task 1
		g.Go(WithGinkgoRecover(func() {
			err := doSomething(ctx, 0*time.Second)
			Expect(err).Should(Succeed())
		}))

		// task 2
		g.Go(WithGinkgoRecover(func() {
			time.Sleep(200 * time.Millisecond)
			Expect(nil).To(HaveOccurred()) // it fails
			log.Info("This log entry will not be logged")
		}))

		// task 3
		g.Go(WithGinkgoRecover(func() {
			// the doSomething should be cancelled because task 2 fails, and
			// the error should be context.Cancelled
			err := doSomething(ctx, 10*time.Minute)
			Expect(err).To(MatchError(context.Canceled))
			log.Info("This log entry should be logged after 200ms")
		}))

		g.Wait()
	})
})
