1 package sa
2
3 import (
4 "context"
5 "fmt"
6 "testing"
7 "time"
8
9 sapb "github.com/letsencrypt/boulder/sa/proto"
10 "github.com/letsencrypt/boulder/test"
11 "google.golang.org/protobuf/types/known/timestamppb"
12 )
13
14 func TestCertsPerNameRateLimitTable(t *testing.T) {
15 ctx := context.Background()
16
17 sa, _, cleanUp := initSA(t)
18 defer cleanUp()
19
20 aprilFirst, err := time.Parse(time.RFC3339, "2019-04-01T00:00:00Z")
21 if err != nil {
22 t.Fatal(err)
23 }
24
25 type inputCase struct {
26 time time.Time
27 names []string
28 }
29 inputs := []inputCase{
30 {aprilFirst, []string{"example.com"}},
31 {aprilFirst, []string{"example.com", "www.example.com"}},
32 {aprilFirst, []string{"example.com", "other.example.com"}},
33 {aprilFirst, []string{"dyndns.org"}},
34 {aprilFirst, []string{"mydomain.dyndns.org"}},
35 {aprilFirst, []string{"mydomain.dyndns.org"}},
36 {aprilFirst, []string{"otherdomain.dyndns.org"}},
37 }
38
39
40
41 var manyNames []string
42 for i := 0; i < 7*24; i++ {
43 manyNames = append(manyNames, fmt.Sprintf("%d.manynames.example.net", i))
44 inputs = append(inputs, inputCase{aprilFirst.Add(time.Duration(i) * time.Hour), manyNames})
45 }
46
47 for _, input := range inputs {
48 tx, err := sa.dbMap.BeginTx(ctx)
49 if err != nil {
50 t.Fatal(err)
51 }
52 err = sa.addCertificatesPerName(ctx, tx, input.names, input.time)
53 if err != nil {
54 t.Fatal(err)
55 }
56 err = tx.Commit()
57 if err != nil {
58 t.Fatal(err)
59 }
60 }
61
62 const aWeek = time.Duration(7*24) * time.Hour
63
64 testCases := []struct {
65 caseName string
66 domainName string
67 expected int64
68 }{
69 {"name doesn't exist", "non.example.org", 0},
70 {"base name gets dinged for all certs including it", "example.com", 3},
71 {"subdomain gets dinged for neighbors", "www.example.com", 3},
72 {"other subdomain", "other.example.com", 3},
73 {"many subdomains", "1.manynames.example.net", 168},
74 {"public suffix gets its own bucket", "dyndns.org", 1},
75 {"subdomain of public suffix gets its own bucket", "mydomain.dyndns.org", 2},
76 {"subdomain of public suffix gets its own bucket 2", "otherdomain.dyndns.org", 1},
77 }
78
79 for _, tc := range testCases {
80 t.Run(tc.caseName, func(t *testing.T) {
81 timeRange := &sapb.Range{
82 EarliestNS: aprilFirst.Add(-1 * time.Second).UnixNano(),
83 Earliest: timestamppb.New(aprilFirst.Add(-1 * time.Second)),
84 LatestNS: aprilFirst.Add(aWeek).UnixNano(),
85 Latest: timestamppb.New(aprilFirst.Add(aWeek)),
86 }
87 count, earliest, err := sa.countCertificatesByName(ctx, sa.dbMap, tc.domainName, timeRange)
88 if err != nil {
89 t.Fatal(err)
90 }
91 if count != tc.expected {
92 t.Errorf("Expected count of %d for %q, got %d", tc.expected, tc.domainName, count)
93 }
94 if earliest.IsZero() {
95
96 test.AssertEquals(t, count, int64(0))
97 } else {
98 test.AssertEquals(t, earliest, aprilFirst)
99 }
100 })
101 }
102 }
103
104 func TestNewOrdersRateLimitTable(t *testing.T) {
105 sa, _, cleanUp := initSA(t)
106 defer cleanUp()
107
108 manyCountRegID := int64(2)
109 start := time.Now().Truncate(time.Minute)
110 req := &sapb.CountOrdersRequest{
111 AccountID: 1,
112 Range: &sapb.Range{
113 EarliestNS: start.UnixNano(),
114 Earliest: timestamppb.New(start),
115 LatestNS: start.Add(time.Minute * 10).UnixNano(),
116 Latest: timestamppb.New(start.Add(time.Minute * 10)),
117 },
118 }
119
120 for i := 0; i <= 10; i++ {
121 tx, err := sa.dbMap.BeginTx(ctx)
122 test.AssertNotError(t, err, "failed to open tx")
123 for j := 0; j < i+1; j++ {
124 err = addNewOrdersRateLimit(ctx, tx, manyCountRegID, start.Add(time.Minute*time.Duration(i)))
125 }
126 test.AssertNotError(t, err, "addNewOrdersRateLimit failed")
127 test.AssertNotError(t, tx.Commit(), "failed to commit tx")
128 }
129
130 count, err := countNewOrders(ctx, sa.dbMap, req)
131 test.AssertNotError(t, err, "countNewOrders failed")
132 test.AssertEquals(t, count.Count, int64(0))
133
134 req.AccountID = manyCountRegID
135 count, err = countNewOrders(ctx, sa.dbMap, req)
136 test.AssertNotError(t, err, "countNewOrders failed")
137 test.AssertEquals(t, count.Count, int64(65))
138
139 req.Range.EarliestNS = start.Add(time.Minute * 5).UnixNano()
140 req.Range.LatestNS = start.Add(time.Minute * 10).UnixNano()
141 count, err = countNewOrders(ctx, sa.dbMap, req)
142 test.AssertNotError(t, err, "countNewOrders failed")
143 test.AssertEquals(t, count.Count, int64(45))
144 }
145
View as plain text