Files
dingtalk-workspace-cli/internal/helpers/drive_pull_plan_coverage_test.go
chichuan 97b6022017 test(drive): make pinned-root TOCTOU reproductions runnable on Windows
Windows keeps the pinned directory locked while a handle inside it is open
(os.Root plus the pull temp file or the upload source), so renaming that
directory fails with a sharing violation. Every "pinned root/ancestor was
swapped" reproduction in the drive mirror tests relied on such a rename, so 13
tests failed on windows-latest. That, not a coverage shortfall, is why
Coverage (Windows) exited 1 before the gate ever ran.

Each reproduction now falls back to injecting the equivalent identity change
when the rename is refused. pinnedPullRoot.verify() and verifyParent() read
current identity only through pullPathStat / pullRootLstat, so pointing those
seams at another directory hits the same fail-closed branches. Unix still
performs the real move and loses no strength.

Assertions that need an actual replacement tree now branch on the helper's
return value. forcePinnedFallbackForTest makes the fallback path itself
regressible on any platform, and a dedicated test covers it.

Verified locally with the fallback forced on: all 13 tests pass and changed
code coverage stays at 100%.
2026-08-13 21:35:48 +08:00

513 lines
17 KiB
Go

package helpers
import (
"context"
"errors"
"io"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/testseam"
)
func newPinnedPullRootForCoverage(t *testing.T, path string) *pinnedPullRoot {
t.Helper()
root, err := openExistingPinnedPullRoot(path)
if err != nil {
t.Fatal(err)
}
t.Cleanup(root.close)
return root
}
func newMissingPinnedPullPlanForCoverage(t *testing.T) *pinnedPullRootPlan {
t.Helper()
root := filepath.Join(t.TempDir(), "missing", "mirror")
plan, err := planPinnedPullRoot(root)
if err != nil {
t.Fatal(err)
}
t.Cleanup(plan.close)
return plan
}
func TestCrossPlatformCoverageDrivePullRootPlanFailures(t *testing.T) {
t.Run("existing root open", func(t *testing.T) {
testseam.Swap(t, &pullOpenRoot, func(string) (*os.Root, error) { return nil, errTestDownload })
if _, err := planPinnedPullRoot(t.TempDir()); err == nil {
t.Fatal("expected existing-root open failure")
}
})
t.Run("ancestor is a file", func(t *testing.T) {
parent := t.TempDir()
file := filepath.Join(parent, "file")
mustWrite(t, file, "x")
if _, err := planPinnedPullRoot(filepath.Join(file, "child")); err == nil ||
(!strings.Contains(err.Error(), "不是目录") && !strings.Contains(err.Error(), "not a directory")) {
t.Fatalf("error = %v", err)
}
})
t.Run("ancestor discovered as file", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "file")
mustWrite(t, file, "x")
calls := 0
testseam.Swap(t, &pullPathStat, func(string) (os.FileInfo, error) {
calls++
if calls == 1 {
return nil, os.ErrNotExist
}
return os.Stat(file)
})
if _, err := planPinnedPullRoot(filepath.Join(t.TempDir(), "missing")); err == nil || !strings.Contains(err.Error(), "不是目录") {
t.Fatalf("error = %v", err)
}
})
t.Run("ancestor open", func(t *testing.T) {
testseam.Swap(t, &pullOpenRoot, func(string) (*os.Root, error) { return nil, errTestDownload })
if _, err := planPinnedPullRoot(filepath.Join(t.TempDir(), "missing")); err == nil {
t.Fatal("expected ancestor open failure")
}
})
t.Run("path stat errors", func(t *testing.T) {
for _, initial := range []bool{true, false} {
t.Run(map[bool]string{true: "initial", false: "ancestor"}[initial], func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullPathStat, func(path string) (os.FileInfo, error) {
calls++
if initial || calls > 1 {
return nil, errTestDownload
}
return nil, os.ErrNotExist
})
if _, err := planPinnedPullRoot(filepath.Join(t.TempDir(), "missing")); err == nil {
t.Fatal("expected path stat failure")
}
})
}
})
t.Run("initial verification", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullRootLstat, func(root *os.Root, name string) (os.FileInfo, error) {
calls++
if calls == 1 {
return nil, errTestDownload
}
return root.Lstat(name)
})
if _, err := planPinnedPullRoot(filepath.Join(t.TempDir(), "missing")); err == nil {
t.Fatal("expected initial plan verification failure")
}
})
t.Run("invalid and changed plan", func(t *testing.T) {
if err := (&pinnedPullRootPlan{}).verify(); err == nil {
t.Fatal("expected invalid plan failure")
}
root := newPinnedPullRootForCoverage(t, t.TempDir())
bad := *root
bad.absDir = filepath.Join(t.TempDir(), "gone")
if err := (&pinnedPullRootPlan{ancestor: &bad}).verify(); err == nil {
t.Fatal("expected changed ancestor failure")
}
})
t.Run("unexpected missing-path lstat", func(t *testing.T) {
plan := newMissingPinnedPullPlanForCoverage(t)
testseam.Swap(t, &pullRootLstat, func(*os.Root, string) (os.FileInfo, error) { return nil, errTestDownload })
if err := plan.verify(); err == nil {
t.Fatal("expected missing-path lstat failure")
}
})
}
func TestCrossPlatformCoverageDrivePullRootMaterializeFailures(t *testing.T) {
t.Run("verification", func(t *testing.T) {
if _, err := (&pinnedPullRootPlan{}).materialize(); err == nil {
t.Fatal("expected materialize verification failure")
}
})
for _, tc := range []struct {
name string
stub func(*testing.T)
}{
{"open ancestor", func(t *testing.T) {
testseam.Swap(t, &pullOpenParentRoot, func(*os.Root, string) (*os.Root, error) { return nil, errTestDownload })
}},
{"mkdir", func(t *testing.T) {
testseam.Swap(t, &pullRootMkdir, func(*os.Root, string, os.FileMode) error { return errTestDownload })
}},
{"created lstat", func(t *testing.T) {
testseam.Swap(t, &pullRootLstat, func(*os.Root, string) (os.FileInfo, error) { return nil, errTestDownload })
}},
{"created not directory", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "file")
mustWrite(t, file, "x")
info, err := os.Lstat(file)
if err != nil {
t.Fatal(err)
}
testseam.Swap(t, &pullRootLstat, func(*os.Root, string) (os.FileInfo, error) { return info, nil })
}},
{"created changes before root identity", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullRootLstat, func(root *os.Root, name string) (os.FileInfo, error) {
calls++
if calls == 2 {
return nil, errTestDownload
}
return root.Lstat(name)
})
}},
{"open created", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullOpenParentRoot, func(root *os.Root, name string) (*os.Root, error) {
calls++
if calls > 1 {
return nil, errTestDownload
}
return root.OpenRoot(name)
})
}},
{"created identity", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullRootStat, func(root *os.Root, name string) (os.FileInfo, error) {
calls++
if calls == 1 {
return nil, errTestDownload
}
return root.Stat(name)
})
}},
{"final root stat", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullRootStat, func(root *os.Root, name string) (os.FileInfo, error) {
calls++
if calls == 3 {
return nil, errTestDownload
}
return root.Stat(name)
})
}},
{"final verification", func(t *testing.T) {
calls := 0
testseam.Swap(t, &pullPathLstat, func(path string) (os.FileInfo, error) {
calls++
if calls >= 2 {
return nil, errTestDownload
}
return os.Lstat(path)
})
}},
} {
t.Run(tc.name, func(t *testing.T) {
plan := newMissingPinnedPullPlanForCoverage(t)
tc.stub(t)
if root, err := plan.materialize(); err == nil {
root.close()
t.Fatal("expected materialize failure")
}
})
}
t.Run("final lstat and verify", func(t *testing.T) {
for _, failAt := range []int{1, 2} {
t.Run(string(rune('0'+failAt)), func(t *testing.T) {
plan := newMissingPinnedPullPlanForCoverage(t)
calls := 0
if failAt == 1 {
testseam.Swap(t, &pullPathLstat, func(string) (os.FileInfo, error) { return nil, errTestDownload })
} else {
testseam.Swap(t, &pullPathStat, func(path string) (os.FileInfo, error) {
calls++
if calls >= 2 {
return nil, errTestDownload
}
return os.Stat(path)
})
}
if root, err := plan.materialize(); err == nil {
root.close()
t.Fatal("expected final materialize failure")
}
})
}
})
t.Run("open existing path identity and verification", func(t *testing.T) {
for _, fail := range []string{"lstat", "verify"} {
t.Run(fail, func(t *testing.T) {
dir := t.TempDir()
if fail == "lstat" {
testseam.Swap(t, &pullPathLstat, func(string) (os.FileInfo, error) { return nil, errTestDownload })
} else {
pathCalls := 0
testseam.Swap(t, &pullPathLstat, func(path string) (os.FileInfo, error) {
pathCalls++
if pathCalls >= 2 {
return nil, errTestDownload
}
return os.Lstat(path)
})
}
if _, err := openExistingPinnedPullRoot(dir); err == nil {
t.Fatal("expected existing-root identity failure")
}
})
}
})
}
func TestCrossPlatformCoverageDrivePullPublishRaces(t *testing.T) {
t.Run("smart concurrent target", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
mustWrite(t, filepath.Join(root, "a.txt"), "older")
testseam.Swap(t, &pullDownloadFile, func(_ context.Context, _ string, _ map[string]string, destination *os.File) error {
if _, err := destination.WriteString("remote"); err != nil {
return err
}
return os.Chtimes(filepath.Join(root, "a.txt"), time.Now(), time.Now().Add(time.Hour))
})
action, err := pullOneFileAtRoot(context.Background(), "", &remoteFile{FileID: "F", ModifiedTimeValid: true}, root, "a.txt", ifExistsSmart)
if err != nil || action != pullActionSkipped {
t.Fatalf("action=%q err=%v", action, err)
}
})
t.Run("link loses to regular target", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
testseam.Swap(t, &pullLink, func(parent *os.Root, _, target string) error {
file, err := parent.OpenFile(target, os.O_CREATE|os.O_WRONLY, 0o600)
if err == nil {
_ = file.Close()
}
return os.ErrExist
})
action, err := pullOneFileAtRoot(context.Background(), "", &remoteFile{FileID: "F"}, root, "a.txt", ifExistsSkip)
if err != nil || action != pullActionSkipped {
t.Fatalf("action=%q err=%v", action, err)
}
})
t.Run("link cleanup", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
testseam.Swap(t, &pullRemove, func(*os.Root, string) error { return errTestDownload })
action, err := pullOneFileAtRoot(context.Background(), "", &remoteFile{FileID: "F"}, root, "a.txt", ifExistsSkip)
if err == nil || action != pullActionFailed || !strings.Contains(err.Error(), "清理临时文件") {
t.Fatalf("action=%q err=%v", action, err)
}
})
t.Run("post publish parent", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
statCalls := 0
testseam.Swap(t, &pullPathStat, func(path string) (os.FileInfo, error) {
statCalls++
if statCalls >= 5 {
return nil, errTestDownload
}
return os.Stat(path)
})
action, err := pullOneFileAtRoot(context.Background(), "", &remoteFile{FileID: "F"}, root, "a.txt", ifExistsOverwrite)
if err == nil || action != pullActionFailed {
t.Fatalf("action=%q err=%v", action, err)
}
})
t.Run("overwrite rename", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
testseam.Swap(t, &pullRename, func(*os.Root, string, string) error { return errTestDownload })
action, err := pullOneFileAtRoot(context.Background(), "", &remoteFile{FileID: "F"}, root, "a.txt", ifExistsOverwrite)
if err == nil || action != pullActionFailed {
t.Fatalf("action=%q err=%v", action, err)
}
})
}
func TestCrossPlatformCoverageDrivePullPlanCallers(t *testing.T) {
t.Run("second preflight verification", func(t *testing.T) {
dir := t.TempDir()
mustWrite(t, filepath.Join(dir, "a.txt"), "local")
root := newPinnedPullRootForCoverage(t, dir)
plan := &pinnedPullRootPlan{absDir: root.absDir, existing: root}
moved := false
testseam.Swap(t, &pullRootLstat, func(parent *os.Root, name string) (os.FileInfo, error) {
info, err := parent.Lstat(name)
if name == "a.txt" && !moved {
moved = true
if renameErr := os.Rename(dir, dir+"-pinned"); renameErr != nil {
// Windows 在固定目录上持有句柄时会锁住它,移走于该平台物理
// 不可达;注入等价的根身份变化,命中同一条二次校验分支。
if runtime.GOOS != "windows" {
t.Fatal(renameErr)
}
swapPinnedRootIdentity(t, dir)
} else if mkdirErr := os.Mkdir(dir, 0o755); mkdirErr != nil {
t.Fatal(mkdirErr)
}
}
return info, err
})
if _, _, err := buildDrivePullPreflightFromPlan(plan, map[string]*remoteFile{"a.txt": {RelPath: "a.txt"}}); err == nil {
t.Fatal("expected second verification failure")
}
})
t.Run("command materialize", func(t *testing.T) {
root := filepath.Join(t.TempDir(), "missing")
caller := pullListingCaller(`{"name":"a.txt","type":"file","fileId":"A"}`)
testseam.Swap(t, &deps, &Deps{Caller: caller, Out: &Formatter{w: io.Discard}})
testseam.Swap(t, &os.Args, []string{"dws", "drive"})
testseam.Swap(t, &pullOpenParentRoot, func(*os.Root, string) (*os.Root, error) { return nil, errTestDownload })
cmd := findDriveSubcommand(t, "pull")
mustSetFlags(t, cmd, map[string]string{"local-folder": root, "remote-folder": "ROOT"})
if err := runDrivePull(cmd, nil); err == nil || !errors.Is(err, errTestDownload) {
t.Fatalf("error = %v", err)
}
})
t.Run("preflight output", func(t *testing.T) {
root := t.TempDir()
caller := pullListingCaller(`{"name":"A.txt","type":"file","fileId":"A"},{"name":"a.txt","type":"file","fileId":"B"}`)
testseam.Swap(t, &deps, &Deps{Caller: caller, Out: &Formatter{w: failingWriter{}}})
testseam.Swap(t, &os.Args, []string{"dws", "drive"})
cmd := findDriveSubcommand(t, "pull")
mustSetFlags(t, cmd, map[string]string{"local-folder": root, "remote-folder": "ROOT"})
if err := runDrivePull(cmd, nil); err == nil {
t.Fatal("expected preflight output failure")
}
})
t.Run("remote helper", func(t *testing.T) {
root := t.TempDir()
installPinnedPullSuccess(t)
action, err := pullRemoteFile(context.Background(), "", &remoteFile{FileID: "F"}, root, "a.txt", ifExistsOverwrite)
if err != nil || action != pullActionDownloaded {
t.Fatalf("action=%q err=%v", action, err)
}
})
t.Run("target construction final verification", func(t *testing.T) {
root := newPinnedPullRootForCoverage(t, t.TempDir())
calls := 0
testseam.Swap(t, &pullRootLstat, func(parent *os.Root, name string) (os.FileInfo, error) {
calls++
if calls >= 2 && name == "." {
return nil, errTestDownload
}
return parent.Lstat(name)
})
if _, err := root.openTarget("a.txt"); err == nil {
t.Fatal("expected target verification failure")
}
})
}
func TestCrossPlatformCoverageDrivePullDefaultTransportWithoutListener(t *testing.T) {
destination, err := os.Create(filepath.Join(t.TempDir(), "payload"))
if err != nil {
t.Fatal(err)
}
defer destination.Close()
if err := defaultPullDownloadFile(context.Background(), ":", nil, destination); err == nil {
t.Fatal("expected invalid request URL")
}
t.Run("transport error", func(t *testing.T) {
testseam.Swap(t, &pullHTTPDo, func(*http.Request) (*http.Response, error) { return nil, errTestDownload })
if err := defaultPullDownloadFile(context.Background(), "https://example.invalid", nil, destination); !errors.Is(err, errTestDownload) {
t.Fatalf("error = %v", err)
}
})
t.Run("status", func(t *testing.T) {
testseam.Swap(t, &pullHTTPDo, func(request *http.Request) (*http.Response, error) {
if request.Header.Get("X-Test") != "yes" {
t.Fatalf("header = %q", request.Header.Get("X-Test"))
}
return &http.Response{StatusCode: http.StatusTeapot, Body: io.NopCloser(strings.NewReader("denied"))}, nil
})
if err := defaultPullDownloadFile(context.Background(), "https://example.invalid", map[string]string{"X-Test": "yes"}, destination); err == nil {
t.Fatal("expected status failure")
}
})
t.Run("success and copy", func(t *testing.T) {
testseam.Swap(t, &pullHTTPDo, func(*http.Request) (*http.Response, error) {
return &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader("payload"))}, nil
})
if err := defaultPullDownloadFile(context.Background(), "https://example.invalid", nil, destination); err != nil {
t.Fatal(err)
}
closed, createErr := os.Create(filepath.Join(t.TempDir(), "closed"))
if createErr != nil {
t.Fatal(createErr)
}
_ = closed.Close()
if err := defaultPullDownloadFile(context.Background(), "https://example.invalid", nil, closed); err == nil {
t.Fatal("expected copy failure")
}
})
}
func TestCrossPlatformCoverageDrivePullMTimeHandle(t *testing.T) {
file, err := os.Create(filepath.Join(t.TempDir(), "mtime"))
if err != nil {
t.Fatal(err)
}
defer file.Close()
if err := setPullFileTimes(file, time.Unix(123, 0)); err != nil {
t.Fatal(err)
}
}
func TestCrossPlatformCoverageDrivePullDryRunLocalPolicies(t *testing.T) {
root := t.TempDir()
path := filepath.Join(root, "a.txt")
mustWrite(t, path, "local")
info, err := os.Stat(path)
if err != nil {
t.Fatal(err)
}
testseam.Swap(t, &deps, &Deps{Out: &Formatter{w: io.Discard}})
remote := map[string]*remoteFile{"a.txt": {RelPath: "a.txt", ModifiedTimeValid: true, ModifiedTime: info.ModTime().UnixMilli()}}
for _, policy := range []string{ifExistsSkip, ifExistsSmart, ifExistsOverwrite} {
if err := printDrivePullDryRunWithLocalInfo(policy, remote, []string{"a.txt"}, nil, map[string]os.FileInfo{"a.txt": info}); err != nil {
t.Fatalf("policy %s: %v", policy, err)
}
}
if err := printDrivePullDryRunWithLocalInfo(ifExistsSkip, remote, []string{"missing.txt"}, nil, nil); err != nil {
t.Fatal(err)
}
}
func TestCrossPlatformCoverageDrivePullRejectNonRegular(t *testing.T) {
if err := rejectNonRegularLocalTarget(filepath.Join(t.TempDir(), "missing")); err != nil {
t.Fatal(err)
}
dir := t.TempDir()
if err := rejectNonRegularLocalTarget(dir); err == nil {
t.Fatal("expected directory rejection")
}
testseam.Swap(t, &pullTargetLstat, func(string) (os.FileInfo, error) { return nil, errTestDownload })
if err := rejectNonRegularLocalTarget("target"); err == nil {
t.Fatal("expected lstat failure")
}
}