github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/graveler/committed/merge_test.go (about)

     1  package committed_test
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"errors"
     7  	"fmt"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/golang/mock/gomock"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/treeverse/lakefs/pkg/graveler"
    14  	"github.com/treeverse/lakefs/pkg/graveler/committed"
    15  	"github.com/treeverse/lakefs/pkg/graveler/committed/mock"
    16  	"github.com/treeverse/lakefs/pkg/graveler/testutil"
    17  )
    18  
    19  type actionType string
    20  
    21  const (
    22  	actionTypeWriteRange  actionType = "write-range"
    23  	actionTypeWriteRecord actionType = "write-record"
    24  )
    25  
    26  type writeAction struct {
    27  	action   actionType
    28  	rng      committed.Range
    29  	key      string
    30  	identity string
    31  }
    32  
    33  type recordMatcher struct {
    34  	key      graveler.Key
    35  	identity []byte
    36  }
    37  
    38  func newRecordMatcher(key string, identity string) recordMatcher {
    39  	return recordMatcher{
    40  		key:      graveler.Key(key),
    41  		identity: []byte(identity),
    42  	}
    43  }
    44  
    45  func (m recordMatcher) Matches(x interface{}) bool {
    46  	record := x.(graveler.ValueRecord)
    47  	return bytes.Equal(m.key, record.Key) && bytes.Equal(m.identity, record.Identity)
    48  }
    49  
    50  func (m recordMatcher) String() string {
    51  	return fmt.Sprintf("is equal to key:%s, identity:%s", m.key, m.identity)
    52  }
    53  
    54  type testValueRecord struct {
    55  	key      string
    56  	identity string
    57  }
    58  
    59  type testRange struct {
    60  	rng     committed.Range
    61  	records []testValueRecord
    62  }
    63  
    64  type testRunResult struct {
    65  	mergeStrategies []graveler.MergeStrategy
    66  	expectedActions []writeAction
    67  	expectedErr     error
    68  }
    69  
    70  type testMetaRange struct {
    71  	ranges []testRange
    72  }
    73  
    74  func (t *testMetaRange) GetMetaRangeID() graveler.MetaRangeID {
    75  	var sb strings.Builder
    76  	for _, rng := range t.ranges {
    77  		sb.WriteString(string(rng.rng.ID))
    78  		sb.WriteString("#")
    79  	}
    80  	return graveler.MetaRangeID(sb.String())
    81  }
    82  
    83  func newTestMetaRange(ranges []testRange) *testMetaRange {
    84  	return &testMetaRange{ranges: ranges}
    85  }
    86  
    87  type testCase struct {
    88  	baseRange      *testMetaRange
    89  	sourceRange    *testMetaRange
    90  	destRange      *testMetaRange
    91  	expectedResult []testRunResult
    92  }
    93  
    94  type testCases map[string]testCase
    95  
    96  func createIter(tr *testMetaRange) committed.Iterator {
    97  	iter := testutil.NewFakeIterator()
    98  	for _, rng := range tr.ranges {
    99  		addRange := rng.rng
   100  		iter.AddRange(&addRange)
   101  		for _, record := range rng.records {
   102  			iter.AddValueRecords(&graveler.ValueRecord{
   103  				Key: graveler.Key(record.key),
   104  				Value: &graveler.Value{
   105  					Identity: []byte(record.identity),
   106  					Data:     nil,
   107  				},
   108  			})
   109  		}
   110  	}
   111  	return iter
   112  }
   113  
   114  func Test_merge(t *testing.T) {
   115  	tests := testCases{
   116  		"dest range added before": {
   117  			baseRange: newTestMetaRange([]testRange{
   118  				{
   119  					rng:     committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   120  					records: nil,
   121  				}, {rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   122  					{"k11", "base:k11"}, {"k12", "base:k12"},
   123  				}},
   124  			}),
   125  			sourceRange: newTestMetaRange([]testRange{{
   126  				rng:     committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   127  				records: nil,
   128  			}}),
   129  			destRange: newTestMetaRange([]testRange{
   130  				{rng: committed.Range{ID: "dest:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   131  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   132  			}),
   133  			expectedResult: []testRunResult{{
   134  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   135  				expectedActions: []writeAction{
   136  					{
   137  						action: actionTypeWriteRange,
   138  						rng:    committed.Range{ID: "dest:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234},
   139  					},
   140  					{
   141  						action: actionTypeWriteRange,
   142  						rng:    committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   143  					},
   144  				},
   145  				expectedErr: nil,
   146  			}},
   147  		},
   148  		"source range added before": {
   149  			baseRange: newTestMetaRange([]testRange{
   150  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   151  				{rng: committed.Range{ID: "base:k7-k8", MinKey: committed.Key("k7"), MaxKey: committed.Key("k8"), Count: 2, EstimatedSize: 1024}},
   152  			}),
   153  			sourceRange: newTestMetaRange([]testRange{
   154  				{rng: committed.Range{ID: "source:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1024}},
   155  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   156  			}),
   157  			destRange: newTestMetaRange([]testRange{
   158  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   159  			}),
   160  			expectedResult: []testRunResult{{
   161  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   162  				expectedActions: []writeAction{
   163  					{
   164  						action: actionTypeWriteRange,
   165  						rng:    committed.Range{ID: "source:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1024},
   166  					},
   167  					{
   168  						action: actionTypeWriteRange,
   169  						rng:    committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024},
   170  					},
   171  				},
   172  			}},
   173  		},
   174  		"source range removed before": {
   175  			baseRange: newTestMetaRange([]testRange{
   176  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1024}},
   177  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   178  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   179  					{"k11", "base:k11"}, {"k12", "base:k12"},
   180  				}},
   181  			}),
   182  			sourceRange: newTestMetaRange([]testRange{
   183  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   184  			}),
   185  			destRange: newTestMetaRange([]testRange{
   186  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1024}},
   187  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024}},
   188  			}),
   189  			expectedResult: []testRunResult{{
   190  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   191  				expectedActions: []writeAction{
   192  					{
   193  						action: actionTypeWriteRange,
   194  						rng:    committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1024},
   195  					},
   196  				},
   197  			}},
   198  		},
   199  		"source range inner change": {
   200  			baseRange: newTestMetaRange([]testRange{
   201  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   202  					{"k1", "base:k1"}, {"k3", "base:k3"},
   203  				}},
   204  				{rng: committed.Range{ID: "base:k4", MinKey: committed.Key("k4"), EstimatedSize: 1024}, records: []testValueRecord{
   205  					{"k4", "base:k4"},
   206  				}},
   207  			}),
   208  			sourceRange: newTestMetaRange([]testRange{
   209  				{rng: committed.Range{ID: "source:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   210  					{"k1", "base:k1"}, {"k2", "source:k2"}, {"k3", "source:k3"},
   211  				}},
   212  			}),
   213  			destRange: newTestMetaRange([]testRange{
   214  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   215  					{"k1", "base:k1"},
   216  					{"k3", "base:k3"},
   217  				}},
   218  			}),
   219  			expectedResult: []testRunResult{{
   220  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   221  				expectedActions: []writeAction{
   222  					{
   223  						action: actionTypeWriteRange,
   224  						rng:    committed.Range{ID: "source:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024},
   225  					},
   226  				},
   227  			}},
   228  		},
   229  		"dest range inner change": {
   230  			baseRange: newTestMetaRange([]testRange{
   231  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   232  					{"k1", "base:k1"},
   233  					{"k3", "base:k3"},
   234  				}},
   235  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   236  					{"k11", "base:k11"}, {"k12", "base:k12"},
   237  				}},
   238  			}),
   239  			sourceRange: newTestMetaRange([]testRange{
   240  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   241  					{"k1", "base:k1"},
   242  					{"k3", "base:k3"},
   243  				}},
   244  			}),
   245  			destRange: newTestMetaRange([]testRange{
   246  				{rng: committed.Range{ID: "dest:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024}, records: []testValueRecord{
   247  					{"k1", "base:k1"},
   248  					{"k2", "dest:k2"},
   249  					{"k3", "dest:k3"},
   250  				}},
   251  			}),
   252  			expectedResult: []testRunResult{{
   253  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   254  				expectedActions: []writeAction{
   255  					{
   256  						action: actionTypeWriteRange,
   257  						rng:    committed.Range{ID: "dest:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), EstimatedSize: 1024},
   258  					},
   259  				},
   260  				expectedErr: nil,
   261  			}},
   262  		},
   263  		"source range append after": {
   264  			baseRange: newTestMetaRange([]testRange{
   265  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), Count: 2, EstimatedSize: 1024}, records: []testValueRecord{
   266  					{"k1", "base:k1"},
   267  					{"k3", "base:k3"},
   268  				}},
   269  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   270  					{"k11", "base:k11"}, {"k12", "base:k12"},
   271  				}},
   272  			}),
   273  			sourceRange: newTestMetaRange([]testRange{
   274  				{rng: committed.Range{ID: "source:k1-k5", MinKey: committed.Key("k1"), MaxKey: committed.Key("k5"), Count: 4, EstimatedSize: 1024}, records: []testValueRecord{
   275  					{"k1", "base:k1"},
   276  					{"k3", "base:k3"},
   277  					{"k4", "source:k4"},
   278  					{"k5", "source:k5"},
   279  				}},
   280  			}),
   281  			destRange: newTestMetaRange([]testRange{
   282  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3"), Count: 2, EstimatedSize: 1024}, records: []testValueRecord{
   283  					{"k1", "base:k1"},
   284  					{"k3", "base:k3"},
   285  				}},
   286  			}),
   287  			expectedResult: []testRunResult{
   288  				{
   289  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   290  					expectedActions: []writeAction{
   291  						{
   292  							action:   actionTypeWriteRecord,
   293  							key:      "k1",
   294  							identity: "base:k1",
   295  						},
   296  						{
   297  							action:   actionTypeWriteRecord,
   298  							key:      "k3",
   299  							identity: "base:k3",
   300  						},
   301  						{
   302  							action:   actionTypeWriteRecord,
   303  							key:      "k4",
   304  							identity: "source:k4",
   305  						},
   306  						{
   307  							action:   actionTypeWriteRecord,
   308  							key:      "k5",
   309  							identity: "source:k5",
   310  						},
   311  					},
   312  				},
   313  			},
   314  		},
   315  		"source range append and remove after": {
   316  			baseRange: newTestMetaRange([]testRange{
   317  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3")}, records: []testValueRecord{
   318  					{"k1", "base:k1"}, {"k3", "base:k3"},
   319  				}},
   320  				{
   321  					rng: committed.Range{ID: "base:k4-k6", MinKey: committed.Key("k4"), MaxKey: committed.Key("k6")}, records: []testValueRecord{
   322  						{"k4", "base:k4"}, {"k6", "base:k6"},
   323  					},
   324  				},
   325  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   326  					{"k11", "base:k11"}, {"k12", "base:k12"},
   327  				}},
   328  			}),
   329  			sourceRange: newTestMetaRange([]testRange{
   330  				{rng: committed.Range{ID: "source:k1-k5", MinKey: committed.Key("k1"), MaxKey: committed.Key("k5")}, records: []testValueRecord{
   331  					{"k1", "base:k1"}, {"k2", "source:k2"}, {"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "source:k5"},
   332  				}},
   333  			}),
   334  			destRange: newTestMetaRange([]testRange{
   335  				{rng: committed.Range{ID: "base:k1-k3", MinKey: committed.Key("k1"), MaxKey: committed.Key("k3")}, records: []testValueRecord{
   336  					{"k1", "base:k1"}, {"k3", "base:k3"},
   337  				}},
   338  				{
   339  					rng: committed.Range{ID: "base:k4-k6", MinKey: committed.Key("k4"), MaxKey: committed.Key("k6")}, records: []testValueRecord{
   340  						{"k4", "base:k4"}, {"k6", "base:k6"},
   341  					},
   342  				},
   343  			}),
   344  			expectedResult: []testRunResult{{
   345  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   346  				expectedActions: []writeAction{
   347  					{
   348  						action:   actionTypeWriteRecord,
   349  						key:      "k1",
   350  						identity: "base:k1",
   351  					},
   352  					{
   353  						action:   actionTypeWriteRecord,
   354  						key:      "k2",
   355  						identity: "source:k2",
   356  					},
   357  					{
   358  						action:   actionTypeWriteRecord,
   359  						key:      "k3",
   360  						identity: "base:k3",
   361  					},
   362  					{
   363  						action:   actionTypeWriteRecord,
   364  						key:      "k4",
   365  						identity: "base:k4",
   366  					},
   367  					{
   368  						action:   actionTypeWriteRecord,
   369  						key:      "k5",
   370  						identity: "source:k5",
   371  					},
   372  				},
   373  				expectedErr: nil,
   374  			}},
   375  		},
   376  		"source range - overlapping ranges": {
   377  			baseRange: newTestMetaRange([]testRange{
   378  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   379  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   380  				}},
   381  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   382  					{"k11", "base:k11"}, {"k12", "base:k12"},
   383  				}},
   384  			}),
   385  			sourceRange: newTestMetaRange([]testRange{
   386  				{rng: committed.Range{ID: "source:k1-k10", MinKey: committed.Key("k1"), MaxKey: committed.Key("k10"), Count: 6, EstimatedSize: 66666}, records: []testValueRecord{
   387  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k4", "source:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"}, {"k10", "source:k10"},
   388  				}},
   389  			}),
   390  			destRange: newTestMetaRange([]testRange{
   391  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   392  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   393  				}},
   394  			}),
   395  			expectedResult: []testRunResult{{
   396  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   397  				expectedActions: []writeAction{
   398  					{action: actionTypeWriteRecord, key: "k1", identity: "base:k1"},
   399  					{action: actionTypeWriteRecord, key: "k3", identity: "base:k3"},
   400  					{action: actionTypeWriteRecord, key: "k4", identity: "source:k4"},
   401  					{action: actionTypeWriteRecord, key: "k5", identity: "base:k5"},
   402  					{action: actionTypeWriteRecord, key: "k6", identity: "base:k6"},
   403  					{action: actionTypeWriteRecord, key: "k10", identity: "source:k10"},
   404  				},
   405  			}},
   406  		},
   407  		"dest range - overlapping ranges": {
   408  			baseRange: newTestMetaRange([]testRange{
   409  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   410  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   411  				}},
   412  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   413  					{"k11", "base:k11"}, {"k12", "base:k12"},
   414  				}},
   415  			}),
   416  			sourceRange: newTestMetaRange([]testRange{
   417  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   418  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   419  				}},
   420  			}),
   421  			destRange: newTestMetaRange([]testRange{
   422  				{rng: committed.Range{ID: "dest:k1-k10", MinKey: committed.Key("k1"), MaxKey: committed.Key("k10"), Count: 6, EstimatedSize: 66666}, records: []testValueRecord{
   423  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k4", "dest:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"}, {"k10", "dest:k10"},
   424  				}},
   425  			}),
   426  			expectedResult: []testRunResult{{
   427  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   428  				expectedActions: []writeAction{
   429  					{action: actionTypeWriteRecord, key: "k1", identity: "base:k1"},
   430  					{action: actionTypeWriteRecord, key: "k3", identity: "base:k3"},
   431  					{action: actionTypeWriteRecord, key: "k4", identity: "dest:k4"},
   432  					{action: actionTypeWriteRecord, key: "k5", identity: "base:k5"},
   433  					{action: actionTypeWriteRecord, key: "k6", identity: "base:k6"},
   434  					{action: actionTypeWriteRecord, key: "k10", identity: "dest:k10"},
   435  				},
   436  				expectedErr: nil,
   437  			}},
   438  		},
   439  		"source - remove at end of range": {
   440  			baseRange: newTestMetaRange([]testRange{
   441  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   442  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   443  				}},
   444  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   445  					{"k11", "base:k11"}, {"k12", "base:k12"},
   446  				}},
   447  			}),
   448  			sourceRange: newTestMetaRange([]testRange{
   449  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 4444}, records: []testValueRecord{
   450  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   451  				}},
   452  			}),
   453  			destRange: newTestMetaRange([]testRange{
   454  				{rng: committed.Range{ID: "dest:k1-k10", MinKey: committed.Key("k1"), MaxKey: committed.Key("k10"), Count: 6, EstimatedSize: 66666}, records: []testValueRecord{
   455  					{"k1", "base:k1"}, {"k3", "base:k3"}, {"k4", "dest:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"}, {"k10", "dest:k10"},
   456  				}},
   457  			}),
   458  			expectedResult: []testRunResult{{
   459  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   460  				expectedActions: []writeAction{
   461  					{action: actionTypeWriteRecord, key: "k1", identity: "base:k1"},
   462  					{action: actionTypeWriteRecord, key: "k3", identity: "base:k3"},
   463  					{action: actionTypeWriteRecord, key: "k4", identity: "dest:k4"},
   464  					{action: actionTypeWriteRecord, key: "k5", identity: "base:k5"},
   465  					{action: actionTypeWriteRecord, key: "k6", identity: "base:k6"},
   466  					{action: actionTypeWriteRecord, key: "k10", identity: "dest:k10"},
   467  				},
   468  				expectedErr: nil,
   469  			}},
   470  		},
   471  		"both added key to range": {
   472  			baseRange: newTestMetaRange([]testRange{
   473  				{rng: committed.Range{ID: "base:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6")}, records: []testValueRecord{
   474  					{"k1", "base:k1"},
   475  					{"k6", "base:k6"},
   476  				}},
   477  			}),
   478  			sourceRange: newTestMetaRange([]testRange{
   479  				{rng: committed.Range{ID: "source:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6")}, records: []testValueRecord{
   480  					{"k1", "base:k1"},
   481  					{"k2", "source:k2"},
   482  					{"k6", "base:k6"},
   483  				}},
   484  			}),
   485  			destRange: newTestMetaRange([]testRange{
   486  				{rng: committed.Range{ID: "dest:k1-k6", MinKey: committed.Key("k1"), MaxKey: committed.Key("k6")}, records: []testValueRecord{
   487  					{"k1", "base:k1"},
   488  					{"k3", "dest:k3"},
   489  					{"k6", "base:k6"},
   490  				}},
   491  			}),
   492  			expectedResult: []testRunResult{{
   493  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   494  				expectedActions: []writeAction{
   495  					{
   496  						action:   actionTypeWriteRecord,
   497  						key:      "k1",
   498  						identity: "base:k1",
   499  					},
   500  					{
   501  						action:   actionTypeWriteRecord,
   502  						key:      "k2",
   503  						identity: "source:k2",
   504  					},
   505  					{
   506  						action:   actionTypeWriteRecord,
   507  						key:      "k3",
   508  						identity: "dest:k3",
   509  					},
   510  					{
   511  						action:   actionTypeWriteRecord,
   512  						key:      "k6",
   513  						identity: "base:k6",
   514  					},
   515  				},
   516  			}},
   517  		},
   518  		"source range removed": {
   519  			baseRange: newTestMetaRange([]testRange{
   520  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   521  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   522  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   523  					{"k11", "base:k11"}, {"k12", "base:k12"},
   524  				}},
   525  			}),
   526  			sourceRange: newTestMetaRange([]testRange{{
   527  				rng:     committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   528  				records: nil,
   529  			}}),
   530  			destRange: newTestMetaRange([]testRange{
   531  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   532  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   533  			}),
   534  			expectedResult: []testRunResult{{
   535  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   536  				expectedActions: []writeAction{
   537  					{
   538  						action: actionTypeWriteRange,
   539  						rng:    committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   540  					},
   541  				},
   542  				expectedErr: nil,
   543  			}},
   544  		},
   545  		"dest range removed": {
   546  			baseRange: newTestMetaRange([]testRange{
   547  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   548  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   549  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   550  					{"k11", "base:k11"}, {"k12", "base:k12"},
   551  				}},
   552  			}),
   553  			sourceRange: newTestMetaRange([]testRange{
   554  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   555  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   556  			}),
   557  			destRange: newTestMetaRange([]testRange{
   558  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   559  			}),
   560  			expectedResult: []testRunResult{{
   561  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   562  				expectedActions: []writeAction{
   563  					{
   564  						action: actionTypeWriteRange,
   565  						rng:    committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   566  					},
   567  				},
   568  				expectedErr: nil,
   569  			}},
   570  		},
   571  		"source key removed from range - same bounds": {
   572  			baseRange: newTestMetaRange([]testRange{
   573  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   574  				{
   575  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   576  					records: []testValueRecord{
   577  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   578  					},
   579  				},
   580  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   581  					{"k11", "base:k11"}, {"k12", "base:k12"},
   582  				}},
   583  			}),
   584  			sourceRange: newTestMetaRange([]testRange{
   585  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   586  				{
   587  					rng: committed.Range{ID: "source:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   588  					records: []testValueRecord{
   589  						{"k3", "base:k3"}, {"k6", "base:k6"},
   590  					},
   591  				},
   592  			}),
   593  			destRange: newTestMetaRange([]testRange{
   594  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   595  				{
   596  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   597  					records: []testValueRecord{
   598  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   599  					},
   600  				},
   601  			}),
   602  			expectedResult: []testRunResult{{
   603  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   604  				expectedActions: []writeAction{
   605  					{action: actionTypeWriteRange, rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   606  					{action: actionTypeWriteRange, rng: committed.Range{ID: "source:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   607  				},
   608  			}},
   609  		},
   610  		"source key removed from range": {
   611  			baseRange: newTestMetaRange([]testRange{
   612  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   613  				{
   614  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   615  					records: []testValueRecord{
   616  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   617  					},
   618  				},
   619  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   620  					{"k11", "base:k11"}, {"k12", "base:k12"},
   621  				}},
   622  			}),
   623  			sourceRange: newTestMetaRange([]testRange{
   624  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   625  				{
   626  					rng: committed.Range{ID: "source:k3-k5", MinKey: committed.Key("k3"), MaxKey: committed.Key("k5"), Count: 2, EstimatedSize: 1234},
   627  					records: []testValueRecord{
   628  						{"k3", "base:k3"}, {"k5", "base:k5"},
   629  					},
   630  				},
   631  			}),
   632  			destRange: newTestMetaRange([]testRange{
   633  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   634  				{
   635  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   636  					records: []testValueRecord{
   637  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   638  					},
   639  				},
   640  			}),
   641  			expectedResult: []testRunResult{{
   642  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   643  				expectedActions: []writeAction{
   644  					{action: actionTypeWriteRange, rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   645  					{action: actionTypeWriteRecord, key: "k3", identity: "base:k3"},
   646  					{action: actionTypeWriteRecord, key: "k5", identity: "base:k5"},
   647  				},
   648  			}},
   649  		},
   650  		"dest key removed from range": {
   651  			baseRange: newTestMetaRange([]testRange{
   652  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   653  				{
   654  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   655  					records: []testValueRecord{
   656  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   657  					},
   658  				},
   659  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
   660  					{"k11", "base:k11"}, {"k12", "base:k12"},
   661  				}},
   662  			}),
   663  			sourceRange: newTestMetaRange([]testRange{
   664  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   665  				{
   666  					rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 4, EstimatedSize: 1234},
   667  					records: []testValueRecord{
   668  						{"k3", "base:k3"}, {"k4", "base:k4"}, {"k5", "base:k5"}, {"k6", "base:k6"},
   669  					},
   670  				},
   671  			}),
   672  			destRange: newTestMetaRange([]testRange{
   673  				{rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   674  				{
   675  					rng: committed.Range{ID: "dest:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
   676  					records: []testValueRecord{
   677  						{"k3", "base:k3"}, {"k6", "base:k6"},
   678  					},
   679  				},
   680  			}),
   681  			expectedResult: []testRunResult{{
   682  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   683  				expectedActions: []writeAction{
   684  					{action: actionTypeWriteRange, rng: committed.Range{ID: "base:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   685  					{action: actionTypeWriteRange, rng: committed.Range{ID: "dest:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   686  				},
   687  				expectedErr: nil,
   688  			}},
   689  		},
   690  		"empty source and base": {
   691  			baseRange:   newTestMetaRange([]testRange{}),
   692  			sourceRange: newTestMetaRange([]testRange{}),
   693  			destRange: newTestMetaRange([]testRange{
   694  				{rng: committed.Range{ID: "dest:k1-k2", MinKey: committed.Key("k1"), MaxKey: committed.Key("k2"), Count: 2, EstimatedSize: 1234}},
   695  				{rng: committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234}},
   696  			}),
   697  			expectedResult: []testRunResult{{
   698  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   699  				expectedActions: []writeAction{},
   700  				expectedErr:     graveler.ErrNoChanges,
   701  			}},
   702  		},
   703  		"dest removed range and added range after source removed range edges": {
   704  			baseRange: newTestMetaRange([]testRange{
   705  				{
   706  					rng: committed.Range{ID: "base:k1-k5", MinKey: committed.Key("k1"), MaxKey: committed.Key("k5"), Count: 5, EstimatedSize: 1234},
   707  					records: []testValueRecord{
   708  						{"k1", "base:k1"},
   709  						{"k2", "base:k2"},
   710  						{"k3", "base:k3"},
   711  						{"k4", "base:k4"},
   712  						{"k5", "base:k5"},
   713  					},
   714  				},
   715  			}),
   716  			sourceRange: newTestMetaRange([]testRange{
   717  				{
   718  					rng: committed.Range{ID: "source:k3-k4", MinKey: committed.Key("k3"), MaxKey: committed.Key("k4"), Count: 2, EstimatedSize: 1234},
   719  					records: []testValueRecord{
   720  						{"k3", "base:k3"}, {"k4", "base:k4"},
   721  					},
   722  				},
   723  			}),
   724  			destRange: newTestMetaRange([]testRange{
   725  				{
   726  					rng: committed.Range{ID: "dest:k6-k7", MinKey: committed.Key("k6"), MaxKey: committed.Key("k7"), Count: 2, EstimatedSize: 1234},
   727  					records: []testValueRecord{
   728  						{"k6", "dest:k6"}, {"k7", "dest:k7"},
   729  					},
   730  				},
   731  			}),
   732  			expectedResult: []testRunResult{{
   733  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   734  				expectedActions: []writeAction{
   735  					{action: actionTypeWriteRecord, key: "k6", identity: "dest:k6"},
   736  					{action: actionTypeWriteRecord, key: "k7", identity: "dest:k7"},
   737  				},
   738  				expectedErr: nil,
   739  			}},
   740  		},
   741  		"no changes": {
   742  			baseRange: newTestMetaRange([]testRange{
   743  				{
   744  					rng: committed.Range{ID: "base:k3-k4", MinKey: committed.Key("k3"), MaxKey: committed.Key("k4"), Count: 2, EstimatedSize: 1234},
   745  					records: []testValueRecord{
   746  						{"k3", "base:k3"}, {"k4", "base:k4"},
   747  					},
   748  				},
   749  			}),
   750  			sourceRange: newTestMetaRange([]testRange{
   751  				{
   752  					rng: committed.Range{ID: "base:k3-k4", MinKey: committed.Key("k3"), MaxKey: committed.Key("k4"), Count: 2, EstimatedSize: 1234},
   753  					records: []testValueRecord{
   754  						{"k3", "base:k3"}, {"k4", "base:k4"},
   755  					},
   756  				},
   757  			}),
   758  			destRange: newTestMetaRange([]testRange{
   759  				{
   760  					rng: committed.Range{ID: "base:k3-k4", MinKey: committed.Key("k3"), MaxKey: committed.Key("k4"), Count: 2, EstimatedSize: 1234},
   761  					records: []testValueRecord{
   762  						{"k3", "base:k3"}, {"k4", "base:k4"},
   763  					},
   764  				},
   765  			}),
   766  			expectedResult: []testRunResult{{
   767  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   768  				expectedActions: []writeAction{},
   769  				expectedErr:     graveler.ErrNoChanges,
   770  			}},
   771  		},
   772  		"source and dest changed record identity": {
   773  			baseRange: newTestMetaRange([]testRange{
   774  				{
   775  					rng:     committed.Range{ID: "base:b-c", MinKey: committed.Key("b"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
   776  					records: []testValueRecord{{key: "b", identity: "b"}, {key: "c", identity: "c"}},
   777  				},
   778  				{
   779  					rng:     committed.Range{ID: "base:d-e", MinKey: committed.Key("d"), MaxKey: committed.Key("e"), Count: 2, EstimatedSize: 1024},
   780  					records: []testValueRecord{{key: "d", identity: "d"}, {key: "e", identity: "e"}},
   781  				},
   782  			}),
   783  			sourceRange: newTestMetaRange([]testRange{
   784  				{
   785  					rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   786  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "d", identity: "d"}},
   787  				},
   788  				{
   789  					rng:     committed.Range{ID: "source:e", MinKey: committed.Key("e"), MaxKey: committed.Key("e"), Count: 2, EstimatedSize: 1024},
   790  					records: []testValueRecord{{key: "e", identity: "e1"}},
   791  				},
   792  			}),
   793  			destRange: newTestMetaRange([]testRange{
   794  				{
   795  					rng:     committed.Range{ID: "base:b-c", MinKey: committed.Key("b"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
   796  					records: []testValueRecord{{key: "b", identity: "b"}, {key: "c", identity: "c"}},
   797  				},
   798  				{
   799  					rng:     committed.Range{ID: "dest:d-e", MinKey: committed.Key("d"), MaxKey: committed.Key("e"), Count: 2, EstimatedSize: 1024},
   800  					records: []testValueRecord{{key: "d", identity: "d1"}, {key: "e", identity: "e"}},
   801  				},
   802  			}),
   803  			expectedResult: []testRunResult{{
   804  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   805  				expectedActions: []writeAction{
   806  					{
   807  						action:   actionTypeWriteRecord,
   808  						key:      "a",
   809  						identity: "a",
   810  					},
   811  					{
   812  						action:   actionTypeWriteRecord,
   813  						key:      "b",
   814  						identity: "b",
   815  					},
   816  					{
   817  						action:   actionTypeWriteRecord,
   818  						key:      "d",
   819  						identity: "d1",
   820  					},
   821  					{
   822  						action:   actionTypeWriteRecord,
   823  						key:      "e",
   824  						identity: "e1",
   825  					},
   826  				},
   827  				expectedErr: nil,
   828  			}},
   829  		},
   830  		"dest removed all source added": {
   831  			baseRange: newTestMetaRange([]testRange{
   832  				{
   833  					rng:     committed.Range{ID: "base:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   834  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "d", identity: "d"}},
   835  				},
   836  			}),
   837  			sourceRange: newTestMetaRange([]testRange{
   838  				{
   839  					rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 4, EstimatedSize: 1024},
   840  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
   841  				},
   842  			}),
   843  			destRange: newTestMetaRange([]testRange{}),
   844  			expectedResult: []testRunResult{{
   845  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   846  				expectedActions: []writeAction{
   847  					{
   848  						action:   actionTypeWriteRecord,
   849  						key:      "b",
   850  						identity: "b",
   851  					},
   852  					{
   853  						action:   actionTypeWriteRecord,
   854  						key:      "c",
   855  						identity: "c",
   856  					},
   857  				},
   858  				expectedErr: nil,
   859  			}},
   860  		},
   861  		"same identity different key": {
   862  			baseRange: newTestMetaRange([]testRange{
   863  				{
   864  					rng:     committed.Range{ID: "base:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   865  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "d", identity: "d"}},
   866  				},
   867  			}),
   868  			sourceRange: newTestMetaRange([]testRange{
   869  				{
   870  					rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 4, EstimatedSize: 1024},
   871  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "a1", identity: "a"}, {key: "c", identity: "c"}},
   872  				},
   873  			}),
   874  			destRange: newTestMetaRange([]testRange{
   875  				{
   876  					rng:     committed.Range{ID: "dest:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   877  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "d", identity: "d"}},
   878  				},
   879  			}),
   880  			expectedResult: []testRunResult{{
   881  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   882  				expectedActions: []writeAction{
   883  					{
   884  						action:   actionTypeWriteRecord,
   885  						key:      "a",
   886  						identity: "a",
   887  					},
   888  					{
   889  						action:   actionTypeWriteRecord,
   890  						key:      "a1",
   891  						identity: "a",
   892  					},
   893  					{
   894  						action:   actionTypeWriteRecord,
   895  						key:      "c",
   896  						identity: "c",
   897  					},
   898  				},
   899  				expectedErr: nil,
   900  			}},
   901  		},
   902  		"dest removed all source range before base": {
   903  			baseRange: newTestMetaRange([]testRange{
   904  				{
   905  					rng:     committed.Range{ID: "base:c-d", MinKey: committed.Key("c"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   906  					records: []testValueRecord{{key: "c", identity: "c"}, {key: "d", identity: "d"}},
   907  				},
   908  			}),
   909  			sourceRange: newTestMetaRange([]testRange{
   910  				{
   911  					rng:     committed.Range{ID: "source:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   912  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}},
   913  				},
   914  			}),
   915  			destRange: newTestMetaRange([]testRange{}),
   916  			expectedResult: []testRunResult{{
   917  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   918  				expectedActions: []writeAction{
   919  					{
   920  						action: actionTypeWriteRange,
   921  						rng:    committed.Range{ID: "source:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   922  					},
   923  				},
   924  				expectedErr: nil,
   925  			}},
   926  		},
   927  		"dest removed all different key different identity": {
   928  			baseRange: newTestMetaRange([]testRange{
   929  				{
   930  					rng:     committed.Range{ID: "base:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   931  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "a2", identity: "a2"}, {key: "b", identity: "b"}},
   932  				},
   933  			}),
   934  			sourceRange: newTestMetaRange([]testRange{
   935  				{
   936  					rng:     committed.Range{ID: "source:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   937  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "a1", identity: "a1"}, {key: "b", identity: "b"}},
   938  				},
   939  			}),
   940  			destRange: newTestMetaRange([]testRange{}),
   941  			expectedResult: []testRunResult{{
   942  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   943  				expectedActions: []writeAction{
   944  					{
   945  						action:   actionTypeWriteRecord,
   946  						key:      "a1",
   947  						identity: "a1",
   948  					},
   949  				},
   950  				expectedErr: nil,
   951  			}},
   952  		},
   953  		"dest removed all base and source same identity": {
   954  			baseRange: newTestMetaRange([]testRange{
   955  				{
   956  					rng:     committed.Range{ID: "base:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   957  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}},
   958  				},
   959  				{
   960  					rng:     committed.Range{ID: "base:d-f", MinKey: committed.Key("d"), MaxKey: committed.Key("f"), Count: 2, EstimatedSize: 1024},
   961  					records: []testValueRecord{{key: "d", identity: "d"}, {key: "f", identity: "f"}},
   962  				},
   963  			}),
   964  			sourceRange: newTestMetaRange([]testRange{
   965  				{
   966  					rng:     committed.Range{ID: "base:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
   967  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}},
   968  				},
   969  				{
   970  					rng:     committed.Range{ID: "source:c-e", MinKey: committed.Key("c"), MaxKey: committed.Key("e"), Count: 2, EstimatedSize: 1024},
   971  					records: []testValueRecord{{key: "c", identity: "c"}, {key: "e", identity: "e"}},
   972  				},
   973  			}),
   974  			destRange: newTestMetaRange([]testRange{}),
   975  			expectedResult: []testRunResult{{
   976  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
   977  				expectedActions: []writeAction{
   978  					{
   979  						action:   actionTypeWriteRecord,
   980  						key:      "c",
   981  						identity: "c",
   982  					},
   983  					{
   984  						action:   actionTypeWriteRecord,
   985  						key:      "e",
   986  						identity: "e",
   987  					},
   988  				},
   989  				expectedErr: nil,
   990  			}},
   991  		},
   992  		"source key before dest range": {
   993  			baseRange: newTestMetaRange([]testRange{
   994  				{
   995  					rng:     committed.Range{ID: "base:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
   996  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
   997  				},
   998  			}),
   999  			sourceRange: newTestMetaRange([]testRange{
  1000  				{
  1001  					rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1002  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
  1003  				},
  1004  			}),
  1005  			destRange: newTestMetaRange([]testRange{
  1006  				{
  1007  					rng:     committed.Range{ID: "dest:b-c", MinKey: committed.Key("b"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1008  					records: []testValueRecord{{key: "b", identity: "b"}, {key: "c", identity: "c"}},
  1009  				},
  1010  				{
  1011  					rng:     committed.Range{ID: "dest:e-f", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2, EstimatedSize: 1024},
  1012  					records: []testValueRecord{{key: "e", identity: "e"}, {key: "f", identity: "f"}},
  1013  				},
  1014  			}),
  1015  			expectedResult: []testRunResult{{
  1016  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1017  				expectedActions: []writeAction{
  1018  					{
  1019  						action:   actionTypeWriteRecord,
  1020  						key:      "b",
  1021  						identity: "b",
  1022  					},
  1023  					{
  1024  						action:   actionTypeWriteRecord,
  1025  						key:      "c",
  1026  						identity: "c",
  1027  					},
  1028  					{
  1029  						action: actionTypeWriteRange,
  1030  						rng:    committed.Range{ID: "dest:e-f", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2, EstimatedSize: 1024},
  1031  					},
  1032  				},
  1033  				expectedErr: nil,
  1034  			}},
  1035  		},
  1036  		"dest key before source range": {
  1037  			baseRange: newTestMetaRange([]testRange{
  1038  				{
  1039  					rng:     committed.Range{ID: "base:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1040  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
  1041  				},
  1042  			}),
  1043  			sourceRange: newTestMetaRange([]testRange{
  1044  				{
  1045  					rng:     committed.Range{ID: "source:b-c", MinKey: committed.Key("b"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1046  					records: []testValueRecord{{key: "b", identity: "b"}, {key: "c", identity: "c"}},
  1047  				},
  1048  				{
  1049  					rng:     committed.Range{ID: "source:e-f", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2, EstimatedSize: 1024},
  1050  					records: []testValueRecord{{key: "e", identity: "e"}, {key: "f", identity: "f"}},
  1051  				},
  1052  			}),
  1053  			destRange: newTestMetaRange([]testRange{
  1054  				{
  1055  					rng:     committed.Range{ID: "dest:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1056  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
  1057  				},
  1058  			}),
  1059  			expectedResult: []testRunResult{{
  1060  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1061  				expectedActions: []writeAction{
  1062  					{
  1063  						action:   actionTypeWriteRecord,
  1064  						key:      "b",
  1065  						identity: "b",
  1066  					},
  1067  					{
  1068  						action:   actionTypeWriteRecord,
  1069  						key:      "c",
  1070  						identity: "c",
  1071  					},
  1072  					{
  1073  						action: actionTypeWriteRange,
  1074  						rng:    committed.Range{ID: "source:e-f", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2, EstimatedSize: 1024},
  1075  					},
  1076  				},
  1077  				expectedErr: nil,
  1078  			}},
  1079  		},
  1080  		"dest range before source key": {
  1081  			baseRange: newTestMetaRange([]testRange{
  1082  				{
  1083  					rng:     committed.Range{ID: "base:c-c", MinKey: committed.Key("c"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1084  					records: []testValueRecord{{key: "c", identity: "c"}},
  1085  				},
  1086  			}),
  1087  			sourceRange: newTestMetaRange([]testRange{
  1088  				{
  1089  					rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1090  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "d", identity: "d"}},
  1091  				},
  1092  			}),
  1093  			destRange: newTestMetaRange([]testRange{
  1094  				{
  1095  					rng:     committed.Range{ID: "dest:a-a", MinKey: committed.Key("a"), MaxKey: committed.Key("a"), Count: 2, EstimatedSize: 1024},
  1096  					records: []testValueRecord{{key: "a", identity: "a"}},
  1097  				},
  1098  				{
  1099  					rng:     committed.Range{ID: "dest:b-b", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1100  					records: []testValueRecord{{key: "b", identity: "b"}},
  1101  				},
  1102  				{
  1103  					rng:     committed.Range{ID: "base:c-c", MinKey: committed.Key("c"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1104  					records: []testValueRecord{{key: "c", identity: "c"}},
  1105  				},
  1106  			}),
  1107  			expectedResult: []testRunResult{{
  1108  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1109  				expectedActions: []writeAction{
  1110  					{
  1111  						action:   actionTypeWriteRecord,
  1112  						key:      "a",
  1113  						identity: "a",
  1114  					},
  1115  					{
  1116  						action: actionTypeWriteRange,
  1117  						rng:    committed.Range{ID: "dest:b-b", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1118  					},
  1119  					{
  1120  						action:   actionTypeWriteRecord,
  1121  						key:      "d",
  1122  						identity: "d",
  1123  					},
  1124  				},
  1125  				expectedErr: nil,
  1126  			}},
  1127  		},
  1128  		"source range before dest key": {
  1129  			baseRange: newTestMetaRange([]testRange{
  1130  				{
  1131  					rng:     committed.Range{ID: "base:c-c", MinKey: committed.Key("c"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1132  					records: []testValueRecord{{key: "c", identity: "c"}},
  1133  				},
  1134  			}),
  1135  			sourceRange: newTestMetaRange([]testRange{
  1136  				{
  1137  					rng:     committed.Range{ID: "source:a-a", MinKey: committed.Key("a"), MaxKey: committed.Key("a"), Count: 2, EstimatedSize: 1024},
  1138  					records: []testValueRecord{{key: "a", identity: "a"}},
  1139  				},
  1140  				{
  1141  					rng:     committed.Range{ID: "source:b-b", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1142  					records: []testValueRecord{{key: "b", identity: "b"}},
  1143  				},
  1144  				{
  1145  					rng:     committed.Range{ID: "base:c-c", MinKey: committed.Key("c"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 1024},
  1146  					records: []testValueRecord{{key: "c", identity: "c"}},
  1147  				},
  1148  			}),
  1149  			destRange: newTestMetaRange([]testRange{
  1150  				{
  1151  					rng:     committed.Range{ID: "dest:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1152  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "d", identity: "d"}},
  1153  				},
  1154  			}),
  1155  			expectedResult: []testRunResult{{
  1156  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1157  				expectedActions: []writeAction{
  1158  					{
  1159  						action:   actionTypeWriteRecord,
  1160  						key:      "a",
  1161  						identity: "a",
  1162  					},
  1163  					{
  1164  						action: actionTypeWriteRange,
  1165  						rng:    committed.Range{ID: "source:b-b", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1166  					},
  1167  					{
  1168  						action:   actionTypeWriteRecord,
  1169  						key:      "d",
  1170  						identity: "d",
  1171  					},
  1172  				},
  1173  				expectedErr: nil,
  1174  			}},
  1175  		},
  1176  		"dest and base are the same": {
  1177  			baseRange: newTestMetaRange([]testRange{
  1178  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1179  					{"k11", "base:k11"}, {"k12", "base:k12"},
  1180  				}},
  1181  			}),
  1182  			sourceRange: newTestMetaRange([]testRange{
  1183  				{rng: committed.Range{ID: "source:k13-k14", MinKey: committed.Key("k13"), MaxKey: committed.Key("k14"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1184  					{"k13", "base:k13"}, {"k14", "base:k14"},
  1185  				}},
  1186  			}),
  1187  			destRange: newTestMetaRange([]testRange{
  1188  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1189  					{"k11", "base:k11"}, {"k12", "base:k12"},
  1190  				}},
  1191  			}),
  1192  			expectedResult: []testRunResult{{
  1193  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1194  				expectedActions: []writeAction{},
  1195  			}},
  1196  		},
  1197  		"source and dest are the same": {
  1198  			baseRange: newTestMetaRange([]testRange{
  1199  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1200  					{"k11", "base:k11"}, {"k12", "base:k12"},
  1201  				}},
  1202  			}),
  1203  			sourceRange: newTestMetaRange([]testRange{
  1204  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1205  					{"k11", "base:k11"}, {"k12", "base:k12"},
  1206  				}},
  1207  			}),
  1208  			destRange: newTestMetaRange([]testRange{
  1209  				{rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
  1210  					{"k11", "base:k11"}, {"k12", "base:k12"},
  1211  				}},
  1212  			}),
  1213  			expectedResult: []testRunResult{{
  1214  				mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone, graveler.MergeStrategyDest, graveler.MergeStrategySrc},
  1215  				expectedActions: []writeAction{},
  1216  				expectedErr:     graveler.ErrNoChanges,
  1217  			}},
  1218  		},
  1219  	}
  1220  
  1221  	runMergeTests(tests, t)
  1222  }
  1223  
  1224  func TestMergeStrategies(t *testing.T) {
  1225  	tests := testCases{
  1226  		// Base branch has a 2 records range, with the keys 'a' and 'b'. Source branch changes the value on key 'a' and leaves key 'b' unchanged
  1227  		// Dest branch deletes both entries, creating a conflict on entry 'a'
  1228  		// As per merge strategies, the expected outcomes are:
  1229  		// - No strategy - a conflict
  1230  		// - Dest strategy - favors dest branch, so both records are deleted, 'ignoring' the value modification on record 'a'
  1231  		// - Source strategy - favors source branch, so record 'a', with the modified value, is written, ignoring its deletion on dest. Record b
  1232  		//   is still deleted as there is no conflict involving it
  1233  		"dest removed all same key different identity": {
  1234  			baseRange: newTestMetaRange([]testRange{
  1235  				{
  1236  					rng:     committed.Range{ID: "base:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1237  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}},
  1238  				},
  1239  			}),
  1240  			sourceRange: newTestMetaRange([]testRange{
  1241  				{
  1242  					rng:     committed.Range{ID: "source:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1243  					records: []testValueRecord{{key: "a", identity: "a1"}, {key: "b", identity: "b"}},
  1244  				},
  1245  			}),
  1246  			destRange: newTestMetaRange([]testRange{}),
  1247  			expectedResult: []testRunResult{
  1248  				{
  1249  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1250  					expectedActions: []writeAction{},
  1251  					expectedErr:     graveler.ErrConflictFound,
  1252  				},
  1253  				{
  1254  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1255  					expectedActions: []writeAction{},
  1256  					expectedErr:     nil,
  1257  				},
  1258  				{
  1259  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1260  					expectedActions: []writeAction{
  1261  						{
  1262  							action:   actionTypeWriteRecord,
  1263  							key:      "a",
  1264  							identity: "a1",
  1265  						},
  1266  					},
  1267  					expectedErr: nil,
  1268  				},
  1269  			},
  1270  		},
  1271  		// Base branch has a 5 records range, with the keys 'k1' through 'k5'. Both source and dest branches modify this range by deleting and
  1272  		// changing this range. Both branches delete records 'k1', 'k2' and 'k5' and while dest branch also deletes entries 'k3' and 'k4', source
  1273  		// branch leaves record 'k3' unchanged and changes the value on record 'k4', creating a conflict
  1274  		// Dest branch also adds 2 new records, 'k6' and 'k7', which should not create a conflict
  1275  		// As per merge strategies, the expected outcomes are:
  1276  		// - No strategy - a conflict
  1277  		// - Dest strategy - favors dest branch, so records 'k1' through 'k5' are deleted, 'ignoring' the value modification on record 'k4'.
  1278  		// - Source strategy - favors source branch, so record 'k4', with the modified value, is written, ignoring its deletion on dest. The rest
  1279  		//   of record 'k1', 'k2' 'k3' and 'k5' are still deleted as there is no conflict involving them. Same goes for 'k6' and 'k7' which are
  1280  		//   written on both 'dest-wins' and 'source-wins' strategies
  1281  		"source and dest change same range conflict": {
  1282  			baseRange: newTestMetaRange([]testRange{
  1283  				{
  1284  					rng: committed.Range{ID: "base:k1-k5", MinKey: committed.Key("k1"), MaxKey: committed.Key("k5"), Count: 5, EstimatedSize: 1234},
  1285  					records: []testValueRecord{
  1286  						{"k1", "base:k1"},
  1287  						{"k2", "base:k2"},
  1288  						{"k3", "base:k3"},
  1289  						{"k4", "base:k4"},
  1290  						{"k5", "base:k5"},
  1291  					},
  1292  				},
  1293  			}),
  1294  			sourceRange: newTestMetaRange([]testRange{
  1295  				{
  1296  					rng: committed.Range{ID: "source:k3-k4", MinKey: committed.Key("k3"), MaxKey: committed.Key("k4"), Count: 2, EstimatedSize: 1234},
  1297  					records: []testValueRecord{
  1298  						{"k3", "base:k3"}, {"k4", "source:k4"},
  1299  					},
  1300  				},
  1301  			}),
  1302  			destRange: newTestMetaRange([]testRange{
  1303  				{
  1304  					rng: committed.Range{ID: "dest:k6-k7", MinKey: committed.Key("k6"), MaxKey: committed.Key("k7"), Count: 2, EstimatedSize: 1234},
  1305  					records: []testValueRecord{
  1306  						{"k6", "dest:k6"}, {"k7", "dest:k7"},
  1307  					},
  1308  				},
  1309  			}),
  1310  			expectedResult: []testRunResult{
  1311  				{
  1312  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1313  					expectedActions: []writeAction{},
  1314  					expectedErr:     graveler.ErrConflictFound,
  1315  				},
  1316  				{
  1317  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1318  					expectedActions: []writeAction{
  1319  						{
  1320  							action:   actionTypeWriteRecord,
  1321  							key:      "k6",
  1322  							identity: "dest:k6",
  1323  						},
  1324  						{
  1325  							action:   actionTypeWriteRecord,
  1326  							key:      "k7",
  1327  							identity: "dest:k7",
  1328  						},
  1329  					},
  1330  					expectedErr: nil,
  1331  				},
  1332  				{
  1333  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1334  					expectedActions: []writeAction{
  1335  						{
  1336  							action:   actionTypeWriteRecord,
  1337  							key:      "k4",
  1338  							identity: "source:k4",
  1339  						},
  1340  						{
  1341  							action:   actionTypeWriteRecord,
  1342  							key:      "k6",
  1343  							identity: "dest:k6",
  1344  						},
  1345  						{
  1346  							action:   actionTypeWriteRecord,
  1347  							key:      "k7",
  1348  							identity: "dest:k7",
  1349  						},
  1350  					},
  1351  					expectedErr: nil,
  1352  				},
  1353  			},
  1354  		},
  1355  		// Base branch has a 2 records range, with the keys 'a' and 'b'. Source branch deletes both records and adds 2 new records - 'c' and 'd'
  1356  		// Dest branch changes the value on key 'a', creating a conflict with the deleted 'a' record on source, and leaves key 'b' unchanged
  1357  		// As per merge strategies, the expected outcomes are:
  1358  		// - No strategy - a conflict
  1359  		// - Dest strategy - favors dest branch, so record 'a', with the modified value, is written, ignoring its deletion on source
  1360  		// - Source strategy - favors source branch, so record 'a' is deleted, ignoring its value change on branch dest
  1361  		// Record 'b' is deleted for both strategies as there is no conflict involving it. Same goes for records 'c' and 'd' that are written,
  1362  		// regardless of merge strategy
  1363  		"dest range before source": {
  1364  			baseRange: newTestMetaRange([]testRange{
  1365  				{
  1366  					rng:     committed.Range{ID: "base:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1367  					records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}},
  1368  				},
  1369  			}),
  1370  			sourceRange: newTestMetaRange([]testRange{
  1371  				{
  1372  					rng:     committed.Range{ID: "source:c-d", MinKey: committed.Key("c"), MaxKey: committed.Key("d"), Count: 2, EstimatedSize: 1024},
  1373  					records: []testValueRecord{{key: "c", identity: "c"}, {key: "d", identity: "d"}},
  1374  				},
  1375  			}),
  1376  			destRange: newTestMetaRange([]testRange{
  1377  				{
  1378  					rng:     committed.Range{ID: "dest:a-b", MinKey: committed.Key("a"), MaxKey: committed.Key("b"), Count: 2, EstimatedSize: 1024},
  1379  					records: []testValueRecord{{key: "a", identity: "a1"}, {key: "b", identity: "b"}},
  1380  				},
  1381  			}),
  1382  			expectedResult: []testRunResult{
  1383  				{
  1384  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1385  					expectedActions: []writeAction{},
  1386  					expectedErr:     graveler.ErrConflictFound,
  1387  				},
  1388  				{
  1389  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1390  					expectedActions: []writeAction{
  1391  						{
  1392  							action:   actionTypeWriteRecord,
  1393  							key:      "a",
  1394  							identity: "a1",
  1395  						},
  1396  						{
  1397  							action:   actionTypeWriteRecord,
  1398  							key:      "c",
  1399  							identity: "c",
  1400  						},
  1401  						{
  1402  							action:   actionTypeWriteRecord,
  1403  							key:      "d",
  1404  							identity: "d",
  1405  						},
  1406  					},
  1407  					expectedErr: nil,
  1408  				},
  1409  				{
  1410  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1411  					expectedActions: []writeAction{
  1412  						{
  1413  							action:   actionTypeWriteRecord,
  1414  							key:      "c",
  1415  							identity: "c",
  1416  						},
  1417  						{
  1418  							action:   actionTypeWriteRecord,
  1419  							key:      "d",
  1420  							identity: "d",
  1421  						},
  1422  					},
  1423  					expectedErr: nil,
  1424  				},
  1425  			},
  1426  		},
  1427  		"source change and dest delete same entry": {
  1428  			baseRange: newTestMetaRange([]testRange{{
  1429  				rng:     committed.Range{ID: "base:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 333},
  1430  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}},
  1431  			}}),
  1432  			sourceRange: newTestMetaRange([]testRange{{
  1433  				rng:     committed.Range{ID: "source:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 123},
  1434  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b1"}, {key: "c", identity: "c"}},
  1435  			}}),
  1436  			destRange: newTestMetaRange([]testRange{{
  1437  				rng:     committed.Range{ID: "dest:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 321},
  1438  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "c", identity: "c"}},
  1439  			}}),
  1440  			expectedResult: []testRunResult{
  1441  				{
  1442  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1443  					expectedActions: []writeAction{
  1444  						{
  1445  							action:   actionTypeWriteRecord,
  1446  							key:      "a",
  1447  							identity: "a",
  1448  						},
  1449  					},
  1450  					expectedErr: graveler.ErrConflictFound,
  1451  				},
  1452  				{
  1453  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1454  					expectedActions: []writeAction{
  1455  						{
  1456  							action:   actionTypeWriteRecord,
  1457  							key:      "a",
  1458  							identity: "a",
  1459  						},
  1460  						{
  1461  							action:   actionTypeWriteRecord,
  1462  							key:      "c",
  1463  							identity: "c",
  1464  						},
  1465  					},
  1466  					expectedErr: nil,
  1467  				},
  1468  				{
  1469  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1470  					expectedActions: []writeAction{
  1471  						{
  1472  							action:   actionTypeWriteRecord,
  1473  							key:      "a",
  1474  							identity: "a",
  1475  						},
  1476  						{
  1477  							action:   actionTypeWriteRecord,
  1478  							key:      "b",
  1479  							identity: "b1",
  1480  						},
  1481  						{
  1482  							action:   actionTypeWriteRecord,
  1483  							key:      "c",
  1484  							identity: "c",
  1485  						},
  1486  					},
  1487  					expectedErr: nil,
  1488  				},
  1489  			},
  1490  		},
  1491  
  1492  		"source delete and dest change same entry": {
  1493  			baseRange: newTestMetaRange([]testRange{{
  1494  				rng:     committed.Range{ID: "base:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 333},
  1495  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}},
  1496  			}}),
  1497  			sourceRange: newTestMetaRange([]testRange{{
  1498  				rng:     committed.Range{ID: "source:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 2, EstimatedSize: 123},
  1499  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "c", identity: "c"}},
  1500  			}}),
  1501  			destRange: newTestMetaRange([]testRange{{
  1502  				rng:     committed.Range{ID: "dest:a-c", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 321},
  1503  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b1"}, {key: "c", identity: "c"}},
  1504  			}}),
  1505  			expectedResult: []testRunResult{
  1506  				{
  1507  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1508  					expectedActions: []writeAction{
  1509  						{
  1510  							action:   actionTypeWriteRecord,
  1511  							key:      "a",
  1512  							identity: "a",
  1513  						},
  1514  					},
  1515  					expectedErr: graveler.ErrConflictFound,
  1516  				},
  1517  				{
  1518  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1519  					expectedActions: []writeAction{
  1520  						{
  1521  							action:   actionTypeWriteRecord,
  1522  							key:      "a",
  1523  							identity: "a",
  1524  						},
  1525  						{
  1526  							action:   actionTypeWriteRecord,
  1527  							key:      "b",
  1528  							identity: "b1",
  1529  						},
  1530  						{
  1531  							action:   actionTypeWriteRecord,
  1532  							key:      "c",
  1533  							identity: "c",
  1534  						},
  1535  					},
  1536  					expectedErr: nil,
  1537  				},
  1538  				{
  1539  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1540  					expectedActions: []writeAction{
  1541  						{
  1542  							action:   actionTypeWriteRecord,
  1543  							key:      "a",
  1544  							identity: "a",
  1545  						},
  1546  						{
  1547  							action:   actionTypeWriteRecord,
  1548  							key:      "c",
  1549  							identity: "c",
  1550  						},
  1551  					},
  1552  					expectedErr: nil,
  1553  				},
  1554  			},
  1555  		},
  1556  
  1557  		"source and dest delete from same range": {
  1558  			baseRange: newTestMetaRange([]testRange{{
  1559  				rng:     committed.Range{ID: "base:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 4, EstimatedSize: 4444},
  1560  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}, {key: "d", identity: "d"}},
  1561  			}}),
  1562  			sourceRange: newTestMetaRange([]testRange{{
  1563  				rng:     committed.Range{ID: "source:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 3, EstimatedSize: 1234},
  1564  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "c", identity: "c1"}, {key: "d", identity: "d"}},
  1565  			}}),
  1566  			destRange: newTestMetaRange([]testRange{{
  1567  				rng:     committed.Range{ID: "dest:a-d", MinKey: committed.Key("a"), MaxKey: committed.Key("d"), Count: 3, EstimatedSize: 4321},
  1568  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b1"}, {key: "d", identity: "d"}},
  1569  			}}),
  1570  			expectedResult: []testRunResult{
  1571  				{
  1572  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1573  					expectedActions: []writeAction{
  1574  						{
  1575  							action:   actionTypeWriteRecord,
  1576  							key:      "a",
  1577  							identity: "a",
  1578  						},
  1579  					},
  1580  					expectedErr: graveler.ErrConflictFound,
  1581  				},
  1582  				{
  1583  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1584  					expectedActions: []writeAction{
  1585  						{
  1586  							action:   actionTypeWriteRecord,
  1587  							key:      "a",
  1588  							identity: "a",
  1589  						},
  1590  						{
  1591  							action:   actionTypeWriteRecord,
  1592  							key:      "b",
  1593  							identity: "b1",
  1594  						},
  1595  						{
  1596  							action:   actionTypeWriteRecord,
  1597  							key:      "d",
  1598  							identity: "d",
  1599  						},
  1600  					},
  1601  					expectedErr: nil,
  1602  				},
  1603  				{
  1604  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1605  					expectedActions: []writeAction{
  1606  						{
  1607  							action:   actionTypeWriteRecord,
  1608  							key:      "a",
  1609  							identity: "a",
  1610  						},
  1611  						{
  1612  							action:   actionTypeWriteRecord,
  1613  							key:      "c",
  1614  							identity: "c1",
  1615  						},
  1616  						{
  1617  							action:   actionTypeWriteRecord,
  1618  							key:      "d",
  1619  							identity: "d",
  1620  						},
  1621  					},
  1622  					expectedErr: nil,
  1623  				},
  1624  			},
  1625  		},
  1626  		"source and dest change same entry": {
  1627  			baseRange: newTestMetaRange([]testRange{{
  1628  				rng:     committed.Range{ID: "base:a-a", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 1234},
  1629  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b"}, {key: "c", identity: "c"}},
  1630  			}}),
  1631  			sourceRange: newTestMetaRange([]testRange{{
  1632  				rng:     committed.Range{ID: "source:a-a", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 1234},
  1633  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b1"}, {key: "c", identity: "c"}},
  1634  			}}),
  1635  			destRange: newTestMetaRange([]testRange{{
  1636  				rng:     committed.Range{ID: "dest:a-a", MinKey: committed.Key("a"), MaxKey: committed.Key("c"), Count: 3, EstimatedSize: 1234},
  1637  				records: []testValueRecord{{key: "a", identity: "a"}, {key: "b", identity: "b2"}, {key: "c", identity: "c"}},
  1638  			}}),
  1639  			expectedResult: []testRunResult{
  1640  				{
  1641  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyNone},
  1642  					expectedActions: []writeAction{
  1643  						{
  1644  							action:   actionTypeWriteRecord,
  1645  							key:      "a",
  1646  							identity: "a",
  1647  						},
  1648  					},
  1649  					expectedErr: graveler.ErrConflictFound,
  1650  				},
  1651  				{
  1652  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategyDest},
  1653  					expectedActions: []writeAction{
  1654  						{
  1655  							action:   actionTypeWriteRecord,
  1656  							key:      "a",
  1657  							identity: "a",
  1658  						},
  1659  						{
  1660  							action:   actionTypeWriteRecord,
  1661  							key:      "b",
  1662  							identity: "b2",
  1663  						},
  1664  						{
  1665  							action:   actionTypeWriteRecord,
  1666  							key:      "c",
  1667  							identity: "c",
  1668  						},
  1669  					},
  1670  					expectedErr: nil,
  1671  				},
  1672  				{
  1673  					mergeStrategies: []graveler.MergeStrategy{graveler.MergeStrategySrc},
  1674  					expectedActions: []writeAction{
  1675  						{
  1676  							action:   actionTypeWriteRecord,
  1677  							key:      "a",
  1678  							identity: "a",
  1679  						},
  1680  						{
  1681  							action:   actionTypeWriteRecord,
  1682  							key:      "b",
  1683  							identity: "b1",
  1684  						},
  1685  						{
  1686  							action:   actionTypeWriteRecord,
  1687  							key:      "c",
  1688  							identity: "c",
  1689  						},
  1690  					},
  1691  					expectedErr: nil,
  1692  				},
  1693  			},
  1694  		},
  1695  	}
  1696  
  1697  	runMergeTests(tests, t)
  1698  }
  1699  
  1700  func runMergeTests(tests testCases, t *testing.T) {
  1701  	for name, tst := range tests {
  1702  		for _, expectedResult := range tst.expectedResult {
  1703  			for _, mergeStrategy := range expectedResult.mergeStrategies {
  1704  				t.Run(name, func(t *testing.T) {
  1705  					ctrl := gomock.NewController(t)
  1706  					defer ctrl.Finish()
  1707  					ctx := context.Background()
  1708  					writer := mock.NewMockMetaRangeWriter(ctrl)
  1709  					for _, action := range expectedResult.expectedActions {
  1710  						switch action.action {
  1711  						case actionTypeWriteRecord:
  1712  							writer.EXPECT().WriteRecord(newRecordMatcher(action.key, action.identity))
  1713  						case actionTypeWriteRange:
  1714  							writer.EXPECT().WriteRange(gomock.Eq(action.rng))
  1715  						}
  1716  					}
  1717  					metaRangeManager := mock.NewMockMetaRangeManager(ctrl)
  1718  					metaRangeManager.EXPECT().NewWriter(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(writer)
  1719  					sourceMetaRangeID := tst.sourceRange.GetMetaRangeID()
  1720  					destMetaRangeID := tst.destRange.GetMetaRangeID()
  1721  					baseMetaRangeID := tst.baseRange.GetMetaRangeID()
  1722  					metaRangeManager.EXPECT().NewMetaRangeIterator(gomock.Any(), gomock.Any(), baseMetaRangeID).AnyTimes().Return(createIter(tst.baseRange), nil)
  1723  					metaRangeManager.EXPECT().NewMetaRangeIterator(gomock.Any(), gomock.Any(), sourceMetaRangeID).AnyTimes().Return(createIter(tst.sourceRange), nil)
  1724  					metaRangeManager.EXPECT().NewMetaRangeIterator(gomock.Any(), gomock.Any(), destMetaRangeID).AnyTimes().Return(createIter(tst.destRange), nil)
  1725  
  1726  					rangeManager := mock.NewMockRangeManager(ctrl)
  1727  
  1728  					writer.EXPECT().Abort().AnyTimes()
  1729  					metaRangeId := graveler.MetaRangeID("merge")
  1730  					writer.EXPECT().Close(gomock.Any()).Return(&metaRangeId, nil).AnyTimes()
  1731  					committedManager := committed.NewCommittedManager(metaRangeManager, rangeManager, params)
  1732  					_, err := committedManager.Merge(ctx, "ns", destMetaRangeID, sourceMetaRangeID, baseMetaRangeID, mergeStrategy)
  1733  					if !errors.Is(err, expectedResult.expectedErr) {
  1734  						t.Fatalf("Merge error='%v', expected='%v'", err, expectedResult.expectedErr)
  1735  					}
  1736  				})
  1737  			}
  1738  		}
  1739  	}
  1740  }
  1741  
  1742  func TestMergeCancelContext(t *testing.T) {
  1743  	ctrl := gomock.NewController(t)
  1744  	defer ctrl.Finish()
  1745  
  1746  	t.Run("source", func(t *testing.T) {
  1747  		base := testutil.NewFakeIterator().
  1748  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
  1749  			AddValueRecords(makeV("b", "dest:b"))
  1750  		source := testutil.NewFakeIterator()
  1751  		destination := testutil.NewFakeIterator().
  1752  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
  1753  			AddValueRecords(makeV("b", "dest:b"))
  1754  		writer := mock.NewMockMetaRangeWriter(ctrl)
  1755  		ctx, cancel := context.WithCancel(context.Background())
  1756  		cancel()
  1757  		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
  1758  		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
  1759  	})
  1760  
  1761  	t.Run("destination", func(t *testing.T) {
  1762  		base := testutil.NewFakeIterator().
  1763  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 2}).
  1764  			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
  1765  		source := testutil.NewFakeIterator().
  1766  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 2}).
  1767  			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
  1768  		destination := testutil.NewFakeIterator()
  1769  		writer := mock.NewMockMetaRangeWriter(ctrl)
  1770  		ctx, cancel := context.WithCancel(context.Background())
  1771  		cancel()
  1772  		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
  1773  		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
  1774  	})
  1775  
  1776  	t.Run("source_and_destination", func(t *testing.T) {
  1777  		base := testutil.NewFakeIterator().
  1778  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 3}).
  1779  			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
  1780  		source := testutil.NewFakeIterator().
  1781  			AddRange(&committed.Range{ID: "two", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2}).
  1782  			AddValueRecords(makeV("e", "source:e"), makeV("f", "source:f"))
  1783  		destination := testutil.NewFakeIterator().
  1784  			AddRange(&committed.Range{ID: "three", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
  1785  			AddValueRecords(makeV("b", "dest:b"))
  1786  		writer := mock.NewMockMetaRangeWriter(ctrl)
  1787  		ctx, cancel := context.WithCancel(context.Background())
  1788  		cancel()
  1789  		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
  1790  		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
  1791  	})
  1792  
  1793  	t.Run("base", func(t *testing.T) {
  1794  		base := testutil.NewFakeIterator()
  1795  		source := testutil.NewFakeIterator().
  1796  			AddRange(&committed.Range{ID: "two", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2}).
  1797  			AddValueRecords(makeV("e", "source:e"), makeV("f", "source:f"))
  1798  		destination := testutil.NewFakeIterator().
  1799  			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
  1800  			AddValueRecords(makeV("b", "dest:b"))
  1801  		writer := mock.NewMockMetaRangeWriter(ctrl)
  1802  		ctx, cancel := context.WithCancel(context.Background())
  1803  		cancel()
  1804  		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
  1805  		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
  1806  	})
  1807  }