86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
# Copyright 2026 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
import json
|
|
import unittest
|
|
import urllib.error
|
|
from email.message import Message
|
|
from unittest.mock import patch
|
|
|
|
from artemis_client import AuthenticationError, JsonTransport, NetworkError, ProtocolError
|
|
|
|
|
|
class FakeResponse:
|
|
def __init__(self, payload: bytes) -> None:
|
|
self.payload = payload
|
|
|
|
def __enter__(self) -> FakeResponse:
|
|
return self
|
|
|
|
def __exit__(self, *args: object) -> None:
|
|
return None
|
|
|
|
def read(self) -> bytes:
|
|
return self.payload
|
|
|
|
|
|
class JsonTransportTests(unittest.TestCase):
|
|
def test_rejects_non_http_base_url(self) -> None:
|
|
with self.assertRaises(ValueError):
|
|
JsonTransport("file:///tmp/artemis")
|
|
|
|
@patch("urllib.request.urlopen")
|
|
def test_sends_json_and_bearer_token(self, urlopen) -> None:
|
|
urlopen.return_value = FakeResponse(json.dumps({"ok": True}).encode())
|
|
transport = JsonTransport("https://host.example/", token="secret")
|
|
|
|
result = transport.request("POST", "/api/run", json_body={"goal": "test"})
|
|
|
|
self.assertEqual(result, {"ok": True})
|
|
request = urlopen.call_args.args[0]
|
|
self.assertEqual(request.full_url, "https://host.example/api/run")
|
|
self.assertEqual(request.headers["Authorization"], "Bearer secret")
|
|
self.assertEqual(json.loads(request.data), {"goal": "test"})
|
|
|
|
@patch("urllib.request.urlopen")
|
|
def test_maps_unauthorized_response(self, urlopen) -> None:
|
|
urlopen.side_effect = urllib.error.HTTPError(
|
|
"https://host.example/api/run",
|
|
401,
|
|
"Unauthorized",
|
|
Message(),
|
|
io.BytesIO(b'{"detail":"bad token"}'),
|
|
)
|
|
transport = JsonTransport("https://host.example")
|
|
|
|
with self.assertRaisesRegex(AuthenticationError, "bad token"):
|
|
transport.request("GET", "/api/run")
|
|
|
|
@patch("urllib.request.urlopen")
|
|
def test_invalid_json_raises_protocol_error(self, urlopen) -> None:
|
|
urlopen.return_value = FakeResponse(b"not-json")
|
|
transport = JsonTransport("https://host.example")
|
|
|
|
with self.assertRaises(ProtocolError):
|
|
transport.request("GET", "/api/status")
|
|
|
|
@patch("urllib.request.urlopen")
|
|
def test_network_failure_is_wrapped(self, urlopen) -> None:
|
|
urlopen.side_effect = urllib.error.URLError("connection refused")
|
|
transport = JsonTransport("https://host.example")
|
|
|
|
with self.assertRaisesRegex(NetworkError, "connection refused"):
|
|
transport.request("GET", "/api/status")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|