|
|
|
@@ -1190,6 +1190,99 @@ func TestCheckURLManifestWithoutTempDirectory(t *testing.T) {
|
|
|
|
|
assert.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestCheckNeverReportsIndexMFAtTopOfBase checks a tree holding index.mf at
|
|
|
|
|
// its top, where gen and fetch write the manifest, against a manifest that
|
|
|
|
|
// does not list it, given by URL and by a path outside the tree: check never
|
|
|
|
|
// reports it, and passes with and without --no-extra-files. index.mf in a
|
|
|
|
|
// subdirectory, and the temp file fetch saves index.mf through, are still
|
|
|
|
|
// reported.
|
|
|
|
|
func TestCheckNeverReportsIndexMFAtTopOfBase(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
files := map[string][]byte{testFileTxt: []byte("hello")}
|
|
|
|
|
manifest := manifestOf(t, files)
|
|
|
|
|
|
|
|
|
|
server := httptest.NewServer(fetchTestHandler(manifest, files))
|
|
|
|
|
t.Cleanup(server.Close)
|
|
|
|
|
|
|
|
|
|
manifestOutsideTree := filepath.Join(t.TempDir(), "other.mf")
|
|
|
|
|
require.NoError(t, os.WriteFile(manifestOutsideTree, manifest, 0o600))
|
|
|
|
|
|
|
|
|
|
for name, manifestArg := range map[string]string{
|
|
|
|
|
"manifest by URL": server.URL + "/" + defaultManifestName,
|
|
|
|
|
"manifest by path": manifestOutsideTree,
|
|
|
|
|
} {
|
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
base := t.TempDir()
|
|
|
|
|
require.NoError(t, os.WriteFile(
|
|
|
|
|
filepath.Join(base, testFileTxt), files[testFileTxt], 0o600))
|
|
|
|
|
require.NoError(t, os.WriteFile(
|
|
|
|
|
filepath.Join(base, defaultManifestName), manifest, 0o600))
|
|
|
|
|
|
|
|
|
|
check := func(flags ...string) (int, string) {
|
|
|
|
|
opts := testOpts(slices.Concat(
|
|
|
|
|
[]string{testApp, cmdCheck}, flags,
|
|
|
|
|
[]string{testFlagBase, base, manifestArg},
|
|
|
|
|
), afero.NewOsFs())
|
|
|
|
|
|
|
|
|
|
return runCLI(opts), testStderr(t, opts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exitCode, stderr := check()
|
|
|
|
|
assert.Equal(t, 0, exitCode, "stderr: %s", stderr)
|
|
|
|
|
assert.NotContains(t, stderr, "EXTRA: "+defaultManifestName)
|
|
|
|
|
|
|
|
|
|
exitCode, stderr = check(testFlagNoExtra)
|
|
|
|
|
assert.Equal(t, 0, exitCode, "stderr: %s", stderr)
|
|
|
|
|
assert.NotContains(t, stderr, "EXTRA: "+defaultManifestName)
|
|
|
|
|
|
|
|
|
|
reported := []string{
|
|
|
|
|
testSubdirManifest,
|
|
|
|
|
tempPathFor(defaultManifestName),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, os.Mkdir(filepath.Join(base, testSubdir), 0o750))
|
|
|
|
|
|
|
|
|
|
for _, path := range reported {
|
|
|
|
|
require.NoError(t,
|
|
|
|
|
os.WriteFile(filepath.Join(base, path), manifest, 0o600))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
exitCode, stderr = check(testFlagNoExtra)
|
|
|
|
|
assert.Equal(t, 1, exitCode, "stderr: %s", stderr)
|
|
|
|
|
assert.NotContains(t, stderr, "EXTRA: "+defaultManifestName)
|
|
|
|
|
|
|
|
|
|
for _, path := range reported {
|
|
|
|
|
assert.Contains(t, stderr, "EXTRA: "+path)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestCheckChecksListedIndexMF checks a tree against a manifest that lists
|
|
|
|
|
// index.mf at the top of the tree, where that file has changed since: check
|
|
|
|
|
// reports it like any other changed file.
|
|
|
|
|
func TestCheckChecksListedIndexMF(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
manifestPath := filepath.Join(t.TempDir(), "other.mf")
|
|
|
|
|
require.NoError(t, os.WriteFile(manifestPath, manifestOf(t, map[string][]byte{
|
|
|
|
|
defaultManifestName: []byte("listed"),
|
|
|
|
|
}), 0o600))
|
|
|
|
|
|
|
|
|
|
base := t.TempDir()
|
|
|
|
|
require.NoError(t, os.WriteFile(
|
|
|
|
|
filepath.Join(base, defaultManifestName), []byte("edited"), 0o600))
|
|
|
|
|
|
|
|
|
|
opts := testOpts([]string{
|
|
|
|
|
testApp, cmdCheck, testFlagBase, base, manifestPath,
|
|
|
|
|
}, afero.NewOsFs())
|
|
|
|
|
assert.Equal(t, 1, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
|
|
|
|
assert.Contains(t, testStderr(t, opts), "HASH_MISMATCH: "+defaultManifestName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// unlistableDirFs is a filesystem on which one directory cannot be listed.
|
|
|
|
|
type unlistableDirFs struct {
|
|
|
|
|
afero.Fs
|
|
|
|
@@ -1238,6 +1331,33 @@ func TestCheckWithUnlistableDirectory(t *testing.T) {
|
|
|
|
|
assert.Contains(t, testStderr(t, opts), "unlisted.txt")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TestCheckReportsUnreadableIndexMFAtTopOfBase has a directory named
|
|
|
|
|
// index.mf at the top of the base that cannot be listed. check leaves out
|
|
|
|
|
// only the report that index.mf is not in the manifest, so it reports the
|
|
|
|
|
// error and fails under --no-extra-files.
|
|
|
|
|
func TestCheckReportsUnreadableIndexMFAtTopOfBase(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
unreadable := filepath.Join(testDir, defaultManifestName)
|
|
|
|
|
|
|
|
|
|
mem := afero.NewMemMapFs()
|
|
|
|
|
require.NoError(t, mem.MkdirAll(unreadable, 0o755))
|
|
|
|
|
writeTestFile(t, mem, testFile1, "hello")
|
|
|
|
|
|
|
|
|
|
opts := testOpts([]string{
|
|
|
|
|
testApp, cmdGenerate, "-q", "-o", testManifest, testDir,
|
|
|
|
|
}, mem)
|
|
|
|
|
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
|
|
|
|
|
|
|
|
|
fs := unlistableDirFs{Fs: mem, dir: unreadable}
|
|
|
|
|
|
|
|
|
|
opts = testOpts([]string{
|
|
|
|
|
testApp, cmdCheck, testFlagNoExtra, testFlagBase, testDir, testManifest,
|
|
|
|
|
}, fs)
|
|
|
|
|
assert.Equal(t, 1, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
|
|
|
|
assert.Contains(t, testStderr(t, opts), "ERROR: "+defaultManifestName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestGenerateAtomicWriteNoTempFileOnSuccess(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|