Skip to content
This repository has been archived by the owner on Sep 12, 2021. It is now read-only.

Commit

Permalink
Added first iintegration tests -- mock http server
Browse files Browse the repository at this point in the history
  • Loading branch information
karthanistyr committed Jul 19, 2018
1 parent 2715f49 commit 4ad2963
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 9 deletions.
File renamed without changes.
18 changes: 11 additions & 7 deletions pymatrix/backend/http.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import aiohttp
import asyncio
import pymatrix.backend.backend
import pymatrix.backend.base

_METHOD_GET="GET"
_METHOD_PUT="PUT"
Expand Down Expand Up @@ -36,7 +36,7 @@ def body(self): return self._body
@property
def is_error(self): return self._is_error

class HttpBackend(pymatrix.backend.backend.BackendBase):
class HttpBackend(pymatrix.backend.base.BackendBase):
"""
A HTTP backend
"""
Expand All @@ -51,7 +51,7 @@ def __init__(self):
async def connect(
self,
hostname,
port=pymatrix.backend.backend.DEFAULT_MARIX_PORT):
port):
"""
Creates a HTTPS session ready to accept messages
"""
Expand All @@ -60,9 +60,13 @@ async def connect(
self.hostname = None
self._port = None

real_port = port
if(real_port is None):
real_port = pymatrix.backend.base.DEFAULT_MARIX_PORT

self._session = aiohttp.ClientSession()
self._hostname = hostname
self._port = port
self._port = real_port

async def disconnect(self):
"""
Expand All @@ -76,20 +80,20 @@ async def write_event(self, message: RestMessage):
Writes events to the backend to send to the server
"""

print(message.__dict__)
response = await self._session.request(
# proxy="http://localhost:8080",
# verify_ssl=False,
method=message.method,
url="https://{hostname}:{port}{url}".format(
url="http://{hostname}:{port}{url}".format(
hostname=self._hostname,
port=self._port,
url=message.url),
json=message.body,
headers=message.headers
)

return_response = Response(await response.json(), True if response.status >= 400 else False)
return_response = Response(await response.json(),
True if response.status >= 400 else False)
return return_response

async def read_events(self):
Expand Down
3 changes: 2 additions & 1 deletion pymatrix/specification/r0/login.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pymatrix.constants
import pymatrix.error
import pymatrix.localisation
import pymatrix.specification.r0

class LoginRequestMessage(pymatrix.specification.base.RequestMessageBase):
def __init__(self, user=None, address=None, password=None,
Expand Down Expand Up @@ -48,7 +49,7 @@ def __init__(self, user=None, address=None, password=None,
"http":
{
"endpoint":
endpoints[pymatrix.constants.EndpointNamesEnum.Login],
pymatrix.specification.r0.endpoints[pymatrix.constants.EndpointNamesEnum.Login],
"method":
"POST"
}
Expand Down
1 change: 1 addition & 0 deletions pymatrix_tests/framework/fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def wrapper(self, func_name, *args, **kwargs):
except Exception as e:
if(stop_time is None):
stop_time = get_microseconds()
self.test_method_cleanup()
return UnitTestResult.complete(func_name, TestStatusEnum.Fail,
stop_time-start_time, e)
wrapper.__dict__[is_test_method] = True
Expand Down
37 changes: 37 additions & 0 deletions pymatrix_tests/integration_tests/helpers/mock_matrix_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import http.server
import io
import sys

class StaticResponseHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
"""
Returns a static string response with a predetermined HTTP status code.
"""
status_code = None
response_body = None

def setup_response(status_code, response_body):
StaticResponseHTTPRequestHandler.status_code = status_code
StaticResponseHTTPRequestHandler.response_body = response_body

def __init__(self, request, client_address, server):
if(StaticResponseHTTPRequestHandler.status_code is None
or StaticResponseHTTPRequestHandler.response_body is None):
raise Exception("Error no status code or response body")
super().__init__(request, client_address, server)

def send_static_response(self):
self.send_response_only(StaticResponseHTTPRequestHandler.status_code)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(StaticResponseHTTPRequestHandler.response_body \
.encode(sys.getfilesystemencoding()))


def do_GET(self):
self.send_static_response()
def do_POST(self):
self.send_static_response()
def do_PUT(self):
self.send_static_response()
def do_DELETE(self):
self.send_static_response()
91 changes: 91 additions & 0 deletions pymatrix_tests/integration_tests/logintests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from pymatrix_tests.framework.fixture import TestClassBase, testmethod
from pymatrix_tests.framework.asserts import Assert
from pymatrix_tests.integration_tests.helpers.mock_matrix_server import StaticResponseHTTPRequestHandler
import pymatrix.client
import pymatrix.specification.base
import pymatrix.specification.r0.login
import asyncio
import http
import http.server
import threading

server_hostname = "localhost"
server_port = 49993

class LoginTests(TestClassBase):

client = None
server = None
worker_thread = None

def test_method_init(self):
self.server = http.server.HTTPServer((server_hostname, server_port), StaticResponseHTTPRequestHandler)
self.server.timeout = 0.1 # will hang for .1 second max
self.worker_thread = threading.Thread(target=self.server.handle_request)
self.worker_thread.start()


self.client = pymatrix.client.ClientFactory.get_client()
asyncio.get_event_loop(). \
run_until_complete(self.client.connect(server_hostname, server_port))

def test_method_cleanup(self):
asyncio.get_event_loop().run_until_complete(self.client.logout())
self.worker_thread.join()
self.server.server_close()

# securely reset the state
StaticResponseHTTPRequestHandler.response_body = None
StaticResponseHTTPRequestHandler.status_code = None

@testmethod
def T_login_should_succeed(self):
# arrange
username = "local_username"
password = "correct_password"
response_home_server = "localhost"
response_user_id = "@{}:{}".format(username, response_home_server)
response_access_token = "ABCDE123456"
response_device_id = "DEVICE123"
response_json = "{{\"user_id\": \"{}\", \
\"access_token\": \"{}\", \
\"home_server\": \"{}\", \
\"device_id\": \"{}\"}}" \
.format(response_user_id, response_access_token,
response_home_server, response_device_id)
StaticResponseHTTPRequestHandler.setup_response(
http.HTTPStatus.OK, response_json)

# act
response = asyncio.get_event_loop() \
.run_until_complete(self.client.login(username, password))

# assert
assert isinstance(response,
pymatrix.specification.r0.login.LoginResponseMessage)
assert response.user_id == response_user_id
assert response.home_server == response_home_server

@testmethod
def T_login_should_fail(self):
# arrange
username = "karthanistyr"
password = "wrongpassword"
errcode = "M_WRONG_PASSWORD"
error = "Error: wrong password"
response_json = "{{\"errcode\": \"{}\", \"error\": \"{}\"}}" \
.format(errcode, error)
StaticResponseHTTPRequestHandler.setup_response(
http.HTTPStatus.FORBIDDEN, response_json)

loop = asyncio.get_event_loop()

# act
response = asyncio.get_event_loop() \
.run_until_complete(self.client.login(username, password))

# assert
assert isinstance(response,
pymatrix.specification.base.ErrorMessageBase)
assert response.error == error
assert response.errcode == errcode
20 changes: 20 additions & 0 deletions pymatrix_tests/tests/specification/basetests.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,23 @@ def _define_message_types(self):

# assert
assert types == MessageType1

@testmethod
def T_get_message_instantiate_first_type_in_tuple(self):
class MessageType1: pass
class ResponseType1: pass
class MessageType2: pass
class ResponseType2: pass
class CustomSpec(pymatrix.specification.base.SpecificationBase):
def _define_message_types(self):
self.message_code_type = {
"type1": (MessageType1, ResponseType1),
"type2": (MessageType2, ResponseType2)
}
message_code = "type1"

# act
req = CustomSpec().get_message(message_code)

# assert
assert isinstance(req, MessageType1)
4 changes: 3 additions & 1 deletion runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
from pymatrix_tests.tests.serialisationtests import SerialisationTests, \
SerialisablePropertyTests, JsonSerialiserTests
from pymatrix_tests.tests.specification.basetests import SpecificationBaseTests
from pymatrix_tests.integration_tests.logintests import LoginTests

classes_to_test = [
SerialisationTests,
SerialisablePropertyTests,
JsonSerialiserTests,
SpecificationBaseTests
SpecificationBaseTests,
LoginTests
]

runner = TestRunner()
Expand Down

0 comments on commit 4ad2963

Please sign in to comment.