Read the upload fake under a lock, since the print runs in the background and the test read it meanwhile: a data race under -race (issue 1598)
This commit is contained in:
@@ -6,12 +6,14 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// uploadFake stands for node-files.upload on another machine: it records the ask and answers a key, or refuses.
|
||||
type uploadFake struct {
|
||||
mu sync.Mutex
|
||||
calls []string
|
||||
key string
|
||||
err error
|
||||
@@ -19,11 +21,20 @@ type uploadFake struct {
|
||||
|
||||
// withUpload puts a fake node-files in the tool side's place, and the bucket file the mesh writes from the binding
|
||||
// (files/bucket.json) where the tool reads it.
|
||||
// seen is the uploads asked so far, read under the fake's lock (the print runs in the background).
|
||||
func (f *uploadFake) seen() []string {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return append([]string(nil), f.calls...)
|
||||
}
|
||||
|
||||
func withUpload(t *testing.T, key string, err error) *uploadFake {
|
||||
t.Helper()
|
||||
f := &uploadFake{key: key, err: err}
|
||||
old := uploadVia
|
||||
uploadVia = func(node, path, bucket string) (string, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.calls = append(f.calls, node+"|"+path+"|"+bucket)
|
||||
return f.key, f.err
|
||||
}
|
||||
@@ -66,8 +77,8 @@ func TestPrintTakesExactlyOneSource(t *testing.T) {
|
||||
t.Errorf("%s: the refusal does not name the rule: %v", name, err)
|
||||
}
|
||||
}
|
||||
if r.bus.asks() != 0 || len(up.calls) != 0 || fake.body != nil {
|
||||
t.Errorf("%d asks queued, %d uploads asked, printer sent %d bytes", r.bus.asks(), len(up.calls), len(fake.body))
|
||||
if r.bus.asks() != 0 || len(up.seen()) != 0 || fake.body != nil {
|
||||
t.Errorf("%d asks queued, %d uploads asked, printer sent %d bytes", r.bus.asks(), len(up.seen()), len(fake.body))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,8 +95,8 @@ func TestPrintOfAFileOfAnotherMachineUploadsThenPrintsTheKey(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(up.calls) != 1 || up.calls[0] != "g14|/home/ops/letter.pdf|brother-test" {
|
||||
t.Fatalf("uploads asked: %v", up.calls)
|
||||
if len(up.seen()) != 1 || up.seen()[0] != "g14|/home/ops/letter.pdf|brother-test" {
|
||||
t.Fatalf("uploads asked: %v", up.seen())
|
||||
}
|
||||
if len(r.bus.published) != 1 {
|
||||
t.Fatalf("%d asks queued", len(r.bus.published))
|
||||
@@ -120,8 +131,8 @@ func TestARefusedUploadIsAnsweredWithItsReasonAndNothingIsPrinted(t *testing.T)
|
||||
if err == nil || !strings.Contains(err.Error(), "is refused by name: it is in .ssh") {
|
||||
t.Fatalf("error = %v", err)
|
||||
}
|
||||
if len(up.calls) != 1 || r.bus.asks() != 0 || fake.body != nil {
|
||||
t.Errorf("%d uploads, %d asks queued, printer sent %d bytes", len(up.calls), r.bus.asks(), len(fake.body))
|
||||
if len(up.seen()) != 1 || r.bus.asks() != 0 || fake.body != nil {
|
||||
t.Errorf("%d uploads, %d asks queued, printer sent %d bytes", len(up.seen()), r.bus.asks(), len(fake.body))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +283,7 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) {
|
||||
}
|
||||
m := got.(map[string]any)
|
||||
id, _ := m["ask"].(string)
|
||||
if m["state"] != "started" || id == "" || len(up.calls) > 1 {
|
||||
if m["state"] != "started" || id == "" || len(up.seen()) > 1 {
|
||||
t.Fatalf("answer %v", m)
|
||||
}
|
||||
for deadline := time.Now().Add(5 * time.Second); ; {
|
||||
@@ -290,8 +301,8 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) {
|
||||
t.Fatal("never done")
|
||||
}
|
||||
}
|
||||
if len(up.calls) != 1 || len(r.bus.published) != 1 || r.bus.published[0].Object != key {
|
||||
t.Errorf("uploads %v, asks %v", up.calls, r.bus.published)
|
||||
if len(up.seen()) != 1 || len(r.bus.published) != 1 || r.bus.published[0].Object != key {
|
||||
t.Errorf("uploads %v, asks %v", up.seen(), r.bus.published)
|
||||
}
|
||||
// An upload that fails after the call answered is the outcome, read with the ask.
|
||||
uploadVia = func(node, path, bucket string) (string, error) {
|
||||
|
||||
Reference in New Issue
Block a user