feat: Snapshot exporting tool (#1877)

In this PR:
1 We create a golang grpc client to request data from rippled
2 We store the data into the specific place
3 Add unittests
4 Create build script, the build can be initiated by set conan option
`snapshot` being true.

Please ignore the grpc server part. It will be implemented in importing
tool.
This commit is contained in:
cyan317
2025-02-12 16:56:04 +00:00
committed by GitHub
parent 624f7ff6d5
commit 3c008b6bb4
11 changed files with 992 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
package export
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"xrplf/clio/clio_snapshot/mocks"
pb "xrplf/clio/clio_snapshot/org/xrpl/rpc/v1"
"github.com/golang/mock/gomock"
)
func TestExportDeltaLedgerData(t *testing.T) {
tests := []struct {
name string
startSeq uint32
endSeq uint32
}{
{"OneSeq", 1, 1},
{"MultipleSeq", 1, 20},
{"EndSeqLessThanStartSeq", 20, 1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockClient := mocks.NewMockXRPLedgerAPIServiceClient(ctrl)
mockResponse := &pb.GetLedgerResponse{}
times := tt.endSeq - tt.startSeq + 1
if tt.endSeq < tt.startSeq {
times = 0
}
mockClient.EXPECT().GetLedger(gomock.Any(), gomock.Any()).Return(mockResponse, nil).Times(int(times))
defer os.RemoveAll("test")
exportFromDeltaLedgerImpl(mockClient, tt.startSeq, tt.endSeq, "test")
_, err := os.Stat("test")
assert.Equal(t, os.IsNotExist(err), tt.endSeq < tt.startSeq)
})
}
}
func TestExportFullLedgerData(t *testing.T) {
tests := []struct {
name string
startSeq uint32
endSeq uint32
}{
{"OneSeq", 1, 1},
{"MultipleSeq", 1, 20},
{"EndSeqLessThanStartSeq", 20, 1},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockClient := mocks.NewMockXRPLedgerAPIServiceClient(ctrl)
mockDataResponse := &pb.GetLedgerDataResponse{}
mockLedgerResponse := &pb.GetLedgerResponse{}
timesLedgerDataCalled := 16
timesLedgerCalled := tt.endSeq - tt.startSeq + 1
if tt.endSeq < tt.startSeq {
timesLedgerCalled = 0
}
mockClient.EXPECT().GetLedgerData(gomock.Any(), gomock.Any()).Return(mockDataResponse, nil).Times(timesLedgerDataCalled)
mockClient.EXPECT().GetLedger(gomock.Any(), gomock.Any()).Return(mockLedgerResponse, nil).Times(int(timesLedgerCalled))
defer os.RemoveAll("test")
exportFromFullLedgerImpl(mockClient, tt.startSeq, tt.endSeq, "test")
_, err := os.Stat("test")
assert.False(t, os.IsNotExist(err))
})
}
}
func TestRoundDown(t *testing.T) {
tests := []struct {
name string
in1 uint32
in2 uint32
out uint32
}{
{"RoundDownToZero", 10, 0, 10},
{"RoundDown12To10", 12, 10, 10},
{"RoundDownToOne", 13, 1, 13},
{"RoundDown100", 103, 100, 100},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, roundDown(tt.in1, tt.in2), tt.out)
})
}
}
func TestGenerateMarkers(t *testing.T) {
tests := []struct {
name string
in uint32
out [][32]byte
}{
{"GenerateMarkers1", 1, [][32]byte{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}},
{"GenerateMarkers2", 2, [][32]byte{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}},
{"GenerateMarkers4", 4, [][32]byte{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
{0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, generateMarkers(tt.in), tt.out)
})
}
}
func TestCheckPath(t *testing.T) {
tests := []struct {
name string
path string
}{
{"Path", "test"},
{"NestedPath", "test/test"}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
checkPath(tt.path)
defer os.RemoveAll(tt.path)
_, err := os.Stat(tt.path)
assert.False(t, os.IsNotExist(err))
})
}
}