Files
wehub-resource-sync bf9395e022
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

173 lines
5.5 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package drive
import (
"context"
"fmt"
"strings"
"testing"
"time"
clie2e "github.com/larksuite/cli/tests/cli_e2e"
"github.com/tidwall/gjson"
)
const (
driveDeleteVisibilityTimeout = 30 * time.Second
driveDeleteVisibilityPoll = 3 * time.Second
)
var driveDeleteVisibilityWait = clie2e.WaitOptions{
// This wait only covers the post-delete visibility lag after Drive accepts
// deletion. The delete command itself is bounded by clie2e.CleanupContext.
Timeout: driveDeleteVisibilityTimeout,
Interval: driveDeleteVisibilityPoll,
}
// CreateDriveFolder creates a Drive folder, optionally under a parent folder, and
// deletes it during parent cleanup.
func CreateDriveFolder(t *testing.T, parentT *testing.T, ctx context.Context, name string, defaultAs string, parentFolderToken string) string {
t.Helper()
if defaultAs == "" {
defaultAs = "bot"
}
args := []string{"drive", "+create-folder", "--name", name}
if parentFolderToken != "" {
args = append(args, "--folder-token", parentFolderToken)
}
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: args,
DefaultAs: defaultAs,
})
if err != nil {
t.Fatalf("create drive folder %q: %v", name, err)
}
result.AssertExitCode(t, 0)
result.AssertStdoutStatus(t, true)
folderToken := gjson.Get(result.Stdout, "data.folder_token").String()
if folderToken == "" {
t.Fatalf("drive folder token should not be empty, stdout:\n%s", result.Stdout)
}
parentT.Cleanup(func() {
cleanupCtx, cancel := clie2e.CleanupContext()
defer cancel()
deleteResult, deleteErr := DeleteDriveResourceAndVerify(cleanupCtx, folderToken, "folder", defaultAs)
clie2e.ReportCleanupFailure(parentT, "delete drive folder "+folderToken, deleteResult, deleteErr)
})
return folderToken
}
// DeleteDriveResourceAndVerify deletes a Drive-backed resource, then polls
// drive meta until the token is either gone or no longer has an accessible URL.
// This prevents cleanup from looking successful when the delete command
// returned a suppressed not_found or partial API error but the resource still
// exists.
func DeleteDriveResourceAndVerify(ctx context.Context, token, docType, defaultAs string) (*clie2e.Result, error) {
return deleteDriveResourceAndVerify(ctx, token, docType, defaultAs, driveDeleteVisibilityWait)
}
func deleteDriveResourceAndVerify(ctx context.Context, token, docType, defaultAs string, visibilityWait clie2e.WaitOptions) (*clie2e.Result, error) {
if defaultAs == "" {
defaultAs = "bot"
}
deleteResult, deleteErr := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{"drive", "+delete", "--file-token", token, "--type", docType, "--yes"},
DefaultAs: defaultAs,
})
if deleteErr != nil || deleteResult == nil {
return deleteResult, deleteErr
}
if deleteResult.ExitCode != 0 {
deleted, verifyErr := IsDriveResourceDeleted(ctx, token, docType, defaultAs)
if verifyErr != nil {
return deleteResult, verifyErr
}
if deleted {
deleteResult.ExitCode = 0
return deleteResult, nil
}
return deleteResult, fmt.Errorf("drive resource %s/%s still exists after delete failed: exit=%d stdout=%s stderr=%s", docType, token, deleteResult.ExitCode, deleteResult.Stdout, deleteResult.Stderr)
}
if err := waitDriveResourceDeleted(ctx, token, docType, defaultAs, visibilityWait); err != nil {
return deleteResult, clie2e.CleanupWarning(
fmt.Errorf("drive resource %s/%s still visible after accepted delete: %w", docType, token, err),
)
}
return deleteResult, nil
}
func waitDriveResourceDeleted(ctx context.Context, token, docType, defaultAs string, opts clie2e.WaitOptions) error {
opts.TimeoutError = func() error {
return fmt.Errorf("drive resource %s/%s still exists %s after delete", docType, token, opts.Timeout)
}
return clie2e.WaitForCondition(ctx, opts, func() (bool, error) {
return IsDriveResourceDeleted(ctx, token, docType, defaultAs)
})
}
func IsDriveResourceDeleted(ctx context.Context, token, docType, defaultAs string) (bool, error) {
if defaultAs == "" {
defaultAs = "bot"
}
result, err := clie2e.RunCmd(ctx, clie2e.Request{
Args: []string{"api", "post", "/open-apis/drive/v1/metas/batch_query"},
DefaultAs: defaultAs,
Data: map[string]any{
"request_docs": []map[string]any{{
"doc_token": token,
"doc_type": docType,
}},
},
})
if err != nil {
return false, err
}
if result.ExitCode != 0 {
combined := strings.ToLower(result.Stdout + "\n" + result.Stderr)
if strings.Contains(combined, "not found") || strings.Contains(combined, "404") {
return true, nil
}
return false, fmt.Errorf("verify drive resource %s/%s after delete: exit=%d stdout=%s stderr=%s", docType, token, result.ExitCode, result.Stdout, result.Stderr)
}
if !isDriveMetaQuerySuccessful(result.Stdout) {
return false, fmt.Errorf("verify drive resource %s/%s after delete returned unsuccessful envelope: stdout=%s stderr=%s", docType, token, result.Stdout, result.Stderr)
}
metas := gjson.Get(result.Stdout, "data.metas").Array()
if len(metas) == 0 {
return true, nil
}
if docType != "folder" {
allURLsCleared := true
for _, meta := range metas {
if meta.Get("url").String() != "" {
allURLsCleared = false
break
}
}
if allURLsCleared {
return true, nil
}
}
return false, nil
}
func isDriveMetaQuerySuccessful(stdout string) bool {
if ok := gjson.Get(stdout, "ok"); ok.Exists() {
return ok.Bool()
}
if code := gjson.Get(stdout, "code"); code.Exists() {
return code.Int() == 0
}
return false
}