Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Officeyutong committed Jun 8, 2024
1 parent 8e872e6 commit f780d35
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 19 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/eun-vm-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Run ubpf vm tests

on:
push:
branches: "master"
pull_request:
branches: "master"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install cmake make clang-15 ninja-build
- name: Build targets
run: |
CC=clang-15 CXX=clang++-15 cmake -S. -Bbuild -DCMAKE_BUILD_TYPE:STRING=Release -G Ninja
CC=clang-15 CXX=clang++-15 cmake --build ./build --config Release --target libebpf_test_runner
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- run: python --version
- run: |
cd vm-test
python -m venv env
source ./env/bin/activate
pip install -r requirements.txt
pytest
2 changes: 2 additions & 0 deletions .github/workflows/run-execution-context-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
branches: "master"
pull_request:
branches: "master"
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
Expand Down
111 changes: 111 additions & 0 deletions vm-test/test_framework/test_jit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import os
import platform
import tempfile
import struct
import re
from subprocess import Popen, PIPE
from nose.plugins.skip import Skip, SkipTest
import ebpf.assembler
import testdata
import pytest
VM = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"../..", "build/vm-test/libebpf_test_runner")
_test_data_dir = os.path.join(os.path.dirname(
os.path.realpath(__file__)), "../test-cases")
try:
xrange
except NameError:
xrange = range


def jit_supported_platform():
"""Is the JIT supported on the current platform."""
return platform.machine() in ['amd64', 'x86_64', 'arm64', 'aarch64']


def check_datafile(filename):
print("Process", filename)
"""
Given assembly source code and an expected result, run the eBPF program and
verify that the result matches. Uses the JIT compiler.
"""
if not jit_supported_platform():
raise SkipTest("JIT is not supported on the current platform")

data = testdata.read(_test_data_dir, filename)
if 'asm' not in data and 'raw' not in data:
raise SkipTest("no asm or raw section in datafile")
if 'result' not in data and 'error' not in data and 'error pattern' not in data:
raise SkipTest("no result or error section in datafile")
if not os.path.exists(VM):
raise SkipTest("VM not found")
if 'no jit' in data:
raise SkipTest("JIT disabled for this testcase (%s)" % data['no jit'])

if 'raw' in data:
code = b''.join(struct.pack("=Q", x) for x in data['raw'])
else:
code = ebpf.assembler.assemble(data['asm'])

memfile = None

if 'mem' in data:
memfile = tempfile.NamedTemporaryFile()
memfile.write(data['mem'])
memfile.flush()

num_register_offsets = 20
if 'no register offset' in data:
# The JIT relies on a fixed register mapping for the call instruction
num_register_offsets = 1

try:
cmd = [VM]
if memfile:
cmd.extend(['-m', memfile.name])
if 'reload' in data:
cmd.extend(['-R'])
if 'unload' in data:
cmd.extend(['-U'])
cmd.extend(['-j', '-'])

vm = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)

stdout, stderr = vm.communicate(code)
stdout = stdout.decode("utf-8")
stderr = stderr.decode("utf-8")
stderr = stderr.strip()

if 'error' in data:
if data['error'] != stderr:
raise AssertionError(
"Expected error %r, got %r" % (data['error'], stderr))
elif 'error pattern' in data:
if not re.search(data['error pattern'], stderr):
raise AssertionError("Expected error matching %r, got %r" % (
data['error pattern'], stderr))
else:
if stderr:
raise AssertionError("Unexpected error %r" % stderr)

if 'result' in data:
if vm.returncode != 0:
raise AssertionError(
"VM exited with status %d, stderr=%r" % (vm.returncode, stderr))
expected = int(data['result'], 0)
result = int(stdout, 0)
if expected != result:
raise AssertionError(
"Expected result 0x%x, got 0x%x, stderr=%r" % (expected, result, stderr))
else:
if vm.returncode == 0:
raise AssertionError("Expected VM to exit with an error code")
finally:
if memfile:
memfile.close()

@pytest.mark.parametrize("filename", testdata.list_files(_test_data_dir))
# @pytest.mark.parametrize("filename", ["rsh32.data"])
def test_datafiles(filename):
# This is now a regular test function that will be called once for each filename
check_datafile(filename)
39 changes: 20 additions & 19 deletions vm-test/test_runner/test_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ int main(int argc, char **argv) {
bool reload = false;

int opt;
while ((opt = getopt_long(argc, argv, "hm:UR", longopts, NULL)) != -1) {
bool jit = false;
while ((opt = getopt_long(argc, argv, "hm:URj", longopts, NULL)) != -1) {
switch (opt) {
case 'm':
mem_filename = optarg;
break;
// case 'j':
// jit = true;
// break;
case 'j':
jit = true;
break;
// case 'r':
// #if defined(__x86_64__) || defined(_M_X64)
// ebpf_set_register_offset(atoi(optarg));
Expand Down Expand Up @@ -161,22 +162,22 @@ int main(int argc, char **argv) {

uint64_t ret;

// if (jit) {
// ebpf_jit_fn fn = ebpf_compile(vm, &errmsg);
// if (fn == NULL) {
// fprintf(stderr, "Failed to compile: %s\n", errmsg);
// free(errmsg);
// free(mem);
// return 1;
// }
// ret = fn(mem, mem_len);
// } else {

// }
if (ebpf_vm_run(vm, mem, mem_len, &ret) < 0) {
ret = UINT64_MAX;
fprintf(stderr, "%s", ebpf_error_string());
if (jit) {
ebpf_jit_fn fn = ebpf_vm_compile(vm);
if (fn == NULL) {
fprintf(stderr, "Failed to compile: %s\n", errmsg);
free(mem);
return 1;
}
ret = fn(mem, mem_len);
} else {
if (ebpf_vm_run(vm, mem, mem_len, &ret) < 0) {
ret = UINT64_MAX;
fprintf(stderr, "%s", ebpf_error_string());
return 1;
}
}

printf("0x%" PRIx64 "\n", ret);

ebpf_vm_destroy(vm);
Expand Down

0 comments on commit f780d35

Please sign in to comment.