package rotator import ( "context" "crypto/x509" "errors" "testing" "time" ) type statusResult struct { status activationStatus certificate *x509.Certificate err error } type scriptedActivationClient struct { results []statusResult confirmations int } func (s *scriptedActivationClient) status(context.Context) (activationStatus, *x509.Certificate, error) { if len(s.results) == 0 { return activationStatus{}, nil, errors.New("no scripted status") } result := s.results[0] s.results = s.results[1:] return result.status, result.certificate, result.err } func (s *scriptedActivationClient) confirm(context.Context, string) error { s.confirmations++ return nil } func TestWaitForCandidateRequiresExpectedPeerCertificate(t *testing.T) { oldCertificate := &x509.Certificate{Raw: []byte("old")} newCertificate := &x509.Certificate{Raw: []byte("new")} pending := activationStatus{ Status: "pending", Phase: "activated", Transaction: "0123456789abcdef0123456789abcdef", CandidateRefID: "bbbbbbbbbbbbb", } client := &scriptedActivationClient{results: []statusResult{ {status: pending, certificate: oldCertificate}, {status: pending, certificate: newCertificate}, {status: activationStatus{Status: "idle", RefID: "bbbbbbbbbbbbb"}, certificate: newCertificate}, }} ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() if err := waitForCandidateWithInterval(ctx, client, "bbbbbbbbbbbbb", pending.Transaction, newCertificate.Raw, time.Millisecond); err != nil { t.Fatal(err) } if client.confirmations != 1 { t.Fatalf("unexpected confirmations: %d", client.confirmations) } } func TestWaitForCandidateDoesNotConfirmOldPeerCertificate(t *testing.T) { pending := activationStatus{ Status: "pending", Phase: "activated", Transaction: "0123456789abcdef0123456789abcdef", CandidateRefID: "bbbbbbbbbbbbb", } client := &scriptedActivationClient{results: []statusResult{ {status: pending, certificate: &x509.Certificate{Raw: []byte("old")}}, }} ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond) defer cancel() if err := waitForCandidateWithInterval(ctx, client, "bbbbbbbbbbbbb", pending.Transaction, []byte("new"), time.Millisecond); err == nil { t.Fatal("old peer certificate was accepted") } if client.confirmations != 0 { t.Fatalf("unexpected confirmations: %d", client.confirmations) } }