196 lines
4.7 KiB
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)
|
|
}
|
|
})
|
|
}
|
|
}
|