check / check (push) Waiting to run
Package mfer handed out a loaded manifest as the unexported type manifest. Without a name for that type, a program using the library could not keep a loaded manifest in a struct field or pass one to its own functions. As sneak approved, the type is now exported as Manifest with its fields kept private. Its existing methods (Files, Signer, CreatedAt, String) are its whole API. NewManifestFromReader and NewManifestFromFile return *Manifest. The two lint suppressions that excused returning an unexported type from them are removed. The type's doc comment now names the two loaders and drops the pointer to the settled design question. String gets a doc comment. A test in package mfer_test uses *mfer.Manifest from outside the package. Model: opus-5-5
98 lines
2.2 KiB
Go
98 lines
2.2 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,
|
|
},
|
|
{
|
|
name: "dot segment",
|
|
path: "a/./b",
|
|
want: `path "a/./b" contains '.' segment`,
|
|
is: errPathDot,
|
|
},
|
|
} {
|
|
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)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSerializeInnerNotSetMessagesVerbatim pins the messages generate and
|
|
// generateOuter return when the inner message is missing.
|
|
func TestSerializeInnerNotSetMessagesVerbatim(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := &Manifest{}
|
|
|
|
err := m.generate(context.Background())
|
|
require.ErrorIs(t, err, errInnerNotSet)
|
|
require.EqualError(t, err, "inner message not set")
|
|
|
|
err = m.generateOuter(context.Background())
|
|
require.ErrorIs(t, err, errInternal)
|
|
require.EqualError(t, err, "inner message not set")
|
|
}
|