decoupling CodexClient from the rest of the system

This commit is contained in:
Marcin Czenko 2025-10-29 18:02:44 +01:00
parent 95d5bf8e2e
commit 57c60263a3
No known key found for this signature in database
GPG Key ID: A0449219BDBA98AE
13 changed files with 119 additions and 84 deletions

View File

@ -7,7 +7,7 @@ import (
"os" "os"
"path" "path"
"go-codex-client/communities" // Import the local communities package "go-codex-client/codexclient"
"github.com/codex-storage/codex-go-bindings/codex" "github.com/codex-storage/codex-go-bindings/codex"
) )
@ -25,7 +25,7 @@ func main() {
} }
// Create Codex client // Create Codex client
client, err := communities.NewCodexClient(codex.Config{ client, err := codexclient.NewCodexClient(codex.Config{
LogFormat: codex.LogFormatNoColors, LogFormat: codex.LogFormatNoColors,
MetricsEnabled: false, MetricsEnabled: false,
BlockRetries: 5, BlockRetries: 5,

View File

@ -8,7 +8,7 @@ import (
"os" "os"
"path" "path"
"go-codex-client/communities" // Import the local communities package "go-codex-client/codexclient"
"github.com/codex-storage/codex-go-bindings/codex" "github.com/codex-storage/codex-go-bindings/codex"
) )
@ -34,7 +34,7 @@ func main() {
fmt.Printf("Uploading %s (%d bytes) to Codex...\n", *file, len(data)) fmt.Printf("Uploading %s (%d bytes) to Codex...\n", *file, len(data))
// Create Codex client and upload // Create Codex client and upload
client, err := communities.NewCodexClient(codex.Config{ client, err := codexclient.NewCodexClient(codex.Config{
LogFormat: codex.LogFormatNoColors, LogFormat: codex.LogFormatNoColors,
MetricsEnabled: false, MetricsEnabled: false,
BlockRetries: 5, BlockRetries: 5,

View File

@ -1,10 +1,12 @@
/* Package communities /* Package codexclientpackage codexclient
* *
* Provides a CodexClient type that you can use to conveniently * Provides a CodexClient type that you can use to conveniently
* upload buffers to Codex. * upload buffers to Codex.
* *
*/ */
package communities
package codexclient
import ( import (
"bytes" "bytes"
@ -12,6 +14,8 @@ import (
"fmt" "fmt"
"io" "io"
"go-codex-client/codexmanifest"
"github.com/codex-storage/codex-go-bindings/codex" "github.com/codex-storage/codex-go-bindings/codex"
) )
@ -58,7 +62,7 @@ func (c *CodexClient) Download(cid string, output io.Writer) error {
return c.DownloadWithContext(context.Background(), cid, output) return c.DownloadWithContext(context.Background(), cid, output)
} }
func (c *CodexClient) TriggerDownload(cid string) (codex.Manifest, error) { func (c *CodexClient) TriggerDownload(cid string) (codexmanifest.CodexManifest, error) {
return c.TriggerDownloadWithContext(context.Background(), cid) return c.TriggerDownloadWithContext(context.Background(), cid)
} }
@ -89,12 +93,34 @@ func (c *CodexClient) LocalDownloadWithContext(ctx context.Context, cid string,
return c.LocalDownload(cid, output) return c.LocalDownload(cid, output)
} }
func (c *CodexClient) FetchManifestWithContext(ctx context.Context, cid string) (codex.Manifest, error) { func (c *CodexClient) FetchManifestWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
return c.node.DownloadManifest(cid) manifest, err := c.node.DownloadManifest(cid)
if err != nil {
return codexmanifest.CodexManifest{}, err
}
return codexmanifest.CodexManifest{
Cid: manifest.Cid,
TreeCid: manifest.TreeCid,
DatasetSize: manifest.DatasetSize,
BlockSize: manifest.BlockSize,
Filename: manifest.Filename,
Mimetype: manifest.Mimetype,
}, nil
} }
func (c *CodexClient) TriggerDownloadWithContext(ctx context.Context, cid string) (codex.Manifest, error) { func (c *CodexClient) TriggerDownloadWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
return c.node.Fetch(cid) manifest, err := c.node.Fetch(cid)
if err != nil {
return codexmanifest.CodexManifest{}, err
}
return codexmanifest.CodexManifest{
Cid: manifest.Cid,
TreeCid: manifest.TreeCid,
DatasetSize: manifest.DatasetSize,
BlockSize: manifest.BlockSize,
Filename: manifest.Filename,
Mimetype: manifest.Mimetype,
}, nil
} }
// UploadArchive is a convenience method for uploading archive data // UploadArchive is a convenience method for uploading archive data

View File

@ -1,7 +1,7 @@
//go:build codex_integration //go:build codex_integration
// +build codex_integration // +build codex_integration
package communities_test package codexclient_test
import ( import (
"bytes" "bytes"
@ -16,19 +16,21 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go-codex-client/codexclient"
"go-codex-client/codextestutils"
"go-codex-client/communities" "go-codex-client/communities"
) )
// CodexClientIntegrationTestSuite demonstrates testify's suite functionality for CodexClient integration tests // CodexClientIntegrationTestSuite demonstrates testify's suite functionality for CodexClient integration tests
type CodexClientIntegrationTestSuite struct { type CodexClientIntegrationTestSuite struct {
suite.Suite suite.Suite
client *communities.CodexClient client communities.CodexClientInterface
} }
// SetupSuite runs once before all tests in the suite // SetupSuite runs once before all tests in the suite
func (suite *CodexClientIntegrationTestSuite) SetupSuite() { func (suite *CodexClientIntegrationTestSuite) SetupSuite() {
var err error var err error
suite.client, err = communities.NewCodexClient(codex.Config{ suite.client, err = codexclient.NewCodexClient(codex.Config{
DataDir: suite.T().TempDir(), DataDir: suite.T().TempDir(),
LogFormat: codex.LogFormatNoColors, LogFormat: codex.LogFormatNoColors,
MetricsEnabled: false, MetricsEnabled: false,
@ -107,7 +109,7 @@ func (suite *CodexClientIntegrationTestSuite) TestIntegration_CheckNonExistingCI
} }
func (suite *CodexClientIntegrationTestSuite) TestIntegration_TriggerDownload() { func (suite *CodexClientIntegrationTestSuite) TestIntegration_TriggerDownload() {
client := NewCodexClientTest(suite.T()) client := codextestutils.NewCodexClientTest(suite.T())
// Generate random payload to ensure proper round-trip verification // Generate random payload to ensure proper round-trip verification
payload := make([]byte, 1024) payload := make([]byte, 1024)

View File

@ -1,4 +1,7 @@
package communities_test //go:build codex_integration
// +build codex_integration
package codexclient_test
import ( import (
"bytes" "bytes"
@ -12,10 +15,11 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go-codex-client/communities" "go-codex-client/codexclient"
"go-codex-client/codextestutils"
) )
func upload(client communities.CodexClient, t *testing.T, buf *bytes.Buffer) string { func upload(client codexclient.CodexClient, t *testing.T, buf *bytes.Buffer) string {
filename := "hello.txt" filename := "hello.txt"
cid, err := client.Upload(buf, filename) cid, err := client.Upload(buf, filename)
if err != nil { if err != nil {
@ -32,12 +36,12 @@ func upload(client communities.CodexClient, t *testing.T, buf *bytes.Buffer) str
// CodexClientTestSuite demonstrates testify's suite functionality for CodexClient tests // CodexClientTestSuite demonstrates testify's suite functionality for CodexClient tests
type CodexClientTestSuite struct { type CodexClientTestSuite struct {
suite.Suite suite.Suite
client *communities.CodexClient client *codexclient.CodexClient
} }
// SetupTest runs before each test method // SetupTest runs before each test method
func (suite *CodexClientTestSuite) SetupTest() { func (suite *CodexClientTestSuite) SetupTest() {
suite.client = NewCodexClientTest(suite.T()) suite.client = codextestutils.NewCodexClientTest(suite.T())
} }
// TearDownTest runs after each test method // TearDownTest runs after each test method

View File

@ -0,0 +1,11 @@
package codexmanifest
type CodexManifest struct {
Cid string
TreeCid string
DatasetSize int
BlockSize int
Filename string
Mimetype string
Protected bool
}

View File

@ -1,14 +1,16 @@
package communities_test //go:build codex_integration
package codextestutils
import ( import (
"go-codex-client/communities" "go-codex-client/codexclient"
"testing" "testing"
"github.com/codex-storage/codex-go-bindings/codex" "github.com/codex-storage/codex-go-bindings/codex"
) )
func NewCodexClientTest(t *testing.T) *communities.CodexClient { func NewCodexClientTest(t *testing.T) *codexclient.CodexClient {
client, err := communities.NewCodexClient(codex.Config{ client, err := codexclient.NewCodexClient(codex.Config{
DataDir: t.TempDir(), DataDir: t.TempDir(),
LogFormat: codex.LogFormatNoColors, LogFormat: codex.LogFormatNoColors,
MetricsEnabled: false, MetricsEnabled: false,

View File

@ -17,6 +17,7 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go.uber.org/zap" "go.uber.org/zap"
"go-codex-client/codexclient"
"go-codex-client/communities" "go-codex-client/communities"
"go-codex-client/protobuf" "go-codex-client/protobuf"
) )
@ -25,14 +26,14 @@ import (
// against a real Codex instance // against a real Codex instance
type CodexArchiveDownloaderIntegrationSuite struct { type CodexArchiveDownloaderIntegrationSuite struct {
suite.Suite suite.Suite
client *communities.CodexClient client communities.CodexClientInterface
uploadedCIDs []string // Track uploaded CIDs for cleanup uploadedCIDs []string // Track uploaded CIDs for cleanup
} }
// SetupSuite runs once before all tests in the suite // SetupSuite runs once before all tests in the suite
func (suite *CodexArchiveDownloaderIntegrationSuite) SetupSuite() { func (suite *CodexArchiveDownloaderIntegrationSuite) SetupSuite() {
var err error var err error
suite.client, err = communities.NewCodexClient(codex.Config{ suite.client, err = codexclient.NewCodexClient(codex.Config{
LogFormat: codex.LogFormatNoColors, LogFormat: codex.LogFormatNoColors,
MetricsEnabled: false, MetricsEnabled: false,
BlockRetries: 5, BlockRetries: 5,

View File

@ -7,17 +7,18 @@ import (
"testing" "testing"
"time" "time"
"github.com/codex-storage/codex-go-bindings/codex"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go-codex-client/communities"
mock_communities "go-codex-client/communities/mock" mock_communities "go-codex-client/communities/mock"
"go-codex-client/protobuf" "go-codex-client/protobuf"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"go.uber.org/zap" "go.uber.org/zap"
"go-codex-client/codexmanifest"
"go-codex-client/communities"
) )
// CodexArchiveDownloaderSuite demonstrates testify's suite functionality // CodexArchiveDownloaderSuite demonstrates testify's suite functionality
@ -64,7 +65,7 @@ func (suite *CodexArchiveDownloaderSuite) TestBasicSingleArchive() {
// Set up mock expectations - same as before // Set up mock expectations - same as before
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "test-cid-1"). TriggerDownloadWithContext(gomock.Any(), "test-cid-1").
Return(codex.Manifest{Cid: "test-cid-1"}, nil). Return(codexmanifest.CodexManifest{Cid: "test-cid-1"}, nil).
Times(1) Times(1)
// First HasCid call returns false, second returns true (simulating polling) // First HasCid call returns false, second returns true (simulating polling)
@ -150,7 +151,7 @@ func (suite *CodexArchiveDownloaderSuite) TestMultipleArchives() {
for _, cid := range expectedCids { for _, cid := range expectedCids {
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), cid). TriggerDownloadWithContext(gomock.Any(), cid).
Return(codex.Manifest{Cid: cid}, nil). Return(codexmanifest.CodexManifest{Cid: cid}, nil).
Times(1) Times(1)
// Each archive becomes available after one poll // Each archive becomes available after one poll
@ -237,7 +238,7 @@ func (suite *CodexArchiveDownloaderSuite) TestErrorDuringTriggerDownload() {
// Mock TriggerDownloadWithContext to simulate an error // Mock TriggerDownloadWithContext to simulate an error
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "test-cid-1"). TriggerDownloadWithContext(gomock.Any(), "test-cid-1").
Return(codex.Manifest{}, assert.AnError). // Return a generic error to simulate failure Return(codexmanifest.CodexManifest{}, assert.AnError). // Return a generic error to simulate failure
Times(1) Times(1)
// No HasCid calls should be made since TriggerDownload fails // No HasCid calls should be made since TriggerDownload fails
@ -289,13 +290,13 @@ func (suite *CodexArchiveDownloaderSuite) TestActualCancellationDuringTriggerDow
// Use DoAndReturn to create a realistic TriggerDownload that waits for cancellation // Use DoAndReturn to create a realistic TriggerDownload that waits for cancellation
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "test-cid-1"). TriggerDownloadWithContext(gomock.Any(), "test-cid-1").
DoAndReturn(func(ctx context.Context, cid string) (codex.Manifest, error) { DoAndReturn(func(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
// Simulate work by waiting for context cancellation // Simulate work by waiting for context cancellation
select { select {
case <-time.After(5 * time.Second): // This should never happen in our test case <-time.After(5 * time.Second): // This should never happen in our test
return codex.Manifest{Cid: cid}, nil return codexmanifest.CodexManifest{Cid: cid}, nil
case <-ctx.Done(): // Wait for actual context cancellation case <-ctx.Done(): // Wait for actual context cancellation
return codex.Manifest{}, ctx.Err() // Return the actual cancellation error return codexmanifest.CodexManifest{}, ctx.Err() // Return the actual cancellation error
} }
}). }).
Times(1) Times(1)
@ -353,7 +354,7 @@ func (suite *CodexArchiveDownloaderSuite) TestCancellationDuringPolling() {
// Mock successful TriggerDownload // Mock successful TriggerDownload
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "test-cid-1"). TriggerDownloadWithContext(gomock.Any(), "test-cid-1").
Return(codex.Manifest{Cid: "test-cid-1"}, nil). Return(codexmanifest.CodexManifest{Cid: "test-cid-1"}, nil).
Times(1) Times(1)
// Mock polling - allow multiple calls, but we'll cancel before completion // Mock polling - allow multiple calls, but we'll cancel before completion
@ -421,7 +422,7 @@ func (suite *CodexArchiveDownloaderSuite) TestPollingTimeout() {
// Mock successful TriggerDownload // Mock successful TriggerDownload
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "test-cid-1"). TriggerDownloadWithContext(gomock.Any(), "test-cid-1").
Return(codex.Manifest{Cid: "test-cid-1"}, nil). Return(codexmanifest.CodexManifest{Cid: "test-cid-1"}, nil).
Times(1) Times(1)
// Mock polling to always return false (simulating timeout) // Mock polling to always return false (simulating timeout)
@ -497,7 +498,7 @@ func (suite *CodexArchiveDownloaderSuite) TestWithExistingArchives() {
// Only archive-2 should be downloaded (not in existingArchiveIDs) // Only archive-2 should be downloaded (not in existingArchiveIDs)
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-2"). TriggerDownloadWithContext(gomock.Any(), "cid-2").
Return(codex.Manifest{Cid: "cid-2"}, nil). Return(codexmanifest.CodexManifest{Cid: "cid-2"}, nil).
Times(1) // Only one call expected Times(1) // Only one call expected
// Only archive-2 should be polled // Only archive-2 should be polled
@ -578,7 +579,7 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_OneSuccessOneError(
// Archive-2 succeeds // Archive-2 succeeds
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-2"). TriggerDownloadWithContext(gomock.Any(), "cid-2").
Return(codex.Manifest{Cid: "cid-2"}, nil) Return(codexmanifest.CodexManifest{Cid: "cid-2"}, nil)
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
HasCid("cid-2"). HasCid("cid-2").
Return(true, nil) Return(true, nil)
@ -586,7 +587,7 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_OneSuccessOneError(
// Archive-1 fails // Archive-1 fails
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-1"). TriggerDownloadWithContext(gomock.Any(), "cid-1").
Return(codex.Manifest{}, fmt.Errorf("trigger failed")) Return(codexmanifest.CodexManifest{}, fmt.Errorf("trigger failed"))
logger := zap.NewNop() logger := zap.NewNop()
downloader := communities.NewCodexArchiveDownloader(suite.mockClient, index, communityID, []string{}, cancelChan, logger) downloader := communities.NewCodexArchiveDownloader(suite.mockClient, index, communityID, []string{}, cancelChan, logger)
@ -634,7 +635,7 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_SuccessErrorCancell
// Archive-3 (newest) succeeds // Archive-3 (newest) succeeds
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-3"). TriggerDownloadWithContext(gomock.Any(), "cid-3").
Return(codex.Manifest{Cid: "cid-3"}, nil) Return(codexmanifest.CodexManifest{Cid: "cid-3"}, nil)
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
HasCid("cid-3"). HasCid("cid-3").
Return(true, nil) Return(true, nil)
@ -642,14 +643,14 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_SuccessErrorCancell
// Archive-2 fails // Archive-2 fails
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-2"). TriggerDownloadWithContext(gomock.Any(), "cid-2").
Return(codex.Manifest{}, fmt.Errorf("trigger failed")) Return(codexmanifest.CodexManifest{}, fmt.Errorf("trigger failed"))
// Archive-1 will be cancelled (no expectations needed) // Archive-1 will be cancelled (no expectations needed)
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-1"). TriggerDownloadWithContext(gomock.Any(), "cid-1").
DoAndReturn(func(ctx context.Context, cid string) (codex.Manifest, error) { DoAndReturn(func(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
<-ctx.Done() // Wait for cancellation <-ctx.Done() // Wait for cancellation
return codex.Manifest{}, ctx.Err() return codexmanifest.CodexManifest{}, ctx.Err()
}). }).
AnyTimes() AnyTimes()
@ -701,7 +702,7 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_SuccessThenCancella
// Archive-2 (newer) succeeds // Archive-2 (newer) succeeds
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-2"). TriggerDownloadWithContext(gomock.Any(), "cid-2").
Return(codex.Manifest{Cid: "cid-2"}, nil) Return(codexmanifest.CodexManifest{Cid: "cid-2"}, nil)
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
HasCid("cid-2"). HasCid("cid-2").
Return(true, nil) Return(true, nil)
@ -709,9 +710,9 @@ func (suite *CodexArchiveDownloaderSuite) TestPartialSuccess_SuccessThenCancella
// Archive-1 will be cancelled // Archive-1 will be cancelled
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-1"). TriggerDownloadWithContext(gomock.Any(), "cid-1").
DoAndReturn(func(ctx context.Context, cid string) (codex.Manifest, error) { DoAndReturn(func(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
<-ctx.Done() // Wait for cancellation <-ctx.Done() // Wait for cancellation
return codex.Manifest{}, ctx.Err() return codexmanifest.CodexManifest{}, ctx.Err()
}). }).
AnyTimes() AnyTimes()
@ -763,9 +764,9 @@ func (suite *CodexArchiveDownloaderSuite) TestNoSuccess_OnlyCancellation() {
// Both archives will be cancelled // Both archives will be cancelled
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), gomock.Any()). TriggerDownloadWithContext(gomock.Any(), gomock.Any()).
DoAndReturn(func(ctx context.Context, cid string) (codex.Manifest, error) { DoAndReturn(func(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
<-ctx.Done() // Wait for cancellation <-ctx.Done() // Wait for cancellation
return codex.Manifest{}, ctx.Err() return codexmanifest.CodexManifest{}, ctx.Err()
}). }).
AnyTimes() AnyTimes()
@ -816,10 +817,10 @@ func (suite *CodexArchiveDownloaderSuite) TestNoSuccess_OnlyErrors() {
// Both archives fail // Both archives fail
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-1"). TriggerDownloadWithContext(gomock.Any(), "cid-1").
Return(codex.Manifest{}, fmt.Errorf("trigger failed for cid-1")) Return(codexmanifest.CodexManifest{}, fmt.Errorf("trigger failed for cid-1"))
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
TriggerDownloadWithContext(gomock.Any(), "cid-2"). TriggerDownloadWithContext(gomock.Any(), "cid-2").
Return(codex.Manifest{}, fmt.Errorf("trigger failed for cid-2")) Return(codexmanifest.CodexManifest{}, fmt.Errorf("trigger failed for cid-2"))
logger := zap.NewNop() logger := zap.NewNop()
downloader := communities.NewCodexArchiveDownloader(suite.mockClient, index, communityID, []string{}, cancelChan, logger) downloader := communities.NewCodexArchiveDownloader(suite.mockClient, index, communityID, []string{}, cancelChan, logger)

View File

@ -4,7 +4,7 @@ import (
"context" "context"
"io" "io"
"github.com/codex-storage/codex-go-bindings/codex" "go-codex-client/codexmanifest"
) )
// Mock generation instruction above will create a mock in package `mock_communities` // Mock generation instruction above will create a mock in package `mock_communities`
@ -26,11 +26,11 @@ type CodexClientInterface interface {
LocalDownloadWithContext(ctx context.Context, cid string, output io.Writer) error LocalDownloadWithContext(ctx context.Context, cid string, output io.Writer) error
// Async download methods // Async download methods
TriggerDownload(cid string) (codex.Manifest, error) TriggerDownload(cid string) (codexmanifest.CodexManifest, error)
TriggerDownloadWithContext(ctx context.Context, cid string) (codex.Manifest, error) TriggerDownloadWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error)
// Manifest methods // Manifest methods
FetchManifestWithContext(ctx context.Context, cid string) (codex.Manifest, error) FetchManifestWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error)
// CID management methods // CID management methods
HasCid(cid string) (bool, error) HasCid(cid string) (bool, error)

View File

@ -17,6 +17,7 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go.uber.org/zap" "go.uber.org/zap"
"go-codex-client/codextestutils"
"go-codex-client/communities" "go-codex-client/communities"
) )
@ -28,14 +29,14 @@ import (
// - CODEX_TIMEOUT_MS (optional; default: 60000) // - CODEX_TIMEOUT_MS (optional; default: 60000)
type CodexIndexDownloaderIntegrationTestSuite struct { type CodexIndexDownloaderIntegrationTestSuite struct {
suite.Suite suite.Suite
client *communities.CodexClient client communities.CodexClientInterface
testDir string testDir string
logger *zap.Logger logger *zap.Logger
} }
// SetupSuite runs once before all tests in the suite // SetupSuite runs once before all tests in the suite
func (suite *CodexIndexDownloaderIntegrationTestSuite) SetupSuite() { func (suite *CodexIndexDownloaderIntegrationTestSuite) SetupSuite() {
suite.client = NewCodexClientTest(suite.T()) suite.client = codextestutils.NewCodexClientTest(suite.T())
// Create logger // Create logger
suite.logger, _ = zap.NewDevelopment() suite.logger, _ = zap.NewDevelopment()

View File

@ -9,13 +9,13 @@ import (
"testing" "testing"
"time" "time"
"github.com/codex-storage/codex-go-bindings/codex"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"go.uber.org/mock/gomock" "go.uber.org/mock/gomock"
"go.uber.org/zap" "go.uber.org/zap"
"go-codex-client/codexmanifest"
"go-codex-client/communities" "go-codex-client/communities"
mock_communities "go-codex-client/communities/mock" mock_communities "go-codex-client/communities/mock"
) )
@ -80,7 +80,7 @@ func (suite *CodexIndexDownloaderTestSuite) TestGotManifest_SuccessClosesChannel
filePath := filepath.Join(suite.testDir, "index.bin") filePath := filepath.Join(suite.testDir, "index.bin")
// Setup mock to return a successful manifest // Setup mock to return a successful manifest
expectedManifest := codex.Manifest{ expectedManifest := codexmanifest.CodexManifest{
Cid: testCid, Cid: testCid,
} }
expectedManifest.DatasetSize = 1024 expectedManifest.DatasetSize = 1024
@ -120,7 +120,7 @@ func (suite *CodexIndexDownloaderTestSuite) TestGotManifest_ErrorDoesNotCloseCha
// Setup mock to return an error // Setup mock to return an error
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
FetchManifestWithContext(gomock.Any(), testCid). FetchManifestWithContext(gomock.Any(), testCid).
Return(codex.Manifest{}, errors.New("fetch error")) Return(codexmanifest.CodexManifest{}, errors.New("fetch error"))
// Create downloader // Create downloader
downloader := communities.NewCodexIndexDownloader(suite.mockClient, testCid, filePath, suite.cancelChan, suite.logger) downloader := communities.NewCodexIndexDownloader(suite.mockClient, testCid, filePath, suite.cancelChan, suite.logger)
@ -155,7 +155,7 @@ func (suite *CodexIndexDownloaderTestSuite) TestGotManifest_CidMismatchDoesNotCl
filePath := filepath.Join(suite.testDir, "index.bin") filePath := filepath.Join(suite.testDir, "index.bin")
// Setup mock to return a manifest with different CID // Setup mock to return a manifest with different CID
mismatchedManifest := codex.Manifest{ mismatchedManifest := codexmanifest.CodexManifest{
Cid: differentCid, // Different CID! Cid: differentCid, // Different CID!
} }
mismatchedManifest.DatasetSize = 1024 mismatchedManifest.DatasetSize = 1024
@ -199,12 +199,12 @@ func (suite *CodexIndexDownloaderTestSuite) TestGotManifest_Cancellation() {
fetchCalled := make(chan struct{}) fetchCalled := make(chan struct{})
suite.mockClient.EXPECT(). suite.mockClient.EXPECT().
FetchManifestWithContext(gomock.Any(), testCid). FetchManifestWithContext(gomock.Any(), testCid).
DoAndReturn(func(ctx context.Context, cid string) (codex.Manifest, error) { DoAndReturn(func(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
close(fetchCalled) // Signal that fetch was called close(fetchCalled) // Signal that fetch was called
// Wait for context cancellation // Wait for context cancellation
<-ctx.Done() <-ctx.Done()
return codex.Manifest{}, ctx.Err() return codexmanifest.CodexManifest{}, ctx.Err()
}) })
// Create downloader // Create downloader
@ -251,7 +251,7 @@ func (suite *CodexIndexDownloaderTestSuite) TestGotManifest_RecordsDatasetSize()
expectedSize := int64(2048) expectedSize := int64(2048)
// Setup mock to return a manifest with specific dataset size // Setup mock to return a manifest with specific dataset size
expectedManifest := codex.Manifest{ expectedManifest := codexmanifest.CodexManifest{
Cid: testCid, Cid: testCid,
} }
expectedManifest.DatasetSize = int(expectedSize) expectedManifest.DatasetSize = int(expectedSize)
@ -504,7 +504,7 @@ func (suite *CodexIndexDownloaderTestSuite) TestLength_ReturnsDatasetSize() {
expectedSize := 4096 expectedSize := 4096
// Setup mock to return a manifest // Setup mock to return a manifest
expectedManifest := codex.Manifest{ expectedManifest := codexmanifest.CodexManifest{
Cid: testCid, Cid: testCid,
} }
expectedManifest.DatasetSize = expectedSize expectedManifest.DatasetSize = expectedSize

View File

@ -11,11 +11,10 @@ package mock_communities
import ( import (
context "context" context "context"
codexmanifest "go-codex-client/codexmanifest"
io "io" io "io"
reflect "reflect" reflect "reflect"
time "time"
"github.com/codex-storage/codex-go-bindings/codex"
gomock "go.uber.org/mock/gomock" gomock "go.uber.org/mock/gomock"
) )
@ -72,10 +71,10 @@ func (mr *MockCodexClientInterfaceMockRecorder) DownloadWithContext(ctx, cid, ou
} }
// FetchManifestWithContext mocks base method. // FetchManifestWithContext mocks base method.
func (m *MockCodexClientInterface) FetchManifestWithContext(ctx context.Context, cid string) (codex.Manifest, error) { func (m *MockCodexClientInterface) FetchManifestWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchManifestWithContext", ctx, cid) ret := m.ctrl.Call(m, "FetchManifestWithContext", ctx, cid)
ret0, _ := ret[0].(codex.Manifest) ret0, _ := ret[0].(codexmanifest.CodexManifest)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -143,23 +142,11 @@ func (mr *MockCodexClientInterfaceMockRecorder) RemoveCid(cid any) *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCid", reflect.TypeOf((*MockCodexClientInterface)(nil).RemoveCid), cid) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveCid", reflect.TypeOf((*MockCodexClientInterface)(nil).RemoveCid), cid)
} }
// SetRequestTimeout mocks base method.
func (m *MockCodexClientInterface) SetRequestTimeout(timeout time.Duration) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetRequestTimeout", timeout)
}
// SetRequestTimeout indicates an expected call of SetRequestTimeout.
func (mr *MockCodexClientInterfaceMockRecorder) SetRequestTimeout(timeout any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRequestTimeout", reflect.TypeOf((*MockCodexClientInterface)(nil).SetRequestTimeout), timeout)
}
// TriggerDownload mocks base method. // TriggerDownload mocks base method.
func (m *MockCodexClientInterface) TriggerDownload(cid string) (codex.Manifest, error) { func (m *MockCodexClientInterface) TriggerDownload(cid string) (codexmanifest.CodexManifest, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TriggerDownload", cid) ret := m.ctrl.Call(m, "TriggerDownload", cid)
ret0, _ := ret[0].(codex.Manifest) ret0, _ := ret[0].(codexmanifest.CodexManifest)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
@ -171,10 +158,10 @@ func (mr *MockCodexClientInterfaceMockRecorder) TriggerDownload(cid any) *gomock
} }
// TriggerDownloadWithContext mocks base method. // TriggerDownloadWithContext mocks base method.
func (m *MockCodexClientInterface) TriggerDownloadWithContext(ctx context.Context, cid string) (codex.Manifest, error) { func (m *MockCodexClientInterface) TriggerDownloadWithContext(ctx context.Context, cid string) (codexmanifest.CodexManifest, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "TriggerDownloadWithContext", ctx, cid) ret := m.ctrl.Call(m, "TriggerDownloadWithContext", ctx, cid)
ret0, _ := ret[0].(codex.Manifest) ret0, _ := ret[0].(codexmanifest.CodexManifest)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }