mirror of
https://github.com/dolthub/dolt.git
synced 2026-05-01 03:29:12 -05:00
Add Set support to merge.ThreeWay
merge.ThreeWay(SetA, SetB, Parent) essentially returns the union of the three Sets. Toward #148
This commit is contained in:
+41
-4
@@ -36,10 +36,10 @@ func newMergeConflict(format string, args ...interface{}) *ErrMergeConflict {
|
||||
// - If the same index is both removed and inserted wrt parent: conflict
|
||||
// - If the same index is inserted wrt parent, but with different values: conflict
|
||||
// - If we are dealing with a set:
|
||||
// - If the same object is both removed and inserted wrt parent: conflict
|
||||
// - `merged` is essentially union(a, b, parent)
|
||||
//
|
||||
// All other modifications are allowed.
|
||||
// Currently, ThreeWay() only works on types.Map.
|
||||
// ThreeWay() works on types.Map, types.Set, and types.Struct.
|
||||
func ThreeWay(a, b, parent types.Value, vwr types.ValueReadWriter) (merged types.Value, err error) {
|
||||
if a == nil && b == nil {
|
||||
return parent, nil
|
||||
@@ -93,8 +93,9 @@ func threeWayMerge(a, b, parent types.Value, vwr types.ValueReadWriter) (merged
|
||||
}
|
||||
|
||||
case types.SetKind:
|
||||
// TODO: Implement plan from BUG148
|
||||
return parent, newMergeConflict("Cannot merge %s.", a.Type().Describe())
|
||||
if aSet, bSet, pSet, ok := setAssert(a, b, parent); ok {
|
||||
return threeWaySetMerge(aSet, bSet, pSet, vwr)
|
||||
}
|
||||
|
||||
case types.StructKind:
|
||||
if aStruct, bStruct, pStruct, ok := structAssert(a, b, parent); ok {
|
||||
@@ -128,6 +129,29 @@ func threeWayMapMerge(a, b, parent types.Map, vwr types.ValueReadWriter) (merged
|
||||
return threeWayOrderedSequenceMerge(parent, aDiff, bDiff, a.Get, b.Get, parent.Get, apply, vwr)
|
||||
}
|
||||
|
||||
func threeWaySetMerge(a, b, parent types.Set, vwr types.ValueReadWriter) (merged types.Value, err error) {
|
||||
aDiff := func(change chan<- types.ValueChanged, stop <-chan struct{}) {
|
||||
a.DiffLeftRight(parent, change, stop)
|
||||
}
|
||||
bDiff := func(change chan<- types.ValueChanged, stop <-chan struct{}) {
|
||||
b.DiffLeftRight(parent, change, stop)
|
||||
}
|
||||
getSelf := func(v types.Value) types.Value {
|
||||
return v
|
||||
}
|
||||
apply := func(target types.Value, change types.ValueChanged, ignored types.Value) types.Value {
|
||||
switch change.ChangeType {
|
||||
case types.DiffChangeAdded, types.DiffChangeModified:
|
||||
return target.(types.Set).Insert(change.V)
|
||||
case types.DiffChangeRemoved:
|
||||
return target.(types.Set).Remove(change.V)
|
||||
default:
|
||||
panic("Not Reached")
|
||||
}
|
||||
}
|
||||
return threeWayOrderedSequenceMerge(parent, aDiff, bDiff, getSelf, getSelf, getSelf, apply, vwr)
|
||||
}
|
||||
|
||||
func threeWayStructMerge(a, b, parent types.Struct, vwr types.ValueReadWriter) (merged types.Value, err error) {
|
||||
aDiff := func(change chan<- types.ValueChanged, stop <-chan struct{}) {
|
||||
a.Diff(parent, change, stop)
|
||||
@@ -201,6 +225,19 @@ func refAssert(a, b, parent types.Value, vwr types.ValueReadWriter) (aValue, bVa
|
||||
return aValue, bValue, pValue, aOk && bOk && pOk
|
||||
}
|
||||
|
||||
func setAssert(a, b, parent types.Value) (aSet, bSet, pSet types.Set, ok bool) {
|
||||
var aOk, bOk, pOk bool
|
||||
aSet, aOk = a.(types.Set)
|
||||
bSet, bOk = b.(types.Set)
|
||||
if parent != nil {
|
||||
pSet, pOk = parent.(types.Set)
|
||||
} else {
|
||||
pSet, pOk = types.NewSet(), true
|
||||
}
|
||||
ok = aOk && bOk && pOk
|
||||
return
|
||||
}
|
||||
|
||||
func structAssert(a, b, parent types.Value) (aStruct, bStruct, pStruct types.Struct, ok bool) {
|
||||
var aOk, bOk, pOk bool
|
||||
aStruct, aOk = a.(types.Struct)
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package merge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/suite"
|
||||
)
|
||||
|
||||
func TestThreeWayMapMerge(t *testing.T) {
|
||||
suite.Run(t, &ThreeWayMapMergeSuite{})
|
||||
}
|
||||
|
||||
func TestThreeWayStructMerge(t *testing.T) {
|
||||
suite.Run(t, &ThreeWayStructMergeSuite{})
|
||||
}
|
||||
|
||||
type kvs []interface{}
|
||||
|
||||
func (kv kvs) items() []interface{} {
|
||||
return kv
|
||||
}
|
||||
|
||||
func (kv kvs) remove(k interface{}) kvs {
|
||||
out := make(kvs, 0, len(kv))
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
if kv[i] != k {
|
||||
out = append(out, kv[i], kv[i+1])
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (kv kvs) set(k, v interface{}) kvs {
|
||||
out := make(kvs, len(kv))
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
out[i], out[i+1] = kv[i], kv[i+1]
|
||||
if kv[i] == k {
|
||||
out[i+1] = v
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var (
|
||||
aa1 = kvs{"a1", "a-one", "a2", "a-two", "a3", "a-three", "a4", "a-four"}
|
||||
aa1a = kvs{"a1", "a-one", "a2", "a-two", "a3", "a-three-diff", "a4", "a-four", "a6", "a-six"}
|
||||
aa1b = kvs{"a1", "a-one", "a3", "a-three-diff", "a4", "a-four", "a5", "a-five"}
|
||||
aaMerged = kvs{"a1", "a-one", "a3", "a-three-diff", "a4", "a-four", "a5", "a-five", "a6", "a-six"}
|
||||
|
||||
mm1 = kvs{}
|
||||
mm1a = kvs{"k1", kvs{"a", 0}}
|
||||
mm1b = kvs{"k1", kvs{"b", 1}}
|
||||
mm1Merged = kvs{"k1", kvs{"a", 0, "b", 1}}
|
||||
|
||||
mm2 = kvs{"k2", aa1, "k3", "k-three"}
|
||||
mm2a = kvs{"k1", kvs{"a", 0}, "k2", aa1a, "k3", "k-three", "k4", "k-four"}
|
||||
mm2b = kvs{"k1", kvs{"b", 1}, "k2", aa1b}
|
||||
mm2Merged = kvs{"k1", kvs{"a", 0, "b", 1}, "k2", aaMerged, "k4", "k-four"}
|
||||
)
|
||||
|
||||
type ThreeWayKeyValMergeSuite struct {
|
||||
ThreeWayMergeSuite
|
||||
}
|
||||
|
||||
type ThreeWayMapMergeSuite struct {
|
||||
ThreeWayKeyValMergeSuite
|
||||
}
|
||||
|
||||
func (s *ThreeWayMapMergeSuite) SetupSuite() {
|
||||
s.create = func(seq seq) (val types.Value) {
|
||||
if seq != nil {
|
||||
keyValues := valsToTypesValues(s.create, seq.items()...)
|
||||
val = types.NewMap(keyValues...)
|
||||
}
|
||||
return
|
||||
}
|
||||
s.typeStr = "Map"
|
||||
}
|
||||
|
||||
type ThreeWayStructMergeSuite struct {
|
||||
ThreeWayKeyValMergeSuite
|
||||
}
|
||||
|
||||
func (s *ThreeWayStructMergeSuite) SetupSuite() {
|
||||
s.create = func(seq seq) (val types.Value) {
|
||||
if seq != nil {
|
||||
kv := seq.items()
|
||||
fields := types.StructData{}
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
fields[kv[i].(string)] = valToTypesValue(s.create, kv[i+1])
|
||||
}
|
||||
val = types.NewStruct("TestStruct", fields)
|
||||
}
|
||||
return
|
||||
}
|
||||
s.typeStr = "struct"
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_DoNothing() {
|
||||
s.tryThreeWayMerge(nil, nil, aa1, aa1, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_NoRecursion() {
|
||||
s.tryThreeWayMerge(aa1a, aa1b, aa1, aaMerged, nil)
|
||||
s.tryThreeWayMerge(aa1b, aa1a, aa1, aaMerged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_RecursiveCreate() {
|
||||
s.tryThreeWayMerge(mm1a, mm1b, mm1, mm1Merged, nil)
|
||||
s.tryThreeWayMerge(mm1b, mm1a, mm1, mm1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_RecursiveCreateNil() {
|
||||
s.tryThreeWayMerge(mm1a, mm1b, nil, mm1Merged, nil)
|
||||
s.tryThreeWayMerge(mm1b, mm1a, nil, mm1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_RecursiveMerge() {
|
||||
s.tryThreeWayMerge(mm2a, mm2b, mm2, mm2Merged, nil)
|
||||
s.tryThreeWayMerge(mm2b, mm2a, mm2, mm2Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_RefMerge() {
|
||||
vs := types.NewTestValueStore()
|
||||
|
||||
strRef := vs.WriteValue(types.NewStruct("Foo", types.StructData{"life": types.Number(42)}))
|
||||
|
||||
m := kvs{"r2", vs.WriteValue(s.create(aa1))}
|
||||
ma := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aa1a))}
|
||||
mb := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aa1b))}
|
||||
mMerged := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aaMerged))}
|
||||
vs.Flush()
|
||||
|
||||
s.tryThreeWayMerge(ma, mb, m, mMerged, vs)
|
||||
s.tryThreeWayMerge(mb, ma, m, mMerged, vs)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_RecursiveMultiLevelMerge() {
|
||||
vs := types.NewTestValueStore()
|
||||
|
||||
m := kvs{"mm1", mm1, "mm2", vs.WriteValue(s.create(mm2))}
|
||||
ma := kvs{"mm1", mm1a, "mm2", vs.WriteValue(s.create(mm2a))}
|
||||
mb := kvs{"mm1", mm1b, "mm2", vs.WriteValue(s.create(mm2b))}
|
||||
mMerged := kvs{"mm1", mm1Merged, "mm2", vs.WriteValue(s.create(mm2Merged))}
|
||||
vs.Flush()
|
||||
|
||||
s.tryThreeWayMerge(ma, mb, m, mMerged, vs)
|
||||
s.tryThreeWayMerge(mb, ma, m, mMerged, vs)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_NilConflict() {
|
||||
s.tryThreeWayConflict(nil, s.create(mm2b), s.create(mm2), "Cannot merge nil Value with")
|
||||
s.tryThreeWayConflict(s.create(mm2a), nil, s.create(mm2), "with nil value.")
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_ImmediateConflict() {
|
||||
s.tryThreeWayConflict(types.NewSet(), s.create(mm2b), s.create(mm2), "Cannot merge Set<> with "+s.typeStr)
|
||||
s.tryThreeWayConflict(s.create(mm2b), types.NewSet(), s.create(mm2), "Cannot merge "+s.typeStr)
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_NestedConflict() {
|
||||
a := mm2a.set("k2", types.NewSet())
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), types.EncodedValue(types.NewSet()))
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), types.EncodedValue(s.create(aa1b)))
|
||||
}
|
||||
|
||||
func (s *ThreeWayKeyValMergeSuite) TestThreeWayMerge_NestedConflictingOperation() {
|
||||
a := mm2a.remove("k2")
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), `removed "k2"`)
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), `modded "k2"`)
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// Copyright 2016 Attic Labs, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, version 2.0:
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
package merge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/suite"
|
||||
)
|
||||
|
||||
func TestThreeWaySetMerge(t *testing.T) {
|
||||
suite.Run(t, &ThreeWaySetMergeSuite{})
|
||||
}
|
||||
|
||||
type items []interface{}
|
||||
|
||||
func (kv items) items() []interface{} {
|
||||
return kv
|
||||
}
|
||||
|
||||
type ThreeWaySetMergeSuite struct {
|
||||
ThreeWayMergeSuite
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) SetupSuite() {
|
||||
s.create = func(i seq) (val types.Value) {
|
||||
if i != nil {
|
||||
keyValues := valsToTypesValues(s.create, i.items()...)
|
||||
val = types.NewSet(keyValues...)
|
||||
}
|
||||
return
|
||||
}
|
||||
s.typeStr = "Set"
|
||||
}
|
||||
|
||||
var (
|
||||
flat = items{"a1", "a2", "a3", "a4"}
|
||||
flatA = items{"a1", "a2", "a5", "a6"}
|
||||
flatB = items{"a1", "a4", "a7", "a5"}
|
||||
flatM = items{"a1", "a5", "a6", "a7"}
|
||||
|
||||
ss1 = items{}
|
||||
ss1a = items{"k1", flatA, items{"a", 0}}
|
||||
ss1b = items{"k1", items{"a", 0}, flatB}
|
||||
ss1Merged = items{"k1", items{"a", 0}, flatA, flatB}
|
||||
)
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_DoNothing() {
|
||||
s.tryThreeWayMerge(nil, nil, flat, flat, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_Primitives() {
|
||||
s.tryThreeWayMerge(flatA, flatB, flat, flatM, nil)
|
||||
s.tryThreeWayMerge(flatB, flatA, flat, flatM, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_HandleEmpty() {
|
||||
s.tryThreeWayMerge(ss1a, ss1b, ss1, ss1Merged, nil)
|
||||
s.tryThreeWayMerge(ss1b, ss1a, ss1, ss1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_HandleNil() {
|
||||
s.tryThreeWayMerge(ss1a, ss1b, nil, ss1Merged, nil)
|
||||
s.tryThreeWayMerge(ss1b, ss1a, nil, ss1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_Refs() {
|
||||
vs := types.NewTestValueStore()
|
||||
|
||||
strRef := vs.WriteValue(types.NewStruct("Foo", types.StructData{"life": types.Number(42)}))
|
||||
|
||||
m := items{vs.WriteValue(s.create(flatA)), vs.WriteValue(s.create(flatB))}
|
||||
ma := items{"r1", vs.WriteValue(s.create(flatA))}
|
||||
mb := items{"r1", strRef, vs.WriteValue(s.create(flatA))}
|
||||
mMerged := items{"r1", strRef, vs.WriteValue(s.create(flatA))}
|
||||
vs.Flush()
|
||||
|
||||
s.tryThreeWayMerge(ma, mb, m, mMerged, vs)
|
||||
s.tryThreeWayMerge(mb, ma, m, mMerged, vs)
|
||||
}
|
||||
|
||||
func (s *ThreeWaySetMergeSuite) TestThreeWayMerge_ImmediateConflict() {
|
||||
s.tryThreeWayConflict(types.NewMap(), s.create(ss1b), s.create(ss1), "Cannot merge Map<, > with "+s.typeStr)
|
||||
s.tryThreeWayConflict(s.create(ss1b), types.NewMap(), s.create(ss1), "Cannot merge "+s.typeStr)
|
||||
}
|
||||
+8
-164
@@ -5,103 +5,21 @@
|
||||
package merge
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/attic-labs/noms/go/types"
|
||||
"github.com/attic-labs/testify/suite"
|
||||
)
|
||||
|
||||
func TestThreeWayMapMerge(t *testing.T) {
|
||||
suite.Run(t, &ThreeWayMapMergeSuite{})
|
||||
type seq interface {
|
||||
items() []interface{}
|
||||
}
|
||||
|
||||
func TestThreeWayStructMerge(t *testing.T) {
|
||||
suite.Run(t, &ThreeWayStructMergeSuite{})
|
||||
}
|
||||
|
||||
type kvs []interface{}
|
||||
|
||||
func (kv kvs) remove(k interface{}) kvs {
|
||||
out := make(kvs, 0, len(kv))
|
||||
for i := 0; i < len(kv); i++ {
|
||||
if kv[i] == k {
|
||||
i++ // skip kv[i] and kv[i+1]
|
||||
continue
|
||||
}
|
||||
out = append(out, kv[i])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (kv kvs) set(k, v interface{}) kvs {
|
||||
out := make(kvs, len(kv))
|
||||
for i := 0; i < len(kv); i++ {
|
||||
out[i] = kv[i]
|
||||
if kv[i] == k {
|
||||
i++
|
||||
out[i] = v
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var (
|
||||
aa1 = kvs{"a1", "a-one", "a2", "a-two", "a3", "a-three", "a4", "a-four"}
|
||||
aa1a = kvs{"a1", "a-one", "a2", "a-two", "a3", "a-three-diff", "a4", "a-four", "a6", "a-six"}
|
||||
aa1b = kvs{"a1", "a-one", "a3", "a-three-diff", "a4", "a-four", "a5", "a-five"}
|
||||
aaMerged = kvs{"a1", "a-one", "a3", "a-three-diff", "a4", "a-four", "a5", "a-five", "a6", "a-six"}
|
||||
|
||||
mm1 = kvs{}
|
||||
mm1a = kvs{"k1", kvs{"a", 0}}
|
||||
mm1b = kvs{"k1", kvs{"b", 1}}
|
||||
mm1Merged = kvs{"k1", kvs{"a", 0, "b", 1}}
|
||||
|
||||
mm2 = kvs{"k2", aa1, "k3", "k-three"}
|
||||
mm2a = kvs{"k1", kvs{"a", 0}, "k2", aa1a, "k3", "k-three", "k4", "k-four"}
|
||||
mm2b = kvs{"k1", kvs{"b", 1}, "k2", aa1b}
|
||||
mm2Merged = kvs{"k1", kvs{"a", 0, "b", 1}, "k2", aaMerged, "k4", "k-four"}
|
||||
)
|
||||
|
||||
type ThreeWayMergeSuite struct {
|
||||
suite.Suite
|
||||
create func(kvs) types.Value
|
||||
create func(seq) types.Value
|
||||
typeStr string
|
||||
}
|
||||
|
||||
type ThreeWayMapMergeSuite struct {
|
||||
ThreeWayMergeSuite
|
||||
}
|
||||
|
||||
func (s *ThreeWayMapMergeSuite) SetupSuite() {
|
||||
s.create = func(kv kvs) (val types.Value) {
|
||||
if kv != nil {
|
||||
keyValues := valsToTypesValues(s.create, kv...)
|
||||
val = types.NewMap(keyValues...)
|
||||
}
|
||||
return
|
||||
}
|
||||
s.typeStr = "Map"
|
||||
}
|
||||
|
||||
type ThreeWayStructMergeSuite struct {
|
||||
ThreeWayMergeSuite
|
||||
}
|
||||
|
||||
func (s *ThreeWayStructMergeSuite) SetupSuite() {
|
||||
s.create = func(kv kvs) (val types.Value) {
|
||||
if kv != nil {
|
||||
fields := types.StructData{}
|
||||
for i := 0; i < len(kv); i += 2 {
|
||||
fields[kv[i].(string)] = valToTypesValue(s.create, kv[i+1])
|
||||
}
|
||||
val = types.NewStruct("TestStruct", fields)
|
||||
}
|
||||
return
|
||||
}
|
||||
s.typeStr = "struct"
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) tryThreeWayMerge(a, b, p, exp kvs, vs types.ValueReadWriter) {
|
||||
func (s *ThreeWayMergeSuite) tryThreeWayMerge(a, b, p, exp seq, vs types.ValueReadWriter) {
|
||||
merged, err := ThreeWay(s.create(a), s.create(b), s.create(p), vs)
|
||||
if s.NoError(err) {
|
||||
expected := s.create(exp)
|
||||
@@ -116,97 +34,23 @@ func (s *ThreeWayMergeSuite) tryThreeWayConflict(a, b, p types.Value, contained
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_DoNothing() {
|
||||
s.tryThreeWayMerge(nil, nil, aa1, aa1, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_NoRecursion() {
|
||||
s.tryThreeWayMerge(aa1a, aa1b, aa1, aaMerged, nil)
|
||||
s.tryThreeWayMerge(aa1b, aa1a, aa1, aaMerged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_RecursiveCreate() {
|
||||
s.tryThreeWayMerge(mm1a, mm1b, mm1, mm1Merged, nil)
|
||||
s.tryThreeWayMerge(mm1b, mm1a, mm1, mm1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_RecursiveCreateNil() {
|
||||
s.tryThreeWayMerge(mm1a, mm1b, nil, mm1Merged, nil)
|
||||
s.tryThreeWayMerge(mm1b, mm1a, nil, mm1Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_RecursiveMerge() {
|
||||
s.tryThreeWayMerge(mm2a, mm2b, mm2, mm2Merged, nil)
|
||||
s.tryThreeWayMerge(mm2b, mm2a, mm2, mm2Merged, nil)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_RefMerge() {
|
||||
vs := types.NewTestValueStore()
|
||||
|
||||
strRef := vs.WriteValue(types.NewStruct("Foo", types.StructData{"life": types.Number(42)}))
|
||||
|
||||
m := kvs{"r2", vs.WriteValue(s.create(aa1))}
|
||||
ma := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aa1a))}
|
||||
mb := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aa1b))}
|
||||
mMerged := kvs{"r1", strRef, "r2", vs.WriteValue(s.create(aaMerged))}
|
||||
vs.Flush()
|
||||
|
||||
s.tryThreeWayMerge(ma, mb, m, mMerged, vs)
|
||||
s.tryThreeWayMerge(mb, ma, m, mMerged, vs)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_RecursiveMultiLevelMerge() {
|
||||
vs := types.NewTestValueStore()
|
||||
|
||||
m := kvs{"mm1", mm1, "mm2", vs.WriteValue(s.create(mm2))}
|
||||
ma := kvs{"mm1", mm1a, "mm2", vs.WriteValue(s.create(mm2a))}
|
||||
mb := kvs{"mm1", mm1b, "mm2", vs.WriteValue(s.create(mm2b))}
|
||||
mMerged := kvs{"mm1", mm1Merged, "mm2", vs.WriteValue(s.create(mm2Merged))}
|
||||
vs.Flush()
|
||||
|
||||
s.tryThreeWayMerge(ma, mb, m, mMerged, vs)
|
||||
s.tryThreeWayMerge(mb, ma, m, mMerged, vs)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_NilConflict() {
|
||||
s.tryThreeWayConflict(nil, s.create(mm2b), s.create(mm2), "Cannot merge nil Value with")
|
||||
s.tryThreeWayConflict(s.create(mm2a), nil, s.create(mm2), "with nil value.")
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_ImmediateConflict() {
|
||||
s.tryThreeWayConflict(types.NewSet(), s.create(mm2b), s.create(mm2), "Cannot merge Set<> with "+s.typeStr)
|
||||
s.tryThreeWayConflict(s.create(mm2b), types.NewSet(), s.create(mm2), "Cannot merge "+s.typeStr)
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_NestedConflict() {
|
||||
a := mm2a.set("k2", types.NewSet())
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), types.EncodedValue(types.NewSet()))
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), types.EncodedValue(s.create(aa1b)))
|
||||
}
|
||||
|
||||
func (s *ThreeWayMergeSuite) TestThreeWayMergeMap_NestedConflictingOperation() {
|
||||
a := mm2a.remove("k2")
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), `removed "k2"`)
|
||||
s.tryThreeWayConflict(s.create(a), s.create(mm2b), s.create(mm2), `modded "k2"`)
|
||||
}
|
||||
|
||||
func valsToTypesValues(f func(kvs) types.Value, kv ...interface{}) []types.Value {
|
||||
func valsToTypesValues(f func(seq) types.Value, items ...interface{}) []types.Value {
|
||||
keyValues := []types.Value{}
|
||||
for _, e := range kv {
|
||||
for _, e := range items {
|
||||
v := valToTypesValue(f, e)
|
||||
keyValues = append(keyValues, v)
|
||||
}
|
||||
return keyValues
|
||||
}
|
||||
|
||||
func valToTypesValue(f func(kvs) types.Value, v interface{}) types.Value {
|
||||
func valToTypesValue(f func(seq) types.Value, v interface{}) types.Value {
|
||||
var v1 types.Value
|
||||
switch t := v.(type) {
|
||||
case string:
|
||||
v1 = types.String(t)
|
||||
case int:
|
||||
v1 = types.Number(t)
|
||||
case kvs:
|
||||
case seq:
|
||||
v1 = f(t)
|
||||
case types.Value:
|
||||
v1 = t
|
||||
|
||||
Reference in New Issue
Block a user