Skip to content

Commit

Permalink
Merge branch 'feature-aws-json' into feature-aws-json-sqs-sendmessage
Browse files Browse the repository at this point in the history
  • Loading branch information
kojisaikiAtSony committed May 15, 2024
2 parents a2d30b4 + 096af9a commit 19a9db9
Show file tree
Hide file tree
Showing 18 changed files with 913 additions and 325 deletions.
1 change: 1 addition & 0 deletions app/conf/mock-data/mock-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ BaseUnitTests:
Queues: # List of queues to create at startup
- Name: unit-queue1 # Queue name
- Name: unit-queue2 # Queue name
RedrivePolicy: '{"maxReceiveCount": 100, "deadLetterTargetArn":"arn:aws:sqs:us-east-1:100010001000:other-queue1"}'
- Name: other-queue1 # Queue name
55 changes: 47 additions & 8 deletions app/fixtures/sqs.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,54 @@ var CreateQueueResponse = models.CreateQueueResponse{
Metadata: models.BASE_RESPONSE_METADATA,
}

var ListQueuesResult = models.ListQueuesResult{
QueueUrls: []string{
fmt.Sprintf("%s/%s", BASE_URL, "unit-queue1"),
fmt.Sprintf("%s/%s", BASE_URL, "unit-queue2"),
},
var GetQueueAttributesRequest = models.GetQueueAttributesRequest{
QueueUrl: fmt.Sprintf("%s/unit-queue1", BASE_URL),
AttributeNames: []string{"All"},
}

var ListQueuesResponse = models.ListQueuesResponse{
Xmlns: models.BASE_XMLNS,
Result: ListQueuesResult,
var GetQueueAttributesResponse = models.GetQueueAttributesResponse{
Xmlns: models.BASE_XMLNS,
Result: models.GetQueueAttributesResult{Attrs: []models.Attribute{
models.Attribute{
Name: "DelaySeconds",
Value: "0",
},
models.Attribute{
Name: "MaximumMessageSize",
Value: "262144",
},
models.Attribute{
Name: "MessageRetentionPeriod",
Value: "345600",
},
models.Attribute{
Name: "ReceiveMessageWaitTimeSeconds",
Value: "0",
},
models.Attribute{
Name: "VisibilityTimeout",
Value: "30",
},
models.Attribute{
Name: "ApproximateNumberOfMessages",
Value: "0",
},
models.Attribute{
Name: "ApproximateNumberOfMessagesNotVisible",
Value: "0",
},
models.Attribute{
Name: "CreatedTimestamp",
Value: "0000000000",
},
models.Attribute{
Name: "LastModifiedTimestamp",
Value: "0000000000",
},
models.Attribute{
Name: "QueueArn",
Value: "arn:aws:sqs:region:accountID:unit-queue1",
},
}},
Metadata: models.BASE_RESPONSE_METADATA,
}
137 changes: 137 additions & 0 deletions app/gosqs/get_queue_attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package gosqs

import (
"fmt"
"net/http"
"strconv"
"strings"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/utils"
"github.com/mitchellh/copystructure"

"github.com/Admiral-Piett/goaws/app/interfaces"

log "github.com/sirupsen/logrus"
)

func GetQueueAttributesV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
requestBody := models.NewGetQueueAttributesRequest()
ok := utils.REQUEST_TRANSFORMER(requestBody, req)
if !ok {
log.Error("Invalid Request - GetQueueAttributesV1")
return createErrorResponseV1(ErrInvalidParameterValue.Type)
}
if requestBody.QueueUrl == "" {
log.Error("Missing QueueUrl - GetQueueAttributesV1")
return createErrorResponseV1(ErrInvalidParameterValue.Type)
}

requestedAttributes := func() map[string]bool {
attrs := map[string]bool{}
if len(requestBody.AttributeNames) == 0 {
return map[string]bool{"All": true}
}
for _, attr := range requestBody.AttributeNames {
if "All" == attr {
return map[string]bool{"All": true}
}
attrs[attr] = true
}
return attrs
}()

dupe, _ := copystructure.Copy(models.AVAILABLE_QUEUE_ATTRIBUTES)
includedAttributes, _ := dupe.(map[string]bool)
_, ok = requestedAttributes["All"]
if !ok {
for attr, _ := range includedAttributes {
_, ok := requestedAttributes[attr]
if !ok {
delete(includedAttributes, attr)
}
}
}

uriSegments := strings.Split(requestBody.QueueUrl, "/")
queueName := uriSegments[len(uriSegments)-1]

log.Infof("Get Queue Attributes: %s", queueName)
queueAttributes := make([]models.Attribute, 0, 0)

app.SyncQueues.RLock()
queue, ok := app.SyncQueues.Queues[queueName]
if !ok {
log.Errorf("Get Queue URL: %s queue does not exist!!!", queueName)
app.SyncQueues.RUnlock()
return createErrorResponseV1(ErrInvalidParameterValue.Type)
}

if _, ok := includedAttributes["DelaySeconds"]; ok {
attr := models.Attribute{Name: "DelaySeconds", Value: strconv.Itoa(queue.DelaySeconds)}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["MaximumMessageSize"]; ok {
attr := models.Attribute{Name: "MaximumMessageSize", Value: strconv.Itoa(queue.MaximumMessageSize)}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["MessageRetentionPeriod"]; ok {
attr := models.Attribute{Name: "MessageRetentionPeriod", Value: strconv.Itoa(queue.MessageRetentionPeriod)}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["ReceiveMessageWaitTimeSeconds"]; ok {
attr := models.Attribute{Name: "ReceiveMessageWaitTimeSeconds", Value: strconv.Itoa(queue.ReceiveMessageWaitTimeSeconds)}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["VisibilityTimeout"]; ok {
attr := models.Attribute{Name: "VisibilityTimeout", Value: strconv.Itoa(queue.VisibilityTimeout)}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["ApproximateNumberOfMessages"]; ok {
attr := models.Attribute{Name: "ApproximateNumberOfMessages", Value: strconv.Itoa(len(queue.Messages))}
queueAttributes = append(queueAttributes, attr)
}
// TODO - implement
//if _, ok := includedAttributes["ApproximateNumberOfMessagesDelayed"]; ok {
// attr := models.Attribute{Name: "ApproximateNumberOfMessagesDelayed", Value: strconv.Itoa(len(queue.Messages))}
// queueAttributes = append(queueAttributes, attr)
//}
if _, ok := includedAttributes["ApproximateNumberOfMessagesNotVisible"]; ok {
attr := models.Attribute{Name: "ApproximateNumberOfMessagesNotVisible", Value: strconv.Itoa(numberOfHiddenMessagesInQueue(*queue))}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["CreatedTimestamp"]; ok {
attr := models.Attribute{Name: "CreatedTimestamp", Value: "0000000000"}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["LastModifiedTimestamp"]; ok {
attr := models.Attribute{Name: "LastModifiedTimestamp", Value: "0000000000"}
queueAttributes = append(queueAttributes, attr)
}
if _, ok := includedAttributes["QueueArn"]; ok {
attr := models.Attribute{Name: "QueueArn", Value: queue.Arn}
queueAttributes = append(queueAttributes, attr)
}
// TODO - implement
//if _, ok := includedAttributes["Policy"]; ok {
// attr := models.Attribute{Name: "Policy", Value: ""}
// queueAttributes = append(queueAttributes, attr)
//}
//if _, ok := includedAttributes["RedriveAllowPolicy"]; ok {
// attr := models.Attribute{Name: "RedriveAllowPolicy", Value: ""}
// queueAttributes = append(queueAttributes, attr)
//}
if _, ok := includedAttributes["RedrivePolicy"]; ok && queue.DeadLetterQueue != nil {
attr := models.Attribute{Name: "RedrivePolicy", Value: fmt.Sprintf(`{"maxReceiveCount":"%d", "deadLetterTargetArn":"%s"}`, queue.MaxReceiveCount, queue.DeadLetterQueue.Arn)}
queueAttributes = append(queueAttributes, attr)
}
app.SyncQueues.RUnlock()

respStruct := models.GetQueueAttributesResponse{
models.BASE_XMLNS,
models.GetQueueAttributesResult{Attrs: queueAttributes},
models.BASE_RESPONSE_METADATA,
}
return http.StatusOK, respStruct
}
178 changes: 178 additions & 0 deletions app/gosqs/get_queue_attributes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
package gosqs

import (
"fmt"
"net/http"
"testing"

"github.com/mitchellh/copystructure"

"github.com/Admiral-Piett/goaws/app/conf"

"github.com/Admiral-Piett/goaws/app/fixtures"
"github.com/Admiral-Piett/goaws/app/interfaces"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/utils"
"github.com/stretchr/testify/assert"
)

func TestGetQueueAttributesV1_success_all(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
utils.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = fixtures.GetQueueAttributesRequest
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetQueueAttributesV1(r)

assert.Equal(t, http.StatusOK, code)
assert.Equal(t, fixtures.GetQueueAttributesResponse, response)
}

func TestGetQueueAttributesV1_success_no_request_attrs_returns_all(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
utils.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = models.GetQueueAttributesRequest{
QueueUrl: "unit-queue1",
}
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetQueueAttributesV1(r)

assert.Equal(t, http.StatusOK, code)
assert.Equal(t, fixtures.GetQueueAttributesResponse, response)
}

func TestGetQueueAttributesV1_success_all_with_redrive_queue(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
utils.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = models.GetQueueAttributesRequest{
QueueUrl: "unit-queue2",
AttributeNames: []string{"All"},
}
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetQueueAttributesV1(r)

dupe, _ := copystructure.Copy(fixtures.GetQueueAttributesResponse)
expectedResponse, _ := dupe.(models.GetQueueAttributesResponse)
expectedResponse.Result.Attrs[9].Value = fmt.Sprintf("%s:%s", fixtures.BASE_ARN, "unit-queue2")
expectedResponse.Result.Attrs = append(expectedResponse.Result.Attrs,
models.Attribute{
Name: "RedrivePolicy",
Value: fmt.Sprintf(`{"maxReceiveCount":"100", "deadLetterTargetArn":"%s:%s"}`, fixtures.BASE_ARN, "other-queue1"),
},
)

assert.Equal(t, http.StatusOK, code)
assert.Equal(t, expectedResponse, response)
}

func TestGetQueueAttributesV1_success_specific_fields(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
utils.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = models.GetQueueAttributesRequest{
QueueUrl: fmt.Sprintf("%s/unit-queue1", fixtures.BASE_URL),
AttributeNames: []string{"DelaySeconds"},
}
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, response := GetQueueAttributesV1(r)

expectedResponse := models.GetQueueAttributesResponse{
Xmlns: models.BASE_XMLNS,
Result: models.GetQueueAttributesResult{Attrs: []models.Attribute{
models.Attribute{
Name: "DelaySeconds",
Value: "0",
},
}},
Metadata: models.BASE_RESPONSE_METADATA,
}

assert.Equal(t, http.StatusOK, code)
assert.Equal(t, expectedResponse, response)
}

func TestGetQueueAttributesV1_request_transformer_error(t *testing.T) {
defer func() {
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
return false
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, _ := GetQueueAttributesV1(r)

assert.Equal(t, http.StatusBadRequest, code)
}

func TestGetQueueAttributesV1_missing_queue_url_in_request_returns_error(t *testing.T) {
defer func() {
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = models.GetQueueAttributesRequest{
QueueUrl: "",
AttributeNames: []string{},
}
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, _ := GetQueueAttributesV1(r)

assert.Equal(t, http.StatusBadRequest, code)
}

func TestGetQueueAttributesV1_missing_queue_returns_error(t *testing.T) {
defer func() {
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request) (success bool) {
v := resultingStruct.(*models.GetQueueAttributesRequest)
*v = fixtures.GetQueueAttributesRequest
return true
}

_, r := utils.GenerateRequestInfo("POST", "/", nil, true)
code, _ := GetQueueAttributesV1(r)

assert.Equal(t, http.StatusBadRequest, code)
}
Loading

0 comments on commit 19a9db9

Please sign in to comment.