diff --git a/lintcmd/cache/prog.go b/lintcmd/cache/prog.go index 3c134cbb..a080abfd 100644 --- a/lintcmd/cache/prog.go +++ b/lintcmd/cache/prog.go @@ -226,7 +226,7 @@ func (c *ProgCache) writeToChild(req *cacheprog.Request, resc chan<- *cacheprog. return err } if err := e.Close(); err != nil { - return nil + return err } if wrote != req.BodySize { return fmt.Errorf("short write writing body to GOCACHEPROG for action %x, output %x: wrote %v; expected %v", diff --git a/lintcmd/cache/prog_test.go b/lintcmd/cache/prog_test.go new file mode 100644 index 00000000..0f150f3e --- /dev/null +++ b/lintcmd/cache/prog_test.go @@ -0,0 +1,54 @@ +package cache + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "strings" + "testing" + + "honnef.co/go/tools/lintcmd/cache/cacheprog" +) + +var errTestWriter = errors.New("test writer failed") + +type failingWriter struct{} + +func (failingWriter) Write([]byte) (int, error) { return 0, errTestWriter } + +func TestWriteToChildReturnsBase64CloseError(t *testing.T) { + const groups = 1000 + bodySize := groups*3 + 1 // The base64 encoder buffers a final padded group. + body := strings.Repeat("x", bodySize) + req := &cacheprog.Request{ + ID: 1, + Command: cacheprog.CmdPut, + ActionID: []byte{1}, + OutputID: []byte{2}, + BodySize: int64(bodySize), + } + var header bytes.Buffer + if err := json.NewEncoder(&header).Encode(req); err != nil { + t.Fatal(err) + } + // Leave three bytes available after the request header and the unpadded + // base64 body, so the final padded group makes the buffer flush and fail + // from Encoder.Close. + bufferSize := header.Len() + 2 + groups*4 + 3 + pc := &ProgCache{ + inFlight: map[int64]chan<- *cacheprog.Response{}, + bw: bufio.NewWriterSize(failingWriter{}, bufferSize), + } + pc.jenc = json.NewEncoder(pc.bw) + got := pc.writeToChild(&cacheprog.Request{ + Command: cacheprog.CmdPut, + ActionID: []byte{1}, + OutputID: []byte{2}, + Body: strings.NewReader(body), + BodySize: int64(bodySize), + }, make(chan *cacheprog.Response, 1)) + if !errors.Is(got, errTestWriter) { + t.Fatalf("writeToChild error = %v, want %v", got, errTestWriter) + } +}