-
-
Notifications
You must be signed in to change notification settings - Fork 614
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c788db
commit 81aa930
Showing
2 changed files
with
194 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package email | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
"time" | ||
|
||
"github.com/jmhodges/clock" | ||
"github.com/letsencrypt/boulder/test" | ||
) | ||
|
||
func TestCreateProspectSuccess(t *testing.T) { | ||
t.Parallel() | ||
|
||
tokenHandler := func(w http.ResponseWriter, r *http.Request) { | ||
json.NewEncoder(w).Encode(map[string]interface{}{ | ||
"access_token": "dummy", | ||
"expires_in": 3600, | ||
}) | ||
} | ||
|
||
prospectHandler := func(w http.ResponseWriter, r *http.Request) { | ||
if r.Header.Get("Authorization") != "Bearer dummy" { | ||
w.WriteHeader(http.StatusUnauthorized) | ||
return | ||
} | ||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
tokenSrv := httptest.NewServer(http.HandlerFunc(tokenHandler)) | ||
defer tokenSrv.Close() | ||
|
||
prospectSrv := httptest.NewServer(http.HandlerFunc(prospectHandler)) | ||
defer prospectSrv.Close() | ||
|
||
clk := clock.NewFake() | ||
client, err := NewPardotClientImpl(clk, "biz-unit", "cid", "csec", tokenSrv.URL, prospectSrv.URL) | ||
test.AssertNotError(t, err, "failed to create client") | ||
|
||
err = client.CreateProspect("[email protected]") | ||
test.AssertNotError(t, err, "CreateProspect should succeed") | ||
} | ||
|
||
func TestCreateProspectUpdateTokenFails(t *testing.T) { | ||
t.Parallel() | ||
|
||
tokenHandler := func(w http.ResponseWriter, r *http.Request) { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
fmt.Fprintln(w, "token error") | ||
} | ||
|
||
prospectHandler := func(w http.ResponseWriter, r *http.Request) { | ||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
tokenSrv := httptest.NewServer(http.HandlerFunc(tokenHandler)) | ||
defer tokenSrv.Close() | ||
|
||
prospectSrv := httptest.NewServer(http.HandlerFunc(prospectHandler)) | ||
defer prospectSrv.Close() | ||
|
||
clk := clock.NewFake() | ||
client, err := NewPardotClientImpl(clk, "biz-unit", "cid", "csec", tokenSrv.URL, prospectSrv.URL) | ||
test.AssertNotError(t, err, "Failed to create client") | ||
|
||
err = client.CreateProspect("[email protected]") | ||
test.AssertError(t, err, "Expected token update to fail") | ||
test.AssertContains(t, err.Error(), "failed to update token") | ||
} | ||
|
||
func TestCreateProspect4xx(t *testing.T) { | ||
t.Parallel() | ||
|
||
gotToken := false | ||
tokenHandler := func(w http.ResponseWriter, r *http.Request) { | ||
gotToken = true | ||
json.NewEncoder(w).Encode(map[string]interface{}{ | ||
"access_token": "dummy", | ||
"expires_in": 3600, | ||
}) | ||
} | ||
|
||
prospectHandler := func(w http.ResponseWriter, r *http.Request) { | ||
w.WriteHeader(http.StatusBadRequest) | ||
io.WriteString(w, "bad request") | ||
} | ||
|
||
tokenSrv := httptest.NewServer(http.HandlerFunc(tokenHandler)) | ||
defer tokenSrv.Close() | ||
|
||
prospectSrv := httptest.NewServer(http.HandlerFunc(prospectHandler)) | ||
defer prospectSrv.Close() | ||
|
||
clk := clock.NewFake() | ||
client, err := NewPardotClientImpl(clk, "biz-unit", "cid", "csec", tokenSrv.URL, prospectSrv.URL) | ||
test.AssertNotError(t, err, "Failed to create client") | ||
|
||
err = client.CreateProspect("[email protected]") | ||
test.Assert(t, gotToken, "Did not attempt to get token") | ||
test.AssertError(t, err, "Should fail on 400") | ||
test.AssertContains(t, err.Error(), "create prospect request returned status 400") | ||
} | ||
|
||
func TestCreateProspectTokenExpiry(t *testing.T) { | ||
t.Parallel() | ||
|
||
// tokenHandler returns "old_token" on the first call and "new_token" on subsequent calls. | ||
tokenRetrieved := false | ||
tokenHandler := func(w http.ResponseWriter, r *http.Request) { | ||
token := "new_token" | ||
if !tokenRetrieved { | ||
token = "old_token" | ||
tokenRetrieved = true | ||
} | ||
json.NewEncoder(w).Encode(map[string]interface{}{ | ||
"access_token": token, | ||
"expires_in": 3600, | ||
}) | ||
} | ||
|
||
// prospectHandler expects "old_token" for the first request and "new_token" for the next. | ||
firstRequest := true | ||
prospectHandler := func(w http.ResponseWriter, r *http.Request) { | ||
expectedToken := "new_token" | ||
if firstRequest { | ||
expectedToken = "old_token" | ||
firstRequest = false | ||
} | ||
if r.Header.Get("Authorization") != "Bearer "+expectedToken { | ||
w.WriteHeader(http.StatusUnauthorized) | ||
return | ||
} | ||
w.WriteHeader(http.StatusOK) | ||
} | ||
|
||
tokenSrv := httptest.NewServer(http.HandlerFunc(tokenHandler)) | ||
defer tokenSrv.Close() | ||
|
||
prospectSrv := httptest.NewServer(http.HandlerFunc(prospectHandler)) | ||
defer prospectSrv.Close() | ||
|
||
clk := clock.NewFake() | ||
client, err := NewPardotClientImpl(clk, "biz-unit", "cid", "csec", tokenSrv.URL, prospectSrv.URL) | ||
test.AssertNotError(t, err, "Failed to create client") | ||
|
||
// First call uses the initial token ("old_token"). | ||
err = client.CreateProspect("[email protected]") | ||
test.AssertNotError(t, err, "CreateProspect should succeed with the initial token") | ||
|
||
// Advance time to force token expiry. | ||
clk.Add(3601 * time.Second) | ||
|
||
// Second call should refresh the token to "new_token". | ||
err = client.CreateProspect("[email protected]") | ||
test.AssertNotError(t, err, "CreateProspect should succeed after refreshing the token") | ||
} | ||
|
||
func TestCreateProspectServerErrorsAfterMaxAttempts(t *testing.T) { | ||
t.Parallel() | ||
|
||
gotAttempts := 0 | ||
tokenHandler := func(w http.ResponseWriter, r *http.Request) { | ||
json.NewEncoder(w).Encode(map[string]interface{}{ | ||
"access_token": "dummy", | ||
"expires_in": 3600, | ||
}) | ||
} | ||
|
||
prospectHandler := func(w http.ResponseWriter, r *http.Request) { | ||
gotAttempts++ | ||
w.WriteHeader(http.StatusServiceUnavailable) | ||
} | ||
|
||
tokenSrv := httptest.NewServer(http.HandlerFunc(tokenHandler)) | ||
defer tokenSrv.Close() | ||
|
||
prospectSrv := httptest.NewServer(http.HandlerFunc(prospectHandler)) | ||
defer prospectSrv.Close() | ||
|
||
client, _ := NewPardotClientImpl(clock.NewFake(), "biz-unit", "cid", "csec", tokenSrv.URL, prospectSrv.URL) | ||
|
||
err := client.CreateProspect("[email protected]") | ||
test.AssertError(t, err, "Should fail after retrying all attempts") | ||
test.AssertEquals(t, maxAttempts, gotAttempts) | ||
test.AssertContains(t, err.Error(), "create prospect request returned status 503") | ||
} |