mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 07:45:30 +00:00
fix(script): keep the task name in the script snapshot; wait for the full env output in tests (#1568)
This commit is contained in:
@@ -27,6 +27,10 @@ type ScriptData struct {
|
||||
// ScriptPayload contains the task data
|
||||
type ScriptPayload struct {
|
||||
Task *Task
|
||||
// TaskName is computed before Task is cloned. The clone has no fetcher
|
||||
// manager, so for an unresolved task without Options.Name its Name()
|
||||
// would return "unknown".
|
||||
TaskName string
|
||||
}
|
||||
|
||||
// getScriptPaths extracts script paths from config
|
||||
@@ -103,7 +107,7 @@ func (d *Downloader) executeScriptAtPath(scriptPath string, data *ScriptData) er
|
||||
cmd.Env = append(os.Environ(),
|
||||
fmt.Sprintf("GOPEED_EVENT=%s", data.Event),
|
||||
fmt.Sprintf("GOPEED_TASK_ID=%s", data.Payload.Task.ID),
|
||||
fmt.Sprintf("GOPEED_TASK_NAME=%s", data.Payload.Task.Name()),
|
||||
fmt.Sprintf("GOPEED_TASK_NAME=%s", data.Payload.TaskName),
|
||||
fmt.Sprintf("GOPEED_TASK_STATUS=%s", data.Payload.Task.Status),
|
||||
)
|
||||
|
||||
@@ -138,6 +142,7 @@ func (d *Downloader) triggerScripts(event ScriptEvent, task *Task, err error) {
|
||||
Time: time.Now().UnixMilli(),
|
||||
Payload: &ScriptPayload{
|
||||
Task: task.clone(),
|
||||
TaskName: task.Name(),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package download
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -126,6 +128,46 @@ func TestScript_ExecuteScriptAtPath_NonExistentFile(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestScript_TaskNameOfUnresolvedTask(t *testing.T) {
|
||||
scriptPath := getTestScriptPath(t, envDumpScriptName())
|
||||
ensureScriptExecutable(t, scriptPath)
|
||||
outputFile := filepath.Join(t.TempDir(), "env_output.txt")
|
||||
|
||||
setupScriptTest(t, func(downloader *Downloader) {
|
||||
cfg, _ := downloader.GetConfig()
|
||||
cfg.Script = &base.ScriptConfig{
|
||||
Enable: true,
|
||||
Paths: []string{scriptPath},
|
||||
}
|
||||
downloader.PutConfig(cfg)
|
||||
|
||||
// Without Options.Name and a resource, the name comes from the fetcher
|
||||
// manager, which the cloned task in the script data does not have.
|
||||
url := "http://127.0.0.1/error.bin"
|
||||
fm, err := downloader.parseFm(url)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
task := NewTask()
|
||||
task.Meta = &fetcher.FetcherMeta{
|
||||
Req: &base.Request{URL: url},
|
||||
Opts: &base.Options{Path: t.TempDir()},
|
||||
}
|
||||
task.fetcherManager = fm
|
||||
if name := task.Name(); name != "error.bin" {
|
||||
t.Fatalf("Expected task name error.bin, got %q", name)
|
||||
}
|
||||
|
||||
t.Setenv("GOPEED_TEST_OUTPUT_FILE", outputFile)
|
||||
downloader.triggerScripts(ScriptEventDownloadDone, task, nil)
|
||||
|
||||
output := waitForFileContains(t, outputFile, "GOPEED_TASK_PATH=", 3*time.Second)
|
||||
if !strings.Contains(output, "GOPEED_TASK_NAME=error.bin") {
|
||||
t.Errorf("Expected GOPEED_TASK_NAME=error.bin in output, got: %s", output)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func createDownloadDoneTask(t *testing.T, downloadDir, fileName string) (*Task, string) {
|
||||
t.Helper()
|
||||
content := []byte("downloaded file")
|
||||
@@ -171,6 +213,31 @@ func waitForFile(t *testing.T, path string, timeout time.Duration) {
|
||||
t.Fatalf("Timeout waiting for file: %s", path)
|
||||
}
|
||||
|
||||
// waitForFileContains waits until the file contains want and returns its content.
|
||||
// Test scripts write the file line by line, so waiting for the file to exist is not enough.
|
||||
func waitForFileContains(t *testing.T, path, want string, timeout time.Duration) string {
|
||||
t.Helper()
|
||||
deadline := time.Now().Add(timeout)
|
||||
for time.Now().Before(deadline) {
|
||||
if content, err := os.ReadFile(path); err == nil && strings.Contains(string(content), want) {
|
||||
return string(content)
|
||||
}
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
content, _ := os.ReadFile(path)
|
||||
t.Fatalf("Timeout waiting for %q in file %s, got: %q", want, path, content)
|
||||
return ""
|
||||
}
|
||||
|
||||
// envDumpScriptName returns the test script that writes the GOPEED_* variables
|
||||
// into the file named by GOPEED_TEST_OUTPUT_FILE.
|
||||
func envDumpScriptName() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return "env_dump.bat"
|
||||
}
|
||||
return "env_dump.sh"
|
||||
}
|
||||
|
||||
func getTestScriptPath(t *testing.T, name string) string {
|
||||
t.Helper()
|
||||
path := filepath.Join("testdata", "scripts", name)
|
||||
|
||||
@@ -91,13 +91,8 @@ func TestScript_EnvironmentVariables(t *testing.T) {
|
||||
t.Setenv("GOPEED_TEST_OUTPUT_FILE", outputFile)
|
||||
downloader.triggerScripts(ScriptEventDownloadDone, task, nil)
|
||||
|
||||
waitForFile(t, outputFile, 3*time.Second)
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
output := string(content)
|
||||
// GOPEED_TASK_PATH is the last line the script writes.
|
||||
output := waitForFileContains(t, outputFile, "GOPEED_TASK_PATH=", 3*time.Second)
|
||||
if !strings.Contains(output, "GOPEED_EVENT=DOWNLOAD_DONE") {
|
||||
t.Errorf("Expected GOPEED_EVENT in output, got: %s", output)
|
||||
}
|
||||
|
||||
@@ -87,13 +87,8 @@ func TestScript_EnvironmentVariables(t *testing.T) {
|
||||
t.Setenv("GOPEED_TEST_OUTPUT_FILE", outputFile)
|
||||
downloader.triggerScripts(ScriptEventDownloadDone, task, nil)
|
||||
|
||||
waitForFile(t, outputFile, 5*time.Second)
|
||||
content, err := os.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read output file: %v", err)
|
||||
}
|
||||
|
||||
output := string(content)
|
||||
// GOPEED_TASK_PATH is the last line the script writes.
|
||||
output := waitForFileContains(t, outputFile, "GOPEED_TASK_PATH=", 5*time.Second)
|
||||
if !strings.Contains(output, "GOPEED_EVENT=DOWNLOAD_DONE") {
|
||||
t.Errorf("Expected GOPEED_EVENT in output, got: %s", output)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user