func TestLDBDatabase(t *testing.T) { assert := assert.New(t) d1 := os.TempDir() dir, err := ioutil.TempDir(d1, "flags") assert.NoError(err) ldbDir := path.Join(dir, "store") spec := fmt.Sprintf("ldb:%s", path.Join(dir, "store")) cs := chunks.NewLevelDBStoreUseFlags(ldbDir, "") ds := datas.NewDatabase(cs) s1 := types.String("A String") s1Ref := ds.WriteValue(s1) ds.Commit("testDs", datas.NewCommit().Set(datas.ValueField, s1Ref)) ds.Close() sp, errRead := ParseDatabaseSpec(spec) assert.NoError(errRead) store, err := sp.Database() assert.NoError(err) assert.Equal(s1, store.ReadValue(s1.Hash())) store.Close() os.Remove(dir) }
func (ds *Dataset) validateRefAsCommit(r types.Ref) types.Struct { v := ds.store.ReadValue(r.TargetHash()) d.Exp.True(v != nil, "%v cannot be found", r) d.Exp.True(v.Type().Equals(datas.NewCommit().Type()), "Not a Commit: %+v", v) return v.(types.Struct) }
func TestAbsolutePaths(t *testing.T) { assert := assert.New(t) s0, s1 := types.String("foo"), types.String("bar") list := types.NewList(s0, s1) emptySet := types.NewSet() db := datas.NewDatabase(chunks.NewMemoryStore()) db.WriteValue(s0) db.WriteValue(s1) db.WriteValue(list) db.WriteValue(emptySet) var err error db, err = db.Commit("ds", datas.NewCommit(list, types.NewSet(), types.EmptyStruct)) assert.NoError(err) head := db.Head("ds") resolvesTo := func(exp types.Value, str string) { p, err := NewAbsolutePath(str) assert.NoError(err) act := p.Resolve(db) if exp == nil { assert.Nil(act) } else { assert.True(exp.Equals(act), "%s Expected %s Actual %s", str, types.EncodedValue(exp), types.EncodedValue(act)) } } resolvesTo(head, "ds") resolvesTo(emptySet, "ds.parents") resolvesTo(list, "ds.value") resolvesTo(s0, "ds.value[0]") resolvesTo(s1, "ds.value[1]") resolvesTo(head, "#"+head.Hash().String()) resolvesTo(list, "#"+list.Hash().String()) resolvesTo(s0, "#"+s0.Hash().String()) resolvesTo(s1, "#"+s1.Hash().String()) resolvesTo(s0, "#"+list.Hash().String()+"[0]") resolvesTo(s1, "#"+list.Hash().String()+"[1]") resolvesTo(nil, "foo") resolvesTo(nil, "foo.parents") resolvesTo(nil, "foo.value") resolvesTo(nil, "foo.value[0]") resolvesTo(nil, "#"+types.String("baz").Hash().String()) resolvesTo(nil, "#"+types.String("baz").Hash().String()+"[0]") }
// Commit updates the commit that a dataset points at. The new Commit struct is constructed using `v`, `opts.Parents`, and `opts.Meta`. // If `opts.Parents` is the zero value (`types.Set{}`) then the current head is used. // If `opts.Meta is the zero value (`types.Struct{}`) then a fully initialized empty Struct is passed to NewCommit. // If the update cannot be performed, e.g., because of a conflict, CommitWith returns an 'ErrMergeNeeded' error and the current snapshot of the dataset so that the client can merge the changes and try again. func (ds *Dataset) Commit(v types.Value, opts CommitOptions) (Dataset, error) { parents := opts.Parents if (parents == types.Set{}) { parents = types.NewSet() if headRef, ok := ds.MaybeHeadRef(); ok { headRef.TargetValue(ds.Database()) // TODO: This is a hack to deconfuse the validation code, which doesn't hold onto validation state between commits. parents = parents.Insert(headRef) } } meta := opts.Meta // Ideally, would like to do 'if meta == types.Struct{}' but types.Struct is not comparable in Go // since it contains a slice. if meta.Type() == nil && len(meta.ChildValues()) == 0 { meta = types.EmptyStruct } newCommit := datas.NewCommit(v, parents, meta) store, err := ds.Database().Commit(ds.id, newCommit) return Dataset{store, ds.id}, err }
func TestWriteValue(t *testing.T) { assert := assert.New(t) factory := chunks.NewMemoryStoreFactory() defer factory.Shutter() router = setupWebServer(factory) defer func() { router = nil }() testString := "Now, what?" authKey = "anauthkeyvalue" w := httptest.NewRecorder() r, err := newRequest("GET", dbName+constants.RootPath, nil) assert.NoError(err) router.ServeHTTP(w, r) lastRoot := w.Body assert.Equal(http.StatusOK, w.Code) craftCommit := func(v types.Value) types.Struct { return datas.NewCommit(v, types.NewSet(), types.NewStruct("Meta", types.StructData{})) } tval := craftCommit(types.Bool(true)) wval := craftCommit(types.String(testString)) chunk1 := types.EncodeValue(tval, nil) chunk2 := types.EncodeValue(wval, nil) refMap := types.NewMap( types.String("ds1"), types.NewRef(tval), types.String("ds2"), types.NewRef(wval)) chunk3 := types.EncodeValue(refMap, nil) body := &bytes.Buffer{} // we would use this func, but it's private so use next line instead: serializeHints(body, map[ref.Ref]struct{}{hint: struct{}{}}) err = binary.Write(body, binary.BigEndian, uint32(0)) assert.NoError(err) chunks.Serialize(chunk1, body) chunks.Serialize(chunk2, body) chunks.Serialize(chunk3, body) w = httptest.NewRecorder() r, err = newRequest("POST", dbName+constants.WriteValuePath+"?access_token="+authKey, ioutil.NopCloser(body)) assert.NoError(err) router.ServeHTTP(w, r) assert.Equal(http.StatusCreated, w.Code) w = httptest.NewRecorder() args := fmt.Sprintf("&last=%s¤t=%s", lastRoot, types.NewRef(refMap).TargetHash()) r, _ = newRequest("POST", dbName+constants.RootPath+"?access_token="+authKey+args, ioutil.NopCloser(body)) router.ServeHTTP(w, r) assert.Equal(http.StatusOK, w.Code, string(w.Body.Bytes())) whash := wval.Hash() hints := map[hash.Hash]struct{}{whash: struct{}{}} rdr := buildGetRefsRequestBody(hints) r, _ = newRequest("POST", dbName+constants.GetRefsPath, rdr) r.Header.Add("Content-Type", "application/x-www-form-urlencoded") router.ServeHTTP(w, r) assert.Equal(http.StatusOK, w.Code, string(w.Body.Bytes())) ms := chunks.NewMemoryStore() chunks.Deserialize(w.Body, ms, nil) v := types.DecodeValue(ms.Get(whash), datas.NewDatabase(ms)) assert.Equal(testString, string(v.(types.Struct).Get(datas.ValueField).(types.String))) }
// CommitWithParents updates the commit that a dataset points at. The new Commit is constructed using v and p. // If the update cannot be performed, e.g., because of a conflict, CommitWithParents returns an 'ErrMergeNeeded' error and the current snapshot of the dataset so that the client can merge the changes and try again. func (ds *Dataset) CommitWithParents(v types.Value, p types.Set) (Dataset, error) { newCommit := datas.NewCommit().Set(datas.ParentsField, p).Set(datas.ValueField, v) store, err := ds.Database().Commit(ds.id, newCommit) return Dataset{store, ds.id}, err }