mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
The module already called itself github.com/luxfi/node while containing no node in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and the Go column of the matrix measured a VM plugin. A repo that fetches the thing it claims to be has not replaced it, so the Go sources move in — 1515 files, the daemon and everything under it — and the build reaches outside this module for nothing. Rust and C++ sit beside it unchanged and are still measured against it by the differential. That is the point of one repo: the reference implementation and the two ports are the same checkout, so parity is a thing you can run rather than a thing you assert. Verified: builds, and the closure carries no lux-private — checked at build time rather than believed. The daemon starts twelve chains on a local network (P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
305 lines
6.9 KiB
Go
305 lines
6.9 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package backup
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/database/zapdb"
|
|
"github.com/luxfi/log"
|
|
"github.com/luxfi/metric"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// newTestDB creates a zapdb for testing (supports backup/restore).
|
|
func newTestDB(t *testing.T) database.Database {
|
|
t.Helper()
|
|
tmpDir := t.TempDir()
|
|
db, err := zapdb.New(tmpDir, nil, "", metric.NewRegistry())
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { db.Close() })
|
|
return db
|
|
}
|
|
|
|
func TestBackupService_New(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
// Test missing database
|
|
_, err := New(Config{
|
|
MetadataDir: t.TempDir(),
|
|
})
|
|
require.Error(err)
|
|
require.Contains(err.Error(), "database is required")
|
|
|
|
// Test missing metadata directory
|
|
db := newTestDB(t)
|
|
|
|
_, err = New(Config{
|
|
DB: db,
|
|
})
|
|
require.Error(err)
|
|
require.Contains(err.Error(), "metadata directory is required")
|
|
|
|
// Test successful creation
|
|
svc, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: t.TempDir(),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
require.NotNil(svc)
|
|
}
|
|
|
|
func TestBackupService_BackupRestore(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
// Create source database with test data
|
|
srcDB := newTestDB(t)
|
|
|
|
testData := map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
"key3": "value3",
|
|
}
|
|
for k, v := range testData {
|
|
require.NoError(srcDB.Put([]byte(k), []byte(v)))
|
|
}
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
// Create backup service
|
|
svc, err := New(Config{
|
|
DB: srcDB,
|
|
MetadataDir: filepath.Join(tmpDir, "meta"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Perform backup (uncompressed)
|
|
var buf bytes.Buffer
|
|
version, err := svc.Backup(&buf, 0, false)
|
|
require.NoError(err)
|
|
require.Greater(version, uint64(0))
|
|
|
|
backupData := buf.Bytes()
|
|
require.NotEmpty(backupData)
|
|
|
|
// Create destination database
|
|
dstDB := newTestDB(t)
|
|
|
|
dstSvc, err := New(Config{
|
|
DB: dstDB,
|
|
MetadataDir: filepath.Join(tmpDir, "meta2"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Restore
|
|
err = dstSvc.Restore(bytes.NewReader(backupData), false)
|
|
require.NoError(err)
|
|
|
|
// Verify data
|
|
for k, expected := range testData {
|
|
actual, err := dstDB.Get([]byte(k))
|
|
require.NoError(err)
|
|
require.Equal(expected, string(actual))
|
|
}
|
|
}
|
|
|
|
func TestBackupService_BackupToFile(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
// Create database with test data
|
|
db := newTestDB(t)
|
|
|
|
require.NoError(db.Put([]byte("test"), []byte("data")))
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
svc, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: filepath.Join(tmpDir, "meta"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Test uncompressed backup
|
|
uncompressedPath := filepath.Join(tmpDir, "backup.db")
|
|
version, err := svc.BackupToFile(uncompressedPath, 0, false)
|
|
require.NoError(err)
|
|
require.Greater(version, uint64(0))
|
|
|
|
info, err := os.Stat(uncompressedPath)
|
|
require.NoError(err)
|
|
require.Greater(info.Size(), int64(0))
|
|
|
|
// Test compressed backup
|
|
compressedPath := filepath.Join(tmpDir, "backup.zst")
|
|
version2, err := svc.BackupToFile(compressedPath, 0, true)
|
|
require.NoError(err)
|
|
require.Greater(version2, uint64(0))
|
|
|
|
info2, err := os.Stat(compressedPath)
|
|
require.NoError(err)
|
|
require.Greater(info2.Size(), int64(0))
|
|
}
|
|
|
|
func TestBackupService_RestoreFromFile(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
// Create source database with test data
|
|
srcDB := newTestDB(t)
|
|
|
|
require.NoError(srcDB.Put([]byte("restore-test"), []byte("restore-value")))
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
srcSvc, err := New(Config{
|
|
DB: srcDB,
|
|
MetadataDir: filepath.Join(tmpDir, "meta-src"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Create compressed backup
|
|
backupPath := filepath.Join(tmpDir, "backup.zst")
|
|
_, err = srcSvc.BackupToFile(backupPath, 0, true)
|
|
require.NoError(err)
|
|
|
|
// Create destination database
|
|
dstDB := newTestDB(t)
|
|
|
|
dstSvc, err := New(Config{
|
|
DB: dstDB,
|
|
MetadataDir: filepath.Join(tmpDir, "meta-dst"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Restore from file
|
|
err = dstSvc.RestoreFromFile(backupPath, true)
|
|
require.NoError(err)
|
|
|
|
// Verify data
|
|
val, err := dstDB.Get([]byte("restore-test"))
|
|
require.NoError(err)
|
|
require.Equal("restore-value", string(val))
|
|
}
|
|
|
|
func TestBackupService_Metadata(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
db := newTestDB(t)
|
|
|
|
require.NoError(db.Put([]byte("meta-test"), []byte("meta-value")))
|
|
|
|
tmpDir := t.TempDir()
|
|
metaDir := filepath.Join(tmpDir, "meta")
|
|
|
|
svc, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: metaDir,
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Initially no metadata
|
|
meta := svc.GetMetadata()
|
|
require.Equal(uint64(0), meta.LastVersion)
|
|
|
|
// Perform backup
|
|
var buf bytes.Buffer
|
|
version, err := svc.Backup(&buf, 0, false)
|
|
require.NoError(err)
|
|
|
|
// Check metadata updated
|
|
meta = svc.GetMetadata()
|
|
require.Equal(version, meta.LastVersion)
|
|
require.False(meta.Incremental)
|
|
|
|
// Verify metadata file exists
|
|
metaPath := filepath.Join(metaDir, MetadataFileName)
|
|
_, err = os.Stat(metaPath)
|
|
require.NoError(err)
|
|
|
|
// Create new service - should load metadata
|
|
svc2, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: metaDir,
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
meta2 := svc2.GetMetadata()
|
|
require.Equal(version, meta2.LastVersion)
|
|
}
|
|
|
|
func TestBackupService_IncrementalBackup(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
db := newTestDB(t)
|
|
|
|
// Initial data
|
|
require.NoError(db.Put([]byte("key1"), []byte("value1")))
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
svc, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: filepath.Join(tmpDir, "meta"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Full backup
|
|
var fullBuf bytes.Buffer
|
|
fullVersion, err := svc.Backup(&fullBuf, 0, false)
|
|
require.NoError(err)
|
|
|
|
meta := svc.GetMetadata()
|
|
require.False(meta.Incremental)
|
|
|
|
// Add more data
|
|
require.NoError(db.Put([]byte("key2"), []byte("value2")))
|
|
|
|
// Incremental backup
|
|
var incrBuf bytes.Buffer
|
|
incrVersion, err := svc.Backup(&incrBuf, fullVersion, false)
|
|
require.NoError(err)
|
|
require.GreaterOrEqual(incrVersion, fullVersion)
|
|
|
|
meta = svc.GetMetadata()
|
|
require.True(meta.Incremental)
|
|
}
|
|
|
|
func TestBackupService_GetLastVersion(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
db := newTestDB(t)
|
|
|
|
require.NoError(db.Put([]byte("version-test"), []byte("data")))
|
|
|
|
tmpDir := t.TempDir()
|
|
|
|
svc, err := New(Config{
|
|
DB: db,
|
|
MetadataDir: filepath.Join(tmpDir, "meta"),
|
|
Log: log.New("test", "backup"),
|
|
})
|
|
require.NoError(err)
|
|
|
|
// Initially 0
|
|
require.Equal(uint64(0), svc.GetLastVersion())
|
|
|
|
// After backup, should have version
|
|
var buf bytes.Buffer
|
|
version, err := svc.Backup(&buf, 0, false)
|
|
require.NoError(err)
|
|
require.Equal(version, svc.GetLastVersion())
|
|
}
|