From eb94cf754964c6f3fd23ea2e45dce82ca9d64f66 Mon Sep 17 00:00:00 2001
From: Leonard Lyubich <leonard@nspcc.ru>
Date: Mon, 4 May 2020 14:37:14 +0300
Subject: [PATCH] service: refactor MetaHeader interface

---
 object/service.go       |  2 +-
 service/epoch.go        | 11 +++++++++++
 service/epoch_test.go   | 21 +++++++++++++++++++++
 service/meta.go         | 39 ++++-----------------------------------
 service/meta_test.go    | 38 ++++++++++++++++----------------------
 service/raw.go          |  6 ++++++
 service/raw_test.go     | 24 ++++++++++++++++++++++++
 service/types.go        | 12 ++++++++++++
 service/verify.go       |  8 ++++----
 service/version.go      | 11 +++++++++++
 service/version_test.go | 21 +++++++++++++++++++++
 11 files changed, 131 insertions(+), 62 deletions(-)
 create mode 100644 service/epoch.go
 create mode 100644 service/epoch_test.go
 create mode 100644 service/raw.go
 create mode 100644 service/raw_test.go
 create mode 100644 service/version.go
 create mode 100644 service/version_test.go

diff --git a/object/service.go b/object/service.go
index 45a8d4b..0e38d70 100644
--- a/object/service.go
+++ b/object/service.go
@@ -31,7 +31,7 @@ type (
 	// All object operations must have TTL, Epoch, Type, Container ID and
 	// permission of usage previous network map.
 	Request interface {
-		service.MetaHeader
+		service.SeizedRequestMetaContainer
 
 		CID() CID
 		Type() RequestType
diff --git a/service/epoch.go b/service/epoch.go
new file mode 100644
index 0000000..7a7a556
--- /dev/null
+++ b/service/epoch.go
@@ -0,0 +1,11 @@
+package service
+
+// SetEpoch is an Epoch field setter.
+func (m *ResponseMetaHeader) SetEpoch(v uint64) {
+	m.Epoch = v
+}
+
+// SetEpoch is an Epoch field setter.
+func (m *RequestMetaHeader) SetEpoch(v uint64) {
+	m.Epoch = v
+}
diff --git a/service/epoch_test.go b/service/epoch_test.go
new file mode 100644
index 0000000..47316c0
--- /dev/null
+++ b/service/epoch_test.go
@@ -0,0 +1,21 @@
+package service
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestGetSetEpoch(t *testing.T) {
+	v := uint64(5)
+
+	items := []EpochContainer{
+		new(ResponseMetaHeader),
+		new(RequestMetaHeader),
+	}
+
+	for _, item := range items {
+		item.SetEpoch(v)
+		require.Equal(t, v, item.GetEpoch())
+	}
+}
diff --git a/service/meta.go b/service/meta.go
index 2714f08..3a945ac 100644
--- a/service/meta.go
+++ b/service/meta.go
@@ -1,44 +1,13 @@
 package service
 
-type (
-	// MetaHeader contains meta information of request.
-	// It provides methods to get or set meta information meta header.
-	// Also contains methods to reset and restore meta header.
-	// Also contains methods to get or set request protocol version
-	MetaHeader interface {
-		ResetMeta() RequestMetaHeader
-		RestoreMeta(RequestMetaHeader)
-
-		TTLContainer
-		EpochContainer
-		VersionContainer
-		RawContainer
-	}
-)
-
-// SetVersion sets protocol version to ResponseMetaHeader.
-func (m *ResponseMetaHeader) SetVersion(v uint32) { m.Version = v }
-
-// SetEpoch sets Epoch to ResponseMetaHeader.
-func (m *ResponseMetaHeader) SetEpoch(v uint64) { m.Epoch = v }
-
-// SetVersion sets protocol version to RequestMetaHeader.
-func (m *RequestMetaHeader) SetVersion(v uint32) { m.Version = v }
-
-// SetEpoch sets Epoch to RequestMetaHeader.
-func (m *RequestMetaHeader) SetEpoch(v uint64) { m.Epoch = v }
-
-// SetRaw is a Raw field setter.
-func (m *RequestMetaHeader) SetRaw(raw bool) {
-	m.Raw = raw
-}
-
 // ResetMeta returns current value and sets RequestMetaHeader to empty value.
-func (m *RequestMetaHeader) ResetMeta() RequestMetaHeader {
+func (m *RequestMetaHeader) CutMeta() RequestMetaHeader {
 	cp := *m
 	m.Reset()
 	return cp
 }
 
 // RestoreMeta sets current RequestMetaHeader to passed value.
-func (m *RequestMetaHeader) RestoreMeta(v RequestMetaHeader) { *m = v }
+func (m *RequestMetaHeader) RestoreMeta(v RequestMetaHeader) {
+	*m = v
+}
diff --git a/service/meta_test.go b/service/meta_test.go
index fb7fb17..a0b85ef 100644
--- a/service/meta_test.go
+++ b/service/meta_test.go
@@ -6,26 +6,20 @@ import (
 	"github.com/stretchr/testify/require"
 )
 
-func TestRequestMetaHeader_SetEpoch(t *testing.T) {
-	m := new(ResponseMetaHeader)
-	epoch := uint64(3)
-	m.SetEpoch(epoch)
-	require.Equal(t, epoch, m.GetEpoch())
-}
-
-func TestRequestMetaHeader_SetVersion(t *testing.T) {
-	m := new(ResponseMetaHeader)
-	version := uint32(3)
-	m.SetVersion(version)
-	require.Equal(t, version, m.GetVersion())
-}
-
-func TestRequestMetaHeader_SetRaw(t *testing.T) {
-	m := new(RequestMetaHeader)
-
-	m.SetRaw(true)
-	require.True(t, m.GetRaw())
-
-	m.SetRaw(false)
-	require.False(t, m.GetRaw())
+func TestCutRestoreMeta(t *testing.T) {
+	items := []func() SeizedMetaHeaderContainer{
+		func() SeizedMetaHeaderContainer {
+			m := new(RequestMetaHeader)
+			m.SetEpoch(1)
+			return m
+		},
+	}
+
+	for _, item := range items {
+		v1 := item()
+		m1 := v1.CutMeta()
+		v1.RestoreMeta(m1)
+
+		require.Equal(t, item(), v1)
+	}
 }
diff --git a/service/raw.go b/service/raw.go
new file mode 100644
index 0000000..0bb4b27
--- /dev/null
+++ b/service/raw.go
@@ -0,0 +1,6 @@
+package service
+
+// SetRaw is a Raw field setter.
+func (m *RequestMetaHeader) SetRaw(raw bool) {
+	m.Raw = raw
+}
diff --git a/service/raw_test.go b/service/raw_test.go
new file mode 100644
index 0000000..ad595ed
--- /dev/null
+++ b/service/raw_test.go
@@ -0,0 +1,24 @@
+package service
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestGetSetRaw(t *testing.T) {
+	items := []RawContainer{
+		new(RequestMetaHeader),
+	}
+
+	for _, item := range items {
+		// init with false
+		item.SetRaw(false)
+
+		item.SetRaw(true)
+		require.True(t, item.GetRaw())
+
+		item.SetRaw(false)
+		require.False(t, item.GetRaw())
+	}
+}
diff --git a/service/types.go b/service/types.go
index cad4b3c..e7bdcd4 100644
--- a/service/types.go
+++ b/service/types.go
@@ -51,6 +51,12 @@ type TTLContainer interface {
 	SetTTL(uint32)
 }
 
+// SeizedMetaHeaderContainer is an interface of container of RequestMetaHeader that can be cut and restored.
+type SeizedMetaHeaderContainer interface {
+	CutMeta() RequestMetaHeader
+	RestoreMeta(RequestMetaHeader)
+}
+
 // RequestMetaContainer is an interface of a fixed set of request meta value containers.
 // Contains:
 // - TTL value;
@@ -64,6 +70,12 @@ type RequestMetaContainer interface {
 	RawContainer
 }
 
+// SeizedRequestMetaContainer is a RequestMetaContainer with seized meta.
+type SeizedRequestMetaContainer interface {
+	RequestMetaContainer
+	SeizedMetaHeaderContainer
+}
+
 // VerbSource is an interface of the container of a token verb value with read access.
 type VerbSource interface {
 	GetVerb() Token_Info_Verb
diff --git a/service/verify.go b/service/verify.go
index 7ac3cf3..3ed8402 100644
--- a/service/verify.go
+++ b/service/verify.go
@@ -118,8 +118,8 @@ var bytesPool = sync.Pool{New: func() interface{} {
 // new signature to headers. If something went wrong, returns error.
 func SignRequestHeader(key *ecdsa.PrivateKey, msg VerifiableRequest) error {
 	// ignore meta header
-	if meta, ok := msg.(MetaHeader); ok {
-		h := meta.ResetMeta()
+	if meta, ok := msg.(SeizedRequestMetaContainer); ok {
+		h := meta.CutMeta()
 
 		defer func() {
 			meta.RestoreMeta(h)
@@ -157,8 +157,8 @@ func SignRequestHeader(key *ecdsa.PrivateKey, msg VerifiableRequest) error {
 // If something went wrong, returns error.
 func VerifyRequestHeader(msg VerifiableRequest) error {
 	// ignore meta header
-	if meta, ok := msg.(MetaHeader); ok {
-		h := meta.ResetMeta()
+	if meta, ok := msg.(SeizedRequestMetaContainer); ok {
+		h := meta.CutMeta()
 
 		defer func() {
 			meta.RestoreMeta(h)
diff --git a/service/version.go b/service/version.go
new file mode 100644
index 0000000..6f4839c
--- /dev/null
+++ b/service/version.go
@@ -0,0 +1,11 @@
+package service
+
+// SetVersion is a Version field setter.
+func (m *ResponseMetaHeader) SetVersion(v uint32) {
+	m.Version = v
+}
+
+// SetVersion is a Version field setter.
+func (m *RequestMetaHeader) SetVersion(v uint32) {
+	m.Version = v
+}
diff --git a/service/version_test.go b/service/version_test.go
new file mode 100644
index 0000000..d102d30
--- /dev/null
+++ b/service/version_test.go
@@ -0,0 +1,21 @@
+package service
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestGetSetVersion(t *testing.T) {
+	v := uint32(7)
+
+	items := []VersionContainer{
+		new(ResponseMetaHeader),
+		new(RequestMetaHeader),
+	}
+
+	for _, item := range items {
+		item.SetVersion(v)
+		require.Equal(t, v, item.GetVersion())
+	}
+}