Files
rt-thread/tools/ci/test_issue_labeler.py
T

188 lines
5.1 KiB
Python

#!/usr/bin/env python3
#
# Copyright (c) 2026, RT-Thread Development Team
#
# SPDX-License-Identifier: Apache-2.0
#
import unittest
import issue_labeler
def make_event(body, labels=(), action="opened"):
return {
"action": action,
"repository": {"full_name": "RT-Thread/rt-thread"},
"issue": {
"number": 42,
"body": body,
"labels": [{"name": label} for label in labels],
},
}
class FakeClient:
def __init__(self, available_labels, current_issue=None):
self.available_labels = [{"name": label} for label in available_labels]
self.current_issue = current_issue
self.calls = []
def list_labels(self, repository):
self.calls.append(("list_labels", repository))
return self.available_labels
def add_labels(self, repository, issue_number, labels):
self.calls.append(("add_labels", repository, issue_number, tuple(labels)))
def get_issue(self, repository, issue_number):
self.calls.append(("get_issue", repository, issue_number))
return self.current_issue
def remove_label(self, repository, issue_number, label):
self.calls.append(("remove_label", repository, issue_number, label))
class FormParsingTests(unittest.TestCase):
def test_maps_only_structured_allowlisted_values(self):
body = """### Affected area
Device drivers
### Hardware/BSP vendor
STM32
### Architecture
ARM / AArch64
### Describe the bug
Mentions GD32 and RISC-V here, but free text must not add labels.
"""
self.assertEqual(
issue_labeler.desired_labels(body),
(
"Component",
"component: drivers",
"BSP",
"BSP: STM32",
"Arch: ARM/AArch64",
),
)
def test_unknown_and_no_response_values_are_ignored(self):
body = """### Affected area
Other / Not sure
### Hardware/BSP vendor
_No response_
### Architecture
x86
"""
self.assertEqual(issue_labeler.desired_labels(body), ())
def test_headings_and_values_are_case_insensitive(self):
body = "### AFFECTED AREA\n\nnetworking\n\n### Architecture\n\nrisc-v\n"
self.assertEqual(
issue_labeler.desired_labels(body),
("Component", "component: net", "Arch: RISC-V"),
)
class EventTests(unittest.TestCase):
def test_accepts_supported_issue_actions(self):
context = issue_labeler.event_context(make_event("", action="edited"))
self.assertEqual(context.issue_number, 42)
def test_rejects_pull_requests_and_other_actions(self):
pull_request = make_event("")
pull_request["issue"]["pull_request"] = {"url": "https://example.test"}
self.assertIsNone(issue_labeler.event_context(pull_request))
self.assertIsNone(
issue_labeler.event_context(make_event("", action="closed"))
)
class LabelApplicationTests(unittest.TestCase):
def test_adds_only_existing_labels_and_preserves_current_labels(self):
body = """### Affected area
Kernel
### Hardware/BSP vendor
GD32
"""
context = issue_labeler.event_context(
make_event(body, labels=("Kernel", "bug"))
)
client = FakeClient(("Kernel", "BSP", "bug"))
result = issue_labeler.apply_labels(client, context)
self.assertEqual(result["added"], ["BSP"])
self.assertEqual(result["missing"], ["BSP: GD32"])
self.assertIn(
("add_labels", "RT-Thread/rt-thread", 42, ("BSP",)), client.calls
)
def test_replaces_stale_vendor_and_architecture_labels(self):
body = """### Hardware/BSP vendor
NXP
### Architecture
RISC-V
"""
context = issue_labeler.event_context(
make_event(
body,
labels=("bug", "BSP", "BSP: STM32", "Arch: ARM/AArch64"),
)
)
client = FakeClient(
(
"bug",
"BSP",
"BSP: STM32",
"BSP: NXP",
"Arch: ARM/AArch64",
"Arch: RISC-V",
),
current_issue=context.issue,
)
result = issue_labeler.apply_labels(client, context)
self.assertEqual(result["added"], ["BSP: NXP", "Arch: RISC-V"])
self.assertEqual(result["removed"], ["BSP: STM32", "Arch: ARM/AArch64"])
self.assertIn(
("remove_label", "RT-Thread/rt-thread", 42, "BSP: STM32"),
client.calls,
)
self.assertIn(
("remove_label", "RT-Thread/rt-thread", 42, "Arch: ARM/AArch64"),
client.calls,
)
def test_dry_run_reports_without_mutating(self):
body = "### Affected area\n\nDocumentation\n"
context = issue_labeler.event_context(make_event(body))
client = FakeClient(("Doc",))
result = issue_labeler.apply_labels(client, context, dry_run=True)
self.assertEqual(result["added"], ["Doc"])
self.assertFalse(any(call[0] == "add_labels" for call in client.calls))
if __name__ == "__main__":
unittest.main()