Skip to content

Commit 1bdd518

Browse files
committed
patchdb path validation
1 parent 87bfd25 commit 1bdd518

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

cmd/cronosd/cmd/patch_db.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,12 @@ Examples:
227227
if len(validDBNames) == 1 {
228228
dbTargetPath = targetPath
229229
} else {
230-
// For multiple databases, treat targetPath as data directory
230+
// For multiple databases, validate that targetPath is a directory, not a *.db file
231+
cleanedTargetPath := filepath.Clean(targetPath)
232+
if filepath.Ext(cleanedTargetPath) == ".db" {
233+
return fmt.Errorf("when patching multiple databases, --target-path must be a data directory (e.g., ~/.cronos/data), not a *.db file path (got %q); remove the .db suffix", targetPath)
234+
}
235+
// Treat targetPath as data directory
231236
dbTargetPath = filepath.Join(targetPath, dbName+".db")
232237
}
233238

cmd/cronosd/cmd/patch_db_test.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package cmd
2+
3+
import (
4+
"path/filepath"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
// TestTargetPathValidation tests that multi-database patching rejects *.db file paths
11+
func TestTargetPathValidation(t *testing.T) {
12+
tests := []struct {
13+
name string
14+
targetPath string
15+
dbCount int
16+
shouldError bool
17+
errorString string
18+
}{
19+
{
20+
name: "single DB with .db extension - allowed",
21+
targetPath: "/path/to/blockstore.db",
22+
dbCount: 1,
23+
shouldError: false,
24+
},
25+
{
26+
name: "single DB without .db extension - allowed (will be validated later)",
27+
targetPath: "/path/to/blockstore",
28+
dbCount: 1,
29+
shouldError: false,
30+
},
31+
{
32+
name: "multiple DBs with data directory - allowed",
33+
targetPath: "/path/to/data",
34+
dbCount: 2,
35+
shouldError: false,
36+
},
37+
{
38+
name: "multiple DBs with .db file path - rejected",
39+
targetPath: "/path/to/blockstore.db",
40+
dbCount: 2,
41+
shouldError: true,
42+
errorString: "must be a data directory",
43+
},
44+
{
45+
name: "multiple DBs with .db file path (trailing slash) - rejected",
46+
targetPath: "/path/to/blockstore.db/",
47+
dbCount: 2,
48+
shouldError: true,
49+
errorString: "must be a data directory",
50+
},
51+
}
52+
53+
for _, tt := range tests {
54+
t.Run(tt.name, func(t *testing.T) {
55+
// Simulate the validation logic from patch_db.go
56+
var dbNames []string
57+
for i := 0; i < tt.dbCount; i++ {
58+
dbNames = append(dbNames, "testdb")
59+
}
60+
61+
var err error
62+
if len(dbNames) == 1 {
63+
// Single DB: no validation in this branch
64+
_ = tt.targetPath
65+
} else {
66+
// Multiple DBs: validate targetPath is not a *.db file
67+
cleanedTargetPath := filepath.Clean(tt.targetPath)
68+
if filepath.Ext(cleanedTargetPath) == ".db" {
69+
err = &targetPathError{path: tt.targetPath}
70+
}
71+
}
72+
73+
if tt.shouldError {
74+
require.Error(t, err)
75+
if tt.errorString != "" {
76+
require.Contains(t, err.Error(), tt.errorString)
77+
}
78+
} else {
79+
require.NoError(t, err)
80+
}
81+
})
82+
}
83+
}
84+
85+
// targetPathError is a helper type to simulate the error from patch_db.go
86+
type targetPathError struct {
87+
path string
88+
}
89+
90+
func (e *targetPathError) Error() string {
91+
return "when patching multiple databases, --target-path must be a data directory (e.g., ~/.cronos/data), not a *.db file path (got \"" + e.path + "\"); remove the .db suffix"
92+
}

0 commit comments

Comments
 (0)