2022-01-03 17:44:19 +00:00
|
|
|
package media_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"git.netflux.io/rob/clipper/media"
|
|
|
|
"github.com/stretchr/testify/require"
|
2022-01-07 12:31:52 +00:00
|
|
|
"go.uber.org/zap"
|
2022-01-03 17:44:19 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// fixtureReader loads a fixture into a ReadCloser with the provided limit.
|
|
|
|
func fixtureReader(t *testing.T, fixturePath string, limit int64) io.ReadCloser {
|
|
|
|
fptr, err := os.Open(fixturePath)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// limitReader to make the mock work realistically, not intended for assertions:
|
|
|
|
return struct {
|
|
|
|
io.Reader
|
|
|
|
io.Closer
|
|
|
|
}{
|
|
|
|
Reader: io.LimitReader(fptr, limit),
|
|
|
|
Closer: fptr,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// helperCommand returns a function that builds an *exec.Cmd which executes a
|
|
|
|
// test function in order to act as a mock process.
|
|
|
|
func helperCommand(t *testing.T, wantCommand, stdoutFile, stderrString string, forceExitCode int) media.CommandFunc {
|
|
|
|
return func(ctx context.Context, name string, args ...string) *exec.Cmd {
|
|
|
|
cs := []string{"-test.run=TestHelperProcess", "--", name}
|
|
|
|
cs = append(cs, args...)
|
|
|
|
cmd := exec.CommandContext(ctx, os.Args[0], cs...)
|
|
|
|
cmd.Env = []string{
|
|
|
|
"GO_WANT_HELPER_PROCESS=1",
|
|
|
|
"GO_WANT_COMMAND=" + wantCommand,
|
|
|
|
"GO_STDOUT_FILE=" + stdoutFile,
|
|
|
|
"GO_STDERR_STRING=" + stderrString,
|
|
|
|
"GO_FORCE_EXIT_CODE=" + strconv.Itoa(forceExitCode),
|
|
|
|
}
|
|
|
|
return cmd
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestHelperProcess is the body for the mock executable process built by
|
|
|
|
// helperCommand.
|
|
|
|
func TestHelperProcess(t *testing.T) {
|
|
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
// Stop the helper process writing to stdout after the test has finished.
|
|
|
|
// This prevents it from writing the "PASS" string which is unwanted in
|
|
|
|
// this context.
|
|
|
|
if !t.Failed() {
|
|
|
|
os.Stdout, _ = os.Open(os.DevNull)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
if exitCode := os.Getenv("GO_FORCE_EXIT_CODE"); exitCode != "0" {
|
|
|
|
c, _ := strconv.Atoi(exitCode)
|
|
|
|
os.Stderr.WriteString(os.Getenv("GO_STDERR_STRING"))
|
|
|
|
os.Exit(c)
|
|
|
|
}
|
|
|
|
|
|
|
|
if wantCommand := os.Getenv("GO_WANT_COMMAND"); wantCommand != "" {
|
|
|
|
gotCmd := strings.Split(strings.Join(os.Args, " "), " -- ")[1]
|
|
|
|
if wantCommand != gotCmd {
|
|
|
|
fmt.Fprintf(os.Stderr, "GO_WANT_COMMAND assertion failed:\nwant = %v\ngot = %v", wantCommand, gotCmd)
|
|
|
|
t.Fail() // necessary to make the test fail
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy stdin to /dev/null. This is required to avoid broken pipe errors in
|
|
|
|
// the tests:
|
|
|
|
_, err := io.Copy(io.Discard, os.Stdin)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// If an output file is provided, then copy that to stdout:
|
|
|
|
if fname := os.Getenv("GO_STDOUT_FILE"); fname != "" {
|
|
|
|
fptr, err := os.Open(fname)
|
|
|
|
require.NoError(t, err)
|
|
|
|
defer fptr.Close()
|
|
|
|
|
|
|
|
_, err = io.Copy(os.Stdout, fptr)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
}
|
2022-01-07 12:31:52 +00:00
|
|
|
|
|
|
|
// testLogger returns a functional development logger.
|
2022-01-07 18:54:56 +00:00
|
|
|
//lint:ignore U1000 helper method
|
2022-01-07 12:31:52 +00:00
|
|
|
func testLogger(t *testing.T) *zap.Logger {
|
|
|
|
l, err := zap.NewDevelopment()
|
|
|
|
require.NoError(t, err)
|
|
|
|
return l
|
|
|
|
}
|