Skip to content

Commit

Permalink
#49: Support (constant) structures
Browse files Browse the repository at this point in the history
  • Loading branch information
theHolgi committed Mar 20, 2024
1 parent 11ed030 commit d488a3d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
7 changes: 5 additions & 2 deletions hammocking/hammocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ def is_array(self) -> bool:

@property
def is_struct(self) -> bool:
return False # TODO
fields = list(self.t.get_canonical().get_fields())
return len(fields) > 0

@property
def spelling(self) -> str:
Expand Down Expand Up @@ -128,7 +129,9 @@ def is_constant(self) -> bool:
return self._type.is_constant

def initializer(self) -> str:
if self._type.is_array or self._type.is_struct:
if self._type.is_struct:
return f"({self._type.spelling}){{0}}"
elif self._type.is_array:
return "{0}"
else:
return f"({self._type.spelling})0"
Expand Down
5 changes: 5 additions & 0 deletions tests/data/mini_c_test/includes/a.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ void a_step(void);
extern int a_u1;
extern int a_y1;

typedef struct {
int a;
int b;
} s_t;

void a_set_u2(int u2);
int a_get_y2(void);

Expand Down
40 changes: 39 additions & 1 deletion tests/hammocking_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ def clang_parse(snippet: str):
"options": TranslationUnit.PARSE_SKIP_FUNCTION_BODIES | TranslationUnit.PARSE_INCOMPLETE,
}
translation_unit = Index.create(excludeDecls=True).parse(**parseOpts)
return next(Hammock.iter_children(translation_unit.cursor))
def is_var_or_func(c: Cursor) -> bool:
return c.kind == CursorKind.VAR_DECL or c.kind == CursorKind.FUNCTION_DECL
return next(filter (is_var_or_func, Hammock.iter_children(translation_unit.cursor)))

class TestVariable:
def test_simple(self):
Expand Down Expand Up @@ -48,6 +50,15 @@ def test_constant_array(self):
assert w.get_definition() == "const int y[3]"
assert w.initializer() == "{0}"

def test_constant_struct(self):
w = Variable(clang_parse("""
typedef struct { int a; int b; } y_t;
extern const y_t y;"""))
assert w.name == "y"
assert w.is_constant() == True
assert w.get_definition() == "const y_t y"
assert w.initializer() == "(const y_t){0}"


class TestFunction:
def test_void_void(self):
Expand Down Expand Up @@ -297,6 +308,33 @@ def test_variable(self):
self.assertEqual(len(mock.writer.variables), 1, "Mockup shall have a variable")
self.assertEqual(mock.writer.variables[0].get_definition(), "int a", "Variable shall be created in the mockup")

def test_struct_variable(self):
"""Mock a struct variable"""
mock = Hammock(["x"])
self.assertFalse(mock.done, "Should not be done yet")
self.assertListEqual(mock.symbols, ["x"])

mock.parse("""typedef struct { int a; int b; } struct_t;
extern struct_t x;""")
self.assertTrue(mock.done, "Should be done now")
self.assertListEqual(mock.symbols, [])
self.assertEqual(len(mock.writer.variables), 1, "Mockup shall have a variable")
self.assertEqual(mock.writer.variables[0].get_definition(), "struct_t x", "Variable shall be created in the mockup")

def test_const_struct_variable(self):
"""Mock a constant struct variable"""
mock = Hammock(["cx"])
self.assertFalse(mock.done, "Should not be done yet")
self.assertListEqual(mock.symbols, ["cx"])

mock.parse("""typedef struct { int a; int b; } struct_t;
extern const struct_t cx;""")
self.assertTrue(mock.done, "Should be done now")
self.assertListEqual(mock.symbols, [])
self.assertEqual(len(mock.writer.variables), 1, "Mockup shall have a variable")
self.assertEqual(mock.writer.variables[0].get_definition(), "const struct_t cx", "Constant shall be created in the mockup")
self.assertEqual(mock.writer.variables[0].initializer(), "(const struct_t){0}", "Constant shall be initialized with struct initializer")

def test_void_func(self):
"""Mock a void(void) function"""
mock = Hammock(["x"])
Expand Down

0 comments on commit d488a3d

Please sign in to comment.