mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-26 03:30:09 -05:00
119a56c3a9
This patch is the first step in moving all reading and writing to the DataStore API, so that we can validate data commited to Noms. The big change here is that types.ReadValue() no longer exists and is replaced with a ReadValue() method on DataStore. A similar WriteValue() method deprecates types.WriteValue(), but fully removing that is left for a later patch. Since a lot of code in the types package needs to read and write values, but cannot import the datas package without creating an import cycle, the types package exports ValueReader and ValueWriter interfaces, which DataStore implements. Thus, a DataStore can be passed to anything in the types package which needs to read or write values (e.g. a collection constructor or typed-ref) Relatedly, this patch also introduces the DataSink interface, so that some public-facing apis no longer need to provide a ChunkSink. Towards #654
164 lines
5.4 KiB
Go
164 lines
5.4 KiB
Go
package walk
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/attic-labs/noms/chunks"
|
|
"github.com/attic-labs/noms/ref"
|
|
"github.com/attic-labs/noms/types"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
func TestWalkTestSuite(t *testing.T) {
|
|
suite.Run(t, &WalkAllTestSuite{})
|
|
suite.Run(t, &WalkTestSuite{})
|
|
}
|
|
|
|
type WalkAllTestSuite struct {
|
|
suite.Suite
|
|
vs *types.ValueStore
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) SetupTest() {
|
|
suite.vs = types.NewTestValueStore()
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) walkWorker(r ref.Ref, expected int) {
|
|
actual := 0
|
|
AllP(types.NewRef(r), suite.vs, func(c types.Value) {
|
|
actual++
|
|
}, 1)
|
|
suite.Equal(expected, actual)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) storeAndRef(v types.Value) ref.Ref {
|
|
return suite.vs.WriteValue(v)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) TestWalkPrimitives() {
|
|
suite.walkWorker(suite.storeAndRef(types.Float64(0.0)), 2)
|
|
suite.walkWorker(suite.storeAndRef(types.NewString("hello")), 2)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) TestWalkComposites() {
|
|
suite.walkWorker(suite.storeAndRef(types.NewList()), 2)
|
|
suite.walkWorker(suite.storeAndRef(types.NewList(types.Bool(false), types.Int32(8))), 4)
|
|
suite.walkWorker(suite.storeAndRef(types.NewSet()), 2)
|
|
suite.walkWorker(suite.storeAndRef(types.NewSet(types.Bool(false), types.Int32(8))), 4)
|
|
suite.walkWorker(suite.storeAndRef(types.NewMap()), 2)
|
|
suite.walkWorker(suite.storeAndRef(types.NewMap(types.Int32(8), types.Bool(true), types.Int32(0), types.Bool(false))), 6)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) NewList(cs chunks.ChunkStore, vs ...types.Value) types.Ref {
|
|
v := types.NewList(vs...)
|
|
r := suite.vs.WriteValue(v)
|
|
return types.NewRef(r)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) NewMap(cs chunks.ChunkStore, vs ...types.Value) types.Ref {
|
|
v := types.NewMap(vs...)
|
|
r := suite.vs.WriteValue(v)
|
|
return types.NewRef(r)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) NewSet(cs chunks.ChunkStore, vs ...types.Value) types.Ref {
|
|
v := types.NewSet(vs...)
|
|
r := suite.vs.WriteValue(v)
|
|
return types.NewRef(r)
|
|
}
|
|
|
|
func (suite *WalkAllTestSuite) TestWalkNestedComposites() {
|
|
cs := chunks.NewMemoryStore()
|
|
suite.walkWorker(suite.storeAndRef(types.NewList(suite.NewSet(cs), types.Int32(8))), 5)
|
|
suite.walkWorker(suite.storeAndRef(types.NewSet(suite.NewList(cs), suite.NewSet(cs))), 6)
|
|
// {"string": "string",
|
|
// "list": [false true],
|
|
// "map": {"nested": "string"}
|
|
// "mtlist": []
|
|
// "set": [5 7 8]
|
|
// []: "wow"
|
|
// }
|
|
nested := types.NewMap(
|
|
types.NewString("string"), types.NewString("string"),
|
|
types.NewString("list"), suite.NewList(cs, types.Bool(false), types.Bool(true)),
|
|
types.NewString("map"), suite.NewMap(cs, types.NewString("nested"), types.NewString("string")),
|
|
types.NewString("mtlist"), suite.NewList(cs),
|
|
types.NewString("set"), suite.NewSet(cs, types.Int32(5), types.Int32(7), types.Int32(8)),
|
|
suite.NewList(cs), types.NewString("wow"), // note that the dupe list chunk is skipped
|
|
)
|
|
suite.walkWorker(suite.storeAndRef(nested), 25)
|
|
}
|
|
|
|
type WalkTestSuite struct {
|
|
WalkAllTestSuite
|
|
shouldSeeItem types.Value
|
|
shouldSee types.Value
|
|
mustSkip types.Value
|
|
deadValue types.Value
|
|
}
|
|
|
|
func (suite *WalkTestSuite) SetupTest() {
|
|
suite.vs = types.NewTestValueStore()
|
|
suite.shouldSeeItem = types.NewString("zzz")
|
|
suite.shouldSee = types.NewList(suite.shouldSeeItem)
|
|
suite.deadValue = types.Uint64(0xDEADBEEF)
|
|
suite.mustSkip = types.NewList(suite.deadValue)
|
|
}
|
|
|
|
func (suite *WalkTestSuite) TestStopWalkImmediately() {
|
|
actual := 0
|
|
SomeP(types.NewList(types.NewSet(), types.NewList()), suite.vs, func(v types.Value) bool {
|
|
actual++
|
|
return true
|
|
}, 1)
|
|
suite.Equal(1, actual)
|
|
}
|
|
|
|
func (suite *WalkTestSuite) skipWorker(composite types.Value) (reached []types.Value) {
|
|
SomeP(composite, suite.vs, func(v types.Value) bool {
|
|
suite.False(v.Equals(suite.deadValue), "Should never have reached %+v", suite.deadValue)
|
|
reached = append(reached, v)
|
|
return v.Equals(suite.mustSkip)
|
|
}, 1)
|
|
return
|
|
}
|
|
|
|
// Skipping a sub-tree must allow other items in the list to be processed.
|
|
func (suite *WalkTestSuite) SkipTestSkipListElement() {
|
|
wholeList := types.NewList(suite.mustSkip, suite.shouldSee, suite.shouldSee)
|
|
reached := suite.skipWorker(wholeList)
|
|
for _, v := range []types.Value{wholeList, suite.mustSkip, suite.shouldSee, suite.shouldSeeItem} {
|
|
suite.Contains(reached, v, "Doesn't contain %+v", v)
|
|
}
|
|
suite.Len(reached, 6)
|
|
}
|
|
|
|
func (suite *WalkTestSuite) SkipTestSkipSetElement() {
|
|
wholeSet := types.NewSet(suite.mustSkip, suite.shouldSee).Insert(suite.shouldSee)
|
|
reached := suite.skipWorker(wholeSet)
|
|
for _, v := range []types.Value{wholeSet, suite.mustSkip, suite.shouldSee, suite.shouldSeeItem} {
|
|
suite.Contains(reached, v, "Doesn't contain %+v", v)
|
|
}
|
|
suite.Len(reached, 4)
|
|
}
|
|
|
|
func (suite *WalkTestSuite) SkipTestSkipMapValue() {
|
|
shouldAlsoSeeItem := types.NewString("Also good")
|
|
shouldAlsoSee := types.NewSet(shouldAlsoSeeItem)
|
|
wholeMap := types.NewMap(suite.shouldSee, suite.mustSkip, shouldAlsoSee, suite.shouldSee)
|
|
reached := suite.skipWorker(wholeMap)
|
|
for _, v := range []types.Value{wholeMap, suite.shouldSee, suite.shouldSeeItem, suite.mustSkip, shouldAlsoSee, shouldAlsoSeeItem} {
|
|
suite.Contains(reached, v, "Doesn't contain %+v", v)
|
|
}
|
|
suite.Len(reached, 8)
|
|
}
|
|
|
|
func (suite *WalkTestSuite) SkipTestSkipMapKey() {
|
|
wholeMap := types.NewMap(suite.mustSkip, suite.shouldSee, suite.shouldSee, suite.shouldSee)
|
|
reached := suite.skipWorker(wholeMap)
|
|
for _, v := range []types.Value{wholeMap, suite.mustSkip, suite.shouldSee, suite.shouldSeeItem} {
|
|
suite.Contains(reached, v, "Doesn't contain %+v", v)
|
|
}
|
|
suite.Len(reached, 8)
|
|
}
|