1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/integration/internal/termtest/stripansi.go
Paweł Gronowski 2ec3e14c0f test: Add tests for logging
1. Add integration tests for the ContainerLogs API call
Each test handle a distinct case of ContainerLogs output.
- Muxed stream, when container is started without tty
- Single stream, when container is started with tty

2. Add unit test for LogReader suite that tests concurrent logging
It checks that there are no race conditions when logging concurrently
from multiple goroutines.

Co-authored-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Cory Snider <csnider@mirantis.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2022-06-10 09:26:17 +02:00

108 lines
3.1 KiB
Go

package termtest // import "github.com/docker/docker/integration/internal/termtest"
import (
"errors"
"regexp"
"github.com/Azure/go-ansiterm"
)
var stripOSC = regexp.MustCompile(`\x1b\][^\x1b\a]*(\x1b\\|\a)`)
// StripANSICommands attempts to strip ANSI console escape and control sequences
// from s, returning a string containing only the final printed characters which
// would be visible onscreen if the string was to be processed by a terminal
// emulator. Basic cursor positioning and screen erase control sequences are
// parsed and processed such that the output of simple CLI commands passed
// through a Windows Pseudoterminal and then this function yields the same
// string as if the output of those commands was redirected to a file.
//
// The only correct way to represent the result of processing ANSI console
// output would be a two-dimensional array of an emulated terminal's display
// buffer. That would be awkward to test against, so this function instead
// attempts to render to a one-dimensional string without extra padding. This is
// an inherently lossy process, and any attempts to render a string containing
// many cursor positioning commands are unlikely to yield satisfactory results.
// Handlers for several ANSI control sequences are also unimplemented; attempts
// to parse a string containing one will panic.
func StripANSICommands(s string, opts ...ansiterm.Option) (string, error) {
// Work around https://github.com/Azure/go-ansiterm/issues/34
s = stripOSC.ReplaceAllLiteralString(s, "")
var h stringHandler
p := ansiterm.CreateParser("Ground", &h, opts...)
_, err := p.Parse([]byte(s))
return h.String(), err
}
type stringHandler struct {
ansiterm.AnsiEventHandler
cursor int
b []byte
}
func (h *stringHandler) Print(b byte) error {
if h.cursor == len(h.b) {
h.b = append(h.b, b)
} else {
h.b[h.cursor] = b
}
h.cursor++
return nil
}
func (h *stringHandler) Execute(b byte) error {
switch b {
case '\b':
if h.cursor > 0 {
if h.cursor == len(h.b) && h.b[h.cursor-1] == ' ' {
h.b = h.b[:len(h.b)-1]
}
h.cursor--
}
case '\r', '\n':
h.Print(b)
}
return nil
}
// Erase Display
func (h *stringHandler) ED(v int) error {
switch v {
case 1: // Erase from start to cursor.
for i := 0; i < h.cursor; i++ {
h.b[i] = ' '
}
case 2, 3: // Erase whole display.
h.b = make([]byte, h.cursor)
for i := range h.b {
h.b[i] = ' '
}
default: // Erase from cursor to end of display.
h.b = h.b[:h.cursor+1]
}
return nil
}
// CUrsor Position
func (h *stringHandler) CUP(x, y int) error {
if x > 1 {
return errors.New("termtest: cursor position not supported for X > 1")
}
if y > len(h.b) {
for n := len(h.b) - y; n > 0; n-- {
h.b = append(h.b, ' ')
}
}
h.cursor = y - 1
return nil
}
func (h stringHandler) DECTCEM(bool) error { return nil } // Text Cursor Enable
func (h stringHandler) SGR(v []int) error { return nil } // Set Graphics Rendition
func (h stringHandler) DA(attrs []string) error { return nil }
func (h stringHandler) Flush() error { return nil }
func (h *stringHandler) String() string {
return string(h.b)
}