package randgen_test

import (
	"context"
	"fmt"
	"net/url"
	"strconv"
	"time"

	. "github.com/onsi/ginkgo"
	"github.com/pingcap/test-infra/sdk/resource"
	_ "github.com/pingcap/test-infra/sdk/resource/impl/k8s"
	"golang.org/x/sync/errgroup"

	"github.com/pingcap/endless/pkg/matcher"
	"github.com/pingcap/endless/pkg/util"
	"github.com/pingcap/endless/pkg/workloadnode"
	"github.com/pingcap/endless/testcase/tiflash/pkg"
)

/*
The case is from https://github.com/lilinghai/go-randgen/tree/tiflash/cases
The cases are as follows:
	aggregation
	cartesian-join
	join
	subquery
	collation
	window
*/
var _ = Describe("Randgen", func() {
	var (
		tc        resource.TiDBCluster
		gorandgen resource.WorkloadNode
		dbURL     *url.URL
		cases     string
		queries   int
		skipErrs  string
	)
	BeforeEach(func() {
		tc = suiteTestCtx.Resource("tc").(resource.TiDBCluster)
		gorandgen = suiteTestCtx.Resource("gorandgen").(resource.WorkloadNode)
		dbURL = matcher.Try(tc.ServiceURL(resource.DBAddr)).(*url.URL)
		queries = matcher.Try(strconv.Atoi(suiteTestCtx.Param("queries", "100000"))).(int)
		skipErrs = suiteTestCtx.Param("skip_errs", "")
		cases = suiteTestCtx.Param("cases", "all")
	})

	Context("randgen test diff tikv with tiflash", func() {
		It("the result should be consistency", func() {
			dbDSN := fmt.Sprintf("root:@tcp(%s)", dbURL.Host)
			duration := 10 * time.Hour
			ctx, cancel := context.WithTimeout(suiteTestCtx, duration)
			// goRandgenCmd := fmt.Sprintf(`bash -c "./run.sh '%s' '%s' '%s' %d '%s' 2>&1 | tee -a /res.log ; exit \${PIPESTATUS[0]}"`, cases, dbDSN, dbDSN, queries, skipErrs)
			goRandgenCmd := fmt.Sprintf(`./run.sh '%s' '%s' '%s' %d '%s'`, cases, dbDSN, dbDSN, queries, skipErrs)
			cmd := workloadnode.CommandContext(ctx, goRandgenCmd)
			// must assign cmd.stdout before cmd.run
			pr := pkg.AssignCmdStdout(cmd)
			defer cmd.Stop()
			g, _ := errgroup.WithContext(ctx)
			g.Go(util.WithGinkgoRecover(func() {
				defer func() {
					cancel()
				}()
				matcher.Try(cmd.Run(gorandgen))
			}))
			g.Go(util.WithGinkgoRecover(func() {
				matcher.Try(pkg.InfoCmdStdout(ctx, pr, pkg.SkipErrorHandler))
			}))
			matcher.Try(g.Wait())
		})
	})
})
