Skip to content

Commit ca7704b

Browse files
committed
Refactor url functions and add tests
1 parent 2693641 commit ca7704b

File tree

2 files changed

+270
-6
lines changed

2 files changed

+270
-6
lines changed

utils/url/url.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"github.com/ARM-software/golang-utils/utils/reflection"
88
)
99

10+
const defaultPathSeparator = "/"
11+
1012
// HasMatchingPathSegments checks whether two path strings match based on their segments.
1113
func HasMatchingPathSegments(pathA, pathB string) (match bool, err error) {
1214
if reflection.IsEmpty(pathA) {
@@ -72,23 +74,23 @@ func HasMatchingPathSegmentsWithParams(pathA, pathB string) (match bool, err err
7274
return
7375
}
7476

75-
// SplitPath returns a slice of the individual segments that make up the path string. It looks for the default "/" path separator when splitting.
77+
// SplitPath returns a slice containing the individual segments that make up the path string. It looks for the default "/" path separator when splitting.
7678
func SplitPath(path string) []string {
77-
return SplitPathWithSeparator(path, "/")
79+
return SplitPathWithSeparator(path, defaultPathSeparator)
7880
}
7981

8082
// SplitPathWithSeparator is similar to SplitPath but allows for specifying the path separator to look for when splitting.
8183
func SplitPathWithSeparator(path string, separator string) []string {
8284
path = strings.TrimSpace(path)
83-
if path == "" || path == separator {
85+
if reflection.IsEmpty(path) || path == separator {
8486
return nil
8587
}
8688

8789
path = strings.Trim(path, separator)
8890
segments := strings.Split(path, separator)
8991
out := segments[:0]
9092
for _, p := range segments {
91-
if p != "" {
93+
if !reflection.IsEmpty(p) {
9294
out = append(out, p)
9395
}
9496
}
@@ -102,7 +104,7 @@ func IsParamSegment(segment string) bool {
102104

103105
// JoinPaths returns a single concatenated path string from the supplied paths and correctly sets the default "/" separator between them.
104106
func JoinPaths(paths ...string) (joinedPath string, err error) {
105-
return JoinPathsWithSeparator("/", paths...)
107+
return JoinPathsWithSeparator(defaultPathSeparator, paths...)
106108
}
107109

108110
// JoinPathsWithSeparator is similar to JoinPaths but allows for specifying the path separator to use.
@@ -114,12 +116,15 @@ func JoinPathsWithSeparator(separator string, paths ...string) (joinedPath strin
114116
if len(paths) == 0 {
115117
return
116118
}
117-
118119
if len(paths) == 1 {
119120
joinedPath = paths[0]
120121
return
121122
}
122123

124+
if reflection.IsEmpty(separator) {
125+
separator = defaultPathSeparator
126+
}
127+
123128
joinedPath = paths[0]
124129
for _, p := range paths[1:] {
125130
pathAHasSlashSuffix := strings.HasSuffix(joinedPath, separator)

utils/url/url_test.go

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package url
22

33
import (
4+
"fmt"
45
"testing"
56

7+
"github.com/ARM-software/golang-utils/utils/commonerrors"
8+
"github.com/ARM-software/golang-utils/utils/commonerrors/errortest"
69
"github.com/stretchr/testify/assert"
710
)
811

@@ -15,3 +18,259 @@ func TestUrl_IsParamSegment(t *testing.T) {
1518
assert.False(t, IsParamSegment("abc"))
1619
})
1720
}
21+
22+
func TestUrl_JoinPaths(t *testing.T) {
23+
tests := []struct {
24+
name string
25+
paths []string
26+
result string
27+
error error
28+
}{
29+
{
30+
"empty paths",
31+
[]string{},
32+
"",
33+
nil,
34+
},
35+
{
36+
"undefined paths",
37+
nil,
38+
"",
39+
commonerrors.ErrUndefined,
40+
},
41+
{
42+
"one path",
43+
[]string{"abc/123"},
44+
"abc/123",
45+
nil,
46+
},
47+
{
48+
"two paths",
49+
[]string{"abc/123", "def/456"},
50+
"abc/123/def/456",
51+
nil,
52+
},
53+
{
54+
"two paths with leading and trailing slashes",
55+
[]string{"abc/123/", "/def/456"},
56+
"abc/123/def/456",
57+
nil,
58+
},
59+
{
60+
"multiple paths",
61+
[]string{"abc/123", "def/456", "zzz", "{param1}", "999"},
62+
"abc/123/def/456/zzz/{param1}/999",
63+
nil,
64+
},
65+
}
66+
67+
for i := range tests {
68+
test := tests[i]
69+
t.Run(fmt.Sprintf("JoinPaths_%v", test.name), func(t *testing.T) {
70+
joinedPaths, err := JoinPaths(test.paths...)
71+
72+
errortest.AssertError(t, err, test.error)
73+
assert.Equal(t, test.result, joinedPaths)
74+
})
75+
}
76+
}
77+
78+
func TestUrl_JoinPathsWithSeparator(t *testing.T) {
79+
tests := []struct {
80+
name string
81+
paths []string
82+
separator string
83+
result string
84+
error error
85+
}{
86+
{
87+
"empty paths",
88+
[]string{},
89+
"/",
90+
"",
91+
nil,
92+
},
93+
{
94+
"undefined paths",
95+
nil,
96+
"~",
97+
"",
98+
commonerrors.ErrUndefined,
99+
},
100+
{
101+
"one path with custom separator",
102+
[]string{"abc/123"},
103+
"|",
104+
"abc/123",
105+
nil,
106+
},
107+
{
108+
"two paths with custom separator",
109+
[]string{"abc/123", "def/456"},
110+
"|",
111+
"abc/123|def/456",
112+
nil,
113+
},
114+
{
115+
"two paths with empty separator",
116+
[]string{"abc/123", "def/456"},
117+
"",
118+
"abc/123/def/456",
119+
nil,
120+
},
121+
{
122+
"two paths with whitespace separator",
123+
[]string{"abc/123", "def/456"},
124+
" ",
125+
"abc/123/def/456",
126+
nil,
127+
},
128+
{
129+
"two paths with leading and trailing slashes and custom separator",
130+
[]string{"abc/123/", "/def/456"},
131+
"#",
132+
"abc/123/#/def/456",
133+
nil,
134+
},
135+
{
136+
"multiple paths with custom separator",
137+
[]string{"abc/123", "def/456", "zzz", "{param1}", "999"},
138+
"~",
139+
"abc/123~def/456~zzz~{param1}~999",
140+
nil,
141+
},
142+
}
143+
144+
for i := range tests {
145+
test := tests[i]
146+
t.Run(fmt.Sprintf("JoinPathsWithSeparator_%v", test.name), func(t *testing.T) {
147+
joinedPaths, err := JoinPathsWithSeparator(test.separator, test.paths...)
148+
149+
errortest.AssertError(t, err, test.error)
150+
assert.Equal(t, test.result, joinedPaths)
151+
})
152+
}
153+
}
154+
155+
func TestUrl_SplitPath(t *testing.T) {
156+
tests := []struct {
157+
name string
158+
path string
159+
result []string
160+
error error
161+
}{
162+
{
163+
"empty path",
164+
"",
165+
[]string{},
166+
nil,
167+
},
168+
{
169+
"path with one segment",
170+
"abc",
171+
[]string{"abc"},
172+
nil,
173+
},
174+
{
175+
"path with two segments",
176+
"abc/123",
177+
[]string{"abc", "123"},
178+
nil,
179+
},
180+
{
181+
"path with multiple segments",
182+
"abc/123/def/456",
183+
[]string{"abc", "123", "def", "456"},
184+
nil,
185+
},
186+
{
187+
"path with multiple segments including param segment",
188+
"abc/123/def/456/zzz/{param1}/999",
189+
[]string{"abc", "123", "def", "456", "zzz", "{param1}", "999"},
190+
nil,
191+
},
192+
}
193+
194+
for i := range tests {
195+
test := tests[i]
196+
t.Run(fmt.Sprintf("JoinPaths_%v", test.name), func(t *testing.T) {
197+
segments := SplitPath(test.path)
198+
199+
if test.result != nil {
200+
for i, s := range segments {
201+
assert.Equal(t, test.result[i], s)
202+
}
203+
} else {
204+
assert.Nil(t, segments)
205+
}
206+
})
207+
}
208+
}
209+
210+
func TestUrl_SplitPathWithSeparator(t *testing.T) {
211+
tests := []struct {
212+
name string
213+
path string
214+
separator string
215+
result []string
216+
error error
217+
}{
218+
{
219+
"empty path",
220+
"",
221+
"",
222+
[]string{},
223+
nil,
224+
},
225+
{
226+
"path with one segment and custom separator",
227+
"abc",
228+
"|",
229+
[]string{"abc"},
230+
nil,
231+
},
232+
{
233+
"path with two segments and custom separator",
234+
"abc|123",
235+
"|",
236+
[]string{"abc", "123"},
237+
nil,
238+
},
239+
{
240+
"path with multiple segments and custom separator",
241+
"abc~123~def~456",
242+
"~",
243+
[]string{"abc", "123", "def", "456"},
244+
nil,
245+
},
246+
{
247+
"path with multiple segments including param segment and custom separator",
248+
"abc~123~def~456~zzz~{param1}~999",
249+
"~",
250+
[]string{"abc", "123", "def", "456", "zzz", "{param1}", "999"},
251+
nil,
252+
},
253+
{
254+
"path with multiple segments including param segment and custom separator with other separators",
255+
"abc~123/def~456~zzz~{param1}|999",
256+
"~",
257+
[]string{"abc", "123/def", "456", "zzz", "{param1}|999"},
258+
nil,
259+
},
260+
}
261+
262+
for i := range tests {
263+
test := tests[i]
264+
t.Run(fmt.Sprintf("JoinPaths_%v", test.name), func(t *testing.T) {
265+
segments := SplitPathWithSeparator(test.path, test.separator)
266+
267+
if test.result != nil {
268+
for i, s := range segments {
269+
assert.Equal(t, test.result[i], s)
270+
}
271+
} else {
272+
assert.Nil(t, segments)
273+
}
274+
})
275+
}
276+
}

0 commit comments

Comments
 (0)