boulder/cmd/admin/pause_identifier_test.go

196 lines
4.7 KiB
Go

package main
import (
"context"
"errors"
"os"
"path"
"strings"
"testing"
blog "github.com/letsencrypt/boulder/log"
sapb "github.com/letsencrypt/boulder/sa/proto"
"github.com/letsencrypt/boulder/test"
"google.golang.org/grpc"
)
func TestReadingPauseCSV(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
data []string
expectedRecords int
}{
{
name: "No data in file",
data: nil,
},
{
name: "valid",
data: []string{"1,dns,example.com"},
expectedRecords: 1,
},
{
name: "valid with duplicates",
data: []string{"1,dns,example.com", "2,dns,example.org", "1,dns,example.com", "1,dns,example.net", "3,dns,example.gov", "3,dns,example.gov"},
expectedRecords: 6,
},
{
name: "invalid with multiple domains on the same line",
data: []string{"1,dns,example.com,example.net"},
},
{
name: "invalid just commas",
data: []string{",,,"},
},
{
name: "invalid only contains accountID",
data: []string{"1"},
},
{
name: "invalid only contains accountID and identifierType",
data: []string{"1,dns"},
},
{
name: "invalid missing identifierType",
data: []string{"1,,example.com"},
},
{
name: "invalid accountID isnt an int",
data: []string{"blorple"},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
log := blog.NewMock()
a := admin{log: log}
csvFile := path.Join(t.TempDir(), path.Base(t.Name()+".csv"))
err := os.WriteFile(csvFile, []byte(strings.Join(testCase.data, "\n")), os.ModePerm)
test.AssertNotError(t, err, "could not write temporary file")
parsedData, err := a.readPausedAccountFile(csvFile)
test.AssertNotError(t, err, "no error expected, but received one")
test.AssertEquals(t, len(parsedData), testCase.expectedRecords)
})
}
}
// mockSAPaused is a mock which always succeeds. It records the PauseRequest it
// received, and returns the number of identifiers as a
// PauseIdentifiersResponse. It does not maintain state of repaused identifiers.
type mockSAPaused struct {
sapb.StorageAuthorityClient
}
func (msa *mockSAPaused) PauseIdentifiers(ctx context.Context, in *sapb.PauseRequest, _ ...grpc.CallOption) (*sapb.PauseIdentifiersResponse, error) {
return &sapb.PauseIdentifiersResponse{Paused: int64(len(in.Identifiers))}, nil
}
// mockSAPausedBroken is a mock which always errors.
type mockSAPausedBroken struct {
sapb.StorageAuthorityClient
}
func (msa *mockSAPausedBroken) PauseIdentifiers(ctx context.Context, in *sapb.PauseRequest, _ ...grpc.CallOption) (*sapb.PauseIdentifiersResponse, error) {
return nil, errors.New("its all jacked up")
}
func TestPauseIdentifiers(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
data []pauseCSVData
saImpl sapb.StorageAuthorityClient
expectRespLen int
expectErr bool
}{
{
name: "no data",
data: nil,
expectErr: true,
},
{
name: "valid single entry",
data: []pauseCSVData{
{
accountID: 1,
identifierType: "dns",
identifierValue: "example.com",
},
},
expectRespLen: 1,
},
{
name: "valid single entry but broken SA",
expectErr: true,
saImpl: &mockSAPausedBroken{},
data: []pauseCSVData{
{
accountID: 1,
identifierType: "dns",
identifierValue: "example.com",
},
},
},
{
name: "valid multiple entries with duplicates",
data: []pauseCSVData{
{
accountID: 1,
identifierType: "dns",
identifierValue: "example.com",
},
{
accountID: 1,
identifierType: "dns",
identifierValue: "example.com",
},
{
accountID: 2,
identifierType: "dns",
identifierValue: "example.org",
},
{
accountID: 3,
identifierType: "dns",
identifierValue: "example.net",
},
{
accountID: 3,
identifierType: "dns",
identifierValue: "example.org",
},
},
expectRespLen: 3,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()
log := blog.NewMock()
// Default to a working mock SA implementation
if testCase.saImpl == nil {
testCase.saImpl = &mockSAPaused{}
}
a := admin{sac: testCase.saImpl, log: log}
responses, err := a.pauseIdentifiers(context.Background(), testCase.data, 10)
if testCase.expectErr {
test.AssertError(t, err, "should have errored, but did not")
} else {
test.AssertNotError(t, err, "should not have errored")
// Batching will consolidate identifiers under the same account.
test.AssertEquals(t, len(responses), testCase.expectRespLen)
}
})
}
}