mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-10-07 21:13:18 +01:00
test(health): assert conversions succeed across a planned restart
This commit is contained in:
@@ -115,6 +115,7 @@ Feature: /health
|
|||||||
| LIBREOFFICE_RESTART_AFTER | 1 |
|
| LIBREOFFICE_RESTART_AFTER | 1 |
|
||||||
When I make 5 sequential "POST" requests to Gotenberg at the "/forms/libreoffice/convert" endpoint, probing "/health" after each, with the following form data and header(s):
|
When I make 5 sequential "POST" requests to Gotenberg at the "/forms/libreoffice/convert" endpoint, probing "/health" after each, with the following form data and header(s):
|
||||||
| files | testdata/page_1.docx | file |
|
| files | testdata/page_1.docx | file |
|
||||||
|
Then all sequential response status codes should be 200
|
||||||
Then all probe response status codes should be 200
|
Then all probe response status codes should be 200
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ type scenario struct {
|
|||||||
resp *httptest.ResponseRecorder
|
resp *httptest.ResponseRecorder
|
||||||
concurrentResps []*httptest.ResponseRecorder
|
concurrentResps []*httptest.ResponseRecorder
|
||||||
probeResps []*httptest.ResponseRecorder
|
probeResps []*httptest.ResponseRecorder
|
||||||
|
sequentialResps []*httptest.ResponseRecorder
|
||||||
workdir string
|
workdir string
|
||||||
teststoreDir string
|
teststoreDir string
|
||||||
gotenbergContainer testcontainers.Container
|
gotenbergContainer testcontainers.Container
|
||||||
@@ -101,6 +102,7 @@ func (s *scenario) reset(ctx context.Context) error {
|
|||||||
s.resp = httptest.NewRecorder()
|
s.resp = httptest.NewRecorder()
|
||||||
s.concurrentResps = nil
|
s.concurrentResps = nil
|
||||||
s.probeResps = nil
|
s.probeResps = nil
|
||||||
|
s.sequentialResps = nil
|
||||||
|
|
||||||
err := os.RemoveAll(s.workdir)
|
err := os.RemoveAll(s.workdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -474,9 +476,10 @@ func (s *scenario) iMakeConcurrentRequestsToGotenberg(ctx context.Context, count
|
|||||||
|
|
||||||
// iMakeSequentialRequestsToGotenbergProbing mirrors the client loop from
|
// iMakeSequentialRequestsToGotenbergProbing mirrors the client loop from
|
||||||
// https://github.com/gotenberg/gotenberg/issues/1648: a conversion, then a
|
// https://github.com/gotenberg/gotenberg/issues/1648: a conversion, then a
|
||||||
// probe, repeated. It records every probe response so a scenario can assert
|
// probe, repeated. It records both the conversion and the probe responses so a
|
||||||
// that a planned process restart never fails the probe. Requests are
|
// scenario can assert that a planned process restart neither fails the probe
|
||||||
// sequential on purpose, since the bug only surfaces between two conversions.
|
// nor breaks the conversions. Requests are sequential on purpose, since the bug
|
||||||
|
// only surfaces between two conversions.
|
||||||
func (s *scenario) iMakeSequentialRequestsToGotenbergProbing(ctx context.Context, count int, method, endpoint, probeEndpoint string, dataTable *godog.Table) error {
|
func (s *scenario) iMakeSequentialRequestsToGotenbergProbing(ctx context.Context, count int, method, endpoint, probeEndpoint string, dataTable *godog.Table) error {
|
||||||
if s.gotenbergContainer == nil {
|
if s.gotenbergContainer == nil {
|
||||||
return errors.New("no Gotenberg container")
|
return errors.New("no Gotenberg container")
|
||||||
@@ -537,6 +540,7 @@ func (s *scenario) iMakeSequentialRequestsToGotenbergProbing(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.probeResps = make([]*httptest.ResponseRecorder, 0, count)
|
s.probeResps = make([]*httptest.ResponseRecorder, 0, count)
|
||||||
|
s.sequentialResps = make([]*httptest.ResponseRecorder, 0, count)
|
||||||
|
|
||||||
for i := range count {
|
for i := range count {
|
||||||
resp, reqErr := doFormDataRequest(method, fmt.Sprintf("%s%s", base, endpoint), fields, files, headers)
|
resp, reqErr := doFormDataRequest(method, fmt.Sprintf("%s%s", base, endpoint), fields, files, headers)
|
||||||
@@ -549,6 +553,7 @@ func (s *scenario) iMakeSequentialRequestsToGotenbergProbing(ctx context.Context
|
|||||||
return fmt.Errorf("request %d: %w", i+1, recErr)
|
return fmt.Errorf("request %d: %w", i+1, recErr)
|
||||||
}
|
}
|
||||||
s.resp = rec
|
s.resp = rec
|
||||||
|
s.sequentialResps = append(s.sequentialResps, rec)
|
||||||
|
|
||||||
probeResp, probeErr := doRequest(http.MethodGet, fmt.Sprintf("%s%s", base, probeEndpoint), nil, nil)
|
probeResp, probeErr := doRequest(http.MethodGet, fmt.Sprintf("%s%s", base, probeEndpoint), nil, nil)
|
||||||
if probeErr != nil {
|
if probeErr != nil {
|
||||||
@@ -579,6 +584,20 @@ func (s *scenario) allProbeResponseStatusCodesShouldBe(expected int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *scenario) allSequentialResponseStatusCodesShouldBe(expected int) error {
|
||||||
|
if len(s.sequentialResps) == 0 {
|
||||||
|
return errors.New("no sequential responses recorded")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, resp := range s.sequentialResps {
|
||||||
|
if resp.Code != expected {
|
||||||
|
return fmt.Errorf("sequential response %d: expected status %d, got %d %q", i+1, expected, resp.Code, resp.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *scenario) allConcurrentResponseStatusCodesShouldBe(expected int) error {
|
func (s *scenario) allConcurrentResponseStatusCodesShouldBe(expected int) error {
|
||||||
if len(s.concurrentResps) == 0 {
|
if len(s.concurrentResps) == 0 {
|
||||||
return errors.New("no concurrent responses recorded")
|
return errors.New("no concurrent responses recorded")
|
||||||
@@ -1759,6 +1778,7 @@ func InitializeScenario(ctx *godog.ScenarioContext) {
|
|||||||
ctx.Then(`^the response status code should be (\d+)$`, s.theResponseStatusCodeShouldBe)
|
ctx.Then(`^the response status code should be (\d+)$`, s.theResponseStatusCodeShouldBe)
|
||||||
ctx.Then(`^all concurrent response status codes should be (\d+)$`, s.allConcurrentResponseStatusCodesShouldBe)
|
ctx.Then(`^all concurrent response status codes should be (\d+)$`, s.allConcurrentResponseStatusCodesShouldBe)
|
||||||
ctx.Then(`^all probe response status codes should be (\d+)$`, s.allProbeResponseStatusCodesShouldBe)
|
ctx.Then(`^all probe response status codes should be (\d+)$`, s.allProbeResponseStatusCodesShouldBe)
|
||||||
|
ctx.Then(`^all sequential response status codes should be (\d+)$`, s.allSequentialResponseStatusCodesShouldBe)
|
||||||
ctx.Then(`^all concurrent responses should have (\d+) PDF\(s\)$`, s.allConcurrentResponsesShouldHavePdfs)
|
ctx.Then(`^all concurrent responses should have (\d+) PDF\(s\)$`, s.allConcurrentResponsesShouldHavePdfs)
|
||||||
ctx.Then(`^the (response|webhook request|file request|server request) header "([^"]*)" should be "([^"]*)"$`, s.theHeaderValueShouldBe)
|
ctx.Then(`^the (response|webhook request|file request|server request) header "([^"]*)" should be "([^"]*)"$`, s.theHeaderValueShouldBe)
|
||||||
ctx.Then(`^the webhook request header "([^"]*)" should carry trace id "([^"]*)"$`, s.theWebhookRequestHeaderShouldCarryTraceID)
|
ctx.Then(`^the webhook request header "([^"]*)" should carry trace id "([^"]*)"$`, s.theWebhookRequestHeaderShouldCarryTraceID)
|
||||||
|
|||||||
Reference in New Issue
Block a user