check / check (push) Waiting to run
ValidatePath refused a .. segment but accepted a . segment, so a manifest could list ./a.txt. check then verified a.txt and also reported it as an extra file, and one file could be listed twice under two spellings despite the listed-once rule. A . segment is now refused when a manifest is written and when it is loaded, and the Path Rules in docs/FORMAT.md list it. Two fetch tests listed ./ paths to check name clashes; such manifests can no longer be built, so those cases are removed. 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")
|
|
}
|