check / check (push) Successful in 2m2s
Every gpg run now has a one-minute deadline (gpgTimeout) on top of its caller's context and is killed when either ends. A timeout is reported as "gpg timed out" under the failing operation instead of "signal: killed". Only gpg itself is killed; WaitDelay (one second) stops the run from waiting on a process gpg left behind that still holds its output, such as a wrapper script that does not exec the real gpg. Builder.Build and Checker.ExtractEmbeddedSigningKeyFP take a context, so ToManifest's context now reaches signing and the contextcheck suppression calling signing non-cancellable is gone. Manifest loading takes no context, so its signature check is bounded by the timeout alone. Model: opus-5-5
88 lines
2.1 KiB
Go
88 lines
2.1 KiB
Go
//nolint:testpackage // white-box tests exercise unexported internals
|
|
package mfer
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestValidatePathMessagesVerbatim pins the exact rendered text of every
|
|
// ValidatePath rejection.
|
|
//
|
|
// These strings are user-visible and are assembled by wrapping static
|
|
// sentinels mid-sentence, which makes them easy to reword by accident
|
|
// while refactoring for errors.Is matchability. Changing one is a
|
|
// deliberate change, not a refactoring side effect.
|
|
func TestValidatePathMessagesVerbatim(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for _, tc := range []struct {
|
|
name string
|
|
path string
|
|
want string
|
|
is error
|
|
}{
|
|
{
|
|
name: "empty",
|
|
path: "",
|
|
want: "path cannot be empty",
|
|
is: errPathEmpty,
|
|
},
|
|
{
|
|
name: "not utf8",
|
|
path: "a\xffb",
|
|
want: `path "a\xffb" is not valid UTF-8`,
|
|
is: errPathNotUTF8,
|
|
},
|
|
{
|
|
name: "backslash",
|
|
path: `a\b`,
|
|
want: `path "a\\b" contains backslash; ` +
|
|
"use forward slashes only",
|
|
is: errPathBackslash,
|
|
},
|
|
{
|
|
name: "absolute",
|
|
path: "/a/b",
|
|
want: `path "/a/b" is absolute; must be relative`,
|
|
is: errPathAbsolute,
|
|
},
|
|
{
|
|
name: "empty segment",
|
|
path: "a//b",
|
|
want: `path "a//b" contains empty segment`,
|
|
is: errPathEmptySegment,
|
|
},
|
|
{
|
|
name: "dotdot segment",
|
|
path: "a/../b",
|
|
want: `path "a/../b" contains '..' segment`,
|
|
is: errPathDotDot,
|
|
},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := ValidatePath(tc.path)
|
|
require.Error(t, err)
|
|
assert.Equal(t, tc.want, err.Error())
|
|
require.ErrorIs(t, err, tc.is)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSerializeInternalErrorMessagesVerbatim pins the two distinct
|
|
// "internal error" messages, which differ between generate and
|
|
// generateOuter and have always done so.
|
|
func TestSerializeInternalErrorMessagesVerbatim(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := &manifest{}
|
|
require.EqualError(t, m.generate(context.Background()),
|
|
"internal error: pbInner not set")
|
|
require.EqualError(t, m.generateOuter(context.Background()), "internal error")
|
|
}
|