Skip to content

Commit

Permalink
fixes panic at goaws/app/gosqs/gosqs.go:376. use case DeleteQueue() w…
Browse files Browse the repository at this point in the history
…hile something is still blocked on ReceiveMessage()
  • Loading branch information
Sebastien cante committed Sep 26, 2019
1 parent 75098e0 commit f7154e4
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 2 deletions.
12 changes: 10 additions & 2 deletions app/gosqs/gosqs.go
Expand Up @@ -373,9 +373,17 @@ func ReceiveMessage(w http.ResponseWriter, req *http.Request) {
loops := waitTimeSeconds * 10
for loops > 0 {
app.SyncQueues.RLock()
found := len(app.SyncQueues.Queues[queueName].Messages)-numberOfHiddenMessagesInQueue(*app.SyncQueues.Queues[queueName]) != 0
_, queueFound := app.SyncQueues.Queues[queueName]
var messageFound bool
if queueFound {
messageFound = len(app.SyncQueues.Queues[queueName].Messages)-numberOfHiddenMessagesInQueue(*app.SyncQueues.Queues[queueName]) != 0
}
app.SyncQueues.RUnlock()
if !found {
if !queueFound {
createErrorResponse(w, req, "QueueNotFound")
return
}
if !messageFound {
time.Sleep(100 * time.Millisecond)
loops--
} else {
Expand Down
96 changes: 96 additions & 0 deletions app/gosqs/gosqs_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"net/url"
"reflect"
"strings"
"sync"
"testing"
"time"

Expand Down Expand Up @@ -1036,6 +1037,101 @@ func TestReceiveMessageWaitTimeEnforced(t *testing.T) {
}
}

func TestReceiveMessage_WithConcurrentDeleteQueue(t *testing.T) {
// create a queue
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Fatal(err)
}
form := url.Values{}
form.Add("Action", "CreateQueue")
form.Add("QueueName", "waiting-queue")
form.Add("Attribute.1.Name", "ReceiveMessageWaitTimeSeconds")
form.Add("Attribute.1.Value", "1")
form.Add("Version", "2012-11-05")
req.PostForm = form

rr := httptest.NewRecorder()
http.HandlerFunc(CreateQueue).ServeHTTP(rr, req)

if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got \n%v want %v",
status, http.StatusOK)
}

var wg sync.WaitGroup

wg.Add(1)
go func() {
defer wg.Done()
// receive message
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Fatal(err)
}

form := url.Values{}
form.Add("Action", "ReceiveMessage")
form.Add("QueueUrl", "http://localhost:4100/queue/waiting-queue")
form.Add("Version", "2012-11-05")
req.PostForm = form

rr := httptest.NewRecorder()

http.HandlerFunc(ReceiveMessage).ServeHTTP(rr, req)

// Check the status code is what we expect.
if status := rr.Code; status != http.StatusBadRequest {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusBadRequest)
}

// Check the response body is what we expect.
expected := "QueueNotFound"
if !strings.Contains(rr.Body.String(), "Not Found") {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}
}()

wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(10 * time.Millisecond) // 10ms to let the ReceiveMessage() block
// delete queue message
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Fatal(err)
}
form := url.Values{}
form.Add("Action", "DeleteQueue")
form.Add("QueueUrl", "http://localhost:4100/queue/waiting-queue")
form.Add("Version", "2012-11-05")
req.PostForm = form

rr := httptest.NewRecorder()
http.HandlerFunc(DeleteQueue).ServeHTTP(rr, req)

if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got \n%v want %v",
status, http.StatusOK)
}
}()

c := make(chan struct{})
go func() {
defer close(c)
wg.Wait()
}()
select {
case <-c:
return // completed successfully
case <-time.After(2 * time.Second):
t.Errorf("concurrent handlers timeout, expecting both to return within timeout")
}

}

func TestSetQueueAttributes_POST_QueueNotFound(t *testing.T) {
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
Expand Down

0 comments on commit f7154e4

Please sign in to comment.