github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/merge/three_way_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 merge
    23  
    24  import (
    25  	"context"
    26  	"testing"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/suite"
    30  
    31  	"github.com/dolthub/dolt/go/store/chunks"
    32  	"github.com/dolthub/dolt/go/store/d"
    33  	"github.com/dolthub/dolt/go/store/types"
    34  )
    35  
    36  func mustValue(val types.Value, err error) types.Value {
    37  	d.PanicIfError(err)
    38  	return val
    39  }
    40  
    41  func mustString(str string, err error) string {
    42  	d.PanicIfError(err)
    43  	return str
    44  }
    45  
    46  type seq interface {
    47  	items() []interface{}
    48  }
    49  
    50  type ThreeWayMergeSuite struct {
    51  	suite.Suite
    52  	vs      *types.ValueStore
    53  	create  func(seq) (types.Value, error)
    54  	typeStr string
    55  }
    56  
    57  func (s *ThreeWayMergeSuite) SetupTest() {
    58  	storage := &chunks.MemoryStorage{}
    59  	s.vs = types.NewValueStore(storage.NewView())
    60  }
    61  
    62  func (s *ThreeWayMergeSuite) TearDownTest() {
    63  	err := s.vs.Close()
    64  	s.NoError(err)
    65  }
    66  
    67  func (s *ThreeWayMergeSuite) tryThreeWayMerge(a, b, p, exp seq) {
    68  	aVal, err := s.create(a)
    69  	s.NoError(err)
    70  	bVal, err := s.create(b)
    71  	s.NoError(err)
    72  	pVal, err := s.create(p)
    73  	s.NoError(err)
    74  	merged, err := ThreeWay(context.Background(), aVal, bVal, pVal, s.vs, nil, nil)
    75  	if s.NoError(err) {
    76  		expected, err := s.create(exp)
    77  		s.NoError(err)
    78  		s.True(expected.Equals(merged), "%s != %s", mustString(types.EncodedValue(context.Background(), expected)), mustString(types.EncodedValue(context.Background(), merged)))
    79  	}
    80  }
    81  
    82  func (s *ThreeWayMergeSuite) tryThreeWayConflict(a, b, p types.Value, contained string) {
    83  	m, err := ThreeWay(context.Background(), a, b, p, s.vs, nil, nil)
    84  	if s.Error(err) {
    85  		s.Contains(err.Error(), contained)
    86  		return
    87  	}
    88  	s.Fail("Expected error!", "Got successful merge: %s", mustString(types.EncodedValue(context.Background(), m)))
    89  }
    90  
    91  func valsToTypesValues(f func(seq) (types.Value, error), items ...interface{}) ([]types.Value, error) {
    92  	keyValues := []types.Value{}
    93  	for _, e := range items {
    94  		v, err := valToTypesValue(f, e)
    95  
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  
   100  		keyValues = append(keyValues, v)
   101  	}
   102  	return keyValues, nil
   103  }
   104  
   105  func valToTypesValue(f func(seq) (types.Value, error), v interface{}) (types.Value, error) {
   106  	var v1 types.Value
   107  	var err error
   108  	switch t := v.(type) {
   109  	case string:
   110  		v1 = types.String(t)
   111  	case int:
   112  		v1 = types.Float(t)
   113  	case seq:
   114  		v1, err = f(t)
   115  	case types.Value:
   116  		v1 = t
   117  	}
   118  	return v1, err
   119  }
   120  
   121  func TestThreeWayMerge_PrimitiveConflict(t *testing.T) {
   122  	threeWayConflict := func(a, b, p types.Value, contained string) {
   123  		mrgr := &merger{}
   124  		m, err := mrgr.threeWay(context.Background(), a, b, p, nil)
   125  		if assert.Error(t, err) {
   126  			assert.Contains(t, err.Error(), contained)
   127  			return
   128  		}
   129  		assert.Fail(t, "Expected error!", "Got successful merge: %s", mustString(types.EncodedValue(context.Background(), m)))
   130  	}
   131  
   132  	a, b, p := types.Float(7), types.String("nope"), types.String("parent")
   133  
   134  	threeWayConflict(a, b, p, "Float and String on top of")
   135  	threeWayConflict(b, a, p, "String and Float on top of")
   136  }