d73287f043
this adds some stuff to ultest so that the set of files created by a test can be inspected after so that we can write some tests for the cp command to observe that it does what it is supposed to do. Change-Id: I98b8fb214058140dfbb117baa7acea6a2cc340e1
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
// Copyright (C) 2021 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package ultest
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"storj.io/storj/cmd/uplinkng/ulloc"
|
|
)
|
|
|
|
// Result captures all the output of running a command for inspection.
|
|
type Result struct {
|
|
Stdout string
|
|
Stderr string
|
|
Ok bool
|
|
Err error
|
|
Files []File
|
|
}
|
|
|
|
// RequireSuccess fails if the Result did not observe a successful execution.
|
|
func (r Result) RequireSuccess(t *testing.T) {
|
|
if !r.Ok {
|
|
errs := parseErrors(r.Stdout)
|
|
require.True(t, r.Ok, "test did not run successfully. errors:\n%s",
|
|
strings.Join(errs, "\n"))
|
|
}
|
|
require.NoError(t, r.Err)
|
|
}
|
|
|
|
// RequireFailure fails if the Result did not observe a failed execution.
|
|
func (r Result) RequireFailure(t *testing.T) Result {
|
|
require.False(t, r.Ok && r.Err == nil, "command ran with no error")
|
|
return r
|
|
}
|
|
|
|
// RequireStdout requires that the execution wrote to stdout the provided string.
|
|
// Blank lines are ignored and all lines are space trimmed for the comparison.
|
|
func (r Result) RequireStdout(t *testing.T, stdout string) Result {
|
|
require.Equal(t, trimNewlineSpaces(stdout), trimNewlineSpaces(r.Stdout))
|
|
return r
|
|
}
|
|
|
|
// RequireStderr requires that the execution wrote to stderr the provided string.
|
|
// Blank lines are ignored and all lines are space trimmed for the comparison.
|
|
func (r Result) RequireStderr(t *testing.T, stderr string) Result {
|
|
require.Equal(t, trimNewlineSpaces(stderr), trimNewlineSpaces(r.Stderr))
|
|
return r
|
|
}
|
|
|
|
// RequireFiles requires that the set of files provided are all of the files that
|
|
// existed at the end of the execution.
|
|
func (r Result) RequireFiles(t *testing.T, files ...File) Result {
|
|
files = append([]File(nil), files...)
|
|
sort.Slice(files, func(i, j int) bool { return files[i].less(files[j]) })
|
|
require.Equal(t, files, r.Files)
|
|
return r
|
|
}
|
|
|
|
func parseErrors(s string) []string {
|
|
lines := strings.Split(s, "\n")
|
|
start := 0
|
|
for i, line := range lines {
|
|
if line == "Errors:" {
|
|
start = i + 1
|
|
} else if len(line) > 0 && line[0] != ' ' {
|
|
return lines[start:i]
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func trimNewlineSpaces(s string) string {
|
|
lines := strings.Split(s, "\n")
|
|
|
|
j := 0
|
|
for _, line := range lines {
|
|
if trimmed := strings.TrimSpace(line); len(trimmed) > 0 {
|
|
lines[j] = trimmed
|
|
j++
|
|
}
|
|
}
|
|
return strings.Join(lines[:j], "\n")
|
|
}
|
|
|
|
// File represents a file existing either locally or remotely.
|
|
type File struct {
|
|
Loc string
|
|
Contents string
|
|
}
|
|
|
|
func (f File) less(g File) bool {
|
|
fl, _ := ulloc.Parse(f.Loc)
|
|
gl, _ := ulloc.Parse(g.Loc)
|
|
return fl.Less(gl)
|
|
}
|