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 }