summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/tests/test_smoke_qemu.py
blob: c0354d204b6ded582d2eff5781699d806a522c1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""Live integration smoke test: boots the demo uproc in QEMU.

Skipped cleanly when qemu-system-riscv64 or the demo firmware is absent.
"""
from __future__ import annotations

import os
import shutil
import unittest

import greeneye as ge
from greeneye.errors import GreenEyeError
from greeneye.probes import compile_condition, install

HERE = os.path.dirname(os.path.abspath(__file__))
DEMO_ELF = os.path.join(HERE, "..", "firmware", "uproc_demo", "build", "uproc_demo.elf")


def qemu_available() -> bool:
    return bool(os.environ.get("GREENEYE_QEMU") or shutil.which("qemu-system-riscv64"))


@unittest.skipUnless(qemu_available(), "qemu-system-riscv64 not installed")
@unittest.skipUnless(os.path.exists(DEMO_ELF), "demo firmware not built (make demo)")
class QemuSmokeTests(unittest.TestCase):
    def test_boot_hook_watch_snapshot_analyze(self):
        session = ge.launch(kernel=DEMO_ELF, record=True, name="unittest-smoke")
        hits = []
        try:
            ctrl = session.symbols.lookup("gsp_ctrl")
            session.hook("rpc_sum", on_enter=lambda hit: hits.append(hit))
            session.watch(ctrl + 16, size=8, kind="w")
            session.run(duration=0.6)
            self.assertTrue(session.target.wait_for_uart("GREEN-EYE UPROC DEMO", timeout=1.0))
            self.assertGreaterEqual(len(hits), 1, "rpc_sum hook never fired")
            after = session.snapshot(ctrl, 0x188, "ctrl")
            self.assertEqual(int.from_bytes(after[0:4], "little"), 0x47535031)
            self.assertGreaterEqual(int.from_bytes(after[16:24], "little"), 7)
        finally:
            directory = getattr(session.recorder, "dir", None)
            session.close()
        if directory:
            from greeneye.analyze import render_summary

            report = render_summary(directory)
            self.assertIn("rpc_sum", report)

    def test_probe_spec_install(self):
        session = ge.launch(kernel=DEMO_ELF, name="unittest-probes")
        try:
            spec = {
                "probes": [
                    {
                        "name": "sum",
                        "symbol": "rpc_sum",
                        "when": "a1 > 0",
                        "on_enter": {"log": ["a0", "a1"], "note": "sum called"},
                    }
                ]
            }
            handles = install(session, spec)
            self.assertEqual(len(handles), 1)
            session.run(duration=0.6)
            self.assertEqual(handles[0].hits, 1)  # self-test calls rpc_sum once
        finally:
            session.close()

    def test_condition_guard(self):
        self.assertIsNone(compile_condition(None))
        check = compile_condition("a0 == 0x2a and a1 < 4")
        self.assertTrue(check({"a0": 0x2A, "a1": 2}))
        self.assertFalse(check({"a0": 0x2B, "a1": 2}))
        with self.assertRaises(GreenEyeError):
            compile_condition("__import__('os').system('true')")


if __name__ == "__main__":
    unittest.main()