diff --git a/app/gosns/gosns.go b/app/gosns/gosns.go index 270cf0a3..304c7936 100644 --- a/app/gosns/gosns.go +++ b/app/gosns/gosns.go @@ -228,7 +228,7 @@ func getSubscription(subsArn string) *models.Subscription { } func createMessageBody(subs *models.Subscription, entry interfaces.AbstractPublishEntry, - messageAttributes map[string]models.SqsMessageAttributeValue) ([]byte, error) { + messageAttributes map[string]models.MessageAttribute) (string, error) { msgId := uuid.NewString() message := models.SNSMessage{ @@ -240,13 +240,13 @@ func createMessageBody(subs *models.Subscription, entry interfaces.AbstractPubli SignatureVersion: "1", SigningCertURL: fmt.Sprintf("http://%s:%s/SimpleNotificationService/%s.pem", models.CurrentEnvironment.Host, models.CurrentEnvironment.Port, msgId), UnsubscribeURL: fmt.Sprintf("http://%s:%s/?Action=Unsubscribe&SubscriptionArn=%s", models.CurrentEnvironment.Host, models.CurrentEnvironment.Port, subs.SubscriptionArn), - MessageAttributes: formatAttributes(messageAttributes), + MessageAttributes: messageAttributes, } if models.MessageStructure(entry.GetMessageStructure()) == models.MessageStructureJSON { m, err := extractMessageFromJSON(entry.GetMessage(), subs.Protocol) if err != nil { - return nil, err + return "", err } message.Message = m } else { @@ -261,29 +261,10 @@ func createMessageBody(subs *models.Subscription, entry interfaces.AbstractPubli } byteMsg, _ := json.Marshal(message) - return byteMsg, nil -} - -func formatAttributes(values map[string]models.SqsMessageAttributeValue) map[string]models.MessageAttributeValue { - attr := make(map[string]models.MessageAttributeValue) - for k, v := range values { - if v.DataType == "String" { - attr[k] = models.MessageAttributeValue{ - DataType: v.DataType, - StringValue: v.Value, - } - } else { - attr[k] = models.MessageAttributeValue{ - DataType: v.DataType, - BinaryValue: v.Value, // TODO - this may need to be a []byte? - } - } - } - return attr + return string(byteMsg), nil } func publishHTTP(subs *models.Subscription, topicArn string, entry interfaces.AbstractPublishEntry) { - messageAttributes := utils.ConvertToOldMessageAttributeValueStructure(entry.GetMessageAttributes()) id := uuid.NewString() msg := models.SNSMessage{ Type: "Notification", @@ -295,7 +276,7 @@ func publishHTTP(subs *models.Subscription, topicArn string, entry interfaces.Ab SignatureVersion: "1", SigningCertURL: fmt.Sprintf("http://%s:%s/SimpleNotificationService/%s.pem", models.CurrentEnvironment.Host, models.CurrentEnvironment.Port, id), UnsubscribeURL: fmt.Sprintf("http://%s:%s/?Action=Unsubscribe&SubscriptionArn=%s", models.CurrentEnvironment.Host, models.CurrentEnvironment.Port, subs.SubscriptionArn), - MessageAttributes: formatAttributes(messageAttributes), + MessageAttributes: entry.GetMessageAttributes(), } signature, err := signMessage(PrivateKEY, &msg) @@ -318,8 +299,7 @@ func publishHTTP(subs *models.Subscription, topicArn string, entry interfaces.Ab // put it in the resulting `body`, so that's all that's in that field when the message is received. If it's not // raw, then we put all this other junk in there too, similar to how AWS stores its metadata in there. func publishSQS(subscription *models.Subscription, topic *models.Topic, entry interfaces.AbstractPublishEntry) error { - messageAttributes := utils.ConvertToOldMessageAttributeValueStructure(entry.GetMessageAttributes()) - if subscription.FilterPolicy != nil && !subscription.FilterPolicy.IsSatisfiedBy(messageAttributes) { + if subscription.FilterPolicy != nil && !subscription.FilterPolicy.IsSatisfiedBy(entry.GetMessageAttributes()) { return nil } @@ -333,8 +313,8 @@ func publishSQS(subscription *models.Subscription, topic *models.Topic, entry in msg := models.SqsMessage{} if subscription.Raw { - msg.MessageAttributes = messageAttributes - msg.MD5OfMessageAttributes = utils.HashAttributes(messageAttributes) + msg.MessageAttributes = entry.GetMessageAttributes() + msg.MD5OfMessageAttributes = utils.HashAttributes(entry.GetMessageAttributes()) // NOTE: Admiral-Piett - commenting this out. I don't understand what this is supposed to achieve // for raw message delivery. I suspect this doesn't work at all, otherwise you'd have to match the @@ -346,9 +326,9 @@ func publishSQS(subscription *models.Subscription, topic *models.Topic, entry in //} else { // msg.MessageBody = []byte(entry.GetMessage()) //} - msg.MessageBody = []byte(entry.GetMessage()) + msg.MessageBody = entry.GetMessage() } else { - m, err := createMessageBody(subscription, entry, messageAttributes) + m, err := createMessageBody(subscription, entry, entry.GetMessageAttributes()) if err != nil { return err } diff --git a/app/gosns/gosns_test.go b/app/gosns/gosns_test.go index 9c791ca8..3a6f95b9 100644 --- a/app/gosns/gosns_test.go +++ b/app/gosns/gosns_test.go @@ -94,8 +94,8 @@ func Test_publishSQS_filter_policy_not_satisfied_by_attributes(t *testing.T) { request := models.PublishRequest{ TopicArn: topicArn, Message: message, - MessageAttributes: map[string]models.MessageAttributeValue{ - "invalid": models.MessageAttributeValue{ + MessageAttributes: map[string]models.MessageAttribute{ + "invalid": models.MessageAttribute{ DataType: "String", StringValue: "garbage", }, @@ -199,11 +199,11 @@ func TestCreateMessageBody_success_NoMessageAttributes(t *testing.T) { Subject: subject, } - result, err := createMessageBody(subs, msg, map[string]models.SqsMessageAttributeValue{}) + result, err := createMessageBody(subs, msg, map[string]models.MessageAttribute{}) assert.Nil(t, err) unmarshalledMessage := &models.SNSMessage{} - json.Unmarshal(result, unmarshalledMessage) + json.Unmarshal([]byte(result), unmarshalledMessage) assert.Equal(t, "Notification", unmarshalledMessage.Type) assert.Equal(t, "", unmarshalledMessage.Token) @@ -225,11 +225,10 @@ func TestCreateMessageBody_success_WithMessageAttributes(t *testing.T) { SubscriptionArn: "subs-arn", Raw: false, } - attributes := map[string]models.SqsMessageAttributeValue{ + attributes := map[string]models.MessageAttribute{ "test": { - DataType: "String", - ValueKey: "StringValue", - Value: "test", + DataType: "String", + StringValue: "test", }, } @@ -280,8 +279,8 @@ func TestCreateMessageBody_JSONMessageStructure_MissingDefaultKey(t *testing.T) snsMessage, err := createMessageBody(subs, msg, nil) + assert.Equal(t, "", snsMessage) assert.Error(t, err) - assert.Nil(t, snsMessage) } func TestCreateMessageBody_JSONMessageStructure_SelectsProtocolSpecificMessageIfAvailable(t *testing.T) { @@ -324,29 +323,6 @@ func TestCreateMessageBody_NonJsonMessageStructure_MessageContainingJson(t *test assert.Contains(t, string(snsMessage), "\"Message\":\"{\\\"default\\\": \\\"default message text\\\", \\\"sqs\\\": \\\"sqs message text\\\"}\"") } -func Test_formatAttributes_success(t *testing.T) { - attrs := map[string]models.SqsMessageAttributeValue{ - "test1": models.SqsMessageAttributeValue{ - Name: "MyAttr", - DataType: "String", - Value: "value1", - }, - "test2": models.SqsMessageAttributeValue{ - Name: "MyAttr", - DataType: "String", - Value: "value2", - }, - } - expected := map[string]models.MessageAttributeValue{ - "test1": {DataType: "String", StringValue: "value1"}, - "test2": {DataType: "String", StringValue: "value2"}, - } - - result := formatAttributes(attrs) - - assert.Equal(t, expected, result) -} - func Test_publishMessageByTopic_sqs_success(t *testing.T) { defer func() { publishSqsMessageFunc = publishSQS diff --git a/app/gosqs/change_message_visibility_test.go b/app/gosqs/change_message_visibility_test.go index 9e09378a..1ddab4e9 100644 --- a/app/gosqs/change_message_visibility_test.go +++ b/app/gosqs/change_message_visibility_test.go @@ -21,7 +21,7 @@ func TestChangeMessageVisibility_POST_SUCCESS(t *testing.T) { q := &models.Queue{ Name: "testing", Messages: []models.SqsMessage{{ - MessageBody: []byte("test1"), + MessageBody: "test1", ReceiptHandle: "123", }}, } diff --git a/app/gosqs/delete_message_batch_test.go b/app/gosqs/delete_message_batch_test.go index f0fb2718..b92d1f8a 100644 --- a/app/gosqs/delete_message_batch_test.go +++ b/app/gosqs/delete_message_batch_test.go @@ -26,15 +26,15 @@ func TestDeleteMessageBatchV1_success_all_message(t *testing.T) { Name: "testing", Messages: []models.SqsMessage{ { - MessageBody: []byte("test%20message%20body%201"), + MessageBody: "test%20message%20body%201", ReceiptHandle: "test1", }, { - MessageBody: []byte("test%20message%20body%202"), + MessageBody: "test%20message%20body%202", ReceiptHandle: "test2", }, { - MessageBody: []byte("test%20message%20body%203"), + MessageBody: "test%20message%20body%203", ReceiptHandle: "test3", }, }, @@ -89,11 +89,11 @@ func TestDeleteMessageBatchV1_success_not_found_message(t *testing.T) { Name: "testing", Messages: []models.SqsMessage{ { - MessageBody: []byte("test%20message%20body%201"), + MessageBody: "test%20message%20body%201", ReceiptHandle: "test1", }, { - MessageBody: []byte("test%20message%20body%203"), + MessageBody: "test%20message%20body%203", ReceiptHandle: "test3", }, }, diff --git a/app/gosqs/delete_message_test.go b/app/gosqs/delete_message_test.go index 847a4f15..33f052bd 100644 --- a/app/gosqs/delete_message_test.go +++ b/app/gosqs/delete_message_test.go @@ -20,7 +20,7 @@ func TestDeleteMessage(t *testing.T) { q := &models.Queue{ Name: "testing", Messages: []models.SqsMessage{{ - MessageBody: []byte("test1"), + MessageBody: "test1", ReceiptHandle: "123", }}, } diff --git a/app/gosqs/message_attributes.go b/app/gosqs/message_attributes.go deleted file mode 100644 index 258f7a84..00000000 --- a/app/gosqs/message_attributes.go +++ /dev/null @@ -1,61 +0,0 @@ -package gosqs - -import ( - "fmt" - "net/http" - - "github.com/Admiral-Piett/goaws/app/models" - log "github.com/sirupsen/logrus" -) - -func extractMessageAttributes(req *http.Request, prefix string) map[string]models.SqsMessageAttributeValue { - attributes := make(map[string]models.SqsMessageAttributeValue) - if prefix != "" { - prefix += "." - } - - for i := 1; true; i++ { - name := req.FormValue(fmt.Sprintf("%sMessageAttribute.%d.Name", prefix, i)) - if name == "" { - break - } - - dataType := req.FormValue(fmt.Sprintf("%sMessageAttribute.%d.Value.DataType", prefix, i)) - if dataType == "" { - log.Warnf("DataType of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name) - continue - } - - // StringListValue and BinaryListValue is currently not implemented - for _, valueKey := range [...]string{"StringValue", "BinaryValue"} { - value := req.FormValue(fmt.Sprintf("%sMessageAttribute.%d.Value.%s", prefix, i, valueKey)) - if value != "" { - attributes[name] = models.SqsMessageAttributeValue{name, dataType, value, valueKey} - } - } - - if _, ok := attributes[name]; !ok { - log.Warnf("StringValue or BinaryValue of MessageAttribute %s is missing, MD5 checksum will most probably be wrong!\n", name) - } - } - - return attributes -} - -func getMessageAttributeResult(a *models.SqsMessageAttributeValue) *models.ResultMessageAttribute { - v := &models.ResultMessageAttributeValue{ - DataType: a.DataType, - } - - switch a.DataType { - case "Binary": - v.BinaryValue = a.Value - default: - v.StringValue = a.Value - } - - return &models.ResultMessageAttribute{ - Name: a.Name, - Value: v, - } -} diff --git a/app/gosqs/receive_message.go b/app/gosqs/receive_message.go index 4f641f5d..c7bcc898 100644 --- a/app/gosqs/receive_message.go +++ b/app/gosqs/receive_message.go @@ -119,7 +119,7 @@ func ReceiveMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) models.SyncQueues.Queues[queueName].LockGroup(msg.GroupID) } - messages = append(messages, getMessageResult(msg)) + messages = append(messages, buildResultMessage(msg)) numMsg++ } @@ -141,34 +141,19 @@ func ReceiveMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) return http.StatusOK, respStruct } -func getMessageResult(m *models.SqsMessage) *models.ResultMessage { - msgMttrs := []*models.ResultMessageAttribute{} - for _, attr := range m.MessageAttributes { - msgMttrs = append(msgMttrs, getMessageAttributeResult(&attr)) - } - - attrsMap := map[string]string{ - "ApproximateFirstReceiveTimestamp": fmt.Sprintf("%d", m.ReceiptTime.UnixNano()/int64(time.Millisecond)), - "SenderId": models.CurrentEnvironment.AccountID, - "ApproximateReceiveCount": fmt.Sprintf("%d", m.NumberOfReceives+1), - "SentTimestamp": fmt.Sprintf("%d", time.Now().UTC().UnixNano()/int64(time.Millisecond)), - } - - var attrs []*models.ResultAttribute - for k, v := range attrsMap { - attrs = append(attrs, &models.ResultAttribute{ - Name: k, - Value: v, - }) - } - +func buildResultMessage(m *models.SqsMessage) *models.ResultMessage { return &models.ResultMessage{ MessageId: m.Uuid, Body: m.MessageBody, ReceiptHandle: m.ReceiptHandle, - MD5OfBody: utils.GetMD5Hash(string(m.MessageBody)), + MD5OfBody: utils.GetMD5Hash(m.MessageBody), MD5OfMessageAttributes: m.MD5OfMessageAttributes, - MessageAttributes: msgMttrs, - Attributes: attrs, + MessageAttributes: m.MessageAttributes, + Attributes: map[string]string{ + "ApproximateFirstReceiveTimestamp": fmt.Sprintf("%d", m.ReceiptTime.UnixNano()/int64(time.Millisecond)), + "SenderId": models.CurrentEnvironment.AccountID, + "ApproximateReceiveCount": fmt.Sprintf("%d", m.NumberOfReceives+1), + "SentTimestamp": fmt.Sprintf("%d", time.Now().UTC().UnixNano()/int64(time.Millisecond)), + }, } } diff --git a/app/gosqs/receive_message_test.go b/app/gosqs/receive_message_test.go index ae529c9b..2ea7ad4b 100644 --- a/app/gosqs/receive_message_test.go +++ b/app/gosqs/receive_message_test.go @@ -16,7 +16,7 @@ import ( // TODO - figure out a better way to handle the wait time in these tests. Maybe in the smoke tests alone // if there's nothing else? -func TestReceiveMessageWaitTimeEnforcedV1(t *testing.T) { +func TestReceiveMessageV1_with_WaitTimeEnforced(t *testing.T) { models.CurrentEnvironment = fixtures.LOCAL_ENVIRONMENT defer func() { models.ResetApp() @@ -44,7 +44,7 @@ func TestReceiveMessageWaitTimeEnforcedV1(t *testing.T) { } // mock sending a message - q.Messages = append(q.Messages, models.SqsMessage{MessageBody: []byte("1")}) + q.Messages = append(q.Messages, models.SqsMessage{MessageBody: "1"}) // receive message _, r = test.GenerateRequestInfo("POST", "/", models.ReceiveMessageRequest{ @@ -62,7 +62,7 @@ func TestReceiveMessageWaitTimeEnforcedV1(t *testing.T) { assert.Equal(t, "1", string(resp.GetResult().(models.ReceiveMessageResult).Messages[0].Body)) } -func TestReceiveMessage_CanceledByClientV1(t *testing.T) { +func TestReceiveMessageV1_CanceledByClient(t *testing.T) { // create a queue models.CurrentEnvironment = fixtures.LOCAL_ENVIRONMENT defer func() { @@ -134,7 +134,7 @@ func TestReceiveMessage_CanceledByClientV1(t *testing.T) { } } -func TestReceiveMessageDelaySecondsV1(t *testing.T) { +func TestReceiveMessageV1_with_DelaySeconds(t *testing.T) { // create a queue models.CurrentEnvironment = fixtures.LOCAL_ENVIRONMENT defer func() { @@ -179,7 +179,7 @@ func TestReceiveMessageDelaySecondsV1(t *testing.T) { } } -func TestReceiveMessageAttributesV1(t *testing.T) { +func TestReceiveMessageV1_with_MessageAttributes(t *testing.T) { // create a queue models.CurrentEnvironment = fixtures.LOCAL_ENVIRONMENT defer func() { @@ -191,12 +191,11 @@ func TestReceiveMessageAttributesV1(t *testing.T) { // send a message q.Messages = append(q.Messages, models.SqsMessage{ - MessageBody: []byte("1"), - MessageAttributes: map[string]models.SqsMessageAttributeValue{ + MessageBody: "1", + MessageAttributes: map[string]models.MessageAttribute{ "TestMessageAttrName": { - Name: "TestMessageAttrName", - DataType: "String", - Value: "TestMessageAttrValue", + DataType: "String", + StringValue: "TestMessageAttrValue", }, }, }) @@ -206,10 +205,14 @@ func TestReceiveMessageAttributesV1(t *testing.T) { status, resp := ReceiveMessageV1(r) result := resp.GetResult().(models.ReceiveMessageResult) + assert.NotEmpty(t, result.Messages[0].Attributes["ApproximateFirstReceiveTimestamp"]) + assert.NotEmpty(t, result.Messages[0].Attributes["SenderId"]) + assert.NotEmpty(t, result.Messages[0].Attributes["ApproximateReceiveCount"]) + assert.NotEmpty(t, result.Messages[0].Attributes["SentTimestamp"]) + assert.Equal(t, http.StatusOK, status) assert.Equal(t, "1", string(result.Messages[0].Body)) assert.Equal(t, 1, len(result.Messages[0].MessageAttributes)) - assert.Equal(t, "TestMessageAttrName", result.Messages[0].MessageAttributes[0].Name) - assert.Equal(t, "String", result.Messages[0].MessageAttributes[0].Value.DataType) - assert.Equal(t, "TestMessageAttrValue", result.Messages[0].MessageAttributes[0].Value.StringValue) + assert.Equal(t, "String", result.Messages[0].MessageAttributes["TestMessageAttrName"].DataType) + assert.Equal(t, "TestMessageAttrValue", result.Messages[0].MessageAttributes["TestMessageAttrName"].StringValue) } diff --git a/app/gosqs/send_message.go b/app/gosqs/send_message.go index d8f93906..c681fa12 100644 --- a/app/gosqs/send_message.go +++ b/app/gosqs/send_message.go @@ -27,7 +27,6 @@ func SendMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) { messageBody := requestBody.MessageBody messageGroupID := requestBody.MessageGroupId messageDeduplicationID := requestBody.MessageDeduplicationId - messageAttributes := requestBody.MessageAttributes queueUrl := getQueueFromPath(requestBody.QueueUrl, req.URL.String()) @@ -58,11 +57,10 @@ func SendMessageV1(req *http.Request) (int, interfaces.AbstractResponseBody) { } log.Debugf("Putting Message in Queue: [%s]", queueName) - msg := models.SqsMessage{MessageBody: []byte(messageBody)} - if len(messageAttributes) > 0 { - oldStyleMessageAttributes := utils.ConvertToOldMessageAttributeValueStructure(messageAttributes) - msg.MessageAttributes = oldStyleMessageAttributes - msg.MD5OfMessageAttributes = utils.HashAttributes(oldStyleMessageAttributes) + msg := models.SqsMessage{MessageBody: messageBody} + if len(requestBody.MessageAttributes) > 0 { + msg.MessageAttributes = requestBody.MessageAttributes + msg.MD5OfMessageAttributes = utils.HashAttributes(requestBody.MessageAttributes) } msg.MD5OfMessageBody = utils.GetMD5Hash(messageBody) msg.Uuid = uuid.NewString() diff --git a/app/gosqs/send_message_batch.go b/app/gosqs/send_message_batch.go index b85b2ecb..790b3907 100644 --- a/app/gosqs/send_message_batch.go +++ b/app/gosqs/send_message_batch.go @@ -15,10 +15,8 @@ import ( ) func SendMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBody) { - requestBody := models.NewSendMessageBatchRequest() ok := utils.REQUEST_TRANSFORMER(requestBody, req, false) - if !ok { log.Error("Invalid Request - SendMessageBatchV1") return utils.CreateErrorResponseV1("InvalidParameterValue", true) @@ -60,11 +58,10 @@ func SendMessageBatchV1(req *http.Request) (int, interfaces.AbstractResponseBody sentEntries := make([]models.SendMessageBatchResultEntry, 0) log.Debug("Putting Message in Queue:", queueName) for _, sendEntry := range sendEntries { - msg := models.SqsMessage{MessageBody: []byte(sendEntry.MessageBody)} + msg := models.SqsMessage{MessageBody: sendEntry.MessageBody} if len(sendEntry.MessageAttributes) > 0 { - oldStyleMessageAttributes := utils.ConvertToOldMessageAttributeValueStructure(sendEntry.MessageAttributes) - msg.MessageAttributes = oldStyleMessageAttributes - msg.MD5OfMessageAttributes = utils.HashAttributes(oldStyleMessageAttributes) + msg.MessageAttributes = sendEntry.MessageAttributes + msg.MD5OfMessageAttributes = utils.HashAttributes(sendEntry.MessageAttributes) } msg.MD5OfMessageBody = utils.GetMD5Hash(sendEntry.MessageBody) msg.GroupID = sendEntry.MessageGroupId diff --git a/app/gosqs/send_message_batch_test.go b/app/gosqs/send_message_batch_test.go index 38f3ce93..794c3906 100644 --- a/app/gosqs/send_message_batch_test.go +++ b/app/gosqs/send_message_batch_test.go @@ -30,10 +30,9 @@ func TestSendMessageBatchV1_Success(t *testing.T) { { Id: "test-msg-with-single-attirbute", MessageBody: "test%20message%20body%202", - MessageAttributes: map[string]models.MessageAttributeValue{ + MessageAttributes: map[string]models.MessageAttribute{ "my-attribute-name": { - BinaryValue: "base64-encoded-value", - DataType: "hogehoge", + DataType: "String", StringValue: "my-attribute-string-value", }, }, @@ -41,15 +40,13 @@ func TestSendMessageBatchV1_Success(t *testing.T) { { Id: "test-msg-with-multi-attirbute", MessageBody: "test%20message%20body%203", - MessageAttributes: map[string]models.MessageAttributeValue{ + MessageAttributes: map[string]models.MessageAttribute{ "my-attribute-name-1": { - BinaryValue: "base64-encoded-value-1", - DataType: "hogehoge", - StringValue: "my-attribute-string-value-1", + BinaryValue: []byte("binary-value-1"), + DataType: "Binary", }, "my-attribute-name-2": { - BinaryValue: "base64-encoded-value-2", - DataType: "hogehoge", + DataType: "String", StringValue: "my-attribute-string-value-2", }, }, diff --git a/app/interfaces/interfaces.go b/app/interfaces/interfaces.go index 064eb162..2515d3fd 100644 --- a/app/interfaces/interfaces.go +++ b/app/interfaces/interfaces.go @@ -22,7 +22,7 @@ type AbstractErrorResponse interface { type AbstractPublishEntry interface { GetMessage() string - GetMessageAttributes() map[string]models.MessageAttributeValue + GetMessageAttributes() map[string]models.MessageAttribute GetMessageStructure() string GetSubject() string } diff --git a/app/models/models.go b/app/models/models.go index 3fd9cb3d..8031bfa4 100644 --- a/app/models/models.go +++ b/app/models/models.go @@ -10,29 +10,28 @@ import ( type MessageStructure string type Protocol string -// TODO - reconcile this with app.SqsMessageAttributeValue - deal with ConvertToOldMessageAttributeValueStructure -type MessageAttributeValue struct { - BinaryListValues []string `json:"BinaryListValues,omitempty"` // currently unsupported by AWS - BinaryValue string `json:"BinaryValue,omitempty"` - DataType string `json:"DataType,omitempty"` - StringListValues []string `json:"StringListValues,omitempty"` // currently unsupported by AWS - StringValue string `json:"StringValue,omitempty"` +type MessageAttribute struct { + BinaryListValues []string `json:"BinaryListValues,omitempty" xml:"BinaryListValues,omitempty"` // currently unsupported by AWS + BinaryValue []byte `json:"BinaryValue,omitempty" xml:"BinaryValue,omitempty"` + DataType string `json:"DataType,omitempty" xml:"DataType,omitempty"` + StringListValues []string `json:"StringListValues,omitempty" xml:"StringListValues,omitempty"` // currently unsupported by AWS + StringValue string `json:"StringValue,omitempty" xml:"StringValue,omitempty"` } type SNSMessage struct { - Type string `json:"Type"` - Token string `json:"Token,omitempty"` - MessageId string `json:"MessageId"` - TopicArn string `json:"TopicArn"` - Subject string `json:"Subject"` - Message string `json:"Message"` - Timestamp string `json:"Timestamp"` - SignatureVersion string `json:"SignatureVersion"` - Signature string `json:"Signature,omitempty"` - SigningCertURL string `json:"SigningCertURL"` - UnsubscribeURL string `json:"UnsubscribeURL"` - SubscribeURL string `json:"SubscribeURL,omitempty"` - MessageAttributes map[string]MessageAttributeValue `json:"MessageAttributes,omitempty"` + Type string `json:"Type"` + Token string `json:"Token,omitempty"` + MessageId string `json:"MessageId"` + TopicArn string `json:"TopicArn"` + Subject string `json:"Subject"` + Message string `json:"Message"` + Timestamp string `json:"Timestamp"` + SignatureVersion string `json:"SignatureVersion"` + Signature string `json:"Signature,omitempty"` + SigningCertURL string `json:"SigningCertURL"` + UnsubscribeURL string `json:"UnsubscribeURL"` + SubscribeURL string `json:"SubscribeURL,omitempty"` + MessageAttributes map[string]MessageAttribute `json:"MessageAttributes,omitempty"` } type Subscription struct { @@ -54,7 +53,7 @@ type Topic struct { type FilterPolicy map[string][]string // Function checks if MessageAttributes passed to Topic satisfy FilterPolicy set by subscription -func (fp *FilterPolicy) IsSatisfiedBy(msgAttrs map[string]SqsMessageAttributeValue) bool { +func (fp *FilterPolicy) IsSatisfiedBy(msgAttrs map[string]MessageAttribute) bool { for policyAttrName, policyAttrValues := range *fp { attrValue, ok := msgAttrs[policyAttrName] if !ok { @@ -68,7 +67,7 @@ func (fp *FilterPolicy) IsSatisfiedBy(msgAttrs map[string]SqsMessageAttributeVal return false } - if !stringInSlice(attrValue.Value, policyAttrValues) { + if !stringInSlice(attrValue.StringValue, policyAttrValues) { return false // the attribute value has to be among filtered ones } } @@ -77,7 +76,7 @@ func (fp *FilterPolicy) IsSatisfiedBy(msgAttrs map[string]SqsMessageAttributeVal } type SqsMessage struct { - MessageBody []byte + MessageBody string Uuid string MD5OfMessageAttributes string MD5OfMessageBody string @@ -86,7 +85,7 @@ type SqsMessage struct { VisibilityTimeout time.Time NumberOfReceives int Retry int - MessageAttributes map[string]SqsMessageAttributeValue + MessageAttributes map[string]MessageAttribute GroupID string DeduplicationID string SentTime time.Time @@ -103,13 +102,6 @@ func (m *SqsMessage) IsReadyForReceipt() bool { return showAt.Before(time.Now()) } -type SqsMessageAttributeValue struct { - Name string - DataType string - Value string - ValueKey string -} - type Queue struct { Name string URL string diff --git a/app/models/models_test.go b/app/models/models_test.go index 909b038c..b1763a1f 100644 --- a/app/models/models_test.go +++ b/app/models/models_test.go @@ -10,43 +10,43 @@ import ( func TestFilterPolicy_IsSatisfiedBy(t *testing.T) { var tests = []struct { filterPolicy *FilterPolicy - messageAttributes map[string]SqsMessageAttributeValue + messageAttributes map[string]MessageAttribute expected bool }{ { &FilterPolicy{"foo": {"bar"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "String", Value: "bar"}}, + map[string]MessageAttribute{"foo": {DataType: "String", StringValue: "bar"}}, true, }, { &FilterPolicy{"foo": {"bar", "xyz"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "String", Value: "xyz"}}, + map[string]MessageAttribute{"foo": {DataType: "String", StringValue: "xyz"}}, true, }, { &FilterPolicy{"foo": {"bar", "xyz"}, "abc": {"def"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "String", Value: "xyz"}, - "abc": {DataType: "String", Value: "def"}}, + map[string]MessageAttribute{"foo": {DataType: "String", StringValue: "xyz"}, + "abc": {DataType: "String", StringValue: "def"}}, true, }, { &FilterPolicy{"foo": {"bar"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "String", Value: "baz"}}, + map[string]MessageAttribute{"foo": {DataType: "String", StringValue: "baz"}}, false, }, { &FilterPolicy{"foo": {"bar"}}, - map[string]SqsMessageAttributeValue{}, + map[string]MessageAttribute{}, false, }, { &FilterPolicy{"foo": {"bar"}, "abc": {"def"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "String", Value: "bar"}}, + map[string]MessageAttribute{"foo": {DataType: "String", StringValue: "bar"}}, false, }, { &FilterPolicy{"foo": {"bar"}}, - map[string]SqsMessageAttributeValue{"foo": {DataType: "Binary", Value: "bar"}}, + map[string]MessageAttribute{"foo": {DataType: "Binary", BinaryValue: []byte("bar")}}, false, }, } diff --git a/app/models/requests.go b/app/models/requests.go index ff6a019f..81ecadc9 100644 --- a/app/models/requests.go +++ b/app/models/requests.go @@ -154,7 +154,6 @@ type GetQueueAttributesRequest struct { func (r *GetQueueAttributesRequest) SetAttributesFromForm(values url.Values) { r.QueueUrl = values.Get("QueueUrl") - // TODO - test me for i := 1; true; i++ { attrKey := fmt.Sprintf("AttributeName.%d", i) attrValue := values.Get(attrKey) @@ -168,8 +167,8 @@ func (r *GetQueueAttributesRequest) SetAttributesFromForm(values url.Values) { /*** Send Message Request */ func NewSendMessageRequest() *SendMessageRequest { return &SendMessageRequest{ - MessageAttributes: make(map[string]MessageAttributeValue), - MessageSystemAttributes: make(map[string]MessageAttributeValue), + MessageAttributes: make(map[string]MessageAttribute), + MessageSystemAttributes: make(map[string]MessageAttribute), } } @@ -177,17 +176,17 @@ type SendMessageRequest struct { DelaySeconds int `json:"DelaySeconds" schema:"DelaySeconds"` // MessageAttributes is custom attributes that users can add on the message as they like. // Please see: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#SQS-SendMessage-request-MessageAttributes - MessageAttributes map[string]MessageAttributeValue `json:"MessageAttributes" schema:"MessageAttributes"` - MessageBody string `json:"MessageBody" schema:"MessageBody"` - MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` - MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` + MessageAttributes map[string]MessageAttribute `json:"MessageAttributes" schema:"MessageAttributes"` + MessageBody string `json:"MessageBody" schema:"MessageBody"` + MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` + MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` // MessageSystemAttributes is custom attributes for AWS services. // Please see: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html#SQS-SendMessage-request-MessageSystemAttributes // On AWS, the only supported attribute is "AWSTraceHeader" that is for AWS X-Ray. // Goaws does not contains X-Ray emulation, so currently MessageSystemAttributes is unsupported. // TODO: Replace with a struct with known attributes "AWSTraceHeader". - MessageSystemAttributes map[string]MessageAttributeValue `json:"MessageSystemAttributes" schema:"MessageSystemAttributes"` - QueueUrl string `json:"QueueUrl" schema:"QueueUrl"` + MessageSystemAttributes map[string]MessageAttribute `json:"MessageSystemAttributes" schema:"MessageSystemAttributes"` + QueueUrl string `json:"QueueUrl" schema:"QueueUrl"` } func (r *SendMessageRequest) SetAttributesFromForm(values url.Values) { @@ -208,10 +207,10 @@ func (r *SendMessageRequest) SetAttributesFromForm(values url.Values) { stringValue := values.Get(fmt.Sprintf("MessageAttribute.%d.Value.StringValue", i)) binaryValue := values.Get(fmt.Sprintf("MessageAttribute.%d.Value.BinaryValue", i)) - r.MessageAttributes[name] = MessageAttributeValue{ + r.MessageAttributes[name] = MessageAttribute{ DataType: dataType, StringValue: stringValue, - BinaryValue: binaryValue, + BinaryValue: []byte(binaryValue), } } } @@ -261,13 +260,13 @@ func (r *SendMessageBatchRequest) SetAttributesFromForm(values url.Values) { binaryValue := values.Get(fmt.Sprintf("Entries.%d.MessageAttributes.%d.Value.BinaryValue", entryIndex, attributeIndex)) if r.Entries[entryIndex].MessageAttributes == nil { - r.Entries[entryIndex].MessageAttributes = make(map[string]MessageAttributeValue) + r.Entries[entryIndex].MessageAttributes = make(map[string]MessageAttribute) } - r.Entries[entryIndex].MessageAttributes[name] = MessageAttributeValue{ + r.Entries[entryIndex].MessageAttributes[name] = MessageAttribute{ DataType: dataType, StringValue: stringValue, - BinaryValue: binaryValue, + BinaryValue: []byte(binaryValue), } if _, ok := r.Entries[entryIndex].MessageAttributes[name]; !ok { @@ -277,13 +276,13 @@ func (r *SendMessageBatchRequest) SetAttributesFromForm(values url.Values) { } type SendMessageBatchRequestEntry struct { - Id string `json:"Id" schema:"Id"` - MessageBody string `json:"MessageBody" schema:"MessageBody"` - DelaySeconds int `json:"DelaySeconds" schema:"DelaySeconds"` // NOTE: not implemented - MessageAttributes map[string]MessageAttributeValue `json:"MessageAttributes" schema:"MessageAttributes"` - MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` - MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` - MessageSystemAttributes map[string]MessageAttributeValue `json:"MessageSystemAttributes" schema:"MessageSystemAttributes"` // NOTE: not implemented + Id string `json:"Id" schema:"Id"` + MessageBody string `json:"MessageBody" schema:"MessageBody"` + DelaySeconds int `json:"DelaySeconds" schema:"DelaySeconds"` // NOTE: not implemented + MessageAttributes map[string]MessageAttribute `json:"MessageAttributes" schema:"MessageAttributes"` + MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` + MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` + MessageSystemAttributes map[string]MessageAttribute `json:"MessageSystemAttributes" schema:"MessageSystemAttributes"` // NOTE: not implemented } // Get Queue Url Request @@ -714,19 +713,19 @@ func NewPublishRequest() *PublishRequest { } type PublishRequest struct { - Message string `json:"Message" schema:"Message"` - MessageAttributes map[string]MessageAttributeValue `json:"MessageAttributes" schema:"MessageAttributes"` - MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` // Not implemented - MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` // Not implemented - MessageStructure string `json:"MessageStructure" schema:"MessageStructure"` - PhoneNumber string `json:"PhoneNumber" schema:"PhoneNumber"` // Not implemented - Subject string `json:"Subject" schema:"Subject"` - TargetArn string `json:"TargetArn" schema:"TargetArn"` // Not implemented - TopicArn string `json:"TopicArn" schema:"TopicArn"` + Message string `json:"Message" schema:"Message"` + MessageAttributes map[string]MessageAttribute `json:"MessageAttributes" schema:"MessageAttributes"` + MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` // Not implemented + MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` // Not implemented + MessageStructure string `json:"MessageStructure" schema:"MessageStructure"` + PhoneNumber string `json:"PhoneNumber" schema:"PhoneNumber"` // Not implemented + Subject string `json:"Subject" schema:"Subject"` + TargetArn string `json:"TargetArn" schema:"TargetArn"` // Not implemented + TopicArn string `json:"TopicArn" schema:"TopicArn"` } func (r *PublishRequest) SetAttributesFromForm(values url.Values) { - attributes := map[string]MessageAttributeValue{} + attributes := map[string]MessageAttribute{} for i := 1; true; i++ { nameKey := fmt.Sprintf("MessageAttributes.entry.%d.Name", i) name := values.Get(nameKey) @@ -745,12 +744,12 @@ func (r *PublishRequest) SetAttributesFromForm(values url.Values) { binaryValue := values.Get(fmt.Sprintf("MessageAttributes.entry.%d.Value.BinaryValue", i)) if r.MessageAttributes == nil { - r.MessageAttributes = make(map[string]MessageAttributeValue) + r.MessageAttributes = make(map[string]MessageAttribute) } - attributes[name] = MessageAttributeValue{ + attributes[name] = MessageAttribute{ DataType: caser.String(dataType), // capitalize StringValue: stringValue, - BinaryValue: binaryValue, + BinaryValue: []byte(binaryValue), } } r.MessageAttributes = attributes @@ -761,7 +760,7 @@ func (r *PublishRequest) GetMessage() string { return r.Message } -func (r *PublishRequest) GetMessageAttributes() map[string]MessageAttributeValue { +func (r *PublishRequest) GetMessageAttributes() map[string]MessageAttribute { return r.MessageAttributes } @@ -872,7 +871,7 @@ type PublishBatchRequest struct { } func (r *PublishBatchRequest) SetAttributesFromForm(values url.Values) { - // TODO - Implement me + // TAG - Implement me } type PublishBatchRequestEntries struct { @@ -880,13 +879,13 @@ type PublishBatchRequestEntries struct { } type PublishBatchRequestEntry struct { - ID string `json:"Id" schema:"Id"` - Message string `json:"Message" schema:"Message"` - MessageAttributes map[string]MessageAttributeValue `json:"MessageAttributes" schema:"MessageAttributes"` // Not implemented - MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` // Not implemented - MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` // Not implemented - MessageStructure string `json:"MessageStructure" schema:"MessageStructure"` - Subject string `json:"Subject" schema:"Subject"` + ID string `json:"Id" schema:"Id"` + Message string `json:"Message" schema:"Message"` + MessageAttributes map[string]MessageAttribute `json:"MessageAttributes" schema:"MessageAttributes"` // Not implemented + MessageDeduplicationId string `json:"MessageDeduplicationId" schema:"MessageDeduplicationId"` // Not implemented + MessageGroupId string `json:"MessageGroupId" schema:"MessageGroupId"` // Not implemented + MessageStructure string `json:"MessageStructure" schema:"MessageStructure"` + Subject string `json:"Subject" schema:"Subject"` } // Satisfy the AbstractPublishEntry interface @@ -894,7 +893,7 @@ func (r *PublishBatchRequestEntry) GetMessage() string { return r.Message } -func (r *PublishBatchRequestEntry) GetMessageAttributes() map[string]MessageAttributeValue { +func (r *PublishBatchRequestEntry) GetMessageAttributes() map[string]MessageAttribute { return r.MessageAttributes } diff --git a/app/models/requests_test.go b/app/models/requests_test.go index 6465f655..9c075802 100644 --- a/app/models/requests_test.go +++ b/app/models/requests_test.go @@ -297,8 +297,8 @@ func TestSendMessageRequest_SetAttributesFromForm_success(t *testing.T) { form.Add("MessageAttribute.4.Value.StringValue", "Value4") r := &SendMessageRequest{ - MessageAttributes: make(map[string]MessageAttributeValue), - MessageSystemAttributes: make(map[string]MessageAttributeValue), + MessageAttributes: make(map[string]MessageAttribute), + MessageSystemAttributes: make(map[string]MessageAttribute), } r.SetAttributesFromForm(form) @@ -308,13 +308,13 @@ func TestSendMessageRequest_SetAttributesFromForm_success(t *testing.T) { attr1 := r.MessageAttributes["Attr1"] assert.Equal(t, "String", attr1.DataType) assert.Equal(t, "Value1", attr1.StringValue) - assert.Equal(t, "", attr1.BinaryValue) + assert.Empty(t, attr1.BinaryValue) assert.NotNil(t, r.MessageAttributes["Attr2"]) attr2 := r.MessageAttributes["Attr2"] assert.Equal(t, "Binary", attr2.DataType) - assert.Equal(t, "", attr2.StringValue) - assert.Equal(t, "VmFsdWUy", attr2.BinaryValue) + assert.Empty(t, attr2.StringValue) + assert.Equal(t, []uint8("VmFsdWUy"), attr2.BinaryValue) } func TestSetQueueAttributesRequest_SetAttributesFromForm_success(t *testing.T) { diff --git a/app/models/responses.go b/app/models/responses.go index acbeaf63..fce4d1a2 100644 --- a/app/models/responses.go +++ b/app/models/responses.go @@ -1,10 +1,7 @@ package models import ( - "encoding/json" - - "github.com/aws/aws-sdk-go-v2/aws" - sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types" + "encoding/xml" ) type ResponseMetadata struct { @@ -54,59 +51,55 @@ func (r ReceiveMessageResponse) GetRequestId() string { } type ResultMessage struct { - MessageId string `xml:"MessageId,omitempty"` - ReceiptHandle string `xml:"ReceiptHandle,omitempty"` - MD5OfBody string `xml:"MD5OfBody,omitempty"` - Body []byte `xml:"Body,omitempty"` - MD5OfMessageAttributes string `xml:"MD5OfMessageAttributes,omitempty"` - MessageAttributes []*ResultMessageAttribute `xml:"MessageAttribute,omitempty"` - Attributes []*ResultAttribute `xml:"Attribute,omitempty"` -} - -// MarshalJSON first converts the ResultMessage to the shape which the SDKs -// expect. When receiving a response from the JSON API, it apparently expects -// QueueAttributes and MessageAttributes to be maps, rather than the former slice -// shape. -func (r *ResultMessage) MarshalJSON() ([]byte, error) { - m := &sqstypes.Message{ - MessageId: &r.MessageId, - ReceiptHandle: &r.ReceiptHandle, - MD5OfBody: &r.MD5OfBody, - Body: aws.String(string(r.Body)), - MD5OfMessageAttributes: &r.MD5OfMessageAttributes, - Attributes: map[string]string{}, - MessageAttributes: map[string]sqstypes.MessageAttributeValue{}, + MessageId string `xml:"MessageId,omitempty"` + ReceiptHandle string `xml:"ReceiptHandle,omitempty"` + MD5OfBody string `xml:"MD5OfBody,omitempty"` + Body string `xml:"Body,omitempty"` + MD5OfMessageAttributes string `xml:"MD5OfMessageAttributes,omitempty"` + MessageAttributes map[string]MessageAttribute `xml:"MessageAttribute,omitempty,attr"` + Attributes map[string]string `xml:"Attribute,omitempty,attr"` +} + +// MarshalXML is a custom marshaler for the ResultMessage struct. We need it because we need to convert the +// maps into something that can be shown as XML. If we ever get rid of the XML response parsing this can go, +// and that would be glorious. +func (r *ResultMessage) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + type Attributes struct { + Name string `xml:"Name,omitempty"` + Value string `xml:"Value,omitempty"` } - - for _, attr := range r.Attributes { - m.Attributes[attr.Name] = attr.Value + var attrs []Attributes + for key, value := range r.Attributes { + attribute := Attributes{ + Name: key, + Value: value, + } + attrs = append(attrs, attribute) } - for _, attr := range r.MessageAttributes { - m.MessageAttributes[attr.Name] = sqstypes.MessageAttributeValue{ - DataType: &attr.Value.DataType, - StringValue: &attr.Value.StringValue, - BinaryValue: []byte(attr.Value.BinaryValue), + type MessageAttributes struct { + Name string `xml:"Name,omitempty"` + Value MessageAttribute `xml:"Value,omitempty"` + } + var messageAttrs []MessageAttributes + for key, value := range r.MessageAttributes { + attribute := MessageAttributes{ + Name: key, + Value: value, } + messageAttrs = append(messageAttrs, attribute) } - - return json.Marshal(m) -} - -type ResultMessageAttributeValue struct { - DataType string `xml:"DataType,omitempty"` - StringValue string `xml:"StringValue,omitempty"` - BinaryValue string `xml:"BinaryValue,omitempty"` -} - -type ResultMessageAttribute struct { - Name string `xml:"Name,omitempty"` - Value *ResultMessageAttributeValue `xml:"Value,omitempty"` -} - -type ResultAttribute struct { - Name string `xml:"Name,omitempty"` - Value string `xml:"Value,omitempty"` + e.EncodeToken(start) + + // Encode the fields + e.EncodeElement(r.MessageId, xml.StartElement{Name: xml.Name{Local: "MessageId"}}) + e.EncodeElement(r.ReceiptHandle, xml.StartElement{Name: xml.Name{Local: "ReceiptHandle"}}) + e.EncodeElement(r.MD5OfBody, xml.StartElement{Name: xml.Name{Local: "MD5OfBody"}}) + e.EncodeElement(r.Body, xml.StartElement{Name: xml.Name{Local: "Body"}}) + e.EncodeElement(attrs, xml.StartElement{Name: xml.Name{Local: "Attribute"}}) + e.EncodeElement(messageAttrs, xml.StartElement{Name: xml.Name{Local: "MessageAttribute"}}) + e.EncodeToken(xml.EndElement{Name: start.Name}) + return nil } type ChangeMessageVisibilityResult struct { diff --git a/app/models/responses_test.go b/app/models/responses_test.go index d9da276f..55a4d409 100644 --- a/app/models/responses_test.go +++ b/app/models/responses_test.go @@ -1,6 +1,7 @@ package models import ( + "encoding/xml" "testing" "github.com/stretchr/testify/assert" @@ -26,3 +27,84 @@ func TestGetQueueAttributesResponse_GetResult(t *testing.T) { assert.Equal(t, expectedAttributes, result) } + +func Test_ResultMessage_MarshalXML_success_with_attributes(t *testing.T) { + input := &ResultMessage{ + MessageId: "message-id", + ReceiptHandle: "receipt-handle", + MD5OfBody: "body-md5", + Body: "message-body", + MD5OfMessageAttributes: "message-attrs-md5", + MessageAttributes: map[string]MessageAttribute{ + "attr1": { + DataType: "String", + StringValue: "string-value", + }, + "attr2": { + DataType: "Binary", + BinaryValue: []byte("binary-value"), + }, + "attr3": { + DataType: "Number", + StringValue: "number-value", + }, + }, + Attributes: map[string]string{ + "ApproximateFirstReceiveTimestamp": "1", + "SenderId": "2", + "ApproximateReceiveCount": "3", + "SentTimestamp": "4", + }, + } + result, err := xml.Marshal(input) + + assert.Nil(t, err) + + resultString := string(result) + + // We have to assert piecemeal like this, the maps go into their lists unordered, which will randomly break this. + entry := "message-idreceipt-handlebody-md5message-body" + assert.Contains(t, resultString, entry) + + entry = "ApproximateFirstReceiveTimestamp1" + assert.Contains(t, resultString, entry) + + entry = "SenderId2" + assert.Contains(t, resultString, entry) + + entry = "ApproximateReceiveCount3" + assert.Contains(t, resultString, entry) + + entry = "SentTimestamp4" + assert.Contains(t, resultString, entry) + + entry = "attr1Stringstring-value" + assert.Contains(t, resultString, entry) + + entry = "attr2binary-valueBinary" + assert.Contains(t, resultString, entry) + + entry = "attr3Numbernumber-value" + assert.Contains(t, resultString, entry) + + entry = "" + assert.Contains(t, resultString, entry) +} + +func Test_ResultMessage_MarshalXML_success_no_attributes(t *testing.T) { + input := &ResultMessage{ + MessageId: "message-id", + ReceiptHandle: "receipt-handle", + MD5OfBody: "body-md5", + Body: "message-body", + MD5OfMessageAttributes: "message-attrs-md5", + } + expectedOutput := "message-idreceipt-handlebody-md5message-body" + + result, err := xml.Marshal(input) + + assert.Nil(t, err) + + resultString := string(result) + assert.Equal(t, resultString, expectedOutput) +} diff --git a/app/utils/utils.go b/app/utils/utils.go index ef7a9fcb..abc5a299 100644 --- a/app/utils/utils.go +++ b/app/utils/utils.go @@ -2,7 +2,6 @@ package utils import ( "crypto/md5" - "encoding/base64" "encoding/binary" "encoding/hex" "encoding/json" @@ -31,9 +30,6 @@ func init() { XmlDecoder.IgnoreUnknownKeys(true) } -// QUESTION - alternately we could have the router.actionHandler method call this, but then our router maps -// need to track the request type AND the function call. I think there'd be a lot of interface switching -// back and forth. func TransformRequest(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) { switch req.Header.Get("Content-Type") { case "application/x-amz-json-1.0": @@ -92,47 +88,18 @@ func CreateErrorResponseV1(errKey string, isSqs bool) (int, interfaces.AbstractR respStruct := models.ErrorResponse{ Result: err.Response(), - RequestId: "00000000-0000-0000-0000-000000000000", // TODO - fix + RequestId: "00000000-0000-0000-0000-000000000000", } return err.StatusCode(), respStruct } -// TODO: -// Refactor internal model for MessageAttribute between SendMessage and ReceiveMessage -// from app.SqsMessageAttributeValue(old) to models.MessageAttributeValue(new) and remove this temporary function. -func ConvertToOldMessageAttributeValueStructure(newValues map[string]models.MessageAttributeValue) map[string]models.SqsMessageAttributeValue { - attributes := make(map[string]models.SqsMessageAttributeValue) - - for name, entry := range newValues { - // StringListValue and BinaryListValue is currently not implemented - // Please refer app/gosqs/message_attributes.go - value := "" - valueKey := "" - if entry.StringValue != "" { - value = entry.StringValue - valueKey = "StringValue" - } else if entry.BinaryValue != "" { - value = entry.BinaryValue - valueKey = "BinaryValue" - } - attributes[name] = models.SqsMessageAttributeValue{ - Name: name, - DataType: entry.DataType, - Value: value, - ValueKey: valueKey, - } - } - - return attributes -} - func GetMD5Hash(text string) string { hasher := md5.New() hasher.Write([]byte(text)) return hex.EncodeToString(hasher.Sum(nil)) } -func HashAttributes(attributes map[string]models.SqsMessageAttributeValue) string { +func HashAttributes(attributes map[string]models.MessageAttribute) string { hasher := md5.New() keys := sortedKeys(attributes) @@ -141,20 +108,19 @@ func HashAttributes(attributes map[string]models.SqsMessageAttributeValue) strin addStringToHash(hasher, key) addStringToHash(hasher, attributeValue.DataType) - if attributeValue.ValueKey == "StringValue" { + if attributeValue.DataType == "String" { hasher.Write([]byte{1}) - addStringToHash(hasher, attributeValue.Value) - } else if attributeValue.ValueKey == "BinaryValue" { + addStringToHash(hasher, attributeValue.StringValue) + } else if attributeValue.DataType == "Binary" { hasher.Write([]byte{2}) - bytes, _ := base64.StdEncoding.DecodeString(attributeValue.Value) - addBytesToHash(hasher, bytes) + addBytesToHash(hasher, attributeValue.BinaryValue) } } return hex.EncodeToString(hasher.Sum(nil)) } -func sortedKeys(attributes map[string]models.SqsMessageAttributeValue) []string { +func sortedKeys(attributes map[string]models.MessageAttribute) []string { var keys []string for key := range attributes { keys = append(keys, key) diff --git a/app/utils/utils_test.go b/app/utils/utils_test.go index 851d836c..f2f02dd0 100644 --- a/app/utils/utils_test.go +++ b/app/utils/utils_test.go @@ -128,7 +128,7 @@ func TestGetMD5Hash(t *testing.T) { } func TestSortedKeys(t *testing.T) { - attributes := map[string]models.SqsMessageAttributeValue{ + attributes := map[string]models.MessageAttribute{ "b": {}, "a": {}, } diff --git a/smoke_tests/sns_publish_test.go b/smoke_tests/sns_publish_test.go index e0667fdf..aaafceb4 100644 --- a/smoke_tests/sns_publish_test.go +++ b/smoke_tests/sns_publish_test.go @@ -219,21 +219,21 @@ func Test_Publish_sqs_json_raw_optional_fields(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, response) - receivedMessage, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + receivedMessages, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ QueueUrl: &models.SyncQueues.Queues["subscribed-queue1"].URL, }) - assert.Len(t, receivedMessage.Messages, 1) - assert.Equal(t, message, *receivedMessage.Messages[0].Body) - assert.Len(t, receivedMessage.Messages[0].MessageAttributes, 1) - assert.Equal(t, "649b2c548f103e499304eda4d6d4c5a2", *receivedMessage.Messages[0].MD5OfBody) - assert.Equal(t, "9c35d992dee4528f7d20c274d61e16f5", *receivedMessage.Messages[0].MD5OfMessageAttributes) - - assert.Equal(t, "String", *receivedMessage.Messages[0].MessageAttributes["test"].DataType) - assert.Equal(t, "value", *receivedMessage.Messages[0].MessageAttributes["test"].StringValue) - assert.Equal(t, []byte{}, receivedMessage.Messages[0].MessageAttributes["test"].BinaryValue) - assert.Nil(t, receivedMessage.Messages[0].MessageAttributes["test"].BinaryListValues) - assert.Nil(t, receivedMessage.Messages[0].MessageAttributes["test"].StringListValues) + assert.Len(t, receivedMessages.Messages, 1) + assert.Equal(t, message, *receivedMessages.Messages[0].Body) + assert.Len(t, receivedMessages.Messages[0].MessageAttributes, 1) + assert.Equal(t, "649b2c548f103e499304eda4d6d4c5a2", *receivedMessages.Messages[0].MD5OfBody) + assert.Equal(t, "9c35d992dee4528f7d20c274d61e16f5", *receivedMessages.Messages[0].MD5OfMessageAttributes) + + assert.Equal(t, "String", *receivedMessages.Messages[0].MessageAttributes["test"].DataType) + assert.Equal(t, "value", *receivedMessages.Messages[0].MessageAttributes["test"].StringValue) + assert.Nil(t, receivedMessages.Messages[0].MessageAttributes["test"].BinaryValue) + assert.Nil(t, receivedMessages.Messages[0].MessageAttributes["test"].BinaryListValues) + assert.Nil(t, receivedMessages.Messages[0].MessageAttributes["test"].StringListValues) } func Test_Publish_sqs_json_not_raw_optional_fields(t *testing.T) { diff --git a/smoke_tests/sqs_delete_message_batch_test.go b/smoke_tests/sqs_delete_message_batch_test.go index fac1fe0e..2eddedd2 100644 --- a/smoke_tests/sqs_delete_message_batch_test.go +++ b/smoke_tests/sqs_delete_message_batch_test.go @@ -404,6 +404,8 @@ func Test_DeleteMessageBatchV1_xml_success_not_found_message(t *testing.T) { sdkConfig.BaseEndpoint = aws.String(server.URL) sqsClient := sqs.NewFromConfig(sdkConfig) + e := httpexpect.Default(t, server.URL) + // create queue createQueueResponse, _ := sqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{ QueueName: &af.QueueName, @@ -423,90 +425,35 @@ func Test_DeleteMessageBatchV1_xml_success_not_found_message(t *testing.T) { messageBody2 := "test%20message%20body%202" messageBody3 := "test%20message%20body%203" - type SendMessageRequestBodyXML struct { - Action string `xml:"Action"` - Version string `xml:"Version"` - QueueUrl string `xml:"QueueUrl"` - MessageBody string `xml:"MessageBody"` - } - - sendMessageRequest1 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody1, - } - sendMessageRequest2 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse2.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody2, - } - sendMessageRequest3 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody3, - } - - // send messages - e := httpexpect.Default(t, server.URL) - e.POST("/"). - WithForm(sendMessageRequest1). - Expect(). - Status(http.StatusOK). - Body().Raw() - - e.POST("/"). - WithForm(sendMessageRequest2). - Expect(). - Status(http.StatusOK). - Body().Raw() - - e.POST("/"). - WithForm(sendMessageRequest3). - Expect(). - Status(http.StatusOK). - Body().Raw() - - type ReceiveMessageRequestBodyXML struct { - Action string `xml:"Action"` - QueueUrl string `xml:"QueueUrl"` - Version string `xml:"Version"` - MaxNumberOfMessages string `xml:"MaxNumberOfMessages"` - } + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: &messageBody1, + }) + assert.Nil(t, err) - receiveMessageRequestBodyXML1 := ReceiveMessageRequestBodyXML{ - Action: "ReceiveMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MaxNumberOfMessages: "10", - } + _, err = sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse2.QueueUrl, + MessageBody: &messageBody2, + }) + assert.Nil(t, err) - receiveMessageRequestBodyXML2 := ReceiveMessageRequestBodyXML{ - Action: "ReceiveMessage", - QueueUrl: *createQueueResponse2.QueueUrl, - Version: "2012-11-05", - MaxNumberOfMessages: "10", - } + _, err = sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: &messageBody3, + }) + assert.Nil(t, err) - // received messages - receivedMessages1 := e.POST("/"). - WithForm(receiveMessageRequestBodyXML1). - Expect(). - Status(http.StatusOK). - Body().Raw() - receivedMessageResponse1 := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(receivedMessages1), &receivedMessageResponse1) + receivedMessageResponse1, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MaxNumberOfMessages: 10, + }) + assert.Nil(t, err) - // received messages - receivedMessages2 := e.POST("/"). - WithForm(receiveMessageRequestBodyXML2). - Expect(). - Status(http.StatusOK). - Body().Raw() - receivedMessageResponse2 := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(receivedMessages2), &receivedMessageResponse2) + receivedMessageResponse2, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse2.QueueUrl, + MaxNumberOfMessages: 10, + }) + assert.Nil(t, err) deleteMessageBatchRequestBodyXML := struct { Action string `xml:"Action"` @@ -522,11 +469,11 @@ func Test_DeleteMessageBatchV1_xml_success_not_found_message(t *testing.T) { deletedMessages := e.POST("/"). WithForm(deleteMessageBatchRequestBodyXML). WithFormField("Entries.0.Id", testId1). - WithFormField("Entries.0.ReceiptHandle", receivedMessageResponse1.Result.Messages[0].ReceiptHandle). + WithFormField("Entries.0.ReceiptHandle", *receivedMessageResponse1.Messages[0].ReceiptHandle). WithFormField("Entries.1.Id", testId2). - WithFormField("Entries.1.ReceiptHandle", receivedMessageResponse2.Result.Messages[0].ReceiptHandle). + WithFormField("Entries.1.ReceiptHandle", *receivedMessageResponse2.Messages[0].ReceiptHandle). WithFormField("Entries.2.Id", testId3). - WithFormField("Entries.2.ReceiptHandle", receivedMessageResponse1.Result.Messages[1].ReceiptHandle). + WithFormField("Entries.2.ReceiptHandle", *receivedMessageResponse1.Messages[1].ReceiptHandle). Expect(). Status(http.StatusOK). Body().Raw() @@ -534,14 +481,11 @@ func Test_DeleteMessageBatchV1_xml_success_not_found_message(t *testing.T) { deleteMessageBatchResponse := models.DeleteMessageBatchResponse{} xml.Unmarshal([]byte(deletedMessages), &deleteMessageBatchResponse) - // confirm no message - receivedMessages3 := e.POST("/"). - WithForm(receiveMessageRequestBodyXML1). - Expect(). - Status(http.StatusOK). - Body().Raw() - receivedMessageResponse3 := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(receivedMessages3), &receivedMessageResponse3) + receivedMessageResponse3, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MaxNumberOfMessages: 10, + }) + assert.Nil(t, err) // success: delete messages assert.Contains(t, deleteMessageBatchResponse.Result.Successful[0].Id, testId1) @@ -554,7 +498,7 @@ func Test_DeleteMessageBatchV1_xml_success_not_found_message(t *testing.T) { assert.Contains(t, deleteMessageBatchResponse.Result.Failed[0].Message, failedMessage) // confirm no message - assert.Empty(t, receivedMessageResponse3.Result.Messages) + assert.Empty(t, receivedMessageResponse3.Messages) } func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { @@ -568,6 +512,8 @@ func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { sdkConfig.BaseEndpoint = aws.String(server.URL) sqsClient := sqs.NewFromConfig(sdkConfig) + e := httpexpect.Default(t, server.URL) + // create queue createQueueResponse, _ := sqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{ QueueName: &af.QueueName, @@ -580,72 +526,29 @@ func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { messageBody2 := "test%20message%20body%202" messageBody3 := "test%20message%20body%203" - type SendMessageRequestBodyXML struct { - Action string `xml:"Action"` - Version string `xml:"Version"` - QueueUrl string `xml:"QueueUrl"` - MessageBody string `xml:"MessageBody"` - } - - sendMessageRequest1 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody1, - } - sendMessageRequest2 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody2, - } - sendMessageRequest3 := SendMessageRequestBodyXML{ - Action: "SendMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MessageBody: messageBody3, - } - - // send messages - e := httpexpect.Default(t, server.URL) - e.POST("/"). - WithForm(sendMessageRequest1). - Expect(). - Status(http.StatusOK). - Body().Raw() - - e.POST("/"). - WithForm(sendMessageRequest2). - Expect(). - Status(http.StatusOK). - Body().Raw() + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: &messageBody1, + }) + assert.Nil(t, err) - e.POST("/"). - WithForm(sendMessageRequest3). - Expect(). - Status(http.StatusOK). - Body().Raw() + _, err = sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: &messageBody2, + }) + assert.Nil(t, err) - var ReceiveMessageRequestBodyXML = struct { - Action string `xml:"Action"` - QueueUrl string `xml:"QueueUrl"` - Version string `xml:"Version"` - MaxNumberOfMessages string `xml:"MaxNumberOfMessages"` - }{ - Action: "ReceiveMessage", - QueueUrl: *createQueueResponse.QueueUrl, - Version: "2012-11-05", - MaxNumberOfMessages: "10", - } + _, err = sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: &messageBody3, + }) + assert.Nil(t, err) - // received messages - receivedMessages := e.POST("/"). - WithForm(ReceiveMessageRequestBodyXML). - Expect(). - Status(http.StatusOK). - Body().Raw() - receivedMessageResponse := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(receivedMessages), &receivedMessageResponse) + receivedMessageResponse, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MaxNumberOfMessages: 10, + }) + assert.Nil(t, err) deleteMessageBatchRequestBodyXML := struct { Action string `xml:"Action"` @@ -661,11 +564,11 @@ func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { deletedMessages := e.POST("/"). WithForm(deleteMessageBatchRequestBodyXML). WithFormField("Entries.0.Id", testId1). - WithFormField("Entries.0.ReceiptHandle", receivedMessageResponse.Result.Messages[0].ReceiptHandle). + WithFormField("Entries.0.ReceiptHandle", *receivedMessageResponse.Messages[0].ReceiptHandle). WithFormField("Entries.1.Id", testId2). - WithFormField("Entries.1.ReceiptHandle", receivedMessageResponse.Result.Messages[1].ReceiptHandle). + WithFormField("Entries.1.ReceiptHandle", *receivedMessageResponse.Messages[1].ReceiptHandle). WithFormField("Entries.2.Id", testId3). - WithFormField("Entries.2.ReceiptHandle", receivedMessageResponse.Result.Messages[2].ReceiptHandle). + WithFormField("Entries.2.ReceiptHandle", *receivedMessageResponse.Messages[2].ReceiptHandle). Expect(). Status(http.StatusOK). Body().Raw() @@ -673,14 +576,11 @@ func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { deleteMessageBatchResponse := models.DeleteMessageBatchResponse{} xml.Unmarshal([]byte(deletedMessages), &deleteMessageBatchResponse) - // confirm no message - receivedMessages2 := e.POST("/"). - WithForm(ReceiveMessageRequestBodyXML). - Expect(). - Status(http.StatusOK). - Body().Raw() - receivedMessageResponse2 := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(receivedMessages2), &receivedMessageResponse) + receivedMessageResponse2, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MaxNumberOfMessages: 10, + }) + assert.Nil(t, err) // check no error assert.Empty(t, deleteMessageBatchResponse.Result.Failed) @@ -691,5 +591,5 @@ func Test_DeleteMessageBatchV1_xml_success_all_deletes(t *testing.T) { assert.Contains(t, deleteMessageBatchResponse.Result.Successful[2].Id, testId3) // confirm no message - assert.Empty(t, receivedMessageResponse2) + assert.Empty(t, receivedMessageResponse2.Messages) } diff --git a/smoke_tests/sqs_receive_message_test.go b/smoke_tests/sqs_receive_message_test.go index c2848523..32c93104 100644 --- a/smoke_tests/sqs_receive_message_test.go +++ b/smoke_tests/sqs_receive_message_test.go @@ -8,6 +8,8 @@ import ( "sync" "testing" + sqstypes "github.com/aws/aws-sdk-go-v2/service/sqs/types" + af "github.com/Admiral-Piett/goaws/app/fixtures" "github.com/Admiral-Piett/goaws/app/models" sf "github.com/Admiral-Piett/goaws/smoke_tests/fixtures" @@ -25,7 +27,47 @@ func Test_ReceiveMessageV1_json(t *testing.T) { models.ResetResources() }() - e := httpexpect.Default(t, server.URL) + sdkConfig, _ := config.LoadDefaultConfig(context.TODO()) + sdkConfig.BaseEndpoint = aws.String(server.URL) + sqsClient := sqs.NewFromConfig(sdkConfig) + + createQueueResponse, _ := sqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{ + QueueName: &af.QueueName, + }) + + assert.Equal(t, fmt.Sprintf("%s/new-queue-1", af.BASE_URL), *createQueueResponse.QueueUrl) + + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: aws.String("MyTestMessage"), + }) + assert.Nil(t, err) + + receiveMessageResponse, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + }) + + assert.Nil(t, err) + + assert.Equal(t, 1, len(receiveMessageResponse.Messages)) + assert.Equal(t, "MyTestMessage", *receiveMessageResponse.Messages[0].Body) + assert.Equal(t, "ad4883a84ad41c79aa3a373698c0d4e9", *receiveMessageResponse.Messages[0].MD5OfBody) + assert.Equal(t, "", *receiveMessageResponse.Messages[0].MD5OfMessageAttributes) + + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["ApproximateFirstReceiveTimestamp"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["SenderId"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["ApproximateReceiveCount"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["SentTimestamp"]) + + assert.Len(t, receiveMessageResponse.Messages[0].MessageAttributes, 0) +} + +func Test_ReceiveMessageV1_json_with_attributes(t *testing.T) { + server := generateServer() + defer func() { + server.Close() + models.ResetResources() + }() sdkConfig, _ := config.LoadDefaultConfig(context.TODO()) sdkConfig.BaseEndpoint = aws.String(server.URL) @@ -37,11 +79,25 @@ func Test_ReceiveMessageV1_json(t *testing.T) { assert.Equal(t, fmt.Sprintf("%s/new-queue-1", af.BASE_URL), *createQueueResponse.QueueUrl) - e.POST("/queue/new-queue-1"). - WithForm(sf.SendMessageRequestBodyXML). - Expect(). - Status(http.StatusOK). - Body().Raw() + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: aws.String("MyTestMessage"), + MessageAttributes: map[string]sqstypes.MessageAttributeValue{ + "attr1": { + DataType: aws.String("String"), + StringValue: aws.String("string-value"), + }, + "attr2": { + DataType: aws.String("Number"), + StringValue: aws.String("number-value"), + }, + "attr3": { + DataType: aws.String("Binary"), + BinaryValue: []byte("binary-value"), + }, + }, + }) + assert.Nil(t, err) receiveMessageResponse, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ QueueUrl: createQueueResponse.QueueUrl, @@ -50,7 +106,22 @@ func Test_ReceiveMessageV1_json(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 1, len(receiveMessageResponse.Messages)) - assert.Equal(t, sf.SendMessageRequestBodyXML.MessageBody, *receiveMessageResponse.Messages[0].Body) + assert.Equal(t, "MyTestMessage", *receiveMessageResponse.Messages[0].Body) + assert.Equal(t, "ad4883a84ad41c79aa3a373698c0d4e9", *receiveMessageResponse.Messages[0].MD5OfBody) + assert.Equal(t, "ae8770938aee44bc548cf65ac377e3bf", *receiveMessageResponse.Messages[0].MD5OfMessageAttributes) + + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["ApproximateFirstReceiveTimestamp"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["SenderId"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["ApproximateReceiveCount"]) + assert.NotEmpty(t, receiveMessageResponse.Messages[0].Attributes["SentTimestamp"]) + + assert.Len(t, receiveMessageResponse.Messages[0].MessageAttributes, 3) + assert.Equal(t, "String", *receiveMessageResponse.Messages[0].MessageAttributes["attr1"].DataType) + assert.Equal(t, "string-value", *receiveMessageResponse.Messages[0].MessageAttributes["attr1"].StringValue) + assert.Equal(t, "Number", *receiveMessageResponse.Messages[0].MessageAttributes["attr2"].DataType) + assert.Equal(t, "number-value", *receiveMessageResponse.Messages[0].MessageAttributes["attr2"].StringValue) + assert.Equal(t, "Binary", *receiveMessageResponse.Messages[0].MessageAttributes["attr3"].DataType) + assert.Equal(t, []uint8("binary-value"), receiveMessageResponse.Messages[0].MessageAttributes["attr3"].BinaryValue) } func Test_ReceiveMessageV1_json_while_concurrent_delete(t *testing.T) { @@ -109,21 +180,114 @@ func Test_ReceiveMessageV1_xml(t *testing.T) { assert.Equal(t, fmt.Sprintf("%s/new-queue-1", af.BASE_URL), *createQueueResponse.QueueUrl) - e.POST("/queue/new-queue-1"). - WithForm(sf.SendMessageRequestBodyXML). + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: aws.String("MyTestMessage"), + }) + assert.Nil(t, err) + + response := e.POST("/queue/new-queue-1"). + WithForm(sf.ReceiveMessageRequestBodyXML). Expect(). Status(http.StatusOK). Body().Raw() - r := e.POST("/queue/new-queue-1"). + var receiveMessageResponse models.ReceiveMessageResponse + xml.Unmarshal([]byte(response), &receiveMessageResponse) + + assert.Equal(t, 1, len(receiveMessageResponse.Result.Messages)) + assert.Equal(t, 1, len(receiveMessageResponse.Result.Messages)) + assert.Equal(t, "MyTestMessage", receiveMessageResponse.Result.Messages[0].Body) + assert.Equal(t, "ad4883a84ad41c79aa3a373698c0d4e9", receiveMessageResponse.Result.Messages[0].MD5OfBody) + assert.Equal(t, "", receiveMessageResponse.Result.Messages[0].MD5OfMessageAttributes) + + entry := "ApproximateFirstReceiveTimestamp" + assert.Contains(t, response, entry) + + entry = "SenderId" + assert.Contains(t, response, entry) + + entry = "ApproximateReceiveCount" + assert.Contains(t, response, entry) + + entry = "SentTimestamp" + assert.Contains(t, response, entry) + + assert.Len(t, receiveMessageResponse.Result.Messages[0].MessageAttributes, 0) +} + +func Test_ReceiveMessageV1_xml_with_attributes(t *testing.T) { + server := generateServer() + defer func() { + server.Close() + models.ResetResources() + }() + + e := httpexpect.Default(t, server.URL) + + sdkConfig, _ := config.LoadDefaultConfig(context.TODO()) + sdkConfig.BaseEndpoint = aws.String(server.URL) + sqsClient := sqs.NewFromConfig(sdkConfig) + + createQueueResponse, _ := sqsClient.CreateQueue(context.TODO(), &sqs.CreateQueueInput{ + QueueName: &af.QueueName, + }) + + assert.Equal(t, fmt.Sprintf("%s/new-queue-1", af.BASE_URL), *createQueueResponse.QueueUrl) + + _, err := sqsClient.SendMessage(context.TODO(), &sqs.SendMessageInput{ + QueueUrl: createQueueResponse.QueueUrl, + MessageBody: aws.String("MyTestMessage"), + MessageAttributes: map[string]sqstypes.MessageAttributeValue{ + "attr1": { + DataType: aws.String("String"), + StringValue: aws.String("string-value"), + }, + "attr2": { + DataType: aws.String("Number"), + StringValue: aws.String("number-value"), + }, + "attr3": { + DataType: aws.String("Binary"), + BinaryValue: []byte("binary-value"), + }, + }, + }) + assert.Nil(t, err) + + response := e.POST("/queue/new-queue-1"). WithForm(sf.ReceiveMessageRequestBodyXML). Expect(). Status(http.StatusOK). Body().Raw() - var r1 models.ReceiveMessageResponse - xml.Unmarshal([]byte(r), &r1) + var receiveMessageResponse models.ReceiveMessageResponse + xml.Unmarshal([]byte(response), &receiveMessageResponse) + + assert.Equal(t, 1, len(receiveMessageResponse.Result.Messages)) + assert.Equal(t, 1, len(receiveMessageResponse.Result.Messages)) + assert.Equal(t, "MyTestMessage", receiveMessageResponse.Result.Messages[0].Body) + assert.Equal(t, "ad4883a84ad41c79aa3a373698c0d4e9", receiveMessageResponse.Result.Messages[0].MD5OfBody) + assert.Equal(t, "", receiveMessageResponse.Result.Messages[0].MD5OfMessageAttributes) + + entry := "ApproximateFirstReceiveTimestamp" + assert.Contains(t, response, entry) + + entry = "SenderId" + assert.Contains(t, response, entry) + + entry = "ApproximateReceiveCount" + assert.Contains(t, response, entry) + + entry = "SentTimestamp" + assert.Contains(t, response, entry) + + entry = "attr1Stringstring-value" + assert.Contains(t, response, entry) + + entry = "attr2Numbernumber-value" + assert.Contains(t, response, entry) - assert.Equal(t, 1, len(r1.Result.Messages)) - assert.Equal(t, sf.SendMessageRequestBodyXML.MessageBody, string(r1.Result.Messages[0].Body)) + entry = "attr3binary-valueBinary" + assert.Contains(t, response, entry) } diff --git a/smoke_tests/sqs_send_message_batch_test.go b/smoke_tests/sqs_send_message_batch_test.go index d3c54469..78b9dfb9 100644 --- a/smoke_tests/sqs_send_message_batch_test.go +++ b/smoke_tests/sqs_send_message_batch_test.go @@ -18,7 +18,6 @@ import ( ) func Test_SendMessageBatchV1_Json_Error_Queue_Not_Found(t *testing.T) { - server := generateServer() defer func() { server.Close() @@ -79,7 +78,6 @@ func Test_SendMessageBatchV1_Json_Error_No_Entry(t *testing.T) { } func TestSendMessageBatchV1_Json_Error_IdNotDistinct(t *testing.T) { - server := generateServer() defer func() { server.Close() @@ -125,7 +123,6 @@ func TestSendMessageBatchV1_Json_Error_IdNotDistinct(t *testing.T) { } func TestSendMessageBatchV1_Json_Error_TooManyEntries(t *testing.T) { - server := generateServer() defer func() { server.Close() @@ -221,8 +218,7 @@ func TestSendMessageBatchV1_Json_Error_TooManyEntries(t *testing.T) { assert.Nil(t, SendMessageBatchOutput) } -func TestSendMessageBatchV1_Json_Success(t *testing.T) { - +func TestSendMessageBatchV1_Json_Success_including_attributes(t *testing.T) { server := generateServer() defer func() { server.Close() @@ -244,16 +240,16 @@ func TestSendMessageBatchV1_Json_Success(t *testing.T) { messageBody1 := "test%20message%20body%201" messageBody2 := "test%20message%20body%202" - binaryAttribute := "binary" - stringAttribute := "String" - numberAttribute := "number" + binaryAttributeKey := "binary-key" + stringAttributeKey := "string-key" + numberAttributeKey := "number-key" binaryType := "Binary" stringType := "String" numberType := "Number" - binaryValue := "base64-encoded-value" - stringValue := "hogeValue" + binaryValue := "binary-value" + stringValue := "string-value" numberValue := "100" sendMessageBatchOutput, error := sqsClient.SendMessageBatch(context.TODO(), &sqs.SendMessageBatchInput{ @@ -266,15 +262,15 @@ func TestSendMessageBatchV1_Json_Success(t *testing.T) { Id: &messageId2, MessageBody: &messageBody2, MessageAttributes: map[string]types.MessageAttributeValue{ - binaryAttribute: { + binaryAttributeKey: { BinaryValue: []byte(binaryValue), DataType: &binaryType, }, - stringAttribute: { + stringAttributeKey: { DataType: &stringType, StringValue: &stringValue, }, - numberAttribute: { + numberAttributeKey: { DataType: &numberType, StringValue: &numberValue, }, @@ -292,55 +288,37 @@ func TestSendMessageBatchV1_Json_Success(t *testing.T) { }) assert.Equal(t, "2", getQueueAttributeOutput.Attributes["ApproximateNumberOfMessages"]) - receiveMessageOutput, _ := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + receiveMessageOutput, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ QueueUrl: &queueUrl, MaxNumberOfMessages: 10, }) + assert.Len(t, receiveMessageOutput.Messages, 2) + assert.Nil(t, err) + receivedMessage1 := receiveMessageOutput.Messages[0] receivedMessage2 := receiveMessageOutput.Messages[1] - assert.Equal(t, messageBody1, string(*receivedMessage1.Body)) - assert.Equal(t, messageBody2, string(*receivedMessage2.Body)) - assert.Equal(t, 3, len(receivedMessage2.MessageAttributes)) - - var attr1, attr2, attr3 models.ResultMessageAttribute - for k, attr := range receivedMessage2.MessageAttributes { - if k == binaryAttribute { - attr1.Name = k - attr1.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - BinaryValue: string(attr.BinaryValue), - } - - } else if k == stringAttribute { - attr2.Name = k - attr2.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - } - } else if k == numberAttribute { - attr3.Name = k - attr3.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - } - } - } - assert.Equal(t, binaryAttribute, attr1.Name) - assert.Equal(t, binaryType, attr1.Value.DataType) - assert.Equal(t, "YmFzZTY0LWVuY29kZWQtdmFsdWU=", attr1.Value.BinaryValue) // base64 encoded value - - assert.Equal(t, stringAttribute, attr2.Name) - assert.Equal(t, stringType, attr2.Value.DataType) - assert.Equal(t, stringValue, attr2.Value.StringValue) - - assert.Equal(t, numberAttribute, attr3.Name) - assert.Equal(t, numberType, attr3.Value.DataType) - assert.Equal(t, numberValue, attr3.Value.StringValue) + assert.Equal(t, messageBody1, *receivedMessage1.Body) + assert.Len(t, receivedMessage1.MessageAttributes, 0) + assert.Equal(t, "1c538b76fce1a234bce865025c02b042", *receivedMessage1.MD5OfBody) + assert.Equal(t, "", *receivedMessage1.MD5OfMessageAttributes) + + assert.Equal(t, messageBody2, *receivedMessage2.Body) + assert.Len(t, receivedMessage2.MessageAttributes, 3) + assert.Equal(t, "58bdcfd42148396616e4260421a9b4e5", *receivedMessage2.MD5OfBody) + assert.Equal(t, "ddfbe54b92058bf5b5f00055fa2032a5", *receivedMessage2.MD5OfMessageAttributes) + + assert.Len(t, receivedMessage2.MessageAttributes, 3) + assert.Equal(t, stringType, *receivedMessage2.MessageAttributes[stringAttributeKey].DataType) + assert.Equal(t, stringValue, *receivedMessage2.MessageAttributes[stringAttributeKey].StringValue) + assert.Equal(t, numberType, *receivedMessage2.MessageAttributes[numberAttributeKey].DataType) + assert.Equal(t, numberValue, *receivedMessage2.MessageAttributes[numberAttributeKey].StringValue) + assert.Equal(t, binaryType, *receivedMessage2.MessageAttributes[binaryAttributeKey].DataType) + assert.Equal(t, []uint8(binaryValue), receivedMessage2.MessageAttributes[binaryAttributeKey].BinaryValue) } -func TestSendMessageBatchV1_Xml_Success(t *testing.T) { +func TestSendMessageBatchV1_Xml_Success_including_attributes(t *testing.T) { server := generateServer() defer func() { server.Close() @@ -362,16 +340,16 @@ func TestSendMessageBatchV1_Xml_Success(t *testing.T) { messageBody1 := "test%20message%20body%201" messageBody2 := "test%20message%20body%202" - binaryAttribute := "binary" - stringAttribute := "String" - numberAttribute := "number" + binaryAttributeKey := "binary-key" + stringAttributeKey := "string-key" + numberAttributeKey := "number-key" binaryType := "Binary" stringType := "String" numberType := "Number" - binaryValue := "YmFzZTY0LWVuY29kZWQtdmFsdWU=" - stringValue := "hogeValue" + binaryValue := "binary-value" + stringValue := "string-value" numberValue := "100" // Target test: send a message @@ -390,13 +368,13 @@ func TestSendMessageBatchV1_Xml_Success(t *testing.T) { WithFormField("Entries.0.MessageBody", messageBody1). WithFormField("Entries.1.Id", messageId2). WithFormField("Entries.1.MessageBody", messageBody2). - WithFormField("Entries.1.MessageAttributes.1.Name", binaryAttribute). + WithFormField("Entries.1.MessageAttributes.1.Name", binaryAttributeKey). WithFormField("Entries.1.MessageAttributes.1.Value.DataType", binaryType). WithFormField("Entries.1.MessageAttributes.1.Value.BinaryValue", binaryValue). - WithFormField("Entries.1.MessageAttributes.2.Name", stringAttribute). + WithFormField("Entries.1.MessageAttributes.2.Name", stringAttributeKey). WithFormField("Entries.1.MessageAttributes.2.Value.DataType", stringType). WithFormField("Entries.1.MessageAttributes.2.Value.StringValue", stringValue). - WithFormField("Entries.1.MessageAttributes.3.Name", numberAttribute). + WithFormField("Entries.1.MessageAttributes.3.Name", numberAttributeKey). WithFormField("Entries.1.MessageAttributes.3.Value.DataType", numberType). WithFormField("Entries.1.MessageAttributes.3.Value.StringValue", numberValue). Expect(). @@ -415,51 +393,32 @@ func TestSendMessageBatchV1_Xml_Success(t *testing.T) { }) assert.Equal(t, "2", getQueueAttributeOutput.Attributes["ApproximateNumberOfMessages"]) - receiveMessageOutput, _ := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + receiveMessageOutput, err := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ QueueUrl: &af.QueueUrl, MaxNumberOfMessages: 10, }) + assert.Len(t, receiveMessageOutput.Messages, 2) + assert.Nil(t, err) + receivedMessage1 := receiveMessageOutput.Messages[0] receivedMessage2 := receiveMessageOutput.Messages[1] - assert.Equal(t, messageBody1, string(*receivedMessage1.Body)) - assert.Equal(t, messageBody2, string(*receivedMessage2.Body)) - assert.Equal(t, 3, len(receivedMessage2.MessageAttributes)) - - var attr1, attr2, attr3 models.ResultMessageAttribute - for k, attr := range receivedMessage2.MessageAttributes { - if k == binaryAttribute { - attr1.Name = k - attr1.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - BinaryValue: string(attr.BinaryValue), - } - - } else if k == stringAttribute { - attr2.Name = k - attr2.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - } - } else if k == numberAttribute { - attr3.Name = k - attr3.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - } - } - } - assert.Equal(t, binaryAttribute, attr1.Name) - assert.Equal(t, binaryType, attr1.Value.DataType) - assert.Equal(t, "YmFzZTY0LWVuY29kZWQtdmFsdWU=", attr1.Value.BinaryValue) // base64 encoded value - - assert.Equal(t, stringAttribute, attr2.Name) - assert.Equal(t, stringType, attr2.Value.DataType) - assert.Equal(t, stringValue, attr2.Value.StringValue) - - assert.Equal(t, numberAttribute, attr3.Name) - assert.Equal(t, numberType, attr3.Value.DataType) - assert.Equal(t, numberValue, attr3.Value.StringValue) - + assert.Equal(t, messageBody1, *receivedMessage1.Body) + assert.Len(t, receivedMessage1.MessageAttributes, 0) + assert.Equal(t, "1c538b76fce1a234bce865025c02b042", *receivedMessage1.MD5OfBody) + assert.Equal(t, "", *receivedMessage1.MD5OfMessageAttributes) + + assert.Equal(t, messageBody2, *receivedMessage2.Body) + assert.Len(t, receivedMessage2.MessageAttributes, 3) + assert.Equal(t, "58bdcfd42148396616e4260421a9b4e5", *receivedMessage2.MD5OfBody) + assert.Equal(t, "ddfbe54b92058bf5b5f00055fa2032a5", *receivedMessage2.MD5OfMessageAttributes) + + assert.Len(t, receivedMessage2.MessageAttributes, 3) + assert.Equal(t, stringType, *receivedMessage2.MessageAttributes[stringAttributeKey].DataType) + assert.Equal(t, stringValue, *receivedMessage2.MessageAttributes[stringAttributeKey].StringValue) + assert.Equal(t, numberType, *receivedMessage2.MessageAttributes[numberAttributeKey].DataType) + assert.Equal(t, numberValue, *receivedMessage2.MessageAttributes[numberAttributeKey].StringValue) + assert.Equal(t, binaryType, *receivedMessage2.MessageAttributes[binaryAttributeKey].DataType) + assert.Equal(t, []uint8(binaryValue), receivedMessage2.MessageAttributes[binaryAttributeKey].BinaryValue) } diff --git a/smoke_tests/sqs_send_message_test.go b/smoke_tests/sqs_send_message_test.go index ed23268d..424959ac 100644 --- a/smoke_tests/sqs_send_message_test.go +++ b/smoke_tests/sqs_send_message_test.go @@ -115,46 +115,23 @@ func Test_SendMessageV1_json_with_attributes(t *testing.T) { assert.Equal(t, "1", getQueueAttributeOutput.Attributes["ApproximateNumberOfMessages"]) // Receive message and check attribute - r3, _ := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + receivedMessages, _ := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ QueueUrl: targetQueueUrl, }) - message := r3.Messages[0] - assert.Equal(t, targetMessageBody, string(*message.Body)) - assert.Equal(t, 3, len(message.MessageAttributes)) - var attr1, attr2, attr3 models.ResultMessageAttribute - for k, attr := range message.MessageAttributes { - if k == "attr1" { - attr1.Name = k - attr1.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - BinaryValue: string(attr.BinaryValue), - } - } else if k == "attr2" { - attr2.Name = k - attr2.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - BinaryValue: string(attr.BinaryValue), - } - } else if k == "attr3" { - attr3.Name = k - attr3.Value = &models.ResultMessageAttributeValue{ - DataType: *attr.DataType, - StringValue: *attr.StringValue, - BinaryValue: string(attr.BinaryValue), - } - } - } - assert.Equal(t, "attr1", attr1.Name) - assert.Equal(t, "String", attr1.Value.DataType) - assert.Equal(t, "attr1_value", attr1.Value.StringValue) - assert.Equal(t, "attr2", attr2.Name) - assert.Equal(t, "Number", attr2.Value.DataType) - assert.Equal(t, "2", attr2.Value.StringValue) - assert.Equal(t, "attr3", attr3.Name) - assert.Equal(t, "Binary", attr3.Value.DataType) - assert.Equal(t, "YXR0cjNfdmFsdWU=", attr3.Value.BinaryValue) // base64 encoded "attr3_value" + + assert.Len(t, receivedMessages.Messages, 1) + assert.Equal(t, targetMessageBody, *receivedMessages.Messages[0].Body) + assert.Len(t, receivedMessages.Messages[0].MessageAttributes, 3) + assert.Equal(t, "6703346b272d00929423e54c28b05d71", *receivedMessages.Messages[0].MD5OfBody) + assert.Equal(t, "f371a019316cbdb918de16040b58ccc2", *receivedMessages.Messages[0].MD5OfMessageAttributes) + + assert.Len(t, receivedMessages.Messages[0].MessageAttributes, 3) + assert.Equal(t, attr1_dataType, *receivedMessages.Messages[0].MessageAttributes["attr1"].DataType) + assert.Equal(t, attr1_value, *receivedMessages.Messages[0].MessageAttributes["attr1"].StringValue) + assert.Equal(t, attr2_dataType, *receivedMessages.Messages[0].MessageAttributes["attr2"].DataType) + assert.Equal(t, attr2_value, *receivedMessages.Messages[0].MessageAttributes["attr2"].StringValue) + assert.Equal(t, attr3_dataType, *receivedMessages.Messages[0].MessageAttributes["attr3"].DataType) + assert.Equal(t, attr3_value, receivedMessages.Messages[0].MessageAttributes["attr3"].BinaryValue) } func Test_SendMessageV1_json_MaximumMessageSize_TooBig(t *testing.T) { @@ -305,7 +282,7 @@ func Test_SendMessageV1_xml_with_attributes(t *testing.T) { WithFormField("MessageAttribute.2.Value.StringValue", "2"). WithFormField("MessageAttribute.3.Name", "attr3"). WithFormField("MessageAttribute.3.Value.DataType", "Binary"). - WithFormField("MessageAttribute.3.Value.BinaryValue", "YXR0cjNfdmFsdWU="). + WithFormField("MessageAttribute.3.Value.BinaryValue", "attr3_value"). Expect(). Status(http.StatusOK). Body().Raw() @@ -316,43 +293,22 @@ func Test_SendMessageV1_xml_with_attributes(t *testing.T) { // Wait for DelaySecond time.Sleep(1 * time.Second) - // Receive message and check attribute - receiveMessageBodyXML := struct { - Action string `xml:"Action"` - Version string `xml:"Version"` - QueueUrl string `xml:"QueueUrl"` - }{ - Action: "ReceiveMessage", - Version: "2012-11-05", - QueueUrl: *targetQueueUrl, - } - r = e.POST("/"). - WithForm(receiveMessageBodyXML). - Expect(). - Status(http.StatusOK). - Body().Raw() - r4 := models.ReceiveMessageResponse{} - xml.Unmarshal([]byte(r), &r4) - message := r4.Result.Messages[0] - assert.Equal(t, "Test Message", string(message.Body)) - assert.Equal(t, 3, len(message.MessageAttributes)) - var attr1, attr2, attr3 models.ResultMessageAttribute - for _, attr := range message.MessageAttributes { - if attr.Name == "attr1" { - attr1 = *attr - } else if attr.Name == "attr2" { - attr2 = *attr - } else if attr.Name == "attr3" { - attr3 = *attr - } - } - assert.Equal(t, "attr1", attr1.Name) - assert.Equal(t, "String", attr1.Value.DataType) - assert.Equal(t, "attr1_value", attr1.Value.StringValue) - assert.Equal(t, "attr2", attr2.Name) - assert.Equal(t, "Number", attr2.Value.DataType) - assert.Equal(t, "2", attr2.Value.StringValue) - assert.Equal(t, "attr3", attr3.Name) - assert.Equal(t, "Binary", attr3.Value.DataType) - assert.Equal(t, "YXR0cjNfdmFsdWU=", attr3.Value.BinaryValue) // base64 encoded "attr3_value" + receivedMessages, _ := sqsClient.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{ + QueueUrl: &af.QueueUrl, + MaxNumberOfMessages: 10, + }) + + assert.Len(t, receivedMessages.Messages, 1) + assert.Equal(t, "Test Message", *receivedMessages.Messages[0].Body) + assert.Len(t, receivedMessages.Messages[0].MessageAttributes, 3) + assert.Equal(t, "d1d4180b7e411c4be86b00fb2ee103eb", *receivedMessages.Messages[0].MD5OfBody) + assert.Equal(t, "f371a019316cbdb918de16040b58ccc2", *receivedMessages.Messages[0].MD5OfMessageAttributes) + + assert.Len(t, receivedMessages.Messages[0].MessageAttributes, 3) + assert.Equal(t, "String", *receivedMessages.Messages[0].MessageAttributes["attr1"].DataType) + assert.Equal(t, "attr1_value", *receivedMessages.Messages[0].MessageAttributes["attr1"].StringValue) + assert.Equal(t, "Number", *receivedMessages.Messages[0].MessageAttributes["attr2"].DataType) + assert.Equal(t, "2", *receivedMessages.Messages[0].MessageAttributes["attr2"].StringValue) + assert.Equal(t, "Binary", *receivedMessages.Messages[0].MessageAttributes["attr3"].DataType) + assert.Equal(t, []uint8("attr3_value"), receivedMessages.Messages[0].MessageAttributes["attr3"].BinaryValue) }