...

Source file src/github.com/letsencrypt/boulder/sa/rate_limits_test.go

Documentation: github.com/letsencrypt/boulder/sa

     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  	// For each hour in a week, add an entry for a certificate that has
    40  	// progressively more names.
    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  				// The count should always be zero if earliest is nil.
    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