Repository: getmoto/moto

Issue:
Creating an SQS Queue instance using the queue's name (instead of the URL) causes failures when sending messages
This appears to be an undocumented feature of boto3 that isn't mirrored in moto.

It occurs with the latest versions of boto3 (`1.22.0`) and moto (`3.1.6`)

Source code:
```
import boto3


class Simple:
    def __init__(self, queue_name):
        self.resource = boto3.resource('sqs')
        self.queue = self.resource.Queue(queue_name)

    def send_message(self, message_body):
        self.queue.send_message(MessageBody=message_body)


if __name__ == '__main__':
    Simple('my-test-queue').send_message('the-body')
```

Test Code:
```
from unittest import TestCase

import boto3 as boto3
from moto import mock_sqs

from simple import Simple


@mock_sqs
class SimpleTest(TestCase):
    def setUp(self) -> None:
        sqs_resource = boto3.resource('sqs')
        sqs_resource.create_queue(
            QueueName='my-test-queue'
        )

        self.simple = Simple('my-test-queue')

    def test_should(self):
        self.simple.send_message('the-body')
```

Reproduction steps:
- Create a file called `simple.py` containing the source code above
- Create a file called `test_simple.py` containing the test code above
- Create an SQS queue called `my-test-queue`
- Execute the source code (`python simple.py`). A message appears in the SQS queue, and no error is thrown
- Run the test (`python -m pytest test_simple.py`). This fails with the following:
```
$ python -m pytest .
================================================================================================================================== test session starts ===================================================================================================================================
platform linux -- Python 3.10.4, pytest-7.1.2, pluggy-1.0.0
rootdir: /tmp/sqs
collected 1 item                                                                                                                                                                                                                                                                         

test_simple.py F                                                                                                                                                                                                                                                                   [100%]

======================================================================================================================================== FAILURES ========================================================================================================================================
_________________________________________________________________________________________________________________________________ SimpleTest.test_should _________________________________________________________________________________________________________________________________

self = <test_simple.SimpleTest testMethod=test_should>

    def test_should(self):
>       self.simple.send_message('the-body')

test_simple.py:20: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
simple.py:10: in send_message
    self.queue.send_message(MessageBody=message_body)
venv/lib64/python3.10/site-packages/boto3/resources/factory.py:580: in do_action
    response = action(self, *args, **kwargs)
venv/lib64/python3.10/site-packages/boto3/resources/action.py:88: in __call__
    response = getattr(parent.meta.client, operation_name)(*args, **params)
venv/lib64/python3.10/site-packages/botocore/client.py:415: in _api_call
    return self._make_api_call(operation_name, kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <botocore.client.SQS object at 0x7f63e9f9ba00>, operation_name = 'SendMessage', api_params = {'MessageBody': 'the-body', 'QueueUrl': 'my-test-queue'}

    def _make_api_call(self, operation_name, api_params):
        operation_model = self._service_model.operation_model(operation_name)
        service_name = self._service_model.service_name
        history_recorder.record('API_CALL', {
            'service': service_name,
            'operation': operation_name,
            'params': api_params,
        })
        if operation_model.deprecated:
            logger.debug('Warning: %s.%s() is deprecated',
                         service_name, operation_name)
        request_context = {
            'client_region': self.meta.region_name,
            'client_config': self.meta.config,
            'has_streaming_input': operation_model.has_streaming_input,
            'auth_type': operation_model.auth_type,
        }
        request_dict = self._convert_to_request_dict(
            api_params, operation_model, context=request_context)
        resolve_checksum_context(request_dict, operation_model, api_params)
    
        service_id = self._service_model.service_id.hyphenize()
        handler, event_response = self.meta.events.emit_until_response(
            'before-call.{service_id}.{operation_name}'.format(
                service_id=service_id,
                operation_name=operation_name),
            model=operation_model, params=request_dict,
            request_signer=self._request_signer, context=request_context)
    
        if event_response is not None:
            http, parsed_response = event_response
        else:
            apply_request_checksum(request_dict)
            http, parsed_response = self._make_request(
                operation_model, request_dict, request_context)
    
        self.meta.events.emit(
            'after-call.{service_id}.{operation_name}'.format(
                service_id=service_id,
                operation_name=operation_name),
            http_response=http, parsed=parsed_response,
            model=operation_model, context=request_context
        )
    
        if http.status_code >= 300:
            error_code = parsed_response.get("Error", {}).get("Code")
            error_class = self.exceptions.from_code(error_code)
>           raise error_class(parsed_response, operation_name)
E           botocore.exceptions.ClientError: An error occurred (InvalidAddress) when calling the SendMessage operation: The address my-test-queue is not valid for this endpoint.

venv/lib64/python3.10/site-packages/botocore/client.py:745: ClientError
================================================================================================================================ short test summary info =================================================================================================================================
FAILED test_simple.py::SimpleTest::test_should - botocore.exceptions.ClientError: An error occurred (InvalidAddress) when calling the SendMessage operation: The address my-test-queue is not valid for this endpoint.
=================================================================================================================================== 1 failed in 0.38s ====================================================================================================================================

```



