test(cmdutils): add tests for PathOrCidPath and ValidatePinName (#11062)
Marcin Rataj committed
Nov 17, 2025 at 18:00 UTC
798b889ba258821c9faa5e4b0af903c21516c4c2
1 file changed
+106
core/commands/cmdutils/utils_test.go
new
+106
@@ -0,0 +1,106 @@
1
+package cmdutils
2
+
3
+import (
4
+ "strings"
5
+ "testing"
6
+
7
+ "github.com/stretchr/testify/assert"
8
+ "github.com/stretchr/testify/require"
9
+)
10
+
11
+func TestPathOrCidPath(t *testing.T) {
12
+ t.Run("valid path is returned as-is", func(t *testing.T) {
13
+ validPath := "/ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"
14
+ p, err := PathOrCidPath(validPath)
15
+ require.NoError(t, err)
16
+ assert.Equal(t, validPath, p.String())
17
+ })
18
+
19
+ t.Run("valid CID is converted to /ipfs/ path", func(t *testing.T) {
20
+ cid := "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"
21
+ p, err := PathOrCidPath(cid)
22
+ require.NoError(t, err)
23
+ assert.Equal(t, "/ipfs/"+cid, p.String())
24
+ })
25
+
26
+ t.Run("valid ipns path is returned as-is", func(t *testing.T) {
27
+ validPath := "/ipns/example.com"
28
+ p, err := PathOrCidPath(validPath)
29
+ require.NoError(t, err)
30
+ assert.Equal(t, validPath, p.String())
31
+ })
32
+
33
+ t.Run("returns original error when both attempts fail", func(t *testing.T) {
34
+ invalidInput := "invalid!@#path"
35
+ _, err := PathOrCidPath(invalidInput)
36
+ require.Error(t, err)
37
+
38
+ // The error should reference the original input attempt.
39
+ // This ensures users get meaningful error messages about their actual input.
40
+ assert.Contains(t, err.Error(), invalidInput,
41
+ "error should mention the original input")
42
+ assert.Contains(t, err.Error(), "path does not have enough components",
43
+ "error should describe the problem with the original input")
44
+ })
45
+
46
+ t.Run("empty string returns error about original input", func(t *testing.T) {
47
+ _, err := PathOrCidPath("")
48
+ require.Error(t, err)
49
+
50
+ // Verify we're not getting an error about "/ipfs/" (the fallback)
51
+ errMsg := err.Error()
52
+ assert.NotContains(t, errMsg, "/ipfs/",
53
+ "error should be about empty input, not the fallback path")
54
+ })
55
+
56
+ t.Run("invalid characters return error about original input", func(t *testing.T) {
57
+ invalidInput := "not a valid path or CID with spaces and /@#$%"
58
+ _, err := PathOrCidPath(invalidInput)
59
+ require.Error(t, err)
60
+
61
+ // The error message should help debug the original input
62
+ assert.True(t, strings.Contains(err.Error(), invalidInput) ||
63
+ strings.Contains(err.Error(), "invalid"),
64
+ "error should reference original problematic input")
65
+ })
66
+
67
+ t.Run("CID with path is converted correctly", func(t *testing.T) {
68
+ cidWithPath := "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/file.txt"
69
+ p, err := PathOrCidPath(cidWithPath)
70
+ require.NoError(t, err)
71
+ assert.Equal(t, "/ipfs/"+cidWithPath, p.String())
72
+ })
73
+}
74
+
75
+func TestValidatePinName(t *testing.T) {
76
+ t.Run("valid pin name is accepted", func(t *testing.T) {
77
+ err := ValidatePinName("my-pin-name")
78
+ assert.NoError(t, err)
79
+ })
80
+
81
+ t.Run("empty pin name is accepted", func(t *testing.T) {
82
+ err := ValidatePinName("")
83
+ assert.NoError(t, err)
84
+ })
85
+
86
+ t.Run("pin name at max length is accepted", func(t *testing.T) {
87
+ maxName := strings.Repeat("a", MaxPinNameBytes)
88
+ err := ValidatePinName(maxName)
89
+ assert.NoError(t, err)
90
+ })
91
+
92
+ t.Run("pin name exceeding max length is rejected", func(t *testing.T) {
93
+ tooLong := strings.Repeat("a", MaxPinNameBytes+1)
94
+ err := ValidatePinName(tooLong)
95
+ require.Error(t, err)
96
+ assert.Contains(t, err.Error(), "max")
97
+ })
98
+
99
+ t.Run("pin name with unicode is counted by bytes", func(t *testing.T) {
100
+ // Unicode character can be multiple bytes
101
+ unicodeName := strings.Repeat("🔒", MaxPinNameBytes/4+1) // emoji is 4 bytes
102
+ err := ValidatePinName(unicodeName)
103
+ require.Error(t, err)
104
+ assert.Contains(t, err.Error(), "bytes")
105
+ })
106
+}