From 5d6f2899b6e5abee3438f2733d7b97e868343ab3 Mon Sep 17 00:00:00 2001
From: Dan Jones <dan.jones@noc.ac.uk>
Date: Thu, 9 Feb 2023 10:31:49 +0000
Subject: [PATCH] tests: coverage for api notify and receive

+ fix to max_messages query string handling
---
 api_notify_test.py   | 59 ++++++++++++++++++++++++++
 api_receive_test.py  | 98 ++++++++++++++++++++++++++++++++++++++++++++
 conftest.py          | 14 ++++++-
 endpoints/receive.py |  3 +-
 4 files changed, 171 insertions(+), 3 deletions(-)
 create mode 100644 api_notify_test.py
 create mode 100644 api_receive_test.py

diff --git a/api_notify_test.py b/api_notify_test.py
new file mode 100644
index 0000000..164ee0a
--- /dev/null
+++ b/api_notify_test.py
@@ -0,0 +1,59 @@
+import flask
+import json
+import pytest
+from unittest.mock import patch, mock_open, call
+from werkzeug.exceptions import HTTPException
+from api import create_app
+from endpoints import notify
+from conftest import get_auth_header
+
+
+@pytest.mark.usefixtures(
+    "mock_clients", "mock_client_credentials", "mock_post_notify", "mock_message_notify"
+)
+def test_post_notify(
+    mock_clients, mock_client_credentials, mock_post_notify, mock_message_notify
+):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        notify, "write_to_queue"
+    ) as mock_write_to_queue, app.test_client() as app_test_client:
+        auth_header = get_auth_header(app_test_client, mock_client_credentials)
+        response = app_test_client.post(
+            "/notify", json=mock_post_notify, headers=auth_header
+        )
+        assert response.status_code == 200
+        mock_write_to_queue.assert_called_once_with(
+            queue_name="client-1-broadcast", msg=json.dumps(mock_message_notify)
+        )
+
+
+@pytest.mark.usefixtures("mock_clients", "mock_post_notify")
+def test_post_send_no_token(mock_clients, mock_post_notify):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        notify, "write_to_queue"
+    ) as mock_write_to_queue, app.test_client() as app_test_client:
+        response = app_test_client.post("/notify", json=mock_post_notify)
+        assert response.status_code == 403
+        mock_write_to_queue.assert_not_called()
+
+
+@pytest.mark.usefixtures("mock_clients", "mock_post_notify")
+def test_post_send_invalid_token(mock_clients, mock_post_notify):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        notify, "write_to_queue"
+    ) as mock_write_to_queue, app.test_client() as app_test_client:
+        auth_header = {"Authorization": "made-up-token"}
+        response = app_test_client.post(
+            "/notify", json=mock_post_notify, headers=auth_header
+        )
+        assert response.status_code == 403
+        mock_write_to_queue.assert_not_called()
diff --git a/api_receive_test.py b/api_receive_test.py
new file mode 100644
index 0000000..cee13f4
--- /dev/null
+++ b/api_receive_test.py
@@ -0,0 +1,98 @@
+import flask
+import json
+import pytest
+from unittest.mock import patch, mock_open, call
+from werkzeug.exceptions import HTTPException
+from api import create_app
+from endpoints import receive
+from conftest import get_auth_header
+
+
+@pytest.mark.usefixtures(
+    "mock_clients", "mock_client_credentials", "mock_read_from_queue_return"
+)
+def test_get_receive(
+    mock_clients, mock_client_credentials, mock_read_from_queue_return
+):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        receive, "read_from_queue"
+    ) as mock_read_from_queue, app.test_client() as app_test_client:
+        mock_read_from_queue.return_value = mock_read_from_queue_return
+        auth_header = get_auth_header(app_test_client, mock_client_credentials)
+        response = app_test_client.get(
+            "/receive", headers=auth_header
+        )
+        assert response.status_code == 200
+        mock_read_from_queue.assert_called_once_with(
+            queue_name="client-1-inbox", max_msgs=10
+        )
+        assert response.json == mock_read_from_queue_return
+
+
+@pytest.mark.usefixtures(
+    "mock_clients", "mock_client_credentials", "mock_read_from_queue_return"
+)
+def test_get_receive_max_messages(
+    mock_clients, mock_client_credentials, mock_read_from_queue_return
+):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        receive, "read_from_queue"
+    ) as mock_read_from_queue, app.test_client() as app_test_client:
+        mock_read_from_queue.return_value = mock_read_from_queue_return
+        auth_header = get_auth_header(app_test_client, mock_client_credentials)
+        max_messages = 2
+        response = app_test_client.get(
+            "/receive", query_string={ "max_messages": max_messages }, headers=auth_header
+        )
+        assert response.status_code == 200
+        mock_read_from_queue.assert_called_once_with(
+            queue_name="client-1-inbox", max_msgs=max_messages
+        )
+        assert response.json == mock_read_from_queue_return
+
+
+@pytest.mark.usefixtures(
+    "mock_clients", "mock_read_from_queue_return"
+)
+def test_get_receive_no_token(
+    mock_clients, mock_read_from_queue_return
+):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        receive, "read_from_queue"
+    ) as mock_read_from_queue, app.test_client() as app_test_client:
+        mock_read_from_queue.return_value = mock_read_from_queue_return
+        response = app_test_client.get(
+            "/receive"
+        )
+        assert response.status_code == 403
+        mock_read_from_queue.assert_not_called()
+
+
+@pytest.mark.usefixtures(
+    "mock_clients", "mock_read_from_queue_return"
+)
+def test_get_receive_invalid_token(
+    mock_clients, mock_read_from_queue_return
+):
+    app = create_app()
+    with patch(
+        "builtins.open", mock_open(read_data=json.dumps(mock_clients))
+    ) as mock_file_open, patch.object(
+        receive, "read_from_queue"
+    ) as mock_read_from_queue, app.test_client() as app_test_client:
+        mock_read_from_queue.return_value = mock_read_from_queue_return
+        auth_header = {"Authorization": "made-up-token"}
+        response = app_test_client.get(
+            "/receive", headers=auth_header
+        )
+        assert response.status_code == 403
+        mock_read_from_queue.assert_not_called()
diff --git a/conftest.py b/conftest.py
index c6fcacd..bf5c70d 100644
--- a/conftest.py
+++ b/conftest.py
@@ -88,5 +88,15 @@ def mock_post_notify():
 
 @pytest.fixture
 def mock_message_notify():
-    post = posts()["send"]
-    return {"message": post["body"]}
+    post = posts()["notify"]
+    return {"topic": "broadcast", "message": post["body"]}
+
+
+@pytest.fixture
+def mock_read_from_queue_return():
+    return [
+        {
+            "topic": "soar.client-1.something",
+            "message": "this is a pub/sub message from client-1"
+        }
+    ]
diff --git a/endpoints/receive.py b/endpoints/receive.py
index bc299fa..8c892ca 100644
--- a/endpoints/receive.py
+++ b/endpoints/receive.py
@@ -22,7 +22,8 @@ class Receive(AuthResource):
         if errors:
             abort(400, message=str(errors))
 
-        max_messages = request.args.get("max_messages", 10)
+        # force query string parameter value into int
+        max_messages = int(request.args.get("max_messages", 10))
 
         allow = self.auth(request)
         if allow:
-- 
GitLab