Skip to content

Commit

Permalink
move tests from ingest to rpc service
Browse files Browse the repository at this point in the history
  • Loading branch information
aditya1702 committed Jan 10, 2025
1 parent 1673546 commit f3b4098
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 104 deletions.
104 changes: 0 additions & 104 deletions internal/services/ingest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package services
import (
"bytes"
"context"
"io"
"net/http"
"os"
"testing"
"time"
Expand All @@ -26,7 +24,6 @@ import (
"github.com/stellar/wallet-backend/internal/tss"
tssrouter "github.com/stellar/wallet-backend/internal/tss/router"
tssstore "github.com/stellar/wallet-backend/internal/tss/store"
"github.com/stellar/wallet-backend/internal/utils"
)

func TestGetLedgerTransactions(t *testing.T) {
Expand Down Expand Up @@ -541,104 +538,3 @@ func TestIngest_LatestSyncedLedgerAheadOfRPC(t *testing.T) {

mockRPCService.AssertExpectations(t)
}

func TestTrackRPCServiceHealth_HealthyService(t *testing.T) {
mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

healthResult := entities.RPCGetHealthResult{
Status: "healthy",
LatestLedger: 100,
OldestLedger: 1,
LedgerRetentionWindow: 0,
}

// Mock the HTTP response for GetHealth
mockResponse := &http.Response{
Body: io.NopCloser(bytes.NewBuffer([]byte(`{
"jsonrpc": "2.0",
"id": 1,
"result": {
"status": "healthy",
"latestLedger": 100,
"oldestLedger": 1,
"ledgerRetentionWindow": 0
}
}`))),
}
mockHTTPClient.On("Post", "http://test-url", "application/json", mock.Anything).Return(mockResponse, nil).Once()

// Start tracking health in background
go rpcService.trackRPCServiceHealth(ctx)

// Get result from heartbeat channel
select {
case result := <-rpcService.GetHeartbeatChannel():
assert.Equal(t, healthResult, result)
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for heartbeat")
}

mockHTTPClient.AssertExpectations(t)
}

func TestTrackRPCServiceHealth_UnhealthyService(t *testing.T) {
var logBuffer bytes.Buffer
log.DefaultLogger.SetOutput(&logBuffer)
defer log.DefaultLogger.SetOutput(os.Stderr)

mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), 70*time.Second)
defer cancel()

// Mock error response for GetHealth with a valid http.Response
mockResponse := &http.Response{
Body: io.NopCloser(bytes.NewBuffer([]byte(`{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "rpc error"
}
}`))),
}
mockHTTPClient.On("Post", "http://test-url", "application/json", mock.Anything).
Return(mockResponse, nil)

go rpcService.trackRPCServiceHealth(ctx)

// Wait long enough for warning to trigger
time.Sleep(65 * time.Second)

logOutput := logBuffer.String()
assert.Contains(t, logOutput, "rpc service unhealthy for over 1m0s")
mockHTTPClient.AssertExpectations(t)
}

func TestTrackRPCService_ContextCancelled(t *testing.T) {
mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

go rpcService.trackRPCServiceHealth(ctx)

// Cancel context immediately
cancel()

// Verify channel is closed after context cancellation
time.Sleep(100 * time.Millisecond)
_, ok := <-rpcService.GetHeartbeatChannel()
assert.False(t, ok, "channel should be closed")

mockHTTPClient.AssertNotCalled(t, "Post")
}
99 changes: 99 additions & 0 deletions internal/services/rpc_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ package services

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"strings"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"

"github.com/stellar/go/support/log"
"github.com/stellar/wallet-backend/internal/entities"
"github.com/stellar/wallet-backend/internal/utils"
)
Expand Down Expand Up @@ -369,3 +373,98 @@ func TestSendGetHealth(t *testing.T) {
assert.Equal(t, "sending getHealth request: sending POST request to RPC: connection failed", err.Error())
})
}

func TestTrackRPCServiceHealth_HealthyService(t *testing.T) {
mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

healthResult := entities.RPCGetHealthResult{
Status: "healthy",
LatestLedger: 100,
OldestLedger: 1,
LedgerRetentionWindow: 0,
}

// Mock the HTTP response for GetHealth
mockResponse := &http.Response{
Body: io.NopCloser(bytes.NewBuffer([]byte(`{
"jsonrpc": "2.0",
"id": 1,
"result": {
"status": "healthy",
"latestLedger": 100,
"oldestLedger": 1,
"ledgerRetentionWindow": 0
}
}`))),
}
mockHTTPClient.On("Post", "http://test-url", "application/json", mock.Anything).Return(mockResponse, nil).Once()

// Get result from heartbeat channel
select {
case result := <-rpcService.GetHeartbeatChannel():
assert.Equal(t, healthResult, result)
case <-time.After(10 * time.Second):
t.Fatal("timeout waiting for heartbeat")
}

mockHTTPClient.AssertExpectations(t)
}

func TestTrackRPCServiceHealth_UnhealthyService(t *testing.T) {
var logBuffer bytes.Buffer
log.DefaultLogger.SetOutput(&logBuffer)
defer log.DefaultLogger.SetOutput(os.Stderr)

mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), 70*time.Second)
defer cancel()

// Mock error response for GetHealth with a valid http.Response
mockResponse := &http.Response{
Body: io.NopCloser(bytes.NewBuffer([]byte(`{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "rpc error"
}
}`))),
}
mockHTTPClient.On("Post", "http://test-url", "application/json", mock.Anything).
Return(mockResponse, nil)

go rpcService.trackRPCServiceHealth(ctx)

// Wait long enough for warning to trigger
time.Sleep(65 * time.Second)

logOutput := logBuffer.String()
assert.Contains(t, logOutput, "rpc service unhealthy for over 1m0s")
mockHTTPClient.AssertExpectations(t)
}

func TestTrackRPCService_ContextCancelled(t *testing.T) {
mockHTTPClient := &utils.MockHTTPClient{}
rpcService, err := NewRPCService("http://test-url", mockHTTPClient)
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()

go rpcService.trackRPCServiceHealth(ctx)

// Cancel context immediately
cancel()

// Verify channel is closed after context cancellation
time.Sleep(100 * time.Millisecond)
_, ok := <-rpcService.GetHeartbeatChannel()
assert.False(t, ok, "channel should be closed")

mockHTTPClient.AssertNotCalled(t, "Post")
}

0 comments on commit f3b4098

Please sign in to comment.