github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/doltdb/feature_version_test.go (about)

     1  // Copyright 2020 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package doltdb_test
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/require"
    23  
    24  	"github.com/dolthub/dolt/go/cmd/dolt/cli"
    25  	"github.com/dolthub/dolt/go/cmd/dolt/commands"
    26  	"github.com/dolthub/dolt/go/libraries/doltcore/doltdb"
    27  	"github.com/dolthub/dolt/go/libraries/doltcore/dtestutils"
    28  	"github.com/dolthub/dolt/go/libraries/doltcore/env"
    29  )
    30  
    31  const (
    32  	newVersion doltdb.FeatureVersion = 1 << 19
    33  	oldVersion doltdb.FeatureVersion = 1 << 13
    34  )
    35  
    36  // |doltdb.FeatureVersion| is manipulated during these integration tests.
    37  // Save a copy here to assert that it was correctly restored.
    38  var DoltFeatureVersionCopy = doltdb.DoltFeatureVersion
    39  
    40  type fvTest struct {
    41  	name   string
    42  	setup  []fvCommand
    43  	expVer doltdb.FeatureVersion
    44  
    45  	// for error path testing
    46  	errCmds []fvCommand
    47  }
    48  
    49  type args []string
    50  
    51  type fvCommand struct {
    52  	user fvUser
    53  	cmd  cli.Command
    54  	args args
    55  }
    56  
    57  func (cmd fvCommand) exec(ctx context.Context, dEnv *env.DoltEnv) int {
    58  	// execute the command using |cmd.user|'s Feature Version
    59  	doltdb.DoltFeatureVersion = cmd.user.vers
    60  	defer func() { doltdb.DoltFeatureVersion = DoltFeatureVersionCopy }()
    61  
    62  	return cmd.cmd.Exec(ctx, cmd.cmd.Name(), cmd.args, dEnv)
    63  }
    64  
    65  type fvUser struct {
    66  	vers doltdb.FeatureVersion
    67  }
    68  
    69  var NewClient = fvUser{vers: newVersion}
    70  var OldClient = fvUser{vers: oldVersion}
    71  
    72  func TestFeatureVersion(t *testing.T) {
    73  
    74  	tests := []fvTest{
    75  		{
    76  			name: "smoke test",
    77  			setup: []fvCommand{
    78  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
    79  			},
    80  			expVer: oldVersion,
    81  		},
    82  		{
    83  			name: "CREATE TABLE statements write feature version",
    84  			setup: []fvCommand{
    85  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
    86  				{NewClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE quiz (pk int PRIMARY KEY);"}},
    87  			},
    88  			expVer: newVersion,
    89  		},
    90  		{
    91  			name: "DROP TABLE statements write feature version",
    92  			setup: []fvCommand{
    93  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
    94  				{NewClient, commands.SqlCmd{}, args{"-q", "DROP TABLE test;"}},
    95  			},
    96  			expVer: newVersion,
    97  		},
    98  		{
    99  			name: "schema changes write feature version",
   100  			setup: []fvCommand{
   101  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
   102  				{NewClient, commands.SqlCmd{}, args{"-q", "ALTER TABLE test ADD COLUMN c0 int;"}},
   103  			},
   104  			expVer: newVersion,
   105  		},
   106  		{
   107  			name: "INSERT statements write feature version",
   108  			setup: []fvCommand{
   109  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
   110  				{NewClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (0);"}},
   111  			},
   112  			expVer: newVersion,
   113  		},
   114  		{
   115  			name: "UPDATE statements write feature version",
   116  			setup: []fvCommand{
   117  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
   118  				{OldClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (0);"}},
   119  				{NewClient, commands.SqlCmd{}, args{"-q", "UPDATE test SET pk = 1;"}},
   120  			},
   121  			expVer: newVersion,
   122  		},
   123  		{
   124  			name: "DELETE statements write feature version",
   125  			setup: []fvCommand{
   126  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
   127  				{OldClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (0);"}},
   128  				{NewClient, commands.SqlCmd{}, args{"-q", "DELETE FROM test WHERE pk = 0;"}},
   129  			},
   130  			expVer: newVersion,
   131  		},
   132  		{
   133  			name: "new client writes to table, locking out old client",
   134  			setup: []fvCommand{
   135  				{OldClient, commands.SqlCmd{}, args{"-q", "CREATE TABLE test (pk int PRIMARY KEY);"}},
   136  				{OldClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (0);"}},
   137  				{NewClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (1);"}},
   138  			},
   139  			errCmds: []fvCommand{
   140  				// old client can't write
   141  				{OldClient, commands.SqlCmd{}, args{"-q", "INSERT INTO test VALUES (2);"}},
   142  				// old client can't read
   143  				{OldClient, commands.SqlCmd{}, args{"-q", "SELECT * FROM test;"}},
   144  			},
   145  			expVer: newVersion,
   146  		},
   147  	}
   148  
   149  	ctx := context.Background()
   150  	for _, test := range tests {
   151  		t.Run(test.name, func(t *testing.T) {
   152  
   153  			doltdb.DoltFeatureVersion = oldVersion
   154  			dEnv := dtestutils.CreateTestEnv()
   155  			doltdb.DoltFeatureVersion = DoltFeatureVersionCopy
   156  
   157  			for _, cmd := range test.setup {
   158  				code := cmd.exec(ctx, dEnv)
   159  				require.Equal(t, 0, code)
   160  			}
   161  			for _, cmd := range test.errCmds {
   162  				code := cmd.exec(ctx, dEnv)
   163  				require.NotEqual(t, 0, code)
   164  			}
   165  
   166  			// execute assertions with newVersion to avoid OutOfDate errors
   167  			doltdb.DoltFeatureVersion = newVersion
   168  			defer func() { doltdb.DoltFeatureVersion = DoltFeatureVersionCopy }()
   169  
   170  			assertFeatureVersion := func(r *doltdb.RootValue) {
   171  				act, ok, err := r.GetFeatureVersion(ctx)
   172  				require.NoError(t, err)
   173  				require.True(t, ok)
   174  				assert.Equal(t, test.expVer, act)
   175  			}
   176  
   177  			working, err := dEnv.WorkingRoot(ctx)
   178  			require.NoError(t, err)
   179  			assertFeatureVersion(working)
   180  		})
   181  
   182  		// ensure |doltdb.DoltFeatureVersion| was restored
   183  		assert.Equal(t, DoltFeatureVersionCopy, doltdb.DoltFeatureVersion)
   184  	}
   185  }