Skip to content

Commit

Permalink
ci(cunit): set generic argument and return types (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
P403n1x87 authored Oct 14, 2022
1 parent a4c5a63 commit a633faf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 31 deletions.
29 changes: 11 additions & 18 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,26 +32,19 @@ jobs:
- name: Install test dependencies
run: |
sudo add-apt-repository -y ppa:deadsnakes/ppa
sudo apt-get -y install \
valgrind \
gdb \
python${{ matrix.python-version }} \
python3.10{,-full}
# Using these actions lead to Python binaries that cause SIGSEGV during
# C unit tests. See
# https://github.com/actions/setup-python/issues/442.

# - name: Install Python
# uses: actions/setup-python@v4
# with:
# python-version: ${{ matrix.python-version }}

# - name: Install Python 3.10
# uses: actions/setup-python@v4
# with:
# python-version: "3.10"
gdb
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}-dev

- name: Install Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"

- name: Compile Austin
run: |
Expand Down
35 changes: 24 additions & 11 deletions test/cunit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import ctypes
import re
from ctypes import CDLL, POINTER, Structure, c_char_p, cast
from ctypes import CDLL, POINTER, Structure, c_char_p, c_long, c_void_p, cast
from pathlib import Path
from subprocess import PIPE, STDOUT, run
from types import ModuleType
from typing import Any, Callable, Optional, Type
from typing import Any, Callable, Optional, Type, Union

from pycparser import c_ast, c_parser
from pycparser.plyparser import ParseError
Expand Down Expand Up @@ -90,7 +90,9 @@ def compile(


class CFunctionDef:
def __init__(self, name: str, args: list[str], rtype: Any) -> None:
def __init__(
self, name: str, args: list[tuple[str, Type[ctypes._SimpleCData]]], rtype: Any
) -> None:
self.name = name
self.args = args
self.rtype = rtype
Expand All @@ -101,7 +103,7 @@ def __init__(self, name: str, fields: list[str]) -> None:
self.name = name
self.fields = fields
self.methods = []
self.constructor = False
self.constructor = None


class CType(Structure):
Expand All @@ -113,16 +115,20 @@ def __del__(self) -> None:
self.destroy()

def __repr__(self) -> str:
return f"<{self.name} CObject at {self.__cself__}>"
return f"<{self.__class__.__name__} CObject at {self.__cself__}>"


class CFunction:
def __init__(self, cfuncdef: CFunctionDef, cfunc: Callable[..., Any]) -> None:
self.__name__ = cfuncdef.name
self.__args__ = cfuncdef.args
self.__args__ = [_[0] for _ in cfuncdef.args]
self.__cfunc__ = cfunc
if cfuncdef.rtype is not None:
self.__cfunc__.restype = cfuncdef.rtype

# Prevent argument values from being truncated/mangled
self.__cfunc__.argtypes = [_[1] for _ in cfuncdef.args]
self.__cfunc__.restype = (
cfuncdef.rtype if cfuncdef.rtype is not None else c_long
)

self._posonly = all(_ is None for _ in self.__args__)

Expand Down Expand Up @@ -207,7 +213,6 @@ def __init__(self) -> None:
self.functions = []

def _get_type(self, node: c_ast.Node) -> None:
print(node)
return self.types[" ".join(node.type.type.names)]

def visit_Typedef(self, node: c_ast.Node) -> None:
Expand All @@ -231,8 +236,16 @@ def visit_Decl(self, node: c_ast.Node) -> None:
if isinstance(ret_type, c_ast.PtrDecl):
if "".join(ret_type.type.type.names) == "char":
rtype = c_char_p
else:
rtype = c_void_p

args = (
[_.name if hasattr(_, "name") else None for _ in node.type.args.params]
[
(_.name, c_void_p if isinstance(_.type, c_ast.PtrDecl) else c_long)
if hasattr(_, "name")
else None
for _ in node.type.args.params
]
if node.type.args is not None
else []
)
Expand Down Expand Up @@ -271,7 +284,7 @@ def collect(self, decl: str) -> dict[str, CTypeDef]:
return {
k: v
for k, v in self.types.items()
if isinstance(v, CTypeDef) and v.constructor
if isinstance(v, CTypeDef) and v.constructor is not None
}


Expand Down
5 changes: 4 additions & 1 deletion test/cunit/test_cache.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from ctypes import c_void_p
from test.cunit import C
from test.cunit.cache import Chain, HashTable, LruCache, Queue, QueueItem

import pytest

NULL = 0
C.free.argtypes = [c_void_p]
C.malloc.restype = c_void_p


def test_queue_item():
Expand Down Expand Up @@ -31,7 +34,7 @@ def test_queue(qsize):

assert qsize == 0 or not q.is_empty()
assert q.is_full()
assert q.enqueue(42, 42) is NULL
assert q.enqueue(42, 42) is None

assert values == [q.dequeue() for _ in range(qsize)]

Expand Down
3 changes: 2 additions & 1 deletion test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from collections import Counter, defaultdict
from io import BytesIO, StringIO
from pathlib import Path
from shutil import rmtree
from subprocess import PIPE, CompletedProcess, Popen, check_output, run
from test import PYTHON_VERSIONS
from time import sleep
Expand Down Expand Up @@ -109,7 +110,7 @@ def bt(binary: Path) -> str:
result = gdb(["bt full", "q"], str(binary), target_dir / "CoreDump")

crash.unlink()
target_dir.rmdir()
rmtree(str(target_dir))

return result

Expand Down

0 comments on commit a633faf

Please sign in to comment.