jira-agent/tests/test_clients.py

151 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import unittest
from _common import agent, jira_cfg, no_sleep
from fake_jira import FakeJira
class ClientsTest(unittest.TestCase):
def setUp(self):
self.fake = FakeJira()
self.jira = agent.JiraClient(jira_cfg(self.fake))
self.jira.sleep = no_sleep
def tearDown(self):
self.fake.stop()
def test_get_and_counters(self):
self.fake.add("AURORA-1")
data = self.jira.get("/rest/api/2/issue/AURORA-1", fields="summary")
self.assertEqual(data["fields"]["summary"], "Тема AURORA-1")
self.assertEqual(self.jira.calls, 1)
self.assertIsNotNone(self.jira.last_call_at)
self.assertEqual(self.fake.requests[-1], ("GET", "/rest/api/2/issue/AURORA-1"))
def test_retry_on_429_with_retry_after(self):
self.fake.add("AURORA-1")
self.fake.fail_next.append((429, {"Retry-After": "0"}))
self.fake.fail_next.append((503, {}))
data = self.jira.get("/rest/api/2/issue/AURORA-1")
self.assertEqual(data["key"], "AURORA-1")
self.assertEqual(self.jira.rate_limited, 2)
self.assertEqual(self.jira.calls, 3) # считаются все полученные ответы, включая 429/503
def test_http_error_not_retried(self):
with self.assertRaises(agent.HttpError) as cm:
self.jira.get("/rest/api/2/issue/NOPE-1")
self.assertEqual(cm.exception.code, 404)
self.assertIn("Does Not Exist", cm.exception.text)
self.assertEqual(self.jira.calls, 1)
self.assertIsNotNone(self.jira.last_call_at)
def test_gives_up_after_five(self):
self.fake.add("AURORA-1")
self.fake.fail_next.extend([(429, {"Retry-After": "0"})] * 5)
with self.assertRaises(agent.HttpError):
self.jira.get("/rest/api/2/issue/AURORA-1")
self.assertEqual(self.jira.rate_limited, 5)
self.assertEqual(self.jira.calls, 5)
def test_basic_auth_header_and_no_secret_in_repr(self):
self.assertTrue(self.jira.headers["Authorization"].startswith("Basic "))
self.assertNotIn("secret", repr(self.jira))
def test_retry_after_lowercase_header(self):
waits = []
self.jira.sleep = waits.append
self.fake.add("AURORA-1")
self.fake.fail_next.append((429, {"retry-after": "7"}))
self.jira.get("/rest/api/2/issue/AURORA-1")
self.assertEqual(waits, [7])
def test_retry_after_not_a_number(self):
waits = []
self.jira.sleep = waits.append
self.fake.add("AURORA-1")
self.fake.fail_next.append((503, {"Retry-After": "Wed, 21 Oct 2026 07:28:00 GMT"}))
self.jira.get("/rest/api/2/issue/AURORA-1")
self.assertEqual(waits, [60])
def test_bearer_header(self):
cfg = jira_cfg(self.fake)
cfg["jira"]["auth"] = {"type": "bearer", "token": "tok123"}
self.assertEqual(agent.JiraClient(cfg).headers["Authorization"], "Bearer tok123")
def test_unreachable_jira_raises_connection_error(self):
cfg = jira_cfg(self.fake)
cfg["jira"]["base_url"] = "http://127.0.0.1:1"
with self.assertRaises(ConnectionError):
agent.JiraClient(cfg).get("/rest/api/2/myself")
def test_non_json_200_becomes_http_error(self):
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
def log_message(self, *a):
pass
def do_GET(self):
body = b"<html>\xff\xfe not json"
self.send_response(200)
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
srv = HTTPServer(("127.0.0.1", 0), H)
threading.Thread(target=srv.serve_forever, daemon=True).start()
try:
cfg = jira_cfg(self.fake)
cfg["jira"]["base_url"] = "http://127.0.0.1:%d" % srv.server_port
jira = agent.JiraClient(cfg)
with self.assertRaises(agent.HttpError) as cm:
jira.get("/x")
self.assertEqual(cm.exception.code, 200)
self.assertEqual(jira.calls, 1)
finally:
srv.shutdown()
srv.server_close()
def test_secret_not_in_log_output(self):
import io
from contextlib import redirect_stdout
buf = io.StringIO()
self.fake.add("AURORA-1")
self.fake.fail_next.append((429, {"Retry-After": "0"}))
with redirect_stdout(buf):
self.jira.get("/rest/api/2/issue/AURORA-1")
agent.log("проверка")
out = buf.getvalue()
self.assertNotIn("secret", out)
self.assertNotIn(self.jira.headers["Authorization"], out)
def test_load_config_requires_fields(self):
import json
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
path = os.path.join(d, "agent.json")
with open(path, "w", encoding="utf-8") as f:
json.dump({"hub_url": "http://x", "hub_token": "t"}, f)
with self.assertRaises(SystemExit):
agent.load_config(path)
with open(path, "w", encoding="utf-8") as f:
json.dump(jira_cfg(self.fake), f)
cfg = agent.load_config(path)
self.assertEqual(cfg["poll_seconds"], 0)
def test_check_command(self):
import json
import os
import tempfile
with tempfile.TemporaryDirectory() as d:
path = os.path.join(d, "agent.json")
with open(path, "w", encoding="utf-8") as f:
json.dump(jira_cfg(self.fake), f)
# хаб недоступен (порт 1), Jira доступен — check печатает оба результата и возвращает 1
self.assertEqual(agent.main(["--config", path, "check"]), 1)
if __name__ == "__main__":
unittest.main()