package app import ( "bytes" "context" "encoding/json" "errors" "io" "net/http" "net/http/httptest" "path/filepath" "strings" "testing" "time" "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/apiclient" authpkg "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/auth" "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/pkg/mcptypes" "github.com/spf13/cobra" ) func appRPCServer(t *testing.T, initOK, listOK bool) *httptest.Server { t.Helper() return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var req struct { ID int `json:"id"` Method string `json:"method"` } _ = json.NewDecoder(r.Body).Decode(&req) w.Header().Set("Content-Type", "application/json") switch req.Method { case "initialize": if !initOK { _ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "id": req.ID, "error": map[string]any{"code": -32601, "message": "init"}}) return } _ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "id": req.ID, "result": map[string]any{"protocolVersion": "2025-03-26"}}) case "tools/list": if !listOK { _ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "id": req.ID, "error": map[string]any{"code": -1, "message": "list"}}) return } _ = json.NewEncoder(w).Encode(map[string]any{ "jsonrpc": "2.0", "id": req.ID, "result": map[string]any{ "tools": []any{map[string]any{ "name": "tool", "description": "desc", "inputSchema": map[string]any{ "properties": map[string]any{"id": map[string]any{"type": "string"}}, "required": []any{"id", 1, ""}, }, }}, }, }) default: _ = json.NewEncoder(w).Encode(map[string]any{"jsonrpc": "2.0", "id": req.ID, "result": map[string]any{}}) } })) } func TestCrossPlatformCoveragePluginAuthCoverage(t *testing.T) { fallback := pluginAuthFromServerDescriptor(mcptypes.ServerDescriptor{Key: "fallback", Endpoint: "%", AuthHeaders: map[string]string{"Authorization": "token"}}) if fallback == nil || fallback.Token != "token" || len(fallback.TrustedDomains) != 0 { t.Fatalf("fallback plugin auth = %#v", fallback) } got := pluginAuthFromServerDescriptor(mcptypes.ServerDescriptor{Key: "server", Endpoint: "https://x.test", CLI: mcptypes.CLIOverlay{ID: "cli"}, AuthHeaders: map[string]string{"Authorization": "Bearer token", "X": "Y"}}) if got == nil || got.Token != "token" || got.ExtraHeaders["X"] != "Y" || len(got.TrustedDomains) != 2 { t.Fatalf("plugin auth = %#v", got) } if anonymous := pluginAuthFromServerDescriptor(mcptypes.ServerDescriptor{Key: "none"}); anonymous == nil || anonymous.Token != "" { t.Fatalf("anonymous plugin ownership = %#v", anonymous) } } func TestCrossPlatformCoverageRawAPIAndTokenCoverage(t *testing.T) { oldProvider := newAccessTokenProvider oldManager := newLegacyTokenManager t.Cleanup(func() { newAccessTokenProvider = oldProvider newLegacyTokenManager = oldManager }) cmd := &cobra.Command{Use: "api"} var out, errOut bytes.Buffer cmd.SetOut(&out) cmd.SetErr(&errOut) cmd.SetContext(context.Background()) invalid := []struct { args []string gf GlobalFlags af apiFlags }{ {[]string{"GET", "/x?a=1"}, GlobalFlags{}, apiFlags{}}, {[]string{"TRACE", "/x"}, GlobalFlags{}, apiFlags{}}, {[]string{"GET", "../x"}, GlobalFlags{}, apiFlags{}}, {[]string{"GET", "/x"}, GlobalFlags{}, apiFlags{params: "x\x00"}}, {[]string{"POST", "/x"}, GlobalFlags{}, apiFlags{data: "x\x00"}}, {[]string{"POST", "/x"}, GlobalFlags{}, apiFlags{params: "-", data: "-"}}, {[]string{"GET", "/x"}, GlobalFlags{Output: "x"}, apiFlags{pageAll: true}}, {[]string{"GET", "/x"}, GlobalFlags{}, apiFlags{params: "{"}}, {[]string{"POST", "/x"}, GlobalFlags{}, apiFlags{data: "{"}}, {[]string{"GET", "https://evil.test/x"}, GlobalFlags{Token: "t"}, apiFlags{}}, } for _, tc := range invalid { if err := runAPI(cmd, tc.args, &tc.gf, &tc.af); err == nil { t.Fatalf("invalid API %#v succeeded", tc) } } for _, raw := range []string{"", "a=1&empty=&=x", "a=1&b=2"} { if got := parseQueryStringToJSON(raw); got == "" { t.Fatalf("query JSON %q empty", raw) } } if got, err := resolveRawAPIToken(context.Background(), " token "); err != nil || got != "token" { t.Fatalf("explicit raw token = %q, %v", got, err) } authpkg.SetClientID("") authpkg.SetClientSecret("") if _, err := resolveRawAPIToken(context.Background(), ""); err == nil { t.Fatal("missing app credentials succeeded") } server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") if strings.Contains(r.URL.Path, "fail") { w.WriteHeader(http.StatusInternalServerError) _, _ = io.WriteString(w, `{"error":"bad"}`) return } _ = json.NewEncoder(w).Encode(map[string]any{"items": []any{1}, "hasMore": false}) })) defer server.Close() host := strings.TrimPrefix(server.URL, "http://") host = strings.Split(host, ":")[0] apiclient.AllowedHosts[host] = true t.Cleanup(func() { delete(apiclient.AllowedHosts, host) }) gf := &GlobalFlags{Token: "token", DryRun: true, Format: "json", Timeout: 1} af := &apiFlags{baseURL: server.URL} if err := runAPI(cmd, []string{"GET", "/ok"}, gf, af); err != nil || out.Len() == 0 { t.Fatalf("API dry run = %q, %v", out.String(), err) } out.Reset() gf.DryRun = false if err := runAPI(cmd, []string{"GET", "/ok"}, gf, af); err != nil || out.Len() == 0 { t.Fatalf("API request = %q, %v", out.String(), err) } out.Reset() af.pageAll = true if err := runAPI(cmd, []string{"GET", "/ok"}, gf, af); err != nil || out.Len() == 0 { t.Fatalf("API pagination = %q, %v", out.String(), err) } client := apiclient.NewClient("token", server.URL) if err := runPaginated(context.Background(), client, apiclient.RawAPIRequest{Method: "GET", Path: "/fail"}, &apiFlags{}, apiclient.ResponseOptions{Out: io.Discard, ErrOut: io.Discard}); err == nil { t.Fatal("failed pagination succeeded") } if _, err := ResolveAuxiliaryAccessToken(context.Background(), "", ""); err == nil { t.Fatal("empty auxiliary config succeeded") } if got, err := ResolveAuxiliaryAccessToken(context.Background(), "ignored", " explicit "); err != nil || got != "explicit" { t.Fatalf("explicit auxiliary token = %q, %v", got, err) } dir := t.TempDir() newAccessTokenProvider = func(string) accessTokenGetter { return fakeAccessTokenGetter{token: "saved"} } newLegacyTokenManager = func(string) legacyTokenGetter { return fakeLegacyTokenGetter{} } if got, err := resolveAccessTokenFromDir(context.Background(), dir); err != nil || got != "saved" { t.Fatalf("saved access token = %q, %v", got, err) } newAccessTokenProvider = func(string) accessTokenGetter { return fakeAccessTokenGetter{} } missing := t.TempDir() if got, err := resolveAccessTokenFromDir(context.Background(), missing); got != "" || !errors.Is(err, authpkg.ErrTokenDataNotFound) { t.Fatalf("missing access token = %q, %v", got, err) } if _, err := ResolveAuxiliaryAccessToken(context.Background(), missing, ""); err == nil { t.Fatal("missing auxiliary credentials succeeded") } if _, err := ForceRefreshAccessToken(context.Background(), ""); err == nil { t.Fatal("empty force refresh config succeeded") } if _, err := ForceRefreshAccessToken(context.Background(), missing); err == nil { t.Fatal("missing force refresh token succeeded") } } func TestCrossPlatformCoverageRootUtilityAndTimingCoverage(t *testing.T) { _ = resolveVerbosity(nil) for _, flags := range []struct { debug bool verbose bool format string json bool }{{}, {verbose: true}, {debug: true}, {format: "json"}, {format: "table"}, {json: true}} { flagCmd := &cobra.Command{Use: "flags"} flagCmd.Flags().Bool("debug", flags.debug, "") flagCmd.Flags().Bool("verbose", flags.verbose, "") flagCmd.Flags().String("format", flags.format, "") flagCmd.Flags().Bool("json", false, "") if flags.json { _ = flagCmd.Flags().Set("json", "true") } _ = resolveVerbosity(flagCmd) _ = commandRequestsJSONErrors(flagCmd) _ = wantsJSONErrors(flagCmd) } _ = commandRequestsJSONErrors(nil) _ = wantsJSONErrors(nil) if got, changed := normalizeProfileFlagArgs([]string{"--profile", "a,", "b"}); !changed || len(got) == 0 { t.Fatalf("profile args = %#v, %v", got, changed) } if _, changed := normalizeProfileFlagArgs([]string{"--profile"}); changed { t.Fatal("incomplete profile flag changed") } if preparseProfileFlag([]string{"--profile=a"}) != "a" || preparseProfileFlag([]string{"--profile", "b"}) != "b" || preparseProfileFlag(nil) != "" { t.Fatal("profile preparse mismatch") } if !argsChanged([]string{"a"}, []string{"b"}) || argsChanged([]string{"a"}, []string{"a"}) { t.Fatal("argsChanged mismatch") } cmd := &cobra.Command{Use: "root"} cmd.SetContext(context.Background()) cmd.Flags().String("output", "", "") if err := configureOutputSink(cmd); err != nil { t.Fatal(err) } path := filepath.Join(t.TempDir(), "nested", "out.txt") _ = cmd.Flags().Set("output", path) if err := configureOutputSink(cmd); err != nil { t.Fatal(err) } _, _ = io.WriteString(cmd.OutOrStdout(), "data") if err := closeOutputSink(cmd); err != nil { t.Fatal(err) } local := &cobra.Command{Use: "local"} local.SetContext(context.Background()) local.SetOut(io.Discard) local.Flags().String("output", "", "") if err := configureOutputSink(local); err != nil { t.Fatal(err) } if err := validateOptionalPath("--x", ""); err != nil { t.Fatal(err) } if err := validateOptionalPath("--x", "bad\x00path"); err == nil { t.Fatal("unsafe path succeeded") } root := &cobra.Command{Use: "root", Short: "root"} bindPersistentFlags(root, &GlobalFlags{}) root.AddCommand(&cobra.Command{Use: "alpha", Short: "alpha"}, &cobra.Command{Use: "hidden", Hidden: true}) configureRootHelp(root) var help bytes.Buffer root.SetOut(&help) _ = root.Help() renderRootGlobalFlags(root) _ = visiblePersistentFlags(root) for _, command := range root.Commands() { _ = commandShort(command) } _ = visibleMCPRootCommands(root) _ = visibleUtilityRootCommands(root) tc := NewTimingCollector() tc.Record("a", time.Microsecond) tc.Record("b", 2*time.Second) for _, d := range []time.Duration{time.Nanosecond, time.Microsecond, time.Millisecond, time.Second} { _ = formatDuration(d) } for _, debug := range []bool{false, true} { if debug { t.Setenv(PerfDebugEnv, "1") } else { t.Setenv(PerfDebugEnv, "") } tc.PrintIfEnabled() } var timingOut bytes.Buffer tc.Print(&timingOut) if timingOut.Len() == 0 { t.Fatal("timing output empty") } t.Setenv("HOME", t.TempDir()) if defaultPerfReportPath() == "" { t.Fatal("default perf path empty") } t.Setenv(PerfReportEnv, "auto") tc.WriteReportIfEnabled("v", "cmd") if _, err := LoadLatestReport(); err != nil { t.Fatal(err) } t.Setenv(PerfReportEnv, "") tc.WriteReportIfEnabled("v", "cmd") _ = exeRelativeConfigDir() merged := mergeTopLevelCommands([]*cobra.Command{{Use: "a"}, {Use: "a"}, {Use: "b"}, nil}) if len(merged) != 2 { t.Fatalf("merged commands = %#v", merged) } dedupRoot := &cobra.Command{Use: "root"} dedupRoot.AddCommand(&cobra.Command{Use: "same"}, &cobra.Command{Use: "same"}) deduplicateCommands(dedupRoot) addPluginCommandsSafe(dedupRoot, []*cobra.Command{{Use: "same"}, {Use: "new"}}) _ = newCompletionCommand(dedupRoot) _ = newCatalogCommand() _ = newConfigCommand() _ = newCacheCommand() _ = newVersionCommand() _ = newAPICommand(&GlobalFlags{}) _ = NewRootCommand(context.Background()) }