Discussion:
Hi @paulmdavies, thanks for raising this. This validation was introduced in #3657 - as a workaround, you should be able to downgrade to Moto 2.2.5.

That PR was introduced specifically because I noticed AWS would throw this error when supplying an invalid URL. I'll do some digging to see what's going on here

Resolving patch:
diff --git a/moto/sqs/exceptions.py b/moto/sqs/exceptions.py
--- a/moto/sqs/exceptions.py
+++ b/moto/sqs/exceptions.py
@@ -128,13 +128,3 @@ def __init__(self, count):
         super().__init__(
             "OverLimit", "{} Actions were found, maximum allowed is 7.".format(count)
         )
-
-
-class InvalidAddress(RESTError):
-    code = 400
-
-    def __init__(self, address):
-        super().__init__(
-            "InvalidAddress",
-            "The address {} is not valid for this endpoint.".format(address),
-        )
diff --git a/moto/sqs/responses.py b/moto/sqs/responses.py
--- a/moto/sqs/responses.py
+++ b/moto/sqs/responses.py
@@ -12,7 +12,6 @@
 
 from .exceptions import (
     EmptyBatchRequest,
-    InvalidAddress,
     InvalidAttributeName,
     ReceiptHandleIsInvalid,
     BatchEntryIdsNotDistinct,
@@ -53,7 +52,8 @@ def _get_queue_name(self):
             if queue_url.startswith("http://") or queue_url.startswith("https://"):
                 return queue_url.split("/")[-1]
             else:
-                raise InvalidAddress(queue_url)
+                # The parameter could be the name itself, which AWS also accepts
+                return queue_url
         except TypeError:
             # Fallback to reading from the URL for botocore
             return self.path.split("/")[-1]


Test patch:
diff --git a/tests/test_sqs/test_sqs.py b/tests/test_sqs/test_sqs.py
--- a/tests/test_sqs/test_sqs.py
+++ b/tests/test_sqs/test_sqs.py
@@ -3018,7 +3018,7 @@ def test_fifo_send_message_when_same_group_id_is_in_dlq():
 
 
 @mock_sqs
-def test_receive_message_should_not_accept_invalid_urls():
+def test_receive_message_using_name__should_return_name_as_url():
     sqs = boto3.resource("sqs", region_name="us-east-1")
     conn = boto3.client("sqs", region_name="us-east-1")
     name = str(uuid4())[0:6]
@@ -3029,17 +3029,10 @@ def test_receive_message_should_not_accept_invalid_urls():
     working_url.should.match(f"/{ACCOUNT_ID}/{name}")
 
     queue = sqs.Queue(name)
-    with pytest.raises(ClientError) as e:
-        queue.send_message(MessageBody="this is a test message")
-    err = e.value.response["Error"]
-    err["Code"].should.equal("InvalidAddress")
-    err["Message"].should.equal(f"The address {name} is not valid for this endpoint.")
+    queue.send_message(MessageBody="this is a test message")
 
-    with pytest.raises(ClientError) as e:
-        conn.receive_message(QueueUrl=name)
-    err = e.value.response["Error"]
-    err["Code"].should.equal("InvalidAddress")
-    err["Message"].should.equal(f"The address {name} is not valid for this endpoint.")
+    resp = queue.receive_messages()
+    resp[0].queue_url.should.equal(name)
 
 
 @mock_sqs