1package tlsrpt
2
3import (
4 "reflect"
5 "testing"
6)
7
8func TestRecord(t *testing.T) {
9 good := func(txt string, want Record) {
10 t.Helper()
11 r, _, err := ParseRecord(txt)
12 if err != nil {
13 t.Fatalf("parse: %s", err)
14 }
15 if !reflect.DeepEqual(r, &want) {
16 t.Fatalf("want %v, got %v", want, *r)
17 }
18 }
19
20 bad := func(txt string) {
21 t.Helper()
22 r, _, err := ParseRecord(txt)
23 if err == nil {
24 t.Fatalf("parse, expected error, got record %v", r)
25 }
26 }
27
28 good("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example;", Record{Version: "TLSRPTv1", RUAs: [][]RUA{{"mailto:tlsrpt@mox.example"}}})
29 good("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example , \t\t https://mox.example/tlsrpt ", Record{Version: "TLSRPTv1", RUAs: [][]RUA{{"mailto:tlsrpt@mox.example", "https://mox.example/tlsrpt"}}})
30 good("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example; ext=yes", Record{Version: "TLSRPTv1", RUAs: [][]RUA{{"mailto:tlsrpt@mox.example"}}, Extensions: []Extension{{"ext", "yes"}}})
31 good("v=TLSRPTv1 ; rua=mailto:x@x.example; rua=mailto:y@x.example", Record{Version: "TLSRPTv1", RUAs: [][]RUA{{"mailto:x@x.example"}, {"mailto:y@x.example"}}})
32
33 bad("v=TLSRPTv0")
34 bad("v=TLSRPTv10")
35 bad("v=TLSRPTv2")
36 bad("v=TLSRPTv1") // missing rua
37 bad("v=TLSRPTv1;") // missing rua
38 bad("v=TLSRPTv1; ext=1") // missing rua
39 bad("v=TLSRPTv1; rua=") // empty rua
40 bad("v=TLSRPTv1; rua=noscheme")
41 bad("v=TLSRPTv1; rua=,, ,") // empty uris
42 bad("v=TLSRPTv1; rua=mailto:x@x.example; more=") // empty value in extension
43 bad("v=TLSRPTv1; rua=mailto:x@x.example; a12345678901234567890123456789012=1") // extension name too long
44 bad("v=TLSRPTv1; rua=mailto:x@x.example; 1%=a") // invalid extension name
45 bad("v=TLSRPTv1; rua=mailto:x@x.example; test==") // invalid extension name
46 bad("v=TLSRPTv1; rua=mailto:x@x.example;;") // additional semicolon
47 bad("v=TLSRPTv1; rua=mailto:x@x.example other") // trailing characters.
48 bad("v=TLSRPTv1; rua=http://bad/%") // bad URI
49
50 const want = `v=TLSRPTv1; rua=mailto:x@mox.example; more=a; ext=2`
51 record := Record{Version: "TLSRPTv1", RUAs: [][]RUA{{"mailto:x@mox.example"}}, Extensions: []Extension{{"more", "a"}, {"ext", "2"}}}
52 got := record.String()
53 if got != want {
54 t.Fatalf("record string, got %q, want %q", got, want)
55 }
56}
57
58func FuzzParseRecord(f *testing.F) {
59 f.Add("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example;")
60 f.Add("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example , \t\t https://mox.example/tlsrpt ")
61 f.Add("v=TLSRPTv1; rua=mailto:tlsrpt@mox.example; ext=yes")
62
63 f.Add("v=TLSRPTv0")
64 f.Add("v=TLSRPTv10")
65 f.Add("v=TLSRPTv2")
66 f.Add("v=TLSRPTv1") // missing rua
67 f.Add("v=TLSRPTv1;") // missing rua
68 f.Add("v=TLSRPTv1; ext=1") // missing rua
69 f.Add("v=TLSRPTv1; rua=") // empty rua
70 f.Add("v=TLSRPTv1; rua=noscheme")
71 f.Add("v=TLSRPTv1; rua=,, ,") // empty uris
72 f.Add("v=TLSRPTv1; rua=mailto:x@x.example; more=") // empty value in extension
73 f.Add("v=TLSRPTv1; rua=mailto:x@x.example; a12345678901234567890123456789012=1") // extension name too long
74 f.Add("v=TLSRPTv1; rua=mailto:x@x.example; 1%=a") // invalid extension name
75 f.Add("v=TLSRPTv1; rua=mailto:x@x.example; test==") // invalid extension name
76 f.Add("v=TLSRPTv1; rua=mailto:x@x.example;;") // additional semicolon
77 f.Fuzz(func(t *testing.T, s string) {
78 r, _, err := ParseRecord(s)
79 if err == nil {
80 _ = r.String()
81 }
82 })
83}
84