From d3e4a5a7a66b7e7792edcd07dc52bfa1cfcb9d9f Mon Sep 17 00:00:00 2001
From: Oleg Kovalov <oleg@hey.com>
Date: Wed, 29 May 2024 13:26:57 +0200
Subject: [PATCH] feat(store,sync): drop NewStoreWithHead

---
 store/init_test.go     |  2 +-
 store/store_test.go    | 25 +++++++----------
 store/testing.go       | 24 ++++++++--------
 sync/sync_head_test.go | 10 ++-----
 sync/sync_test.go      | 64 +++++++++++++++++++++++++++---------------
 5 files changed, 68 insertions(+), 57 deletions(-)

diff --git a/store/init_test.go b/store/init_test.go
index bad02ea7..190e032c 100644
--- a/store/init_test.go
+++ b/store/init_test.go
@@ -20,9 +20,9 @@ func TestInitStore_NoReinit(t *testing.T) {
 
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
-	exchange := local.NewExchange(NewTestStore(ctx, t, head))
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
+	exchange := local.NewExchange(newStoreWithHead(t, ctx, ds, head))
 	store, err := NewStore[*headertest.DummyHeader](ds)
 	require.NoError(t, err)
 
diff --git a/store/store_test.go b/store/store_test.go
index a96a1ef4..8bff8998 100644
--- a/store/store_test.go
+++ b/store/store_test.go
@@ -20,10 +20,9 @@ func TestStore(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
-	store, err := NewStoreWithHead(ctx, ds, suite.Head())
-	require.NoError(t, err)
+	store := newStoreWithHead(t, ctx, ds, suite.Head())
 
-	err = store.Start(ctx)
+	err := store.Start(ctx)
 	require.NoError(t, err)
 
 	head, err := store.Head(ctx)
@@ -107,10 +106,9 @@ func TestStore_GetRangeByHeight_ExpectedRange(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
-	store, err := NewStoreWithHead(ctx, ds, suite.Head())
-	require.NoError(t, err)
+	store := newStoreWithHead(t, ctx, ds, suite.Head())
 
-	err = store.Start(ctx)
+	err := store.Start(ctx)
 	require.NoError(t, err)
 
 	head, err := store.Head(ctx)
@@ -143,10 +141,9 @@ func TestStore_Append_BadHeader(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
-	store, err := NewStoreWithHead(ctx, ds, suite.Head())
-	require.NoError(t, err)
+	store := newStoreWithHead(t, ctx, ds, suite.Head())
 
-	err = store.Start(ctx)
+	err := store.Start(ctx)
 	require.NoError(t, err)
 
 	head, err := store.Head(ctx)
@@ -168,10 +165,9 @@ func TestStore_GetRange(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
-	store, err := NewStoreWithHead(ctx, ds, suite.Head())
-	require.NoError(t, err)
+	store := newStoreWithHead(t, ctx, ds, suite.Head())
 
-	err = store.Start(ctx)
+	err := store.Start(ctx)
 	require.NoError(t, err)
 
 	head, err := store.Head(ctx)
@@ -245,13 +241,12 @@ func TestStorePendingCacheMiss(t *testing.T) {
 
 	ds := sync.MutexWrap(datastore.NewMapDatastore())
 
-	store, err := NewStoreWithHead(ctx, ds, suite.Head(),
+	store := newStoreWithHead(t, ctx, ds, suite.Head(),
 		WithWriteBatchSize(100),
 		WithStoreCacheSize(100),
 	)
-	require.NoError(t, err)
 
-	err = store.Start(ctx)
+	err := store.Start(ctx)
 	require.NoError(t, err)
 	err = store.Append(ctx, suite.GenDummyHeaders(100)...)
 	require.NoError(t, err)
diff --git a/store/testing.go b/store/testing.go
index b415bcea..23abd95c 100644
--- a/store/testing.go
+++ b/store/testing.go
@@ -5,24 +5,24 @@ import (
 	"testing"
 
 	"github.com/ipfs/go-datastore"
-	"github.com/ipfs/go-datastore/sync"
 	"github.com/stretchr/testify/require"
 
 	"github.com/celestiaorg/go-header"
-	"github.com/celestiaorg/go-header/headertest"
 )
 
-// NewTestStore creates initialized and started in memory header Store which is useful for testing.
-func NewTestStore(ctx context.Context, t *testing.T, head *headertest.DummyHeader) header.Store[*headertest.DummyHeader] {
-	store, err := NewStoreWithHead(ctx, sync.MutexWrap(datastore.NewMapDatastore()), head)
-	require.NoError(t, err)
+// NewStoreWithHead initiates a new Store and forcefully sets a given trusted header as head.
+func newStoreWithHead[H header.Header[H]](
+	tb testing.TB,
+	ctx context.Context,
+	ds datastore.Batching,
+	head H,
+	opts ...Option,
+) *Store[H] {
+	store, err := newStore[H](ds, opts...)
+	require.NoError(tb, err)
 
-	err = store.Start(ctx)
-	require.NoError(t, err)
+	err = store.Init(ctx, head)
+	require.NoError(tb, err)
 
-	t.Cleanup(func() {
-		err := store.Stop(ctx)
-		require.NoError(t, err)
-	})
 	return store
 }
diff --git a/sync/sync_head_test.go b/sync/sync_head_test.go
index 29b75ff4..b952b232 100644
--- a/sync/sync_head_test.go
+++ b/sync/sync_head_test.go
@@ -7,15 +7,12 @@ import (
 	"testing"
 	"time"
 
-	"github.com/ipfs/go-datastore"
-	sync2 "github.com/ipfs/go-datastore/sync"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
 	"github.com/celestiaorg/go-header"
 	"github.com/celestiaorg/go-header/headertest"
 	"github.com/celestiaorg/go-header/local"
-	"github.com/celestiaorg/go-header/store"
 )
 
 func TestSyncer_incomingNetworkHeadRaces(t *testing.T) {
@@ -61,11 +58,10 @@ func TestSyncer_HeadWithTrustedHead(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	localStore := store.NewTestStore(ctx, t, head)
+	localStore := newTestStore(t, ctx, head)
+	remoteStore := newTestStore(t, ctx, head)
 
-	remoteStore, err := store.NewStoreWithHead(ctx, sync2.MutexWrap(datastore.NewMapDatastore()), head)
-	require.NoError(t, err)
-	err = remoteStore.Append(ctx, suite.GenDummyHeaders(100)...)
+	err := remoteStore.Append(ctx, suite.GenDummyHeaders(100)...)
 	require.NoError(t, err)
 
 	// create a wrappedGetter to track exchange interactions
diff --git a/sync/sync_test.go b/sync/sync_test.go
index dc108cc5..b4b806bc 100644
--- a/sync/sync_test.go
+++ b/sync/sync_test.go
@@ -5,6 +5,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/ipfs/go-datastore"
+	"github.com/ipfs/go-datastore/sync"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
@@ -21,15 +23,15 @@ func TestSyncSimpleRequestingHead(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
+	remoteStore := newTestStore(t, ctx, head)
 	err := remoteStore.Append(ctx, suite.GenDummyHeaders(100)...)
 	require.NoError(t, err)
 
 	_, err = remoteStore.GetByHeight(ctx, 100)
 	require.NoError(t, err)
 
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -67,9 +69,9 @@ func TestDoSyncFullRangeFromExternalPeer(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	remoteStore := newTestStore(t, ctx, head)
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -106,9 +108,9 @@ func TestSyncCatchUp(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	remoteStore := newTestStore(t, ctx, head)
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -157,9 +159,9 @@ func TestSyncPendingRangesWithMisses(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	remoteStore := newTestStore(t, ctx, head)
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -224,9 +226,9 @@ func TestSyncer_FindHeadersReturnsCorrectRange(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	remoteStore := newTestStore(t, ctx, head)
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -260,9 +262,9 @@ func TestSyncerIncomingDuplicate(t *testing.T) {
 	suite := headertest.NewTestSuite(t)
 	head := suite.Head()
 
-	remoteStore := store.NewTestStore(ctx, t, head)
-	localStore := store.NewTestStore(ctx, t, head)
-	syncer, err := NewSyncer[*headertest.DummyHeader](
+	remoteStore := newTestStore(t, ctx, head)
+	localStore := newTestStore(t, ctx, head)
+	syncer, err := NewSyncer(
 		&delayedGetter[*headertest.DummyHeader]{Getter: local.NewExchange(remoteStore)},
 		localStore,
 		headertest.NewDummySubscriber(),
@@ -301,12 +303,12 @@ func TestSync_InvalidSyncTarget(t *testing.T) {
 	head := suite.Head()
 
 	// create a local store which is initialised at genesis height
-	localStore := store.NewTestStore(ctx, t, head)
+	localStore := newTestStore(t, ctx, head)
 	// create a peer which is already on height 100
-	remoteStore := headertest.NewStore[*headertest.DummyHeader](t, suite, 100)
+	remoteStore := headertest.NewStore(t, suite, 100)
 
-	syncer, err := NewSyncer[*headertest.DummyHeader](
-		local.NewExchange[*headertest.DummyHeader](remoteStore),
+	syncer, err := NewSyncer(
+		local.NewExchange(remoteStore),
 		localStore,
 		headertest.NewDummySubscriber(),
 		WithBlockTime(time.Nanosecond),
@@ -396,3 +398,21 @@ func (d *delayedGetter[H]) GetRangeByHeight(ctx context.Context, from H, to uint
 		return nil, ctx.Err()
 	}
 }
+
+// newTestStore creates initialized and started in memory header Store which is useful for testing.
+func newTestStore(tb testing.TB, ctx context.Context, head *headertest.DummyHeader) header.Store[*headertest.DummyHeader] {
+	store, err := store.NewStore[*headertest.DummyHeader](sync.MutexWrap(datastore.NewMapDatastore()))
+	require.NoError(tb, err)
+
+	err = store.Init(ctx, head)
+	require.NoError(tb, err)
+
+	err = store.Start(ctx)
+	require.NoError(tb, err)
+
+	tb.Cleanup(func() {
+		err := store.Stop(ctx)
+		require.NoError(tb, err)
+	})
+	return store
+}