Skip to content

Commit ad1e0e7

Browse files
committed
mbox: add unit tests and patchwork signature
Add unit tests for the Format and SanitizeFilename functions covering headers, body structure, postscript handling, comment tag extraction, list From replacement and mbox envelope framing. Append a signature block (-- \npatchwork $version) after the diff when no signature is already present. Always insert a --- separator before the diff even when there is no postscript section. Remove the CRLF normalization hack since go-mbox canonicalizes line endings in both directions: the Writer normalizes to LF for storage, the Reader normalizes to CRLF for parsing. Signed-off-by: Robin Jarry <robin@jarry.cc>
1 parent 9a6532d commit ad1e0e7

3 files changed

Lines changed: 56 additions & 14 deletions

File tree

‎cmd/pw/http/main.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/getpatchwork/patchwork/pkg/db/migrations"
2121
"github.com/getpatchwork/patchwork/pkg/events"
2222
"github.com/getpatchwork/patchwork/pkg/log"
23+
"github.com/getpatchwork/patchwork/pkg/mbox"
2324
"github.com/getpatchwork/patchwork/pkg/web"
2425
)
2526

@@ -37,6 +38,8 @@ func (c *CLI) Run(ctx *pw.Context) error {
3738
bus := events.Start(ctx, ctx.DB)
3839
defer bus.Shutdown()
3940

41+
mbox.Version = ctx.Version
42+
4043
router := web.NewRouter(ctx.Config, ctx.DB, bus, ctx.Version)
4144
router.Mount("/", api.NewRouter(ctx.Config, ctx.DB, ctx.Config.Http.BaseURL, bus))
4245

‎pkg/mbox/mbox.go‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"bufio"
1010
"bytes"
1111
"context"
12-
"fmt"
1312
"regexp"
1413
"strconv"
1514
"strings"
@@ -24,9 +23,12 @@ import (
2423
"github.com/getpatchwork/patchwork/pkg/log"
2524
)
2625

26+
var Version string
27+
2728
var (
2829
postscriptRe = regexp.MustCompile(`(?m)^-{2,3} ?$`)
2930
mboxResponseRe = regexp.MustCompile(`(?mi)^(Tested|Reviewed|Acked|Signed-off|Nacked|Reported)-by:.*$`)
31+
signatureRe = regexp.MustCompile(`(?m)^-- $`)
3032
safeFilenameRe = regexp.MustCompile(`[^a-z0-9_.-]+`)
3133
)
3234

@@ -111,10 +113,11 @@ func Format(sub Submission) []byte {
111113
body += "\n" + sub.Diff
112114
}
113115

114-
sc := bufio.NewScanner(strings.NewReader(body))
115-
for sc.Scan() {
116-
fmt.Fprintf(w, "%s\r\n", sc.Text())
116+
if Version != "" && !signatureRe.MatchString(body) {
117+
body += "-- \npatchwork " + Version + "\n"
117118
}
119+
120+
_, _ = w.Write([]byte(body))
118121
mw.Close()
119122

120123
return buf.Bytes()

‎pkg/mbox/mbox_test.go‎

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,13 @@ func TestFormatBasicPatch(t *testing.T) {
9696
}
9797
}
9898

99-
func TestFormatCRLF(t *testing.T) {
99+
func TestFormatParseable(t *testing.T) {
100100
sub := baseSubmission()
101101
out := Format(sub)
102102

103-
_, body := parseMbox(t, out)
104-
for i, line := range strings.Split(body, "\n") {
105-
if line == "" {
106-
continue
107-
}
108-
if !strings.HasSuffix(line, "\r") {
109-
t.Errorf("line %d not CRLF terminated: %q", i+1, line)
110-
break
111-
}
103+
mr := gombox.NewReader(bytes.NewReader(out))
104+
if _, err := mr.NextMessage(); err != nil {
105+
t.Errorf("output not parseable as mbox: %v", err)
112106
}
113107
}
114108

@@ -244,6 +238,48 @@ func TestFormatMboxEnvelope(t *testing.T) {
244238
}
245239
}
246240

241+
func TestFormatSignature(t *testing.T) {
242+
Version = "4.0.0"
243+
defer func() { Version = "" }()
244+
245+
sub := baseSubmission()
246+
out := Format(sub)
247+
248+
_, body := parseMbox(t, out)
249+
body = strings.ReplaceAll(body, "\r\n", "\n")
250+
if !strings.Contains(body, "-- \npatchwork 4.0.0\n") {
251+
t.Errorf("body missing signature, got:\n%q", body)
252+
}
253+
}
254+
255+
func TestFormatNoSignatureWhenPresent(t *testing.T) {
256+
Version = "4.0.0"
257+
defer func() { Version = "" }()
258+
259+
sub := baseSubmission()
260+
sub.Diff = "diff --git a/f b/f\n-- \nsome tool 1.0\n"
261+
out := Format(sub)
262+
263+
_, body := parseMbox(t, out)
264+
body = strings.ReplaceAll(body, "\r\n", "\n")
265+
if strings.Contains(body, "patchwork 4.0.0") {
266+
t.Error("should not add signature when one already exists")
267+
}
268+
}
269+
270+
func TestFormatNoSignatureWhenVersionEmpty(t *testing.T) {
271+
Version = ""
272+
273+
sub := baseSubmission()
274+
out := Format(sub)
275+
276+
_, body := parseMbox(t, out)
277+
body = strings.ReplaceAll(body, "\r\n", "\n")
278+
if strings.Contains(body, "-- \n") {
279+
t.Error("should not add signature when Version is empty")
280+
}
281+
}
282+
247283
func TestSanitizeFilename(t *testing.T) {
248284
tests := []struct {
249285
input string

0 commit comments

Comments
 (0)