From d938ecaba203a4dacc10c38527a52eca546230d7 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Sun, 4 Jan 2015 07:56:20 -0800 Subject: [PATCH] Escape stdout/stderr YAML-like elements for TAP output Fixes https://github.com/GoogleCloudPlatform/kubernetes/issues/3094 --- hack/e2e.go | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/hack/e2e.go b/hack/e2e.go index 1306a7e0021..b4a7fabdc42 100644 --- a/hack/e2e.go +++ b/hack/e2e.go @@ -31,6 +31,7 @@ import ( "path" "path/filepath" "sort" + "strconv" "strings" "time" ) @@ -334,7 +335,7 @@ func Test() (results ResultsByTest) { if *tap { fmt.Printf(" ---\n duration_ms: %.3f\n", duration_secs) } - printBashOutputs(" ", " ", stdout, stderr) + printBashOutputs(" ", " ", stdout, stderr, *tap) if *tap { fmt.Printf(" ...\n") } @@ -432,7 +433,7 @@ func runBashUntil(stepName, bashFragment string) func() { headerprefix = "# " + headerprefix lineprefix = "# " + lineprefix } - printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes())) + printBashOutputs(headerprefix, lineprefix, string(stdout.Bytes()), string(stderr.Bytes()), false) } } @@ -471,19 +472,44 @@ func finishRunning(stepName string, cmd *exec.Cmd) (bool, string, string) { return true, "", "" } -func printBashOutputs(headerprefix, lineprefix, stdout, stderr string) { +func printBashOutputs(headerprefix, lineprefix, stdout, stderr string, escape bool) { // The |'s (plus appropriate prefixing) are to make this look - // "YAMLish" to the Jenkins TAP plugin + // "YAMLish" to the Jenkins TAP plugin: + // https://wiki.jenkins-ci.org/display/JENKINS/TAP+Plugin if stdout != "" { fmt.Printf("%vstdout: |\n", headerprefix) + if escape { + stdout = escapeOutput(stdout) + } printPrefixedLines(lineprefix, stdout) } if stderr != "" { fmt.Printf("%vstderr: |\n", headerprefix) + if escape { + stderr = escapeOutput(stderr) + } printPrefixedLines(lineprefix, stderr) } } +// Escape stdout/stderr so the Jenkins YAMLish parser doesn't barf on +// it. This escaping is crude (it masks all colons as something humans +// will hopefully see as a colon, for instance), but it should get the +// job done without pulling in a whole YAML package. +func escapeOutput(s string) (out string) { + for _, r := range s { + switch { + case !strconv.IsPrint(r): + out += " " + case r == ':': + out += "\u02D0" // "ː", MODIFIER LETTER TRIANGULAR COLON + default: + out += string(r) + } + } + return +} + func printPrefixedLines(prefix, s string) { for _, line := range strings.Split(s, "\n") { fmt.Printf("%v%v\n", prefix, line)