github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/cmd/noms/noms_sync_test.go (about)

     1  // Copyright 2019 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  // This file incorporates work covered by the following copyright and
    16  // permission notice:
    17  //
    18  // Copyright 2016 Attic Labs, Inc. All rights reserved.
    19  // Licensed under the Apache License, version 2.0:
    20  // http://www.apache.org/licenses/LICENSE-2.0
    21  
    22  package main
    23  
    24  import (
    25  	"context"
    26  	"os"
    27  	"testing"
    28  
    29  	"github.com/stretchr/testify/suite"
    30  
    31  	"github.com/dolthub/dolt/go/store/datas"
    32  	"github.com/dolthub/dolt/go/store/nbs"
    33  	"github.com/dolthub/dolt/go/store/spec"
    34  	"github.com/dolthub/dolt/go/store/types"
    35  	"github.com/dolthub/dolt/go/store/util/clienttest"
    36  )
    37  
    38  func TestSync(t *testing.T) {
    39  	suite.Run(t, &nomsSyncTestSuite{})
    40  }
    41  
    42  type nomsSyncTestSuite struct {
    43  	clienttest.ClientTestSuite
    44  }
    45  
    46  func (s *nomsSyncTestSuite) TestSyncValidation() {
    47  	cs, err := nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir, clienttest.DefaultMemTableSize)
    48  	s.NoError(err)
    49  	sourceDB := datas.NewDatabase(cs)
    50  	source1, err := sourceDB.GetDataset(context.Background(), "src")
    51  	s.NoError(err)
    52  	source1, err = sourceDB.CommitValue(context.Background(), source1, types.Float(42))
    53  	s.NoError(err)
    54  	source1HeadRef, err := mustHead(source1).Hash(types.Format_7_18)
    55  	s.NoError(err)
    56  	source1.Database().Close()
    57  	sourceSpecMissingHashSymbol := spec.CreateValueSpecString("nbs", s.DBDir, source1HeadRef.String())
    58  
    59  	sinkDatasetSpec := spec.CreateValueSpecString("nbs", s.DBDir2, "dest")
    60  
    61  	defer func() {
    62  		err := recover()
    63  		s.Equal(clienttest.ExitError{Code: 1}, err)
    64  	}()
    65  
    66  	s.MustRun(main, []string{"sync", sourceSpecMissingHashSymbol, sinkDatasetSpec})
    67  }
    68  
    69  func (s *nomsSyncTestSuite) TestSync() {
    70  	defer s.NoError(os.RemoveAll(s.DBDir2))
    71  
    72  	cs, err := nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir, clienttest.DefaultMemTableSize)
    73  	s.NoError(err)
    74  	sourceDB := datas.NewDatabase(cs)
    75  	source1, err := sourceDB.GetDataset(context.Background(), "src")
    76  	s.NoError(err)
    77  	source1, err = sourceDB.CommitValue(context.Background(), source1, types.Float(42))
    78  	s.NoError(err)
    79  	source1HeadRef, err := mustHead(source1).Hash(types.Format_7_18) // Remember first head, so we can sync to it.
    80  	s.NoError(err)
    81  	source1, err = sourceDB.CommitValue(context.Background(), source1, types.Float(43))
    82  	s.NoError(err)
    83  	sourceDB.Close()
    84  
    85  	// Pull from a hash to a not-yet-existing dataset in a new DB
    86  	sourceSpec := spec.CreateValueSpecString("nbs", s.DBDir, "#"+source1HeadRef.String())
    87  	sinkDatasetSpec := spec.CreateValueSpecString("nbs", s.DBDir2, "dest")
    88  	sout, _ := s.MustRun(main, []string{"sync", sourceSpec, sinkDatasetSpec})
    89  	s.Regexp("Synced", sout)
    90  
    91  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir2, clienttest.DefaultMemTableSize)
    92  	s.NoError(err)
    93  	db := datas.NewDatabase(cs)
    94  	dest, err := db.GetDataset(context.Background(), "dest")
    95  	s.NoError(err)
    96  	s.True(types.Float(42).Equals(mustHeadValue(dest)))
    97  	db.Close()
    98  
    99  	// Pull from a dataset in one DB to an existing dataset in another
   100  	sourceDataset := spec.CreateValueSpecString("nbs", s.DBDir, "src")
   101  	sout, _ = s.MustRun(main, []string{"sync", sourceDataset, sinkDatasetSpec})
   102  	s.Regexp("Synced", sout)
   103  
   104  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir2, clienttest.DefaultMemTableSize)
   105  	s.NoError(err)
   106  	db = datas.NewDatabase(cs)
   107  	dest, err = db.GetDataset(context.Background(), "dest")
   108  	s.NoError(err)
   109  	s.True(types.Float(43).Equals(mustHeadValue(dest)))
   110  	db.Close()
   111  
   112  	// Pull when sink dataset is already up to date
   113  	sout, _ = s.MustRun(main, []string{"sync", sourceDataset, sinkDatasetSpec})
   114  	s.Regexp("up to date", sout)
   115  
   116  	// Pull from a source dataset to a not-yet-existing dataset in another DB, BUT all the needed chunks already exists in the sink.
   117  	sinkDatasetSpec = spec.CreateValueSpecString("nbs", s.DBDir2, "dest2")
   118  	sout, _ = s.MustRun(main, []string{"sync", sourceDataset, sinkDatasetSpec})
   119  	s.Regexp("Created", sout)
   120  
   121  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir2, clienttest.DefaultMemTableSize)
   122  	s.NoError(err)
   123  	db = datas.NewDatabase(cs)
   124  	dest, err = db.GetDataset(context.Background(), "dest2")
   125  	s.NoError(err)
   126  	s.True(types.Float(43).Equals(mustHeadValue(dest)))
   127  	db.Close()
   128  }
   129  
   130  func (s *nomsSyncTestSuite) TestSync_Issue2598() {
   131  	defer s.NoError(os.RemoveAll(s.DBDir2))
   132  
   133  	cs, err := nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir, clienttest.DefaultMemTableSize)
   134  	s.NoError(err)
   135  	sourceDB := datas.NewDatabase(cs)
   136  	// Create dataset "src1", which has a lineage of two commits.
   137  	source1, err := sourceDB.GetDataset(context.Background(), "src1")
   138  	s.NoError(err)
   139  	source1, err = sourceDB.CommitValue(context.Background(), source1, types.Float(42))
   140  	s.NoError(err)
   141  	source1, err = sourceDB.CommitValue(context.Background(), source1, types.Float(43))
   142  	s.NoError(err)
   143  
   144  	// Create dataset "src2", with a lineage of one commit.
   145  	source2, err := sourceDB.GetDataset(context.Background(), "src2")
   146  	s.NoError(err)
   147  	source2, err = sourceDB.CommitValue(context.Background(), source2, types.Float(1))
   148  	s.NoError(err)
   149  
   150  	sourceDB.Close() // Close Database backing both Datasets
   151  
   152  	// Sync over "src1"
   153  	sourceDataset := spec.CreateValueSpecString("nbs", s.DBDir, "src1")
   154  	sinkDatasetSpec := spec.CreateValueSpecString("nbs", s.DBDir2, "dest")
   155  	sout, _ := s.MustRun(main, []string{"sync", sourceDataset, sinkDatasetSpec})
   156  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir2, clienttest.DefaultMemTableSize)
   157  	s.NoError(err)
   158  	db := datas.NewDatabase(cs)
   159  	dest, err := db.GetDataset(context.Background(), "dest")
   160  	s.NoError(err)
   161  	s.True(types.Float(43).Equals(mustHeadValue(dest)))
   162  	db.Close()
   163  
   164  	// Now, try syncing a second dataset. This crashed in issue #2598
   165  	sourceDataset2 := spec.CreateValueSpecString("nbs", s.DBDir, "src2")
   166  	sinkDatasetSpec2 := spec.CreateValueSpecString("nbs", s.DBDir2, "dest2")
   167  	sout, _ = s.MustRun(main, []string{"sync", sourceDataset2, sinkDatasetSpec2})
   168  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir2, clienttest.DefaultMemTableSize)
   169  	s.NoError(err)
   170  	db = datas.NewDatabase(cs)
   171  	dest, err = db.GetDataset(context.Background(), "dest2")
   172  	s.NoError(err)
   173  	s.True(types.Float(1).Equals(mustHeadValue(dest)))
   174  	db.Close()
   175  
   176  	sout, _ = s.MustRun(main, []string{"sync", sourceDataset, sinkDatasetSpec})
   177  	s.Regexp("up to date", sout)
   178  }
   179  
   180  func (s *nomsSyncTestSuite) TestRewind() {
   181  	var err error
   182  	cs, err := nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir, clienttest.DefaultMemTableSize)
   183  	s.NoError(err)
   184  	sourceDB := datas.NewDatabase(cs)
   185  	src, err := sourceDB.GetDataset(context.Background(), "foo")
   186  	s.NoError(err)
   187  	src, err = sourceDB.CommitValue(context.Background(), src, types.Float(42))
   188  	s.NoError(err)
   189  	rewindRef := mustHeadRef(src).TargetHash()
   190  	src, err = sourceDB.CommitValue(context.Background(), src, types.Float(43))
   191  	s.NoError(err)
   192  	sourceDB.Close() // Close Database backing both Datasets
   193  
   194  	sourceSpec := spec.CreateValueSpecString("nbs", s.DBDir, "#"+rewindRef.String())
   195  	sinkDatasetSpec := spec.CreateValueSpecString("nbs", s.DBDir, "foo")
   196  	s.MustRun(main, []string{"sync", sourceSpec, sinkDatasetSpec})
   197  
   198  	cs, err = nbs.NewLocalStore(context.Background(), types.Format_Default.VersionString(), s.DBDir, clienttest.DefaultMemTableSize)
   199  	s.NoError(err)
   200  	db := datas.NewDatabase(cs)
   201  	dest, err := db.GetDataset(context.Background(), "foo")
   202  	s.NoError(err)
   203  	s.True(types.Float(42).Equals(mustHeadValue(dest)))
   204  	db.Close()
   205  }