Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong response or 404 with XML body matcher and concurrency #1796

Open
benjamin-ratier opened this issue Sep 21, 2023 · 0 comments
Open

Wrong response or 404 with XML body matcher and concurrency #1796

benjamin-ratier opened this issue Sep 21, 2023 · 0 comments

Comments

@benjamin-ratier
Copy link

benjamin-ratier commented Sep 21, 2023

MockServer version

5.15.0

To Reproduce

  • Declare 2 endpoints, with a XML body matcher, and two different bodies/responses
  • Call these endpoints concurrently
  • Sometimes, the correct response is returned for the call. Sometimes, the other response is returned, sometimes we get a 404

Expected behaviour

Always have the expected response.

Other info

It looks like the issue has already been encountered, but without enough info: #901

It only happens with XML body matcher. Other matchers seem OK with concurrency.

Reproduction test

package testing

import (
	"bytes"
	"fmt"
	"net/http"
	"sync"
	"testing"
	"time"

	"github.com/go-resty/resty/v2"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

type RequestMatcher struct {
	Method string      `json:"method,omitempty"`
	Path   string      `json:"path,omitempty"`
	Body   BodyMatcher `json:"body,omitempty"`
}

type BodyMatcher struct {
	Type string `json:"type,omitempty"`
	XML  string `json:"xml,omitempty"`
}

type Expectation struct {
	Request  RequestMatcher `json:"httpRequest,omitempty"`
	Response Response       `json:"httpResponse,omitempty"`
	Priority int32          `json:"priority,omitempty"`
}

type Response struct {
	Body       string              `json:"body,omitempty"`
	Headers    map[string][]string `json:"headers,omitempty"`
	StatusCode int32               `json:"statusCode,omitempty"`
}

func resetExpectations(t *testing.T) {
	t.Helper()

	c := resty.New().SetBaseURL(fmt.Sprintf("http://%s:%d", "mockserver", 46311))
	resp, err := c.NewRequest().
		Put("mockserver/reset")
	assert.NoError(t, err, "")
	assert.Equal(t, http.StatusOK, resp.StatusCode())
}

func createExpectations(t *testing.T) {
	t.Helper()

	c := resty.New().SetBaseURL(fmt.Sprintf("http://%s:%d", "mockserver", 46311))
	c.NewRequest().
		SetDoNotParseResponse(true).
		SetBody(Expectation{
			Request: RequestMatcher{
				Method: "POST",
				Path:   "/Test",
				Body: BodyMatcher{
					Type: "XML",
					XML:  "<a>1</a>",
				},
			},
			Response: Response{
				Body: "<r>1</r>",
			},
		}).Put("/mockserver/expectation")
	c.NewRequest().
		SetDoNotParseResponse(true).
		SetBody(Expectation{
			Request: RequestMatcher{
				Method: "POST",
				Path:   "/Test",
				Body: BodyMatcher{
					Type: "XML",
					XML:  "<a>2</a>",
				},
			},
			Response: Response{
				Body: "<r>2</r>",
			},
		}).Put("/mockserver/expectation")
}

func TestCall(t *testing.T) {
	resetExpectations(t)
	createExpectations(t)

	c := resty.New().SetBaseURL(fmt.Sprintf("http://%s:%d", "mockserver", 46311)).SetDoNotParseResponse(true)

	call := func(source string) {

		resp, err := c.NewRequest().SetBody("<a>1</a>").Post("/Test")
		require.NoError(t, err)

		buf := new(bytes.Buffer)
		buf.ReadFrom(resp.RawResponse.Body)

		assert.Equal(t, "<r>1</r>", buf.String(), source)

		// ===========

		resp, err = c.NewRequest().SetBody("<a>2</a>").Post("/Test")
		require.NoError(t, err)

		buf = new(bytes.Buffer)
		buf.ReadFrom(resp.RawResponse.Body)

		assert.Equal(t, "<r>2</r>", buf.String(), source)
	}

	iterations := 10

	// This loop won't fail
	for i := 0; i < iterations; i++ {
		call("sequential")
	}

	var wg sync.WaitGroup
	wg.Add(iterations)

	// This loop will fail
	for i := 0; i < iterations; i++ {
		time.Sleep(10 * time.Millisecond)

		go func() {
			call("parallel")
			wg.Done()
		}()
	}

	wg.Wait()
}

Result and log file

I joined the Go test output, and the mockserver logs for iterations := 5 (we have a 404 and a confusion)

log.txt
test_output.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant