github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ccl/changefeedccl/validations_test.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Licensed as a CockroachDB Enterprise file under the Cockroach Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //     https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt
     8  
     9  package changefeedccl
    10  
    11  import (
    12  	"context"
    13  	gosql "database/sql"
    14  	"math/rand"
    15  	"sync/atomic"
    16  	"testing"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/ccl/changefeedccl/cdctest"
    19  	"github.com/cockroachdb/cockroach/pkg/ccl/utilccl"
    20  	"github.com/cockroachdb/cockroach/pkg/util/ctxgroup"
    21  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    22  	"github.com/cockroachdb/cockroach/pkg/workload/bank"
    23  	"github.com/cockroachdb/cockroach/pkg/workload/workloadsql"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  func TestCatchupScanOrdering(t *testing.T) {
    28  	defer leaktest.AfterTest(t)()
    29  	defer utilccl.TestingEnableEnterprise()()
    30  
    31  	testFn := func(t *testing.T, db *gosql.DB, f cdctest.TestFeedFactory) {
    32  		t.Run("bank", func(t *testing.T) {
    33  			ctx := context.Background()
    34  			const numRows, numRanges, payloadBytes, maxTransfer = 10, 10, 10, 999
    35  			gen := bank.FromConfig(numRows, numRows, payloadBytes, numRanges)
    36  			var l workloadsql.InsertsDataLoader
    37  			if _, err := workloadsql.Setup(ctx, db, gen, l); err != nil {
    38  				t.Fatal(err)
    39  			}
    40  
    41  			var nowString string
    42  			require.NoError(t, db.QueryRow("SELECT cluster_logical_timestamp()").Scan(&nowString))
    43  
    44  			existingChangeCount := 50
    45  			for i := 0; i < existingChangeCount; i++ {
    46  				if err := randomBankTransfer(numRows, maxTransfer, db); err != nil {
    47  					t.Fatal(err)
    48  				}
    49  			}
    50  
    51  			bankFeed := feed(t, f, `CREATE CHANGEFEED FOR bank WITH updated, cursor=$1`, nowString)
    52  			defer closeFeed(t, bankFeed)
    53  
    54  			var done int64
    55  			g := ctxgroup.WithContext(ctx)
    56  			g.GoCtx(func(ctx context.Context) error {
    57  				for {
    58  					if atomic.LoadInt64(&done) > 0 {
    59  						return nil
    60  					}
    61  
    62  					if err := randomBankTransfer(numRows, maxTransfer, db); err != nil {
    63  						return err
    64  					}
    65  				}
    66  			})
    67  
    68  			v := cdctest.NewOrderValidator(`bank`)
    69  			seenChanges := 0
    70  			for {
    71  				m, err := bankFeed.Next()
    72  				if err != nil {
    73  					t.Fatal(err)
    74  				} else if len(m.Key) > 0 || len(m.Value) > 0 {
    75  					updated, _, err := cdctest.ParseJSONValueTimestamps(m.Value)
    76  					if err != nil {
    77  						t.Fatal(err)
    78  					}
    79  					err = v.NoteRow(m.Partition, string(m.Key), string(m.Value), updated)
    80  					if err != nil {
    81  						t.Fatal(err)
    82  					}
    83  					seenChanges++
    84  					if seenChanges >= 200 {
    85  						atomic.StoreInt64(&done, 1)
    86  						break
    87  					}
    88  				}
    89  			}
    90  			for _, f := range v.Failures() {
    91  				t.Error(f)
    92  			}
    93  
    94  			if err := g.Wait(); err != nil {
    95  				t.Errorf(`%+v`, err)
    96  			}
    97  		})
    98  	}
    99  	t.Run(`sinkless`, sinklessTest(testFn))
   100  	t.Run(`enterprise`, enterpriseTest(testFn))
   101  }
   102  
   103  // TODO(dan): This bit is copied from the bank workload. It's
   104  // currently much easier to do this than to use the real Ops,
   105  // which is silly. Fixme.
   106  func randomBankTransfer(numRows, maxTransfer int, db *gosql.DB) error {
   107  	from := rand.Intn(numRows)
   108  	to := rand.Intn(numRows)
   109  	for from == to {
   110  		to = rand.Intn(numRows)
   111  	}
   112  	amount := rand.Intn(maxTransfer)
   113  	_, err := db.Exec(`UPDATE bank
   114  					SET balance = CASE id WHEN $1 THEN balance-$3 WHEN $2 THEN balance+$3 END
   115  					WHERE id IN ($1, $2)
   116  				`, from, to, amount)
   117  	return err
   118  }