Files
dingtalk-workspace-cli/internal/helpers/drive_coverage_more_test.go

361 lines
15 KiB
Go

package helpers
import (
"bytes"
"context"
"errors"
"io"
"os"
"path/filepath"
"strings"
"testing"
"github.com/spf13/cobra"
)
func executeDriveEdge(t *testing.T, caller *scriptedToolCaller, args ...string) error {
t.Helper()
oldDeps := deps
oldArgs := os.Args
InitDeps(caller)
deps.Out.w = io.Discard
deps.Out.errW = io.Discard
t.Cleanup(func() {
deps = oldDeps
os.Args = oldArgs
})
root := newDriveCommand()
installExampleGlobalFlags(root)
root.SilenceErrors = true
root.SilenceUsage = true
root.SetOut(io.Discard)
root.SetErr(io.Discard)
root.SetArgs(args)
os.Args = append([]string{"dws", "drive"}, args...)
return root.Execute()
}
func TestCrossPlatformCoverageParseDriveUploadInfoRemainingCoverage(t *testing.T) {
cases := []struct {
name string
json string
err bool
}{
{"resource array", `{"result":{"uploadId":"u","resourceUrls":[{"url":"https://upload.invalid","headers":{"X-Test":"yes","skip":1}}]}}`, false},
{"flat resource and headers", `{"uploadId":"u","resourceUrl":"https://upload.invalid","headers":{"X-Test":"yes","skip":1}}`, false},
{"upload URL fallback", `{"uploadId":"u","uploadUrl":"https://upload.invalid"}`, false},
{"non-map first URL", `{"uploadId":"u","resourceUrls":[1]}`, true},
{"missing upload id", `{"resourceUrl":"https://upload.invalid"}`, true},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
url, id, headers, err := parseDriveUploadInfo(tc.json)
if (err != nil) != tc.err {
t.Fatalf("parse error=%v, wantErr=%v", err, tc.err)
}
if !tc.err && (url == "" || id == "" || headers == nil) {
t.Fatalf("parse result url=%q id=%q headers=%v", url, id, headers)
}
})
}
}
func TestCrossPlatformCoverageDriveUploadValidationAndDryRunCoverage(t *testing.T) {
file := filepath.Join(t.TempDir(), "fixture.txt")
if err := os.WriteFile(file, []byte("fixture"), 0o600); err != nil {
t.Fatal(err)
}
cases := []struct {
name string
args []string
err bool
}{
{"missing file", []string{"upload"}, true},
{"unreadable file", []string{"upload", "--file", file + ".missing"}, true},
{"directory", []string{"upload", "--file", t.TempDir()}, true},
{"numeric drive folder", []string{"upload", "--file", file, "--folder", "123"}, true},
{"drive dry run", []string{"upload", "--file", file, "--file-name", "named.txt", "--dry-run"}, false},
{"numeric doc folder", []string{"upload", "--file", file, "--workspace", "space", "--folder", "123"}, true},
{"doc dry run extension", []string{"upload", "--file", file, "--file-name", "named", "--workspace", "space", "--dry-run"}, false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
err := executeDriveEdge(t, &scriptedToolCaller{dry: strings.Contains(strings.Join(tc.args, " "), "--dry-run")}, tc.args...)
if (err != nil) != tc.err {
t.Fatalf("Execute(%v) error=%v, wantErr=%v", tc.args, err, tc.err)
}
})
}
}
func TestCrossPlatformCoverageDriveUploadTransportCoverage(t *testing.T) {
file := filepath.Join(t.TempDir(), "fixture.txt")
if err := os.WriteFile(file, []byte("fixture"), 0o600); err != nil {
t.Fatal(err)
}
boom := errors.New("boom")
t.Run("drive credentials error", func(t *testing.T) {
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{err: boom}}}, "upload", "--file", file); !errors.Is(err, boom) {
t.Fatalf("error=%v", err)
}
})
t.Run("drive credentials parse error", func(t *testing.T) {
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: `{}`}}}, "upload", "--file", file); err == nil {
t.Fatal("parse error returned nil")
}
})
t.Run("drive put error", func(t *testing.T) {
old := httpPutFile
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return boom }
t.Cleanup(func() { httpPutFile = old })
payload := `{"uploadId":"u","resourceUrl":"https://upload.invalid"}`
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: payload}}}, "upload", "--file", file); !errors.Is(err, boom) {
t.Fatalf("error=%v", err)
}
})
t.Run("drive commit", func(t *testing.T) {
old := httpPutFile
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return nil }
t.Cleanup(func() { httpPutFile = old })
payload := `{"uploadId":"u","resourceUrl":"https://upload.invalid"}`
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: payload}, {text: `{}`}}}, "upload", "--file", file, "--space-id", "space", "--folder", "uuid"); err != nil {
t.Fatalf("error=%v", err)
}
})
docArgs := []string{"upload", "--file", file, "--workspace", "space", "--folder", "uuid", "--convert"}
t.Run("doc credentials error", func(t *testing.T) {
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{err: boom}}}, docArgs...); !errors.Is(err, boom) {
t.Fatalf("error=%v", err)
}
})
t.Run("doc credentials parse error", func(t *testing.T) {
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: `{}`}}}, docArgs...); err == nil {
t.Fatal("parse error returned nil")
}
})
t.Run("doc put error", func(t *testing.T) {
old := httpPutFile
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return boom }
t.Cleanup(func() { httpPutFile = old })
payload := `{"resourceUrl":"https://upload.invalid","uploadKey":"key"}`
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: payload}}}, docArgs...); !errors.Is(err, boom) {
t.Fatalf("error=%v", err)
}
})
t.Run("doc commit", func(t *testing.T) {
old := httpPutFile
httpPutFile = func(context.Context, string, map[string]string, string, int64) error { return nil }
t.Cleanup(func() { httpPutFile = old })
payload := `{"resourceUrl":"https://upload.invalid","uploadKey":"key"}`
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: payload}, {text: `{}`}}}, docArgs...); err != nil {
t.Fatalf("error=%v", err)
}
})
}
func TestCrossPlatformCoverageUploadDriveFileDataStrictTransaction(t *testing.T) {
credential := `{"result":{"uploadType":"httpToCenterWithToken","resourceUrl":"https://c.example.com/u?upload_key=u1","uploadId":"u1","headers":{"dentry-token":"token"}}}`
request := DriveUploadRequest{FilePath: "fixture.bin", FileName: "fixture.bin", FileSize: 7, SpaceID: "space", ParentID: "folder", MIMEType: "application/octet-stream"}
t.Run("success with parent", func(t *testing.T) {
caller := &scriptedToolCaller{steps: []scriptedToolStep{{text: credential}, {text: `{"success":true,"result":{"fileId":"n1"}}`}}}
installScriptedCaller(t, caller)
SetHTTPPutFile(func(context.Context, string, map[string]string, string, int64) error { return nil })
t.Cleanup(func() { SetHTTPPutFile(nil) })
result, err := UploadDriveFileData(context.Background(), request)
if err != nil || result["success"] != true || caller.calls != 2 {
t.Fatalf("result=%v calls=%d error=%v", result, caller.calls, err)
}
if caller.args["spaceId"] != "space" || caller.args["parentId"] != "folder" {
t.Fatalf("commit args=%v", caller.args)
}
})
t.Run("success with overwrite", func(t *testing.T) {
caller := &scriptedToolCaller{steps: []scriptedToolStep{{text: credential}, {text: `{"success":true}`}}}
installScriptedCaller(t, caller)
SetHTTPPutFile(func(context.Context, string, map[string]string, string, int64) error { return nil })
t.Cleanup(func() { SetHTTPPutFile(nil) })
overwrite := request
overwrite.ParentID = "ignored"
overwrite.OverwriteFile = "existing"
if _, err := UploadDriveFileData(context.Background(), overwrite); err != nil {
t.Fatal(err)
}
if caller.args["overwriteFileId"] != "existing" {
t.Fatalf("commit args=%v", caller.args)
}
})
t.Run("credential refresh callback", func(t *testing.T) {
caller := &scriptedToolCaller{steps: []scriptedToolStep{{text: credential}, {text: credential}, {text: `{"success":true}`}}}
installScriptedCaller(t, caller)
putCalls := 0
SetHTTPPutFile(func(context.Context, string, map[string]string, string, int64) error {
putCalls++
if putCalls == 1 {
return &httpStatusError{StatusCode: 401, Body: "expired"}
}
return nil
})
t.Cleanup(func() { SetHTTPPutFile(nil) })
if _, err := UploadDriveFileData(context.Background(), request); err != nil {
t.Fatal(err)
}
if caller.calls != 3 || putCalls != 2 {
t.Fatalf("caller calls=%d put calls=%d", caller.calls, putCalls)
}
})
for _, tc := range []struct {
name string
request DriveUploadRequest
steps []scriptedToolStep
putErr error
want string
}{
{name: "invalid request", request: DriveUploadRequest{}, want: "invalid drive upload request"},
{name: "credential failure", request: request, steps: []scriptedToolStep{{err: errors.New("credentials")}}, want: "credentials"},
{name: "put failure", request: request, steps: []scriptedToolStep{{text: credential}}, putErr: errors.New("put failed"), want: "put failed"},
{name: "commit failure", request: request, steps: []scriptedToolStep{{text: credential}, {err: errors.New("commit failed")}}, want: "commit failed"},
{name: "empty commit", request: request, steps: []scriptedToolStep{{text: credential}, {text: " "}}, want: "no business result"},
{name: "malformed commit", request: request, steps: []scriptedToolStep{{text: credential}, {text: "{"}}, want: "parse commit_upload response"},
{name: "empty object commit", request: request, steps: []scriptedToolStep{{text: credential}, {text: `{}`}}, want: "empty JSON object"},
} {
t.Run(tc.name, func(t *testing.T) {
caller := &scriptedToolCaller{steps: tc.steps}
installScriptedCaller(t, caller)
SetHTTPPutFile(func(context.Context, string, map[string]string, string, int64) error { return tc.putErr })
t.Cleanup(func() { SetHTTPPutFile(nil) })
_, err := UploadDriveFileData(context.Background(), tc.request)
if err == nil || !strings.Contains(err.Error(), tc.want) {
t.Fatalf("error=%v, want %q", err, tc.want)
}
})
}
}
func TestCrossPlatformCoverageDriveCommandRemainingEdges(t *testing.T) {
file := filepath.Join(t.TempDir(), "fixture.txt")
_ = os.WriteFile(file, []byte("fixture"), 0o600)
cases := [][]string{
{"list", "--workspace", "space", "--folder", "123"},
{"mkdir", "--name", "folder", "--folder", "123"},
{"upload-info", "--file-name", "x", "--file-size", "1", "--folder", "123"},
{"commit", "--file-name", "x", "--file-size", "1", "--upload-id", "u", "--folder", "123"},
{"copy", "--node", "node", "--folder", "123"},
{"move", "--node", "node", "--folder", "123"},
}
for _, args := range cases {
if err := executeDriveEdge(t, &scriptedToolCaller{}, args...); err == nil {
t.Fatalf("Execute(%v) returned nil", args)
}
}
if err := executeDriveEdge(t, &scriptedToolCaller{dry: true}, "download", "--node", "node", "--output", file, "--dry-run"); err != nil {
t.Fatalf("dry download: %v", err)
}
}
func TestCrossPlatformCoverageDriveDownloadDirectoryCoverage(t *testing.T) {
oldGet := httpGetFile
httpGetFile = func(context.Context, string, map[string]string, string) error { return nil }
t.Cleanup(func() { httpGetFile = oldGet })
dir := t.TempDir()
for _, payload := range []string{
`{"resourceUrl":"https://download.invalid/path/from-url.txt","fileName":""}`,
`{"resourceUrl":"https://download.invalid/path/from-url.txt","fileName":"folder/name.txt"}`,
} {
if err := executeDriveEdge(t, &scriptedToolCaller{steps: []scriptedToolStep{{text: payload}}}, "download", "--node", "node", "--output", dir); err != nil {
t.Fatalf("download: %v", err)
}
}
}
func TestCrossPlatformCoverageDriveConfirmationCancellationCoverage(t *testing.T) {
oldStdin := os.Stdin
t.Cleanup(func() { os.Stdin = oldStdin })
for _, test := range []struct {
args []string
wantObservableCancel bool
}{
{args: []string{"delete", "--node", "node"}, wantObservableCancel: true},
{args: []string{"publish", "set", "--node", "node"}},
{args: []string{"publish", "unset", "--node", "node"}},
} {
file, err := os.CreateTemp(t.TempDir(), "stdin")
if err != nil {
t.Fatal(err)
}
if _, err := file.WriteString("no\n"); err != nil {
t.Fatal(err)
}
_, _ = file.Seek(0, 0)
os.Stdin = file
err = executeDriveEdge(t, &scriptedToolCaller{}, test.args...)
if err == nil || !strings.Contains(err.Error(), "用户取消了操作") {
t.Fatalf("cancel %v = %v, want 用户取消了操作", test.args, err)
}
_ = file.Close()
}
}
func TestCrossPlatformCoverageDriveInfoDocFallbackCoverage(t *testing.T) {
oldArgs := os.Args
os.Args = []string{"dws", "drive", "info"}
t.Cleanup(func() { os.Args = oldArgs })
boom := errors.New("boom")
cases := []struct {
name string
steps []scriptedToolStep
err bool
}{
{"drive error", []scriptedToolStep{{err: boom}}, true},
{"invalid drive JSON", []scriptedToolStep{{text: `{`}}, false},
{"no result", []scriptedToolStep{{text: `{}`}}, false},
{"ordinary file", []scriptedToolStep{{text: `{"result":{"extension":"pdf"}}`}}, false},
{"doc lookup error", []scriptedToolStep{{text: `{"result":{"message":"钉钉文档","fileId":""}}`}, {err: boom}}, false},
{"invalid doc JSON", []scriptedToolStep{{text: `{"result":{"extension":"adoc","fileId":"node"}}`}, {text: `{`}}, false},
{"empty flat doc", []scriptedToolStep{{text: `{"result":{"extension":"axls","fileId":"node"}}`}, {text: `{}`}}, false},
{"flat doc merge", []scriptedToolStep{{text: `{"result":{"extension":"amind","fileId":"node","path":"/drive","fileSize":3,"type":"doc"}}`}, {text: `{"title":"Doc","path":"existing"}`}}, false},
{"wrapped doc", []scriptedToolStep{{text: `{"result":{"extension":"adraw","fileId":"node","dentryId":"d"}}`}, {text: `{"result":{"title":"Doc"}}`}}, false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
caller := &scriptedToolCaller{steps: tc.steps}
old := deps
InitDeps(caller)
deps.Out.w = &bytes.Buffer{}
deps.Out.errW = io.Discard
t.Cleanup(func() { deps = old })
err := driveInfoWithDocFallback("fallback-node", map[string]any{"fileId": "fallback-node"})
if (err != nil) != tc.err {
t.Fatalf("error=%v, wantErr=%v", err, tc.err)
}
})
}
}
func TestCrossPlatformCoverageDriveSmallHelperEdges(t *testing.T) {
for _, ext := range []string{"adoc", "AXLS", "amind", "adraw", "pdf"} {
_ = isDingTalkDocExtension(ext)
}
cmd := &cobra.Command{Use: "upload"}
cmd.Flags().String("file", "", "")
cmd.Flags().String("file-name", "", "")
cmd.Flags().String("name", "", "")
cmd.Flags().String("workspace", "", "")
cmd.Flags().String("workspace-id", "", "")
cmd.Flags().String("folder", "", "")
cmd.Flags().String("parent-id", "", "")
cmd.Flags().String("space-id", "", "")
cmd.Flags().String("mime-type", "", "")
cmd.Flags().Bool("convert", false, "")
if err := cmd.Flags().Set("file", t.TempDir()); err != nil {
t.Fatal(err)
}
if err := runDriveUpload(cmd, nil); err == nil {
t.Fatal("directory upload returned nil")
}
}