You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: merge_test.go
    path of file: ./repos/lakeFS/pkg/graveler/committed
    
    the code of the file until where you have to start completion: package committed_test

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"strings"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
	"github.com/treeverse/lakefs/pkg/graveler"
	"github.com/treeverse/lakefs/pkg/graveler/committed"
	"github.com/treeverse/lakefs/pkg/graveler/committed/mock"
	"github.com/treeverse/lakefs/pkg/graveler/testutil"
)

type actionType string

const (
	actionTypeWriteRange  actionType = "write-range"
	actionTypeWriteRecord actionType = "write-record"
)

type writeAction struct {
	action   actionType
	rng      committed.Range
	key      string
	identity string
}

type recordMatcher struct {
	key      graveler.Key
	identity []byte
}

func newRecordMatcher(key string, identity string) recordMatcher {
	return recordMatcher{
		key:      graveler.Key(key),
		identity: []byte(identity),
	}
}

func (m recordMatcher) Matches(x interface{}) bool {
	record := x.(graveler.ValueRecord)
	return bytes.Equal(m.key, record.Key) && bytes.Equal(m.identity, record.Identity)
}

func (m recordMatcher) String() string {
	return fmt.Sprintf("is equal to key:%s, identity:%s", m.key, m.identity)
}

type testValueRecord struct {
	key      string
	identity string
}

type testRange struct {
	rng     committed.Range
	records []testValueRecord
}

type testRunResult struct {
	mergeStrategies []graveler.MergeStrategy
	expectedActions []writeAction
	expectedErr     error
}

type testMetaRange struct {
	ranges []testRange
}

func (t *testMetaRange) GetMetaRangeID() graveler.MetaRangeID {
	var sb strings.Builder
	for _, rng := range t.ranges {
		sb.WriteString(string(rng.rng.ID))
		sb.WriteString("#")
	}
	return graveler.MetaRangeID(sb.String())
}

func newTestMetaRange(ranges []testRange) *testMetaRange {
	return &testMetaRange{ranges: ranges}
}

type testCase struct {
	baseRange      *testMetaRange
	sourceRange    *testMetaRange
	destRange      *testMetaRange
	expectedResult []testRunResult
}

type testCases map[string]testCase

func createIter(tr *testMetaRange) committed.Iterator {
	iter := testutil.NewFakeIterator()
	for _, rng := range tr.ranges {
		addRange := rng.rng
		iter.AddRange(&addRange)
		for _, record := range rng.records {
			iter.AddValueRecords(&graveler.ValueRecord{
				Key: graveler.Key(record.key),
				Value: &graveler.Value{
					Identity: []byte(record.identity),
					Data:     nil,
				},
			})
		}
	}
	return iter
}

func Test_merge(t *testing.T) {
	tests := testCases{
		"dest range added before": {
			baseRange: newTestMetaRange([]testRange{
				{
					rng:     committed.Range{ID: "base:k3-k6", MinKey: committed.Key("k3"), MaxKey: committed.Key("k6"), Count: 2, EstimatedSize: 1234},
					records: nil,
				}, {rng: committed.Range{ID: "base:k11-k12", MinKey: committed.Key("k11"), MaxKey: committed.Key("k12"), Count: 2, EstimatedSize: 4444}, records: []testValueRecord{
					{"k11", "base:k11"}, {"k12", "ba
    
func TestMergeCancelContext(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	t.Run("source", func(t *testing.T) {
		base := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
			AddValueRecords(makeV("b", "dest:b"))
		source := testutil.NewFakeIterator()
		destination := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
			AddValueRecords(makeV("b", "dest:b"))
		writer := mock.NewMockMetaRangeWriter(ctrl)
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
	})

	t.Run("destination", func(t *testing.T) {
		base := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 2}).
			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
		source := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 2}).
			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
		destination := testutil.NewFakeIterator()
		writer := mock.NewMockMetaRangeWriter(ctrl)
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
	})

	t.Run("source_and_destination", func(t *testing.T) {
		base := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("a"), MaxKey: committed.Key("cz"), Count: 3}).
			AddValueRecords(makeV("a", "base:a"), makeV("c", "base:c"))
		source := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "two", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2}).
			AddValueRecords(makeV("e", "source:e"), makeV("f", "source:f"))
		destination := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "three", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
			AddValueRecords(makeV("b", "dest:b"))
		writer := mock.NewMockMetaRangeWriter(ctrl)
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
	})

	t.Run("base", func(t *testing.T) {
		base := testutil.NewFakeIterator()
		source := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "two", MinKey: committed.Key("e"), MaxKey: committed.Key("f"), Count: 2}).
			AddValueRecords(makeV("e", "source:e"), makeV("f", "source:f"))
		destination := testutil.NewFakeIterator().
			AddRange(&committed.Range{ID: "one", MinKey: committed.Key("b"), MaxKey: committed.Key("b"), Count: 1}).
			AddValueRecords(makeV("b", "dest:b"))
		writer := mock.NewMockMetaRangeWriter(ctrl)
		ctx, cancel := context.WithCancel(context.Background())
		cancel()
		err := committed.Merge(ctx, writer, base, source, destination, graveler.MergeStrategyNone)
		assert.True(t, errors.Is(err, context.Canceled), "context canceled error")
	})
}