github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/cmd/noms/noms_commit_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/d"
    32  	"github.com/dolthub/dolt/go/store/datas"
    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  type nomsCommitTestSuite struct {
    39  	clienttest.ClientTestSuite
    40  }
    41  
    42  func TestNomsCommit(t *testing.T) {
    43  	suite.Run(t, &nomsCommitTestSuite{})
    44  }
    45  
    46  func (s *nomsCommitTestSuite) setupDataset(name string, doCommit bool) (sp spec.Spec, ref types.Ref) {
    47  	var err error
    48  	sp, err = spec.ForDataset(spec.CreateValueSpecString("nbs", s.DBDir, name))
    49  	s.NoError(err)
    50  
    51  	v := types.String("testcommit")
    52  	ref, err = sp.GetDatabase(context.Background()).WriteValue(context.Background(), v)
    53  	s.NoError(err)
    54  
    55  	if doCommit {
    56  		_, err = sp.GetDatabase(context.Background()).CommitValue(context.Background(), sp.GetDataset(context.Background()), ref)
    57  		s.NoError(err)
    58  	}
    59  	return
    60  }
    61  
    62  func (s *nomsCommitTestSuite) TestNomsCommitReadPathFromStdin() {
    63  	sp, ref := s.setupDataset("commitTestStdin", false)
    64  	defer sp.Close()
    65  
    66  	_, ok := sp.GetDataset(context.Background()).MaybeHead()
    67  	s.False(ok, "should not have a commit")
    68  
    69  	oldStdin := os.Stdin
    70  	newStdin, stdinWriter, err := os.Pipe()
    71  	s.NoError(err)
    72  
    73  	os.Stdin = newStdin
    74  	defer func() {
    75  		os.Stdin = oldStdin
    76  	}()
    77  
    78  	go func() {
    79  		stdinWriter.Write([]byte("#" + ref.TargetHash().String() + "\n"))
    80  		stdinWriter.Close()
    81  	}()
    82  	stdoutString, stderrString := s.MustRun(main, []string{"commit", sp.String()})
    83  	s.Empty(stderrString)
    84  	s.Contains(stdoutString, "New head #")
    85  
    86  	sp, _ = spec.ForDataset(sp.String())
    87  	defer sp.Close()
    88  
    89  	commit, ok := sp.GetDataset(context.Background()).MaybeHead()
    90  	s.True(ok, "should have a commit now")
    91  	value, ok, err := commit.MaybeGet(datas.ValueField)
    92  	s.NoError(err)
    93  	s.True(ok)
    94  	h, err := value.Hash(types.Format_7_18)
    95  	s.NoError(err)
    96  	s.True(h == ref.TargetHash(), "commit.value hash == writevalue hash")
    97  
    98  	meta, ok, err := commit.MaybeGet(datas.CommitMetaField)
    99  	s.NoError(err)
   100  	s.True(ok)
   101  	d, ok, err := meta.(types.Struct).MaybeGet("date")
   102  	s.NoError(err)
   103  	s.True(ok)
   104  	s.NotEmpty(d)
   105  }
   106  
   107  func (s *nomsCommitTestSuite) TestNomsCommitToDatasetWithoutHead() {
   108  	sp, ref := s.setupDataset("commitTest", false)
   109  	defer sp.Close()
   110  
   111  	_, ok := sp.GetDataset(context.Background()).MaybeHead()
   112  	s.False(ok, "should not have a commit")
   113  
   114  	stdoutString, stderrString := s.MustRun(main, []string{"commit", "#" + ref.TargetHash().String(), sp.String()})
   115  	s.Empty(stderrString)
   116  	s.Contains(stdoutString, "New head #")
   117  
   118  	sp, _ = spec.ForDataset(sp.String())
   119  	defer sp.Close()
   120  
   121  	commit, ok := sp.GetDataset(context.Background()).MaybeHead()
   122  	s.True(ok, "should have a commit now")
   123  	value, ok, err := commit.MaybeGet(datas.ValueField)
   124  	s.NoError(err)
   125  	s.True(ok)
   126  	h, err := value.Hash(types.Format_7_18)
   127  	s.NoError(err)
   128  	s.True(h == ref.TargetHash(), "commit.value hash == writevalue hash")
   129  
   130  	metaVal, ok, err := commit.MaybeGet(datas.CommitMetaField)
   131  	s.NoError(err)
   132  	s.True(ok)
   133  	meta := metaVal.(types.Struct)
   134  	d, ok, err := meta.MaybeGet("date")
   135  	s.NoError(err)
   136  	s.True(ok)
   137  	s.NotEmpty(d)
   138  }
   139  
   140  func structFieldEqual(old, now types.Struct, field string) bool {
   141  	oldValue, oldOk, err := old.MaybeGet(field)
   142  	d.PanicIfError(err)
   143  	nowValue, nowOk, err := now.MaybeGet(field)
   144  	d.PanicIfError(err)
   145  	return oldOk && nowOk && nowValue.Equals(oldValue)
   146  }
   147  
   148  func (s *nomsCommitTestSuite) runDuplicateTest(allowDuplicate bool) {
   149  	dsName := "commitTestDuplicate"
   150  	sp, ref := s.setupDataset(dsName, true)
   151  	defer sp.Close()
   152  
   153  	_, ok, err := sp.GetDataset(context.Background()).MaybeHeadValue()
   154  	s.NoError(err)
   155  	s.True(ok, "should have a commit")
   156  
   157  	cliOptions := []string{"commit"}
   158  	if allowDuplicate {
   159  		cliOptions = append(cliOptions, "--allow-dupe=1")
   160  	}
   161  	cliOptions = append(cliOptions, dsName+".value", sp.String())
   162  
   163  	stdoutString, stderrString, errI := s.Run(main, cliOptions)
   164  	s.Nil(errI)
   165  	s.Empty(stderrString)
   166  	if allowDuplicate {
   167  		s.NotContains(stdoutString, "Commit aborted")
   168  		s.Contains(stdoutString, "New head #")
   169  	} else {
   170  		s.Contains(stdoutString, "Commit aborted")
   171  	}
   172  
   173  	sp, _ = spec.ForDataset(sp.String())
   174  	defer sp.Close()
   175  
   176  	value, ok, err := sp.GetDataset(context.Background()).MaybeHeadValue()
   177  	s.NoError(err)
   178  	s.True(ok, "should still have a commit")
   179  	valH, err := value.Hash(types.Format_7_18)
   180  	s.NoError(err)
   181  	refH, err := ref.Hash(types.Format_7_18)
   182  	s.NoError(err)
   183  	s.True(valH == refH, "commit.value hash == previous commit hash")
   184  }
   185  
   186  func (s *nomsCommitTestSuite) TestNomsCommitDuplicate() {
   187  	s.runDuplicateTest(false)
   188  	s.runDuplicateTest(true)
   189  }
   190  
   191  func (s *nomsCommitTestSuite) TestNomsCommitMetadata() {
   192  	dsName := "commitTestMetadata"
   193  	sp, _ := s.setupDataset(dsName, true)
   194  	defer sp.Close()
   195  
   196  	dsHead, ok := sp.GetDataset(context.Background()).MaybeHead()
   197  	s.True(ok)
   198  	metaOldVal, ok, err := dsHead.MaybeGet(datas.CommitMetaField)
   199  	s.NoError(err)
   200  	s.True(ok)
   201  	metaOld := metaOldVal.(types.Struct)
   202  
   203  	stdoutString, stderrString, errI := s.Run(main, []string{"commit", "--allow-dupe=1", "--message=foo", dsName + ".value", sp.String()})
   204  	s.Nil(errI)
   205  	s.Empty(stderrString)
   206  	s.Contains(stdoutString, "New head #")
   207  
   208  	sp, _ = spec.ForDataset(sp.String())
   209  	defer sp.Close()
   210  
   211  	dsHead, ok = sp.GetDataset(context.Background()).MaybeHead()
   212  	s.True(ok)
   213  	metaNewVal, ok, err := dsHead.MaybeGet(datas.CommitMetaField)
   214  	s.NoError(err)
   215  	s.True(ok)
   216  	metaNew := metaNewVal.(types.Struct)
   217  
   218  	s.False(metaOld.Equals(metaNew), "meta didn't change")
   219  	s.False(structFieldEqual(metaOld, metaNew, "date"), "date didn't change")
   220  	s.False(structFieldEqual(metaOld, metaNew, "message"), "message didn't change")
   221  	msgVal, ok, err := metaNew.MaybeGet("message")
   222  	s.NoError(err)
   223  	s.True(ok)
   224  	s.True(msgVal.Equals(types.String("foo")), "message wasn't set")
   225  
   226  	metaOld = metaNew
   227  
   228  	stdoutString, stderrString = s.MustRun(main, []string{"commit", "--allow-dupe=1", "--meta=message=bar", "--date=" + spec.CommitMetaDateFormat[:20], dsName + ".value", sp.String()})
   229  	s.Empty(stderrString)
   230  	s.Contains(stdoutString, "New head #")
   231  
   232  	sp, _ = spec.ForDataset(sp.String())
   233  	defer sp.Close()
   234  
   235  	dsHead, ok = sp.GetDataset(context.Background()).MaybeHead()
   236  	s.True(ok)
   237  	metaNewVal, ok, err = dsHead.MaybeGet(datas.CommitMetaField)
   238  	s.NoError(err)
   239  	s.True(ok)
   240  	metaNew = metaNewVal.(types.Struct)
   241  
   242  	s.False(metaOld.Equals(metaNew), "meta didn't change")
   243  	s.False(structFieldEqual(metaOld, metaNew, "date"), "date didn't change")
   244  	s.False(structFieldEqual(metaOld, metaNew, "message"), "message didn't change")
   245  
   246  	msgVal, ok, err = metaNew.MaybeGet("message")
   247  	s.NoError(err)
   248  	s.True(ok)
   249  	s.True(msgVal.Equals(types.String("bar")), "message wasn't set")
   250  }
   251  
   252  func (s *nomsCommitTestSuite) TestNomsCommitHashNotFound() {
   253  	sp, _ := s.setupDataset("commitTestBadHash", true)
   254  	defer sp.Close()
   255  
   256  	s.Panics(func() {
   257  		s.MustRun(main, []string{"commit", "#9ei6fbrs0ujo51vifd3f2eebufo4lgdu", sp.String()})
   258  	})
   259  }
   260  
   261  func (s *nomsCommitTestSuite) TestNomsCommitMetadataBadDateFormat() {
   262  	sp, ref := s.setupDataset("commitTestMetadata", true)
   263  	defer sp.Close()
   264  
   265  	s.Panics(func() {
   266  		s.MustRun(main, []string{"commit", "--allow-dupe=1", "--date=a", "#" + ref.TargetHash().String(), sp.String()})
   267  	})
   268  }
   269  
   270  func (s *nomsCommitTestSuite) TestNomsCommitInvalidMetadataPaths() {
   271  	sp, ref := s.setupDataset("commitTestMetadataPaths", true)
   272  	defer sp.Close()
   273  
   274  	s.Panics(func() {
   275  		s.MustRun(main, []string{"commit", "--allow-dupe=1", "--meta-p=#beef", "#" + ref.TargetHash().String(), sp.String()})
   276  	})
   277  }
   278  
   279  func (s *nomsCommitTestSuite) TestNomsCommitInvalidMetadataFieldName() {
   280  	sp, ref := s.setupDataset("commitTestMetadataFields", true)
   281  	defer sp.Close()
   282  
   283  	s.Panics(func() {
   284  		s.MustRun(main, []string{"commit", "--allow-dupe=1", "--meta=_foo=bar", "#" + ref.TargetHash().String(), sp.String()})
   285  	})
   286  }