From 9a961e21b1001d48fd8fe27b7f54d62d9da27dd6 Mon Sep 17 00:00:00 2001
From: Alex Vanin <alexey@nspcc.ru>
Date: Thu, 15 Apr 2021 10:23:52 +0300
Subject: [PATCH] [#477] metabase: Move `MergeSplitInfo` to storage/util pkg

This function already reused in different storage engine parts
so it makes sense to keep it in separate package.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
---
 pkg/local_object_storage/engine/get.go        |  4 +-
 pkg/local_object_storage/engine/head.go       |  4 +-
 pkg/local_object_storage/engine/range.go      |  4 +-
 pkg/local_object_storage/metabase/put.go      | 19 +-----
 pkg/local_object_storage/util/splitinfo.go    | 21 ++++++
 .../util/splitinfo_test.go                    | 66 +++++++++++++++++++
 6 files changed, 95 insertions(+), 23 deletions(-)
 create mode 100644 pkg/local_object_storage/util/splitinfo.go
 create mode 100644 pkg/local_object_storage/util/splitinfo_test.go

diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go
index bc79d76c9..e7c7fd696 100644
--- a/pkg/local_object_storage/engine/get.go
+++ b/pkg/local_object_storage/engine/get.go
@@ -5,8 +5,8 @@ import (
 
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-node/pkg/core/object"
-	meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
 	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
 	"go.uber.org/zap"
 )
 
@@ -71,7 +71,7 @@ func (e *StorageEngine) Get(prm *GetPrm) (*GetRes, error) {
 					outSI = objectSDK.NewSplitInfo()
 				}
 
-				meta.MergeSplitInfo(siErr.SplitInfo(), outSI)
+				util.MergeSplitInfo(siErr.SplitInfo(), outSI)
 
 				// stop iterating over shards if SplitInfo structure is complete
 				if outSI.Link() != nil && outSI.LastPart() != nil {
diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go
index f0386b00f..6c22ad2ab 100644
--- a/pkg/local_object_storage/engine/head.go
+++ b/pkg/local_object_storage/engine/head.go
@@ -3,8 +3,8 @@ package engine
 import (
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-node/pkg/core/object"
-	meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
 	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
 	"github.com/pkg/errors"
 	"go.uber.org/zap"
 )
@@ -86,7 +86,7 @@ func (e *StorageEngine) Head(prm *HeadPrm) (*HeadRes, error) {
 					outSI = objectSDK.NewSplitInfo()
 				}
 
-				meta.MergeSplitInfo(siErr.SplitInfo(), outSI)
+				util.MergeSplitInfo(siErr.SplitInfo(), outSI)
 
 				// stop iterating over shards if SplitInfo structure is complete
 				if outSI.Link() != nil && outSI.LastPart() != nil {
diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go
index 32f346e5a..ee6b2a4e9 100644
--- a/pkg/local_object_storage/engine/range.go
+++ b/pkg/local_object_storage/engine/range.go
@@ -5,8 +5,8 @@ import (
 
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-node/pkg/core/object"
-	meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase"
 	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/shard"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
 	"go.uber.org/zap"
 )
 
@@ -90,7 +90,7 @@ func (e *StorageEngine) GetRange(prm *RngPrm) (*RngRes, error) {
 					outSI = objectSDK.NewSplitInfo()
 				}
 
-				meta.MergeSplitInfo(siErr.SplitInfo(), outSI)
+				util.MergeSplitInfo(siErr.SplitInfo(), outSI)
 
 				// stop iterating over shards if SplitInfo structure is complete
 				if outSI.Link() != nil && outSI.LastPart() != nil {
diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go
index bfe6bcb63..f2e426a0f 100644
--- a/pkg/local_object_storage/metabase/put.go
+++ b/pkg/local_object_storage/metabase/put.go
@@ -9,6 +9,7 @@ import (
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-node/pkg/core/object"
 	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobovnicza"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
 	"go.etcd.io/bbolt"
 )
 
@@ -416,7 +417,7 @@ func updateSplitInfo(tx *bbolt.Tx, addr *objectSDK.Address, from *objectSDK.Spli
 		return fmt.Errorf("can't unmarshal split info from root index: %w", err)
 	}
 
-	result := MergeSplitInfo(from, to)
+	result := util.MergeSplitInfo(from, to)
 
 	rawSplitInfo, err = result.Marshal()
 	if err != nil {
@@ -448,22 +449,6 @@ func splitInfoFromObject(obj *object.Object) (*objectSDK.SplitInfo, error) {
 	return info, nil
 }
 
-// MergeSplitInfo ignores conflicts and rewrites `to` with non empty values
-// from `from`.
-func MergeSplitInfo(from, to *objectSDK.SplitInfo) *objectSDK.SplitInfo {
-	to.SetSplitID(from.SplitID()) // overwrite SplitID and ignore conflicts
-
-	if lp := from.LastPart(); lp != nil {
-		to.SetLastPart(lp)
-	}
-
-	if link := from.Link(); link != nil {
-		to.SetLink(link)
-	}
-
-	return to
-}
-
 // isLinkObject returns true if object contains parent header and list
 // of children.
 func isLinkObject(obj *object.Object) bool {
diff --git a/pkg/local_object_storage/util/splitinfo.go b/pkg/local_object_storage/util/splitinfo.go
new file mode 100644
index 000000000..f17fc0794
--- /dev/null
+++ b/pkg/local_object_storage/util/splitinfo.go
@@ -0,0 +1,21 @@
+package util
+
+import (
+	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
+)
+
+// MergeSplitInfo ignores conflicts and rewrites `to` with non empty values
+// from `from`.
+func MergeSplitInfo(from, to *objectSDK.SplitInfo) *objectSDK.SplitInfo {
+	to.SetSplitID(from.SplitID()) // overwrite SplitID and ignore conflicts
+
+	if lp := from.LastPart(); lp != nil {
+		to.SetLastPart(lp)
+	}
+
+	if link := from.Link(); link != nil {
+		to.SetLink(link)
+	}
+
+	return to
+}
diff --git a/pkg/local_object_storage/util/splitinfo_test.go b/pkg/local_object_storage/util/splitinfo_test.go
new file mode 100644
index 000000000..51bb84d58
--- /dev/null
+++ b/pkg/local_object_storage/util/splitinfo_test.go
@@ -0,0 +1,66 @@
+package util_test
+
+import (
+	"math/rand"
+	"testing"
+
+	"github.com/google/uuid"
+	"github.com/nspcc-dev/neofs-api-go/pkg/object"
+	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/util"
+	"github.com/stretchr/testify/require"
+)
+
+func TestMergeSplitInfo(t *testing.T) {
+	uid, err := uuid.NewUUID()
+	require.NoError(t, err)
+
+	splitID := object.NewSplitID()
+	splitID.SetUUID(uid)
+
+	var rawLinkID, rawLastID [32]byte
+	linkID := object.NewID()
+	lastID := object.NewID()
+
+	_, err = rand.Read(rawLinkID[:])
+	require.NoError(t, err)
+	linkID.SetSHA256(rawLinkID)
+
+	_, err = rand.Read(rawLastID[:])
+	require.NoError(t, err)
+	lastID.SetSHA256(rawLastID)
+
+	target := object.NewSplitInfo() // target is SplitInfo struct with all fields set
+	target.SetSplitID(splitID)
+	target.SetLastPart(lastID)
+	target.SetLink(linkID)
+
+	t.Run("merge empty", func(t *testing.T) {
+		to := object.NewSplitInfo()
+
+		result := util.MergeSplitInfo(target, to)
+		require.Equal(t, result, target)
+	})
+
+	t.Run("merge link", func(t *testing.T) {
+		from := object.NewSplitInfo()
+		from.SetSplitID(splitID)
+		from.SetLastPart(lastID)
+
+		to := object.NewSplitInfo()
+		to.SetLink(linkID)
+
+		result := util.MergeSplitInfo(from, to)
+		require.Equal(t, result, target)
+	})
+	t.Run("merge last", func(t *testing.T) {
+		from := object.NewSplitInfo()
+		from.SetSplitID(splitID)
+		from.SetLink(linkID)
+
+		to := object.NewSplitInfo()
+		to.SetLastPart(lastID)
+
+		result := util.MergeSplitInfo(from, to)
+		require.Equal(t, result, target)
+	})
+}