github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sqlmigrations/migrations_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package sqlmigrations
    12  
    13  import (
    14  	"bytes"
    15  	"context"
    16  	"fmt"
    17  	"strings"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/cockroachdb/cockroach/pkg/base"
    22  	"github.com/cockroachdb/cockroach/pkg/gossip"
    23  	"github.com/cockroachdb/cockroach/pkg/keys"
    24  	"github.com/cockroachdb/cockroach/pkg/kv"
    25  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    26  	"github.com/cockroachdb/cockroach/pkg/sql"
    27  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    28  	"github.com/cockroachdb/cockroach/pkg/sqlmigrations/leasemanager"
    29  	"github.com/cockroachdb/cockroach/pkg/testutils"
    30  	"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
    31  	"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
    32  	"github.com/cockroachdb/cockroach/pkg/util/leaktest"
    33  	"github.com/cockroachdb/cockroach/pkg/util/log"
    34  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    35  	"github.com/cockroachdb/errors"
    36  	"github.com/gogo/protobuf/proto"
    37  	"github.com/stretchr/testify/require"
    38  )
    39  
    40  var (
    41  	noopMigration1 = migrationDescriptor{
    42  		name:   "noop 1",
    43  		workFn: func(_ context.Context, _ runner) error { return nil },
    44  	}
    45  	noopMigration2 = migrationDescriptor{
    46  		name:   "noop 2",
    47  		workFn: func(_ context.Context, _ runner) error { return nil },
    48  	}
    49  	errorMigration = migrationDescriptor{
    50  		name:   "error",
    51  		workFn: func(_ context.Context, _ runner) error { return errors.New("errorMigration") },
    52  	}
    53  	panicMigration = migrationDescriptor{
    54  		name:   "panic",
    55  		workFn: func(_ context.Context, _ runner) error { panic("panicMigration") },
    56  	}
    57  )
    58  
    59  type fakeLeaseManager struct {
    60  	extendErr          error
    61  	releaseErr         error
    62  	leaseTimeRemaining time.Duration
    63  }
    64  
    65  func (f *fakeLeaseManager) AcquireLease(
    66  	ctx context.Context, key roachpb.Key,
    67  ) (*leasemanager.Lease, error) {
    68  	return &leasemanager.Lease{}, nil
    69  }
    70  
    71  func (f *fakeLeaseManager) ExtendLease(ctx context.Context, l *leasemanager.Lease) error {
    72  	return f.extendErr
    73  }
    74  
    75  func (f *fakeLeaseManager) ReleaseLease(ctx context.Context, l *leasemanager.Lease) error {
    76  	return f.releaseErr
    77  }
    78  
    79  func (f *fakeLeaseManager) TimeRemaining(l *leasemanager.Lease) time.Duration {
    80  	// Default to a reasonable amount of time left if the field wasn't set.
    81  	if f.leaseTimeRemaining == 0 {
    82  		return leaseRefreshInterval * 2
    83  	}
    84  	return f.leaseTimeRemaining
    85  }
    86  
    87  type fakeDB struct {
    88  	codec   keys.SQLCodec
    89  	kvs     map[string][]byte
    90  	scanErr error
    91  	putErr  error
    92  }
    93  
    94  func (f *fakeDB) Scan(
    95  	ctx context.Context, begin, end interface{}, maxRows int64,
    96  ) ([]kv.KeyValue, error) {
    97  	if f.scanErr != nil {
    98  		return nil, f.scanErr
    99  	}
   100  	min := f.codec.MigrationKeyPrefix()
   101  	max := min.PrefixEnd()
   102  	if !bytes.Equal(begin.(roachpb.Key), min) {
   103  		return nil, errors.Errorf("expected begin key %q, got %q", min, begin)
   104  	}
   105  	if !bytes.Equal(end.(roachpb.Key), max) {
   106  		return nil, errors.Errorf("expected end key %q, got %q", max, end)
   107  	}
   108  	var results []kv.KeyValue
   109  	for k, v := range f.kvs {
   110  		results = append(results, kv.KeyValue{
   111  			Key:   []byte(k),
   112  			Value: &roachpb.Value{RawBytes: v},
   113  		})
   114  	}
   115  	return results, nil
   116  }
   117  
   118  func (f *fakeDB) Get(ctx context.Context, key interface{}) (kv.KeyValue, error) {
   119  	return kv.KeyValue{}, errors.New("unimplemented")
   120  }
   121  
   122  func (f *fakeDB) Put(ctx context.Context, key, value interface{}) error {
   123  	if f.putErr != nil {
   124  		return f.putErr
   125  	}
   126  	if f.kvs != nil {
   127  		f.kvs[string(key.(roachpb.Key))] = []byte(value.(string))
   128  	}
   129  	return nil
   130  }
   131  
   132  func (f *fakeDB) Txn(context.Context, func(context.Context, *kv.Txn) error) error {
   133  	return errors.New("unimplemented")
   134  }
   135  
   136  func TestEnsureMigrations(t *testing.T) {
   137  	defer leaktest.AfterTest(t)()
   138  	codec := keys.SystemSQLCodec
   139  	db := &fakeDB{codec: codec}
   140  	mgr := Manager{
   141  		stopper:      stop.NewStopper(),
   142  		leaseManager: &fakeLeaseManager{},
   143  		db:           db,
   144  		codec:        codec,
   145  	}
   146  	defer mgr.stopper.Stop(context.Background())
   147  
   148  	fnGotCalled := false
   149  	fnGotCalledDescriptor := migrationDescriptor{
   150  		name: "got-called-verifier",
   151  		workFn: func(context.Context, runner) error {
   152  			fnGotCalled = true
   153  			return nil
   154  		},
   155  	}
   156  	testCases := []struct {
   157  		preCompleted []migrationDescriptor
   158  		migrations   []migrationDescriptor
   159  		expectedErr  string
   160  	}{
   161  		{
   162  			nil,
   163  			nil,
   164  			"",
   165  		},
   166  		{
   167  			nil,
   168  			[]migrationDescriptor{noopMigration1},
   169  			"",
   170  		},
   171  		{
   172  			[]migrationDescriptor{noopMigration1},
   173  			[]migrationDescriptor{noopMigration1},
   174  			"",
   175  		},
   176  		{
   177  			[]migrationDescriptor{},
   178  			[]migrationDescriptor{noopMigration1, noopMigration2},
   179  			"",
   180  		},
   181  		{
   182  			[]migrationDescriptor{noopMigration1},
   183  			[]migrationDescriptor{noopMigration1, noopMigration2},
   184  			"",
   185  		},
   186  		{
   187  			[]migrationDescriptor{noopMigration1, noopMigration2, panicMigration},
   188  			[]migrationDescriptor{noopMigration1, noopMigration2, panicMigration},
   189  			"",
   190  		},
   191  		{
   192  			[]migrationDescriptor{noopMigration1, noopMigration2},
   193  			[]migrationDescriptor{noopMigration1, noopMigration2, fnGotCalledDescriptor},
   194  			"",
   195  		},
   196  		{
   197  			[]migrationDescriptor{noopMigration1, noopMigration2},
   198  			[]migrationDescriptor{noopMigration1, noopMigration2, errorMigration},
   199  			fmt.Sprintf("failed to run migration %q", errorMigration.name),
   200  		},
   201  	}
   202  
   203  	defer func(prev []migrationDescriptor) { backwardCompatibleMigrations = prev }(backwardCompatibleMigrations)
   204  
   205  	for _, tc := range testCases {
   206  		t.Run("", func(t *testing.T) {
   207  			db.kvs = make(map[string][]byte)
   208  			for _, name := range tc.preCompleted {
   209  				db.kvs[string(migrationKey(codec, name))] = []byte{}
   210  			}
   211  			backwardCompatibleMigrations = tc.migrations
   212  
   213  			err := mgr.EnsureMigrations(context.Background(), roachpb.Version{} /* bootstrapVersion */)
   214  			if !testutils.IsError(err, tc.expectedErr) {
   215  				t.Errorf("expected error %q, got error %v", tc.expectedErr, err)
   216  			}
   217  			if err != nil {
   218  				return
   219  			}
   220  
   221  			for _, migration := range tc.migrations {
   222  				if _, ok := db.kvs[string(migrationKey(codec, migration))]; !ok {
   223  					t.Errorf("expected key %s to be written, but it wasn't", migrationKey(codec, migration))
   224  				}
   225  			}
   226  			if len(db.kvs) != len(tc.migrations) {
   227  				t.Errorf("expected %d key to be written, but %d were",
   228  					len(tc.migrations), len(db.kvs))
   229  			}
   230  		})
   231  	}
   232  	if !fnGotCalled {
   233  		t.Errorf("expected fnGotCalledDescriptor to be run by the migration coordinator, but it wasn't")
   234  	}
   235  }
   236  
   237  func TestSkipMigrationsIncludedInBootstrap(t *testing.T) {
   238  	defer leaktest.AfterTest(t)()
   239  	ctx := context.Background()
   240  	codec := keys.SystemSQLCodec
   241  	db := &fakeDB{codec: codec}
   242  	mgr := Manager{
   243  		stopper:      stop.NewStopper(),
   244  		leaseManager: &fakeLeaseManager{},
   245  		db:           db,
   246  		codec:        codec,
   247  	}
   248  	defer mgr.stopper.Stop(ctx)
   249  	defer func(prev []migrationDescriptor) {
   250  		backwardCompatibleMigrations = prev
   251  	}(backwardCompatibleMigrations)
   252  
   253  	v := roachpb.MustParseVersion("19.1")
   254  	fnGotCalled := false
   255  	backwardCompatibleMigrations = []migrationDescriptor{{
   256  		name:                "got-called-verifier",
   257  		includedInBootstrap: v,
   258  		workFn: func(context.Context, runner) error {
   259  			fnGotCalled = true
   260  			return nil
   261  		},
   262  	}}
   263  	// If the cluster has been bootstrapped at an old version, the migration should run.
   264  	require.NoError(t, mgr.EnsureMigrations(ctx, roachpb.Version{} /* bootstrapVersion */))
   265  	require.True(t, fnGotCalled)
   266  	fnGotCalled = false
   267  	// If the cluster has been bootstrapped at a new version, the migration should
   268  	// not run.
   269  	require.NoError(t, mgr.EnsureMigrations(ctx, v /* bootstrapVersion */))
   270  	require.False(t, fnGotCalled)
   271  }
   272  
   273  func TestClusterWideMigrationOnlyRunBySystemTenant(t *testing.T) {
   274  	defer leaktest.AfterTest(t)()
   275  	testutils.RunTrueAndFalse(t, "system tenant", func(t *testing.T, systemTenant bool) {
   276  		var codec keys.SQLCodec
   277  		if systemTenant {
   278  			codec = keys.SystemSQLCodec
   279  		} else {
   280  			codec = keys.MakeSQLCodec(roachpb.MakeTenantID(5))
   281  		}
   282  
   283  		ctx := context.Background()
   284  		db := &fakeDB{codec: codec}
   285  		mgr := Manager{
   286  			stopper:      stop.NewStopper(),
   287  			leaseManager: &fakeLeaseManager{},
   288  			db:           db,
   289  			codec:        codec,
   290  		}
   291  		defer mgr.stopper.Stop(ctx)
   292  		defer func(prev []migrationDescriptor) {
   293  			backwardCompatibleMigrations = prev
   294  		}(backwardCompatibleMigrations)
   295  
   296  		fnGotCalled := false
   297  		backwardCompatibleMigrations = []migrationDescriptor{{
   298  			name:        "got-called-verifier",
   299  			clusterWide: true,
   300  			workFn: func(context.Context, runner) error {
   301  				fnGotCalled = true
   302  				return nil
   303  			},
   304  		}}
   305  		// The migration should only be run by the system tenant.
   306  		require.NoError(t, mgr.EnsureMigrations(ctx, roachpb.Version{} /* bootstrapVersion */))
   307  		require.Equal(t, systemTenant, fnGotCalled)
   308  	})
   309  }
   310  
   311  func TestDBErrors(t *testing.T) {
   312  	defer leaktest.AfterTest(t)()
   313  	codec := keys.SystemSQLCodec
   314  	db := &fakeDB{codec: codec}
   315  	mgr := Manager{
   316  		stopper:      stop.NewStopper(),
   317  		leaseManager: &fakeLeaseManager{},
   318  		db:           db,
   319  		codec:        codec,
   320  	}
   321  	defer mgr.stopper.Stop(context.Background())
   322  
   323  	migration := noopMigration1
   324  	defer func(prev []migrationDescriptor) { backwardCompatibleMigrations = prev }(backwardCompatibleMigrations)
   325  	backwardCompatibleMigrations = []migrationDescriptor{migration}
   326  	testCases := []struct {
   327  		scanErr     error
   328  		putErr      error
   329  		expectedErr string
   330  	}{
   331  		{
   332  			nil,
   333  			nil,
   334  			"",
   335  		},
   336  		{
   337  			fmt.Errorf("context deadline exceeded"),
   338  			nil,
   339  			"failed to get list of completed migrations.*context deadline exceeded",
   340  		},
   341  		{
   342  			nil,
   343  			fmt.Errorf("context deadline exceeded"),
   344  			"failed to persist record of completing migration.*context deadline exceeded",
   345  		},
   346  	}
   347  	for _, tc := range testCases {
   348  		t.Run("", func(t *testing.T) {
   349  			db.scanErr = tc.scanErr
   350  			db.putErr = tc.putErr
   351  			db.kvs = make(map[string][]byte)
   352  			err := mgr.EnsureMigrations(context.Background(), roachpb.Version{} /* bootstrapVersion */)
   353  			if !testutils.IsError(err, tc.expectedErr) {
   354  				t.Errorf("expected error %q, got error %v", tc.expectedErr, err)
   355  			}
   356  			if err != nil {
   357  				return
   358  			}
   359  			if _, ok := db.kvs[string(migrationKey(codec, migration))]; !ok {
   360  				t.Errorf("expected key %s to be written, but it wasn't", migrationKey(codec, migration))
   361  			}
   362  			if len(db.kvs) != len(backwardCompatibleMigrations) {
   363  				t.Errorf("expected %d key to be written, but %d were",
   364  					len(backwardCompatibleMigrations), len(db.kvs))
   365  			}
   366  		})
   367  	}
   368  }
   369  
   370  // ExtendLease and ReleaseLease errors should not, by themselves, cause the
   371  // migration process to fail. Not being able to acquire the lease should, but
   372  // we don't test that here due to the added code that would be needed to change
   373  // its retry settings to allow for testing it in a reasonable amount of time.
   374  func TestLeaseErrors(t *testing.T) {
   375  	defer leaktest.AfterTest(t)()
   376  	codec := keys.SystemSQLCodec
   377  	db := &fakeDB{codec: codec, kvs: make(map[string][]byte)}
   378  	mgr := Manager{
   379  		stopper: stop.NewStopper(),
   380  		leaseManager: &fakeLeaseManager{
   381  			extendErr:  fmt.Errorf("context deadline exceeded"),
   382  			releaseErr: fmt.Errorf("context deadline exceeded"),
   383  		},
   384  		db:    db,
   385  		codec: codec,
   386  	}
   387  	defer mgr.stopper.Stop(context.Background())
   388  
   389  	migration := noopMigration1
   390  	defer func(prev []migrationDescriptor) { backwardCompatibleMigrations = prev }(backwardCompatibleMigrations)
   391  	backwardCompatibleMigrations = []migrationDescriptor{migration}
   392  	if err := mgr.EnsureMigrations(context.Background(), roachpb.Version{} /* bootstrapVersion */); err != nil {
   393  		t.Error(err)
   394  	}
   395  	if _, ok := db.kvs[string(migrationKey(codec, migration))]; !ok {
   396  		t.Errorf("expected key %s to be written, but it wasn't", migrationKey(codec, migration))
   397  	}
   398  	if len(db.kvs) != len(backwardCompatibleMigrations) {
   399  		t.Errorf("expected %d key to be written, but %d were",
   400  			len(backwardCompatibleMigrations), len(db.kvs))
   401  	}
   402  }
   403  
   404  // The lease not having enough time left on it to finish migrations should
   405  // cause the process to exit via a call to log.Fatal.
   406  func TestLeaseExpiration(t *testing.T) {
   407  	defer leaktest.AfterTest(t)()
   408  	codec := keys.SystemSQLCodec
   409  	db := &fakeDB{codec: codec, kvs: make(map[string][]byte)}
   410  	mgr := Manager{
   411  		stopper:      stop.NewStopper(),
   412  		leaseManager: &fakeLeaseManager{leaseTimeRemaining: time.Nanosecond},
   413  		db:           db,
   414  		codec:        codec,
   415  	}
   416  	defer mgr.stopper.Stop(context.Background())
   417  
   418  	oldLeaseRefreshInterval := leaseRefreshInterval
   419  	leaseRefreshInterval = time.Microsecond
   420  	defer func() { leaseRefreshInterval = oldLeaseRefreshInterval }()
   421  
   422  	exitCalled := make(chan bool)
   423  	log.SetExitFunc(true /* hideStack */, func(int) { exitCalled <- true })
   424  	defer log.ResetExitFunc()
   425  	// Disable stack traces to make the test output in teamcity less deceiving.
   426  	defer log.DisableTracebacks()()
   427  
   428  	waitForExitMigration := migrationDescriptor{
   429  		name: "wait for exit to be called",
   430  		workFn: func(context.Context, runner) error {
   431  			select {
   432  			case <-exitCalled:
   433  				return nil
   434  			case <-time.After(10 * time.Second):
   435  				return fmt.Errorf("timed out waiting for exit to be called")
   436  			}
   437  		},
   438  	}
   439  	defer func(prev []migrationDescriptor) { backwardCompatibleMigrations = prev }(backwardCompatibleMigrations)
   440  	backwardCompatibleMigrations = []migrationDescriptor{waitForExitMigration}
   441  	if err := mgr.EnsureMigrations(context.Background(), roachpb.Version{} /* bootstrapVersion */); err != nil {
   442  		t.Error(err)
   443  	}
   444  }
   445  
   446  // migrationTest assists in testing the effects of a migration. It provides
   447  // methods to edit the list of migrations run at server startup, start a test
   448  // server, and run an individual migration. The test server's KV and SQL
   449  // interfaces are intended to be accessed directly to verify the effect of the
   450  // migration. Any mutations to the list of migrations run at server startup are
   451  // reverted at the end of the test.
   452  type migrationTest struct {
   453  	oldMigrations []migrationDescriptor
   454  	server        serverutils.TestServerInterface
   455  	sqlDB         *sqlutils.SQLRunner
   456  	kvDB          *kv.DB
   457  	memMetrics    *sql.MemoryMetrics
   458  }
   459  
   460  // makeMigrationTest creates a new migrationTest.
   461  //
   462  // The caller is responsible for calling the test's close method at the end of
   463  // the test.
   464  func makeMigrationTest(ctx context.Context, t testing.TB) migrationTest {
   465  	t.Helper()
   466  
   467  	oldMigrations := append([]migrationDescriptor(nil), backwardCompatibleMigrations...)
   468  	memMetrics := sql.MakeMemMetrics("migration-test-internal", time.Minute)
   469  	return migrationTest{
   470  		oldMigrations: oldMigrations,
   471  		memMetrics:    &memMetrics,
   472  	}
   473  }
   474  
   475  // pop removes the migration whose name starts with namePrefix from the list of
   476  // migrations run at server startup. It fails the test if the number of
   477  // migrations that match namePrefix is not exactly one.
   478  //
   479  // You must not call pop after calling start.
   480  func (mt *migrationTest) pop(t testing.TB, namePrefix string) migrationDescriptor {
   481  	t.Helper()
   482  
   483  	if mt.server != nil {
   484  		t.Fatal("migrationTest.pop must be called before mt.start")
   485  	}
   486  
   487  	var migration migrationDescriptor
   488  	var newMigrations []migrationDescriptor
   489  	for _, m := range backwardCompatibleMigrations {
   490  		if strings.HasPrefix(m.name, namePrefix) {
   491  			migration = m
   492  			continue
   493  		}
   494  		newMigrations = append(newMigrations, m)
   495  	}
   496  	if n := len(backwardCompatibleMigrations) - len(newMigrations); n != 1 {
   497  		t.Fatalf("expected prefix %q to match exactly one migration, but matched %d", namePrefix, n)
   498  	}
   499  	backwardCompatibleMigrations = newMigrations
   500  	return migration
   501  }
   502  
   503  // start starts a test server with the given serverArgs.
   504  func (mt *migrationTest) start(t testing.TB, serverArgs base.TestServerArgs) {
   505  	server, sqlDB, kvDB := serverutils.StartServer(t, serverArgs)
   506  	mt.server = server
   507  	mt.sqlDB = sqlutils.MakeSQLRunner(sqlDB)
   508  	mt.kvDB = kvDB
   509  }
   510  
   511  // runMigration triggers a manual run of migration. It does not mark migration
   512  // as completed, so subsequent calls will cause migration to be re-executed.
   513  // This is useful for verifying idempotency.
   514  //
   515  // You must call start before calling runMigration.
   516  func (mt *migrationTest) runMigration(ctx context.Context, m migrationDescriptor) error {
   517  	if m.workFn == nil {
   518  		// Migration has been baked in. Ignore it.
   519  		return nil
   520  	}
   521  	return m.workFn(ctx, runner{
   522  		settings:    mt.server.ClusterSettings(),
   523  		codec:       keys.SystemSQLCodec,
   524  		db:          mt.kvDB,
   525  		sqlExecutor: mt.server.InternalExecutor().(*sql.InternalExecutor),
   526  	})
   527  }
   528  
   529  // close stops the test server and restores package-global state.
   530  func (mt *migrationTest) close(ctx context.Context) {
   531  	if mt.server != nil {
   532  		mt.server.Stopper().Stop(ctx)
   533  	}
   534  	backwardCompatibleMigrations = mt.oldMigrations
   535  }
   536  
   537  func TestCreateSystemTable(t *testing.T) {
   538  	defer leaktest.AfterTest(t)()
   539  	ctx := context.Background()
   540  
   541  	table := sqlbase.NamespaceTable
   542  	table.ID = keys.MaxReservedDescID
   543  
   544  	prevPrivileges, ok := sqlbase.SystemAllowedPrivileges[table.ID]
   545  	defer func() {
   546  		if ok {
   547  			// Restore value of privileges.
   548  			sqlbase.SystemAllowedPrivileges[table.ID] = prevPrivileges
   549  		} else {
   550  			delete(sqlbase.SystemAllowedPrivileges, table.ID)
   551  		}
   552  	}()
   553  	sqlbase.SystemAllowedPrivileges[table.ID] = sqlbase.SystemAllowedPrivileges[keys.NamespaceTableID]
   554  
   555  	table.Name = "dummy"
   556  	nameKey := sqlbase.NewPublicTableKey(table.ParentID, table.Name).Key(keys.SystemSQLCodec)
   557  	descKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, table.ID)
   558  	descVal := sqlbase.WrapDescriptor(&table)
   559  
   560  	mt := makeMigrationTest(ctx, t)
   561  	defer mt.close(ctx)
   562  
   563  	mt.start(t, base.TestServerArgs{})
   564  
   565  	// Verify that the keys were not written.
   566  	if kv, err := mt.kvDB.Get(ctx, nameKey); err != nil {
   567  		t.Error(err)
   568  	} else if kv.Exists() {
   569  		t.Errorf("expected %q not to exist, got %v", nameKey, kv)
   570  	}
   571  	if kv, err := mt.kvDB.Get(ctx, descKey); err != nil {
   572  		t.Error(err)
   573  	} else if kv.Exists() {
   574  		t.Errorf("expected %q not to exist, got %v", descKey, kv)
   575  	}
   576  
   577  	migration := migrationDescriptor{
   578  		name: "add system.dummy table",
   579  		workFn: func(ctx context.Context, r runner) error {
   580  			return createSystemTable(ctx, r, table)
   581  		},
   582  	}
   583  	if err := mt.runMigration(ctx, migration); err != nil {
   584  		t.Fatal(err)
   585  	}
   586  
   587  	// Verify that the appropriate keys were written.
   588  	if kv, err := mt.kvDB.Get(ctx, nameKey); err != nil {
   589  		t.Error(err)
   590  	} else if !kv.Exists() {
   591  		t.Errorf("expected %q to exist, got that it doesn't exist", nameKey)
   592  	}
   593  	var descriptor sqlbase.Descriptor
   594  	if err := mt.kvDB.GetProto(ctx, descKey, &descriptor); err != nil {
   595  		t.Error(err)
   596  	} else if !proto.Equal(descVal, &descriptor) {
   597  		t.Errorf("expected %v for key %q, got %v", descVal, descKey, descriptor)
   598  	}
   599  
   600  	// Verify the idempotency of the migration.
   601  	if err := mt.runMigration(ctx, migration); err != nil {
   602  		t.Fatal(err)
   603  	}
   604  }
   605  
   606  func TestAdminUserExists(t *testing.T) {
   607  	defer leaktest.AfterTest(t)()
   608  	ctx := context.Background()
   609  
   610  	mt := makeMigrationTest(ctx, t)
   611  	defer mt.close(ctx)
   612  
   613  	migration := mt.pop(t, "add system.users isRole column and create admin role")
   614  	mt.start(t, base.TestServerArgs{})
   615  
   616  	// Create a user named "admin". We have to do a manual insert as "CREATE USER"
   617  	// knows about "isRole", but the migration hasn't run yet.
   618  	mt.sqlDB.Exec(t, `INSERT INTO system.users (username, "hashedPassword") VALUES ($1, '')`,
   619  		sqlbase.AdminRole)
   620  
   621  	// The revised migration in v2.1 upserts the admin user, so this should succeed.
   622  	if err := mt.runMigration(ctx, migration); err != nil {
   623  		t.Errorf("expected success, got %q", err)
   624  	}
   625  }
   626  
   627  func TestPublicRoleExists(t *testing.T) {
   628  	defer leaktest.AfterTest(t)()
   629  	ctx := context.Background()
   630  
   631  	mt := makeMigrationTest(ctx, t)
   632  	defer mt.close(ctx)
   633  
   634  	migration := mt.pop(t, "disallow public user or role name")
   635  	mt.start(t, base.TestServerArgs{})
   636  
   637  	// Create a user (we check for user or role) named "public".
   638  	// We have to do a manual insert as "CREATE USER" knows to disallow "public".
   639  	mt.sqlDB.Exec(t, `INSERT INTO system.users (username, "hashedPassword", "isRole") VALUES ($1, '', false)`,
   640  		sqlbase.PublicRole)
   641  
   642  	e := `found a user named public which is now a reserved name.`
   643  	// The revised migration in v2.1 upserts the admin user, so this should succeed.
   644  	if err := mt.runMigration(ctx, migration); !testutils.IsError(err, e) {
   645  		t.Errorf("expected error %q got %q", e, err)
   646  	}
   647  
   648  	// Now try with a role instead of a user.
   649  	mt.sqlDB.Exec(t, `DELETE FROM system.users WHERE username = $1`, sqlbase.PublicRole)
   650  	mt.sqlDB.Exec(t, `INSERT INTO system.users (username, "hashedPassword", "isRole") VALUES ($1, '', true)`,
   651  		sqlbase.PublicRole)
   652  
   653  	e = `found a role named public which is now a reserved name.`
   654  	// The revised migration in v2.1 upserts the admin user, so this should succeed.
   655  	if err := mt.runMigration(ctx, migration); !testutils.IsError(err, e) {
   656  		t.Errorf("expected error %q got %q", e, err)
   657  	}
   658  
   659  	// Drop it and try again.
   660  	mt.sqlDB.Exec(t, `DELETE FROM system.users WHERE username = $1`, sqlbase.PublicRole)
   661  	if err := mt.runMigration(ctx, migration); err != nil {
   662  		t.Errorf("expected success, got %q", err)
   663  	}
   664  }
   665  
   666  func TestReplayMigrations(t *testing.T) {
   667  	defer leaktest.AfterTest(t)()
   668  	ctx := context.Background()
   669  
   670  	mt := makeMigrationTest(ctx, t)
   671  	defer mt.close(ctx)
   672  
   673  	mt.start(t, base.TestServerArgs{})
   674  
   675  	// Test all migrations again. Starting the server did the first round.
   676  	for _, m := range backwardCompatibleMigrations {
   677  		if err := mt.runMigration(ctx, m); err != nil {
   678  			t.Error(err)
   679  		}
   680  	}
   681  }
   682  
   683  func TestExpectedInitialRangeCount(t *testing.T) {
   684  	defer leaktest.AfterTest(t)()
   685  
   686  	ctx := context.Background()
   687  	s, sqlDB, kvDB := serverutils.StartServer(t, base.TestServerArgs{})
   688  	defer s.Stopper().Stop(ctx)
   689  
   690  	testutils.SucceedsSoon(t, func() error {
   691  		lastMigration := backwardCompatibleMigrations[len(backwardCompatibleMigrations)-1]
   692  		if _, err := kvDB.Get(ctx, migrationKey(keys.SystemSQLCodec, lastMigration)); err != nil {
   693  			return errors.New("last migration has not completed")
   694  		}
   695  
   696  		sysCfg := s.GossipI().(*gossip.Gossip).GetSystemConfig()
   697  		if sysCfg == nil {
   698  			return errors.New("gossipped system config not available")
   699  		}
   700  
   701  		rows, err := sqlDB.Query(`SELECT range_id, start_key, end_key FROM crdb_internal.ranges`)
   702  		if err != nil {
   703  			return err
   704  		}
   705  		defer rows.Close()
   706  		nranges := 0
   707  		for rows.Next() {
   708  			var rangeID int
   709  			var startKey, endKey []byte
   710  			if err := rows.Scan(&rangeID, &startKey, &endKey); err != nil {
   711  				return err
   712  			}
   713  			if sysCfg.NeedsSplit(startKey, endKey) {
   714  				return fmt.Errorf("range %d needs split", rangeID)
   715  			}
   716  			nranges++
   717  		}
   718  		if rows.Err() != nil {
   719  			return err
   720  		}
   721  
   722  		expectedRanges, err := s.ExpectedInitialRangeCount()
   723  		if err != nil {
   724  			return err
   725  		}
   726  		if expectedRanges != nranges {
   727  			return fmt.Errorf("expected %d ranges but got %d", expectedRanges, nranges)
   728  		}
   729  
   730  		return nil
   731  	})
   732  }
   733  
   734  func TestUpdateSystemLocationData(t *testing.T) {
   735  	defer leaktest.AfterTest(t)()
   736  	ctx := context.Background()
   737  
   738  	mt := makeMigrationTest(ctx, t)
   739  	defer mt.close(ctx)
   740  
   741  	migration := mt.pop(t, "update system.locations with default location data")
   742  	mt.start(t, base.TestServerArgs{})
   743  
   744  	// Check that we don't have any data in the system.locations table without the migration.
   745  	var count int
   746  	mt.sqlDB.QueryRow(t, `SELECT count(*) FROM system.locations`).Scan(&count)
   747  	if count != 0 {
   748  		t.Fatalf("Exected to find 0 rows in system.locations. Found  %d instead", count)
   749  	}
   750  
   751  	// Run the migration to insert locations.
   752  	if err := mt.runMigration(ctx, migration); err != nil {
   753  		t.Errorf("expected success, got %q", err)
   754  	}
   755  
   756  	// Check that we have all of the expected locations.
   757  	mt.sqlDB.QueryRow(t, `SELECT count(*) FROM system.locations`).Scan(&count)
   758  	if count != len(roachpb.DefaultLocationInformation) {
   759  		t.Fatalf("Exected to find 0 rows in system.locations. Found  %d instead", count)
   760  	}
   761  }
   762  
   763  func TestMigrateNamespaceTableDescriptors(t *testing.T) {
   764  	defer leaktest.AfterTest(t)()
   765  	ctx := context.Background()
   766  
   767  	mt := makeMigrationTest(ctx, t)
   768  	defer mt.close(ctx)
   769  
   770  	migration := mt.pop(t, "create new system.namespace table")
   771  	mt.start(t, base.TestServerArgs{})
   772  
   773  	// Since we're already on 20.1, mimic the beginning state by deleting the
   774  	// new namespace descriptor.
   775  	key := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, keys.NamespaceTableID)
   776  	require.NoError(t, mt.kvDB.Del(ctx, key))
   777  
   778  	deprecatedKey := sqlbase.MakeDescMetadataKey(keys.SystemSQLCodec, keys.DeprecatedNamespaceTableID)
   779  	desc := &sqlbase.Descriptor{}
   780  	require.NoError(t, mt.kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
   781  		_, err := txn.GetProtoTs(ctx, deprecatedKey, desc)
   782  		return err
   783  	}))
   784  
   785  	// Run the migration.
   786  	require.NoError(t, mt.runMigration(ctx, migration))
   787  
   788  	require.NoError(t, mt.kvDB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
   789  		// Check that the persisted descriptors now match our in-memory versions,
   790  		// ignoring create and modification times.
   791  		{
   792  			ts, err := txn.GetProtoTs(ctx, key, desc)
   793  			require.NoError(t, err)
   794  			table := desc.Table(ts)
   795  			table.CreateAsOfTime = sqlbase.NamespaceTable.CreateAsOfTime
   796  			table.ModificationTime = sqlbase.NamespaceTable.ModificationTime
   797  			require.True(t, table.Equal(sqlbase.NamespaceTable))
   798  		}
   799  		{
   800  			ts, err := txn.GetProtoTs(ctx, deprecatedKey, desc)
   801  			require.NoError(t, err)
   802  			table := desc.Table(ts)
   803  			table.CreateAsOfTime = sqlbase.DeprecatedNamespaceTable.CreateAsOfTime
   804  			table.ModificationTime = sqlbase.DeprecatedNamespaceTable.ModificationTime
   805  			require.True(t, table.Equal(sqlbase.DeprecatedNamespaceTable))
   806  		}
   807  		return nil
   808  	}))
   809  }
   810  
   811  func TestAlterSystemJobsTable(t *testing.T) {
   812  	defer leaktest.AfterTest(t)()
   813  	ctx := context.Background()
   814  
   815  	// We need to use "old" jobs table descriptor without newly added columns
   816  	// in order to test migration.
   817  	// oldJobsTableSchema is system.jobs definition prior to 20.2
   818  	oldJobsTableSchema := `
   819  CREATE TABLE system.jobs (
   820  	id                INT8      DEFAULT unique_rowid() PRIMARY KEY,
   821  	status            STRING    NOT NULL,
   822  	created           TIMESTAMP NOT NULL DEFAULT now(),
   823  	payload           BYTES     NOT NULL,
   824  	progress          BYTES,
   825  	INDEX (status, created),
   826  
   827  	FAMILY (id, status, created, payload),
   828  	FAMILY progress (progress)
   829  )
   830  `
   831  	oldJobsTable, err := sql.CreateTestTableDescriptor(
   832  		context.Background(),
   833  		keys.SystemDatabaseID,
   834  		keys.JobsTableID,
   835  		oldJobsTableSchema,
   836  		sqlbase.JobsTable.Privileges,
   837  	)
   838  	require.NoError(t, err)
   839  
   840  	const primaryFamilyName = "fam_0_id_status_created_payload"
   841  	oldPrimaryFamilyColumns := []string{"id", "status", "created", "payload"}
   842  	newPrimaryFamilyColumns := append(
   843  		oldPrimaryFamilyColumns, "created_by_type", "created_by_id")
   844  
   845  	// Sanity check oldJobsTable does not have new columns.
   846  	require.Equal(t, 5, len(oldJobsTable.Columns))
   847  	require.Equal(t, 2, len(oldJobsTable.Families))
   848  	require.Equal(t, primaryFamilyName, oldJobsTable.Families[0].Name)
   849  	require.Equal(t, oldPrimaryFamilyColumns, oldJobsTable.Families[0].ColumnNames)
   850  
   851  	jobsTable := sqlbase.JobsTable
   852  	sqlbase.JobsTable = oldJobsTable
   853  	defer func() {
   854  		sqlbase.JobsTable = jobsTable
   855  	}()
   856  
   857  	mt := makeMigrationTest(ctx, t)
   858  	defer mt.close(ctx)
   859  
   860  	migration := mt.pop(t, "add created_by columns to system.jobs")
   861  	mt.start(t, base.TestServerArgs{})
   862  
   863  	// Run migration and verify we have added columns and renamed column family.
   864  	require.NoError(t, mt.runMigration(ctx, migration))
   865  
   866  	newJobsTable := sqlbase.GetTableDescriptor(
   867  		mt.kvDB, keys.SystemSQLCodec, "system", "jobs")
   868  	require.Equal(t, 7, len(newJobsTable.Columns))
   869  	require.Equal(t, "created_by_type", newJobsTable.Columns[5].Name)
   870  	require.Equal(t, "created_by_id", newJobsTable.Columns[6].Name)
   871  	require.Equal(t, 2, len(newJobsTable.Families))
   872  	// Ensure we keep old family name.
   873  	require.Equal(t, primaryFamilyName, newJobsTable.Families[0].Name)
   874  	// Make sure our primary family has new columns added to it.
   875  	require.Equal(t, newPrimaryFamilyColumns, newJobsTable.Families[0].ColumnNames)
   876  
   877  	// Run the migration again -- it should be a no-op.
   878  	require.NoError(t, mt.runMigration(ctx, migration))
   879  	newJobsTableAgain := sqlbase.GetTableDescriptor(
   880  		mt.kvDB, keys.SystemSQLCodec, "system", "jobs")
   881  	require.True(t, proto.Equal(newJobsTable, newJobsTableAgain))
   882  }