func TestModePutUpload(t *testing.T) {
	for _, tc := range multiChunkTestCases {
		t.Run(tc.name, func(t *testing.T) {
			db := newTestDB(t, nil)
			wantTimestamp := time.Now().UTC().UnixNano()
			defer setNow(func() (t int64) {
				return wantTimestamp
			})()
			chunks := generateTestRandomChunks(tc.count)
			unreserveChunkBatch(t, db, 0, chunks...)
			_, err := db.Put(context.Background(), storage.ModePutUpload, chunks...)
			if err != nil {
				t.Fatal(err)
			}
			binIDs := make(map[uint8]uint64)
			for _, ch := range chunks {
				po := db.po(ch.Address())
				binIDs[po]++
				newRetrieveIndexesTest(db, ch, wantTimestamp, 0)(t)
				newPullIndexTest(db, ch, binIDs[po], nil)(t)
				newPushIndexTest(db, ch, wantTimestamp, nil)(t)
				newPinIndexTest(db, ch, leveldb.ErrNotFound)(t)
			}
			newItemsCountTest(db.postageIndexIndex, tc.count)(t)
			newIndexGCSizeTest(db)(t)
		})
	}
}
TestModePutUpload validates ModePutUpload index values on the provided DB.
package localstore
import (
	"bytes"
	"context"
	"encoding/binary"
	"errors"
	"fmt"
	"sync"
	"testing"
	"time"
	"github.com/ethsana/sana/pkg/postage"
	postagetesting "github.com/ethsana/sana/pkg/postage/testing"
	"github.com/ethsana/sana/pkg/shed"
	"github.com/ethsana/sana/pkg/storage"
	"github.com/ethsana/sana/pkg/swarm"
	"github.com/syndtr/goleveldb/leveldb"
)
var putModes = []storage.ModePut{
	storage.ModePutRequest,
	storage.ModePutRequestPin,
	storage.ModePutSync,
	storage.ModePutUpload,
	storage.ModePutUploadPin,
	storage.ModePutRequestCache,
}
func TestModePutRequest(t *testing.T) {
	t.Cleanup(setWithinRadiusFunc(func(_ *DB, _ shed.Item) bool { return false }))
	for _, tc := range multiChunkTestCases {
		t.Run(tc.name, func(t *testing.T) {
			db := newTestDB(t, nil)
			chunks := generateTestRandomChunks(tc.count)
			unreserveChunkBatch(t, db, 0, chunks...)
			var storeTimestamp int64
			t.Run("first put", func(t *testing.T) {
				wantTimestamp := time.Now().UTC().UnixNano()
				defer setNow(func() (t int64) {
					return wantTimestamp
				})()
				storeTimestamp = wantTimestamp
				_, err := db.Put(context.Background(), storage.ModePutRequest, chunks...)
				if err != nil {
					t.Fatal(err)
				}
				for _, ch := range chunks {
					newRetrieveIndexesTestWithAccess(db, ch, wantTimestamp, wantTimestamp)(t)
				}
				newItemsCountTest(db.gcIndex, tc.count)(t)
				newItemsCountTest(db.pullIndex, tc.count)(t)
				newItemsCountTest(db.postageIndexIndex, tc.count)(t)
				newIndexGCSizeTest(db)(t)
			})
			t.Run("second put", func(t *testing.T) {
				wantTimestamp := time.Now().UTC().UnixNano()
				defer setNow(func() (t int64) {
					return wantTimestamp
				})()
				_, err := db.Put(context.Background(), storage.ModePutRequest, chunks...)
				if err != nil {
					t.Fatal(err)
				}
				for _, ch := range chunks {
					newRetrieveIndexesTestWithAccess(db, ch, storeTimestamp, storeTimestamp)(t)
				}
				newItemsCountTest(db.gcIndex, tc.count)(t)
				newItemsCountTest(db.pullIndex, tc.count)(t)
				newItemsCountTest(db.postageIndexIndex, tc.count)(t)
				newIndexGCSizeTest(db)(t)
			})
		})
	}
}
func TestModePutRequestPin(t *testing.T) {
	t.Cleanup(setWithinRadiusFunc(func(_ *DB, _ shed.Item) bool { return false }))
	for _, tc := range multiChunkTestCases {
		t.Run(tc.name, func(t *testing.T) {
			db := newTestDB(t, nil)
			chunks := generateTestRandomChunks(tc.count)
			unreserveChunkBatch(t, db, 0, chunks...)
			wantTimestamp := time.Now().UTC().UnixNano()
			defer setNow(func() (t int64) {
				return wantTimestamp
			})()
			_, err := db.Put(context.Background(), storage.ModePutRequestPin, chunks...)
			if err != nil {
				t.Fatal(err)
			}
			for _, ch := range chunks {
				newRetrieveIndexesTestWithAccess(db, ch, wantTimestamp, wantTimestamp)(t)
				newPinIndexTest(db, ch, nil)(t)
			}
			newItemsCountTest(db.postageChunksIndex, tc.count)(t)
			newItemsCountTest(db.postageIndexIndex, tc.count)(t)
			newItemsCountTest(db.gcIndex, 0)(t)
			newIndexGCSizeTest(db)(t)
		})
	}
}
func TestModePutRequestCache(t *testing.T) {
	t.Cleanup(setWithinRadiusFunc(func(_ *DB, _ shed.Item) bool { return true }))
	for _, tc := range multiChunkTestCases {
		t.Run(tc.name, func(t *testing.T) {
			db := newTestDB(t, nil)
			var chunks []swarm.Chunk
			for i := 0; i < tc.count; i++ {
				chunk := generateTestRandomChunkAt(swarm.NewAddress(db.baseKey), 2)
				chunks = append(chunks, chunk)
			}
			unreserveChunkBatch(t, db, 2, chunks...)
			wantTimestamp := time.Now().UTC().UnixNano()
			defer setNow(func() (t int64) {
				return wantTimestamp
			})()
			_, err := db.Put(context.Background(), storage.ModePutRequestCache, chunks...)
			if err != nil {
				t.Fatal(err)
			}
			for _, ch := range chunks {
				newRetrieveIndexesTestWithAccess(db, ch, wantTimestamp, wantTimestamp)(t)
				newPinIndexTest(db, ch, leveldb.ErrNotFound)(t)
			}
			newItemsCountTest(db.postageChunksIndex, tc.count)(t)
			newItemsCountTest(db.postageIndexIndex, tc.count)(t)
			newItemsCountTest(db.gcIndex, tc.count)(t)
			newIndexGCSizeTest(db)(t)
		})
	}
}
func TestModePutSync(t *testing.T) {
	t.Cleanup(setWithinRadiusFunc(func(_ *DB, _ shed.Item) bool { return false }))
	for _, tc := range multiChunkTestCases {
		t.Run(tc.name, func(t *testing.T) {
			db := newTestDB(t, nil)
			wantTimestamp := time.Now().UTC().UnixNano()
			defer setNow(func() (t int64) {
				return wantTimestamp
			})()
			chunks := generateTestRandomChunks(tc.count)
			unreserveChunkBatch(t, db, 0, chunks...)
			_, err := db.Put(context.Background(), storage.ModePutSync, chunks...)
			if err != nil {
				t.Fatal(err)
			}
			binIDs := make(map[uint8]uint64)
			for _, ch := range chunks {
				po := db.po(ch.Address())
				binIDs[po]++
				newRetrieveIndexesTestWithAccess(db, ch, wantTimestamp, wantTimestamp)(t)
				newPullIndexTest(db, ch, binIDs[po], nil)(t)
				newPinIndexTest(db, ch, leveldb.ErrNotFound)(t)
				newIndexGCSizeTest(db)(t)
			}
			newItemsCountTest(db.postageChunksIndex, tc.count)(t)
			newItemsCountTest(db.postageIndexIndex, tc.count)(t)
			newItemsCountTest(db.gcIndex, tc.count)(t)
			newIndexGCSizeTest(db)(t)
		})
	}
}