diff --git a/.cirrus.yml b/.cirrus.yml index 5ccf8745f..bb3761c58 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -64,6 +64,24 @@ build_python_lib_task: dist_artifacts: path: "target/wheels/*" +test_python_lib_task: + container: + matrix: + - image: python:3.8 + - image: python:3.9 + - image: python:3.10 + - image: python:3.11 + - image: python:3.12 + setup_script: + - apt-get update + - apt-get install -y curl + - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + - chmod +x rustup-init.sh && ./rustup-init.sh -y --profile minimal + build_script: + - source $HOME/.cargo/env + - python -m pip install tox + - make pytest + functional_task: # Run for PRs with a specific label required_pr_labels: run-functional-tests diff --git a/Makefile b/Makefile index 6803b060e..f2cd296d8 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,13 @@ pylib: $(call out_console,MATURIN,Building python bindings ...) $(CONTAINER_RUNTIME) run --rm --name retis_build_maturin -v $$PWD:/io:z ghcr.io/pyo3/maturin build -m retis-events/Cargo.toml -F python-lib +pytest-deps: + @which tox &> /dev/null || (echo "Please install tox ('pip install tox')."; exit 1) + +pytest: pytest-deps + $(call out_console,TOX,Testing python bindings ...) + cd retis-events && tox + clean-ebpf: $(call out_console,CLEAN,cleaning ebpf progs...) for i in $(EBPF_PROBES) $(EBPF_HOOKS); do \ @@ -127,6 +134,7 @@ help: $(PRINT) 'release -- Builds Retis with the release option.' $(PRINT) 'test -- Builds and runs unit tests.' $(PRINT) 'pylib -- Builds the python bindings.' + $(PRINT) 'pytest -- Tests the python bindings (requires "tox" installed).' $(PRINT) $(PRINT) 'Optional variables that can be used to override the default behavior:' $(PRINT) 'V -- If set to 1 the verbose output will be printed.' @@ -142,4 +150,4 @@ help: $(PRINT) 'NOVENDOR -- Avoid to self detect and consume the vendored headers' $(PRINT) ' shipped with libbpf-sys.' -.PHONY: all bench clean clean-ebpf ebpf $(EBPF_PROBES) $(EBPF_HOOKS) help install release test pylib +.PHONY: all bench clean clean-ebpf ebpf $(EBPF_PROBES) $(EBPF_HOOKS) help install release test pylib pytest-deps pytest diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index d2b76a41d..c481f7975 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -100,6 +100,7 @@ flavor coding style for the BPF parts. 1. `cargo clippy -- -D warnings` 1. `make test V=1`, or to include runtime tests, `CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER=sudo CARGO_CMD_OPTS="--features=test_cap_bpf" make test V=1` + 1. `make pytest V=1` 1. Make sure commits are [signed off](https://www.kernel.org/doc/html/latest/process/submitting-patches.html?highlight=signed%20off#developer-s-certificate-of-origin-1-1). 1. Use a clear, concise and descriptive title. diff --git a/retis-events/pytests/test_reader.py b/retis-events/pytests/test_reader.py new file mode 100644 index 000000000..150a720ed --- /dev/null +++ b/retis-events/pytests/test_reader.py @@ -0,0 +1,61 @@ +from retis import * + +import pytest + + +def verify_event(e): + """Verify the event is valid""" + assert e.__class__ == Event + assert isinstance(e.raw(), dict) + assert isinstance(e.show(), str) + assert "userspace" in e or "kernel" in e + + +def verify_event_reader(r): + assert r.__class__ == EventReader + for e in r: + verify_event(e) + + +def verify_series_reader(r): + assert r.__class__ == SeriesReader + for s in r: + assert s.__class__ == EventSeries + length = len(s) + i = 0 + + for e in s: + verify_event(e) + i += 1 + + assert i == length + + +def test_event_reader(): + """Test event reader is capable of reading valid events""" + r = EventReader("test_data/test_events.json") + verify_event_reader(r) + + +def test_series_reader(): + """Test SeriesReader is capable of reading sorted events""" + r = SeriesReader("test_data/test_events_sorted.json") + verify_series_reader(r) + + +def test_event_File(): + """Test EventFile is capable of reading reader is capable generating + iterators""" + f = EventFile("test_data/test_events.json") + assert not f.sorted() + verify_event_reader(f.iter_events()) + + with pytest.raises(Exception): + f.iter_series() + + sf = EventFile("test_data/test_events_sorted.json") + assert sf.sorted() + verify_series_reader(sf.iter_series()) + + with pytest.raises(Exception): + sf.iter_events() diff --git a/retis-events/test_data/test_events_sorted.json b/retis-events/test_data/test_events_sorted.json new file mode 100644 index 000000000..d6d418fef --- /dev/null +++ b/retis-events/test_data/test_events_sorted.json @@ -0,0 +1,3 @@ +[{"common":{"smp_id":0,"task":{"comm":"napi/phy0-8197","pid":1360,"tgid":1360},"timestamp":23868643385999},"kernel":{"probe_type":"kprobe","symbol":"tcp_v4_rcv"},"skb":{},"skb-tracking":{"orig_head":18446616568293939200,"skb":18446616546229617920,"timestamp":23868643385999},"tracking":{"idx":0,"skb":{"orig_head":18446616568293939200,"skb":18446616546229617920,"timestamp":23868643385999}}}] +[{"common":{"smp_id":2,"task":{"comm":"napi/phy0-8197","pid":1360,"tgid":1360},"timestamp":23868955262984},"kernel":{"probe_type":"raw_tracepoint","symbol":"openvswitch:ovs_dp_upcall"},"ovs":{"cmd":1,"cpu":1,"event_type":"upcall","port":3366920467},"skb":{},"skb-tracking":{"orig_head":18446616576100907520,"skb":18446616546107689472,"timestamp":23868955262984},"tracking":{"idx":0,"skb":{"orig_head":18446616576100907520,"skb":18446616546107689472,"timestamp":23868955262984}}},{"common":{"smp_id":3,"task":{"comm":"napi/phy0-8197","pid":1360,"tgid":1360},"timestamp":23868955276361},"kernel":{"probe_type":"kretprobe","symbol":"ovs_dp_upcall"},"ovs":{"event_type":"upcall_return","ret":0,"upcall_cpu":1,"upcall_ts":23868955262984},"skb":{},"skb-tracking":{"orig_head":18446616576100907520,"skb":18446616546107689472,"timestamp":23868955262984},"tracking":{"idx":1,"skb":{"orig_head":18446616576100907520,"skb":18446616546107689472,"timestamp":23868955262984}}}] +[{"common":{"smp_id":0,"task":{"comm":"napi/phy0-8197","pid":1360,"tgid":1360},"timestamp":23868955449721},"kernel":{"probe_type":"raw_tracepoint","symbol":"skb:kfree_skb"},"skb":{},"skb-drop":{"drop_reason":"NO_SOCKET"},"skb-tracking":{"orig_head":18446616575285769216,"skb":18446616552502694400,"timestamp":23868955437572},"tracking":{"idx":0,"skb":{"orig_head":18446616575285769216,"skb":18446616552502694400,"timestamp":23868955437572}}}] diff --git a/retis-events/tox.ini b/retis-events/tox.ini new file mode 100644 index 000000000..240d9ce91 --- /dev/null +++ b/retis-events/tox.ini @@ -0,0 +1,12 @@ +[tox] +requires = + tox>=4 +env_list = py{38,39,310,311,312} + +[testenv] +description = Run unit tests +deps = + pytest>=7 + maturin>=1.7 +commands = + pytest {posargs:pytests}