Skip to content

Commit 9a9fbeb

Browse files
fix: enable adding multiple modifiers to the same interaction (#47)
There was a bug which meant that modifiers based on attempt count would be overwitten because they were stored with the same key in the modifiers map. We fix this by adding the attempt count to the key so that now the keys are different and multiple modifiers can be added for the same interaction based on attempt. Co-authored-by: Andrea Rosa <[email protected]>
1 parent 83a4313 commit 9a9fbeb

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

internal/app/concurrent_proxy_stage_test.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/form3tech-oss/pact-proxy/internal/app/configuration"
14-
"github.com/form3tech-oss/pact-proxy/pkg/pactproxy"
1513
"github.com/pact-foundation/pact-go/dsl"
1614
log "github.com/sirupsen/logrus"
1715
"github.com/stretchr/testify/assert"
16+
17+
"github.com/form3tech-oss/pact-proxy/internal/app/configuration"
18+
"github.com/form3tech-oss/pact-proxy/pkg/pactproxy"
1819
)
1920

2021
const (
@@ -256,6 +257,26 @@ func (s *ConcurrentProxyStage) the_second_user_response_should_have_the_right_st
256257
return s
257258
}
258259

260+
func (s *ConcurrentProxyStage) all_responses_should_have_the_expected_return_values() *ConcurrentProxyStage {
261+
statuses := make(map[int]int)
262+
bodies := make(map[string]int)
263+
for _, res := range s.userResponses {
264+
statuses[res.StatusCode] += 1
265+
bd, err := io.ReadAll(res.Body)
266+
s.assert.NoError(err)
267+
res.Body.Close()
268+
bodies[strings.ReplaceAll(strings.TrimSpace(string(bd)), "\"", "")] += 1
269+
}
270+
s.assert.Len(statuses, 3)
271+
s.assert.Len(bodies, 2)
272+
s.assert.Equal(1, statuses[http.StatusInternalServerError])
273+
s.assert.Equal(1, statuses[http.StatusOK])
274+
s.assert.Equal(1, statuses[http.StatusTeapot])
275+
s.assert.Equal(2, bodies["{name:any}"])
276+
s.assert.Equal(1, bodies["{name:Form3}"])
277+
return s
278+
}
279+
259280
func (s *ConcurrentProxyStage) all_the_address_responses_should_have_the_right_status_code() *ConcurrentProxyStage {
260281
expectedLen := s.concurrentAddressRequestsPerSecond * int(s.concurrentAddressRequestsDuration/time.Second)
261282
s.assert.Len(s.addressResponses, expectedLen, "number of address responses is not as expected")
@@ -280,3 +301,40 @@ func (s *ConcurrentProxyStage) the_proxy_waits_for_all_address_responses() *Conc
280301

281302
return s
282303
}
304+
305+
func (s *ConcurrentProxyStage) the_concurrent_requests_are_sent_with_multiple_modifiers_for_same_interaction() {
306+
err := s.pact.Verify(func() (err error) {
307+
attempt := 1
308+
s.proxy.ForInteraction(postNamePactWithAnyName).AddModifier("$.status", fmt.Sprintf("%d", http.StatusTeapot), &attempt)
309+
attempt = 2
310+
s.proxy.ForInteraction(postNamePactWithAnyName).AddModifier("$.status", fmt.Sprintf("%d", http.StatusInternalServerError), &attempt)
311+
attempt = 3
312+
s.proxy.ForInteraction(postNamePactWithAnyName).AddModifier("$.body.name", "Form3", &attempt)
313+
314+
wg := sync.WaitGroup{}
315+
316+
wg.Add(1)
317+
go func() {
318+
defer wg.Done()
319+
s.makeUserRequest()
320+
}()
321+
322+
wg.Add(1)
323+
go func() {
324+
defer wg.Done()
325+
s.makeUserRequest()
326+
}()
327+
328+
wg.Add(1)
329+
go func() {
330+
defer wg.Done()
331+
s.makeUserRequest()
332+
}()
333+
334+
wg.Wait()
335+
336+
return nil
337+
})
338+
339+
s.assert.NoError(err)
340+
}

internal/app/concurrent_proxy_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@ func TestConcurrentRequestsForSameModifierBasedOnAttempt(t *testing.T) {
3434
the_second_user_response_should_have_the_right_status_code_and_body()
3535
}
3636

37+
func TestMultipleModifiersForSameInteraction(t *testing.T) {
38+
given, when, then := NewConcurrentProxyStage(t)
39+
given.
40+
a_pact_that_allows_any_names()
41+
when.
42+
the_concurrent_requests_are_sent_with_multiple_modifiers_for_same_interaction()
43+
then.
44+
all_responses_should_have_the_expected_return_values()
45+
46+
}
47+
3748
func TestConcurrentRequestsWaitForAllPacts(t *testing.T) {
3849
given, when, then := NewConcurrentProxyStage(t)
3950

internal/app/pactproxy/modifier.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ type interactionModifiers struct {
2222
}
2323

2424
func (im *interactionModifier) Key() string {
25-
return strings.Join([]string{im.Interaction, im.Path}, "_")
25+
var key string
26+
if im.Attempt != nil {
27+
key = strings.Join([]string{im.Interaction, im.Path, strconv.Itoa(*im.Attempt)}, "_")
28+
} else {
29+
key = strings.Join([]string{im.Interaction, im.Path}, "_")
30+
}
31+
return key
2632
}
2733

2834
func (ims *interactionModifiers) AddModifier(modifier *interactionModifier) {

0 commit comments

Comments
 (0)