remove special characters (like double or single quotes) from name to prevent
creating filesystem paths that can cause errors when parsing through scripts.
Test-names (t.Name()) for sub-tests allow free-form names to be used, for example:
t.Run("engine restart shouldn't kill alive containers", func(t *testing.T) {
Which would result in the quote (') to be included in the filename,
which is valid, but can cause issues when processing with shell scripts;
find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz
[...]
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option
This patch adds a `sanitizedTestName` utility that replaces special characters
with an underscore to prevent such issues.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -218,7 +218,7 @@ func New(t testing.TB, ops ...Option) *Daemon {
|
| 218 | 218 |
dest = os.Getenv("DEST")
|
| 219 | 219 |
} |
| 220 | 220 |
assert.Assert(t, dest != "", "Please set the DOCKER_INTEGRATION_DAEMON_DEST or the DEST environment variable") |
| 221 |
- dest = filepath.Join(dest, t.Name()) |
|
| 221 |
+ dest = filepath.Join(dest, sanitizedTestName(t)) |
|
| 222 | 222 |
|
| 223 | 223 |
if os.Getenv("DOCKER_ROOTLESS") != "" {
|
| 224 | 224 |
if os.Getenv("DOCKER_REMAP_ROOT") != "" {
|
| ... | ... |
@@ -242,6 +242,53 @@ func New(t testing.TB, ops ...Option) *Daemon {
|
| 242 | 242 |
return d |
| 243 | 243 |
} |
| 244 | 244 |
|
| 245 |
+// sanitizedTestName removes special characters (like double or single quotes) |
|
| 246 |
+// from name to prevent creating filesystem paths that can cause |
|
| 247 |
+// errors when parsing through scripts. |
|
| 248 |
+// |
|
| 249 |
+// Test-names (t.Name()) for sub-tests allow free-form names to be used, |
|
| 250 |
+// for example: |
|
| 251 |
+// |
|
| 252 |
+// t.Run("engine restart shouldn't kill alive containers", func(t *testing.T) {
|
|
| 253 |
+// |
|
| 254 |
+// Which would result in the quote (') to be included in the filename,
|
|
| 255 |
+// which is valid, but can cause issues when processing with shell scripts; |
|
| 256 |
+// |
|
| 257 |
+// find bundles -path '*/root/*overlay2' -prune -o -type f \( -name '*-report.json' -o -name '*.log' -o -name '*.out' -o -name '*.prof' -o -name '*-report.xml' \) -print | xargs sudo tar -czf /tmp/reports.tar.gz |
|
| 258 |
+// [...] |
|
| 259 |
+// xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option |
|
| 260 |
+// |
|
| 261 |
+// sanitizedTestName replaces special characters with an underscore to prevent |
|
| 262 |
+// such issues. |
|
| 263 |
+func sanitizedTestName(t testing.TB) string {
|
|
| 264 |
+ t.Helper() |
|
| 265 |
+ parts := strings.Split(t.Name(), "/") |
|
| 266 |
+ for i := range parts {
|
|
| 267 |
+ parts[i] = sanitizePathComponent(parts[i]) |
|
| 268 |
+ } |
|
| 269 |
+ return filepath.Join(parts...) |
|
| 270 |
+} |
|
| 271 |
+ |
|
| 272 |
+func sanitizePathComponent(name string) string {
|
|
| 273 |
+ var b strings.Builder |
|
| 274 |
+ for _, r := range name {
|
|
| 275 |
+ if (r >= 'a' && r <= 'z') || |
|
| 276 |
+ (r >= 'A' && r <= 'Z') || |
|
| 277 |
+ (r >= '0' && r <= '9') || |
|
| 278 |
+ r == '-' || r == '_' {
|
|
| 279 |
+ b.WriteRune(r) |
|
| 280 |
+ } else {
|
|
| 281 |
+ b.WriteByte('_')
|
|
| 282 |
+ } |
|
| 283 |
+ } |
|
| 284 |
+ |
|
| 285 |
+ out := strings.TrimLeft(strings.TrimSpace(b.String()), "-") |
|
| 286 |
+ if out == "" {
|
|
| 287 |
+ return "_" |
|
| 288 |
+ } |
|
| 289 |
+ return out |
|
| 290 |
+} |
|
| 291 |
+ |
|
| 245 | 292 |
// BinaryPath returns the binary and its arguments. |
| 246 | 293 |
func (d *Daemon) BinaryPath() (string, error) {
|
| 247 | 294 |
dockerdBinary, err := exec.LookPath(d.dockerdBinary) |
| 248 | 295 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,93 @@ |
| 0 |
+package daemon |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "path/filepath" |
|
| 4 |
+ "testing" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+// regression test for https://github.com/moby/moby/issues/52300 |
|
| 8 |
+func TestSanitizeTestName(t *testing.T) {
|
|
| 9 |
+ tests := []struct {
|
|
| 10 |
+ name string |
|
| 11 |
+ want string |
|
| 12 |
+ }{
|
|
| 13 |
+ {
|
|
| 14 |
+ name: "shouldn't do something", |
|
| 15 |
+ want: "TestSanitizeTestName/shouldn_t_do_something", |
|
| 16 |
+ }, |
|
| 17 |
+ {
|
|
| 18 |
+ name: `double "quotes"`, |
|
| 19 |
+ want: "TestSanitizeTestName/double__quotes_", |
|
| 20 |
+ }, |
|
| 21 |
+ {
|
|
| 22 |
+ name: "contains spaces", |
|
| 23 |
+ want: "TestSanitizeTestName/contains_spaces", |
|
| 24 |
+ }, |
|
| 25 |
+ {
|
|
| 26 |
+ name: "contains ..dots", |
|
| 27 |
+ want: "TestSanitizeTestName/contains___dots", |
|
| 28 |
+ }, |
|
| 29 |
+ {
|
|
| 30 |
+ name: "..starts-with-dots", |
|
| 31 |
+ want: "TestSanitizeTestName/__starts-with-dots", |
|
| 32 |
+ }, |
|
| 33 |
+ {
|
|
| 34 |
+ name: ".starts-with-dot", |
|
| 35 |
+ want: "TestSanitizeTestName/_starts-with-dot", |
|
| 36 |
+ }, |
|
| 37 |
+ {
|
|
| 38 |
+ name: "ends-with-dot.", |
|
| 39 |
+ want: "TestSanitizeTestName/ends-with-dot_", |
|
| 40 |
+ }, |
|
| 41 |
+ {
|
|
| 42 |
+ name: "--starts-with-dash", |
|
| 43 |
+ want: "TestSanitizeTestName/starts-with-dash", |
|
| 44 |
+ }, |
|
| 45 |
+ {
|
|
| 46 |
+ name: "_starts-with-underscore", |
|
| 47 |
+ want: "TestSanitizeTestName/_starts-with-underscore", |
|
| 48 |
+ }, |
|
| 49 |
+ {
|
|
| 50 |
+ name: "ends-with-dash-", |
|
| 51 |
+ want: "TestSanitizeTestName/ends-with-dash-", |
|
| 52 |
+ }, |
|
| 53 |
+ {
|
|
| 54 |
+ name: "foo/bar", |
|
| 55 |
+ want: "TestSanitizeTestName/foo/bar", |
|
| 56 |
+ }, |
|
| 57 |
+ {
|
|
| 58 |
+ name: `foo/"bar"`, |
|
| 59 |
+ want: "TestSanitizeTestName/foo/_bar_", |
|
| 60 |
+ }, |
|
| 61 |
+ {
|
|
| 62 |
+ name: "foo/..bar", |
|
| 63 |
+ want: "TestSanitizeTestName/foo/__bar", |
|
| 64 |
+ }, |
|
| 65 |
+ {
|
|
| 66 |
+ name: "../foo", |
|
| 67 |
+ want: "TestSanitizeTestName/__/foo", |
|
| 68 |
+ }, |
|
| 69 |
+ {
|
|
| 70 |
+ name: "foo/..", |
|
| 71 |
+ want: "TestSanitizeTestName/foo/__", |
|
| 72 |
+ }, |
|
| 73 |
+ {
|
|
| 74 |
+ name: "'", |
|
| 75 |
+ want: "TestSanitizeTestName/_", |
|
| 76 |
+ }, |
|
| 77 |
+ {
|
|
| 78 |
+ name: "...", |
|
| 79 |
+ want: "TestSanitizeTestName/___", |
|
| 80 |
+ }, |
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ for _, tc := range tests {
|
|
| 84 |
+ t.Run(tc.name, func(t *testing.T) {
|
|
| 85 |
+ out := sanitizedTestName(t) |
|
| 86 |
+ want := filepath.FromSlash(tc.want) // let's be nice to Windows. |
|
| 87 |
+ if out != want {
|
|
| 88 |
+ t.Errorf("got %q, want %q", out, want)
|
|
| 89 |
+ } |
|
| 90 |
+ }) |
|
| 91 |
+ } |
|
| 92 |
+} |