@@ -6,11 +6,14 @@ import (
66 "io"
77 "net/http"
88 "net/http/httptest"
9+ "sync/atomic"
910 "testing"
1011 "time"
1112
1213 "github.com/jmhodges/clock"
14+ "github.com/letsencrypt/boulder/metrics"
1315 "github.com/letsencrypt/boulder/test"
16+ "github.com/prometheus/client_golang/prometheus"
1417)
1518
1619func defaultTokenHandler (w http.ResponseWriter , r * http.Request ) {
@@ -44,7 +47,7 @@ func TestSendContactSuccess(t *testing.T) {
4447 defer contactSrv .Close ()
4548
4649 clk := clock .NewFake ()
47- client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
50+ client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
4851 test .AssertNotError (t , err , "failed to create client" )
4952
5053 err = client .
SendContact (
"[email protected] " )
@@ -70,7 +73,7 @@ func TestSendContactUpdateTokenFails(t *testing.T) {
7073 defer contactSrv .Close ()
7174
7275 clk := clock .NewFake ()
73- client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
76+ client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
7477 test .AssertNotError (t , err , "Failed to create client" )
7578
7679 err = client .
SendContact (
"[email protected] " )
@@ -94,7 +97,7 @@ func TestSendContact4xx(t *testing.T) {
9497 defer contactSrv .Close ()
9598
9699 clk := clock .NewFake ()
97- client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
100+ client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
98101 test .AssertNotError (t , err , "Failed to create client" )
99102
100103 err = client .
SendContact (
"[email protected] " )
@@ -142,7 +145,7 @@ func TestSendContactTokenExpiry(t *testing.T) {
142145 defer contactSrv .Close ()
143146
144147 clk := clock .NewFake ()
145- client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
148+ client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
146149 test .AssertNotError (t , err , "Failed to create client" )
147150
148151 // First call uses the initial token ("old_token").
@@ -172,7 +175,7 @@ func TestSendContactServerErrorsAfterMaxAttempts(t *testing.T) {
172175 contactSrv := httptest .NewServer (http .HandlerFunc (contactHandler ))
173176 defer contactSrv .Close ()
174177
175- client , _ := NewPardotClientImpl (clock .NewFake (), "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
178+ client , _ := NewPardotClientImpl (clock .NewFake (), "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
176179
177180 err := client .
SendContact (
"[email protected] " )
178181 test .AssertError (t , err , "Should fail after retrying all attempts" )
@@ -200,11 +203,38 @@ func TestSendContactRedactsEmail(t *testing.T) {
200203 defer contactSrv .Close ()
201204
202205 clk := clock .NewFake ()
203- client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL )
206+ client , err := NewPardotClientImpl (clk , "biz-unit" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , nil )
204207 test .AssertNotError (t , err , "failed to create client" )
205208
206209 err = client .SendContact (emailToTest )
207210 test .AssertError (t , err , "SendContact should fail" )
208211 test .AssertNotContains (t , err .Error (), emailToTest )
209212 test .AssertContains (t , err .Error (), "[REDACTED]" )
210213}
214+
215+ func TestSendContactDeduplication (t * testing.T ) {
216+ t .Parallel ()
217+
218+ tokenSrv := httptest .NewServer (http .HandlerFunc (defaultTokenHandler ))
219+ defer tokenSrv .Close ()
220+
221+ var contactHits int32
222+ contactSrv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
223+ atomic .AddInt32 (& contactHits , 1 )
224+ w .WriteHeader (http .StatusOK )
225+ }))
226+ defer contactSrv .Close ()
227+
228+ cache := NewHashedEmailCache (1000 , metrics .NoopRegisterer )
229+ client , _ := NewPardotClientImpl (clock .New (), "biz" , "cid" , "csec" , tokenSrv .URL , contactSrv .URL , cache )
230+
231+ err := client .
SendContact (
"[email protected] " )
232+ test .AssertNotError (t , err , "SendContact should succeed on first call" )
233+ test .AssertMetricWithLabelsEquals (t , client .emailCache .requests , prometheus.Labels {"status" : "miss" }, 1 )
234+
235+ err = client .
SendContact (
"[email protected] " )
236+ test .AssertNotError (t , err , "SendContact should succeed on second call" )
237+
238+ test .AssertEquals (t , int32 (1 ), atomic .LoadInt32 (& contactHits ))
239+ test .AssertMetricWithLabelsEquals (t , client .emailCache .requests , prometheus.Labels {"status" : "hit" }, 1 )
240+ }
0 commit comments