| index 1de0d74de..6ea48fdab 100644 |
| --- a/deploy_test.go |
| +++ b/deploy_test.go |
| @@ -221,7 +221,7 @@ func TestWatchVersionSucceedsWhenHeaderMatches(t *testing.T) { |
| go func() { time.Sleep(30 * time.Millisecond); mu.Lock(); ver = "new5678"; mu.Unlock() }() |
| var out bytes.Buffer |
| err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 2*time.Second, 10*time.Millisecond) |
| + 2*time.Second, 10*time.Millisecond, nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| @@ -237,7 +237,7 @@ func TestWatchVersionTimeoutDiagnostics(t *testing.T) { |
| defer srv.Close() |
| var out bytes.Buffer |
| err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 50*time.Millisecond, 10*time.Millisecond) |
| + 50*time.Millisecond, 10*time.Millisecond, nil) |
| if err == nil { |
| t.Fatal("must time out") |
| } |
| @@ -259,7 +259,7 @@ func TestWatchVersionMatchingHeaderNon2xxNotLive(t *testing.T) { |
| defer srv.Close() |
| var out bytes.Buffer |
| err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 50*time.Millisecond, 10*time.Millisecond) |
| + 50*time.Millisecond, 10*time.Millisecond, nil) |
| if err == nil { |
| t.Fatal("a 502 carrying the new version header must NOT be reported live") |
| } |
| @@ -279,7 +279,7 @@ func TestWatchVersionNoHeaderDiagnostic(t *testing.T) { |
| defer srv.Close() |
| var out bytes.Buffer |
| err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 50*time.Millisecond, 10*time.Millisecond) |
| + 50*time.Millisecond, 10*time.Millisecond, nil) |
| if err == nil || !strings.Contains(err.Error(), "no X-Carlos-Version") { |
| t.Fatalf("old-edge diagnostic: %v", err) |
| } |
| @@ -298,7 +298,7 @@ func TestWatchVersionNonOKNoHeaderDiagnostic(t *testing.T) { |
| })) |
| var out bytes.Buffer |
| err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 50*time.Millisecond, 10*time.Millisecond) |
| + 50*time.Millisecond, 10*time.Millisecond, nil) |
| srv.Close() |
| if err == nil { |
| t.Fatalf("HTTP %d: must time out", code) |
| @@ -350,7 +350,7 @@ func TestWatchVersionSweepsTargetsConcurrently(t *testing.T) { |
| targets[i] = watchTarget{Host: fmt.Sprintf("h%d.test", i), Origin: s.URL} |
| } |
| var out bytes.Buffer |
| - err := watchVersion(&out, targets, "new5678", 5*time.Second, 10*time.Millisecond) |
| + err := watchVersion(&out, targets, "new5678", 5*time.Second, 10*time.Millisecond, nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| @@ -382,7 +382,7 @@ func TestWatchVersionCacheBustsEveryPoll(t *testing.T) { |
| defer srv.Close() |
| var out bytes.Buffer |
| _ = watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| - 35*time.Millisecond, 10*time.Millisecond) |
| + 35*time.Millisecond, 10*time.Millisecond, nil) |
| |
| mu.Lock() |
| defer mu.Unlock() |
| @@ -423,3 +423,47 @@ func TestDeployingLine(t *testing.T) { |
| } |
| } |
| } |
| + |
| +// TestWatchVersionTimeoutCarriesWakeReasonAndLogsHint (issue #131's tail): |
| +// the timeout report used to end with a hint that could not help — the wake |
| +// reason was journal-only and the suggested command was the box-local form. |
| +// With diagnostics wired, the report carries the host's last platform-stream |
| +// error and names the command that shows the whole timeline. |
| +func TestWatchVersionTimeoutCarriesWakeReasonAndLogsHint(t *testing.T) { |
| + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| + w.WriteHeader(http.StatusServiceUnavailable) |
| + })) |
| + defer srv.Close() |
| + var out bytes.Buffer |
| + var asked []string |
| + diag := &watchDiagnostics{ |
| + wakeReason: func(host string) string { |
| + asked = append(asked, host) |
| + return "wake failed: nothing is promoted for this instance's channel" |
| + }, |
| + logsHint: "carlos logs -app lpay -account bde -stream platform", |
| + } |
| + err := watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| + 50*time.Millisecond, 10*time.Millisecond, diag) |
| + if err == nil { |
| + t.Fatal("watch should have timed out") |
| + } |
| + for _, want := range []string{ |
| + "wake failed: nothing is promoted", |
| + "full timeline: carlos logs -app lpay -account bde -stream platform", |
| + } { |
| + if !strings.Contains(err.Error(), want) { |
| + t.Fatalf("timeout report missing %q:\n%v", want, err) |
| + } |
| + } |
| + if len(asked) != 1 || asked[0] != "x.test" { |
| + t.Fatalf("wakeReason asked for %v, want the one pending host", asked) |
| + } |
| + // A reason lookup that finds nothing adds nothing — no empty line. |
| + diag.wakeReason = func(string) string { return "" } |
| + err = watchVersion(&out, []watchTarget{{Host: "x.test", Origin: srv.URL}}, "new5678", |
| + 50*time.Millisecond, 10*time.Millisecond, diag) |
| + if err == nil || strings.Contains(err.Error(), "\n \n") { |
| + t.Fatalf("empty reason printed a blank line: %v", err) |
| + } |
| +} |