diff --git a/hammocking/hammocking.py b/hammocking/hammocking.py index b40852c..84a6cc6 100755 --- a/hammocking/hammocking.py +++ b/hammocking/hammocking.py @@ -65,12 +65,12 @@ def is_array(self) -> bool: or self.t.kind == TypeKind.INCOMPLETEARRAY \ or self.t.kind == TypeKind.VARIABLEARRAY \ or self.t.kind == TypeKind.DEPENDENTSIZEDARRAY - + @property def is_struct(self) -> bool: fields = list(self.t.get_canonical().get_fields()) return len(fields) > 0 - + def initializer(self) -> str: if self.is_struct: return f"({self.spelling}){{0}}" @@ -96,9 +96,9 @@ def __init__(self, configfile: Path = None): return config = configparser.ConfigParser() config.read_string(configfile.read_text()) - # Read generic settings + # Read generic settings self._scan(config.items(section=self.section)) - # Read OS-specific settings + # Read OS-specific settings self._scan(config.items(section=f"{self.section}.{sys.platform}")) def _scan(self, items: Iterator[Tuple[str, str]]) -> None: @@ -132,13 +132,13 @@ def get_definition(self, with_type: bool = True) -> str: return self._type.render(self.name) else: return self.name - + def is_constant(self) -> bool: """Is constant qualified""" return self._type.is_constant - + def initializer(self) -> str: - """C expression to represent the value "0" according to the variable type""" + """C expression to represent the value "0" according to the variable type""" return self._type.initializer() def __repr__(self) -> str: diff --git a/hammocking/templates/gmock/mockup.cc.j2 b/hammocking/templates/gmock/mockup.cc.j2 index bd79b22..411eb43 100644 --- a/hammocking/templates/gmock/mockup.cc.j2 +++ b/hammocking/templates/gmock/mockup.cc.j2 @@ -1,6 +1,6 @@ #include "mockup{{suffix}}.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; {% for variable in variables %} {% if variable.is_constant() %} @@ -15,12 +15,12 @@ extern "C" { {{function.get_signature()}}{ {% if function.has_return_value() %} - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->{{function.get_call()}}; else return {{function.default_return()}}; {% else %} - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->{{function.get_call()}}; {% endif %} } /* {{function.name}} */ diff --git a/hammocking/templates/gmock/mockup.h.j2 b/hammocking/templates/gmock/mockup.h.j2 index 2ad3516..03091bc 100644 --- a/hammocking/templates/gmock/mockup.h.j2 +++ b/hammocking/templates/gmock/mockup.h.j2 @@ -9,16 +9,25 @@ extern "C" { {% endfor %} } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } {% for function in functions %} - MOCK_METHOD(({{function.return_type}}), {{function.name}}, ({{function.get_param_types()}})); + MOCK_METHOD(({{function.return_type}}), {{function.name}}, ({{function.get_param_types()}})); {% endfor %} }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup{{suffix}}_h */ diff --git a/tests/data/gmock_test/test_add_function_get/mockup.cc b/tests/data/gmock_test/test_add_function_get/mockup.cc index 8ae7069..9f00dbb 100644 --- a/tests/data/gmock_test/test_add_function_get/mockup.cc +++ b/tests/data/gmock_test/test_add_function_get/mockup.cc @@ -1,12 +1,12 @@ #include "mockup.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; extern "C" { int a_get_y2(){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->a_get_y2(); else return (int)0; diff --git a/tests/data/gmock_test/test_add_function_get/mockup.h b/tests/data/gmock_test/test_add_function_get/mockup.h index 2eeae23..e20568c 100644 --- a/tests/data/gmock_test/test_add_function_get/mockup.h +++ b/tests/data/gmock_test/test_add_function_get/mockup.h @@ -6,14 +6,23 @@ extern "C" { } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: - MOCK_METHOD((int), a_get_y2, ()); + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } + MOCK_METHOD((int), a_get_y2, ()); }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ diff --git a/tests/data/gmock_test/test_add_function_set_one_arg/mockup.cc b/tests/data/gmock_test/test_add_function_set_one_arg/mockup.cc index 22abc96..dad8b60 100644 --- a/tests/data/gmock_test/test_add_function_set_one_arg/mockup.cc +++ b/tests/data/gmock_test/test_add_function_set_one_arg/mockup.cc @@ -1,12 +1,12 @@ #include "mockup.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; extern "C" { void set_some_int(int some_value){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->set_some_int(some_value); } /* set_some_int */ } diff --git a/tests/data/gmock_test/test_add_function_set_one_arg/mockup.h b/tests/data/gmock_test/test_add_function_set_one_arg/mockup.h index 1812d21..61a5ffe 100644 --- a/tests/data/gmock_test/test_add_function_set_one_arg/mockup.h +++ b/tests/data/gmock_test/test_add_function_set_one_arg/mockup.h @@ -6,14 +6,23 @@ extern "C" { } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: - MOCK_METHOD((void), set_some_int, (int)); + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } + MOCK_METHOD((void), set_some_int, (int)); }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ diff --git a/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.cc b/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.cc index a123e34..daa5dbd 100644 --- a/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.cc +++ b/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.cc @@ -1,12 +1,12 @@ #include "mockup.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; extern "C" { float my_func(float unnamed1){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->my_func(unnamed1); else return (float)0; diff --git a/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.h b/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.h index 33b3fbb..7b5c2c6 100644 --- a/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.h +++ b/tests/data/gmock_test/test_add_function_with_unnamed_arg/mockup.h @@ -6,14 +6,23 @@ extern "C" { } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: - MOCK_METHOD((float), my_func, (float)); + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } + MOCK_METHOD((float), my_func, (float)); }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ diff --git a/tests/data/gmock_test/test_empty_templates/mockup.cc b/tests/data/gmock_test/test_empty_templates/mockup.cc index 8c205d2..37d15fe 100644 --- a/tests/data/gmock_test/test_empty_templates/mockup.cc +++ b/tests/data/gmock_test/test_empty_templates/mockup.cc @@ -1,6 +1,6 @@ #include "mockup.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; extern "C" { diff --git a/tests/data/gmock_test/test_empty_templates/mockup.h b/tests/data/gmock_test/test_empty_templates/mockup.h index e821dfc..5e56358 100644 --- a/tests/data/gmock_test/test_empty_templates/mockup.h +++ b/tests/data/gmock_test/test_empty_templates/mockup.h @@ -6,13 +6,22 @@ extern "C" { } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ diff --git a/tests/data/gmock_test/test_mini_c_gmock/mockup.cc b/tests/data/gmock_test/test_mini_c_gmock/mockup.cc index 5b2a464..d8563e0 100644 --- a/tests/data/gmock_test/test_mini_c_gmock/mockup.cc +++ b/tests/data/gmock_test/test_mini_c_gmock/mockup.cc @@ -1,6 +1,6 @@ #include "mockup.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; int a_y1; int a_y4; @@ -11,50 +11,50 @@ const int const_array[3] = {0}; extern "C" { int a_get_y2(){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->a_get_y2(); else return (int)0; } /* a_get_y2 */ int a_get_y3_and_set_u5(int u5){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->a_get_y3_and_set_u5(u5); else return (int)0; } /* a_get_y3_and_set_u5 */ int a_get_y5(){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->a_get_y5(); else return (int)0; } /* a_get_y5 */ void a_get_y6(int * y6){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->a_get_y6(y6); } /* a_get_y6 */ int c_get_y3_and_set_u5(int u5){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) return mockup_global_ptr->c_get_y3_and_set_u5(u5); else return (int)0; } /* c_get_y3_and_set_u5 */ void c_set_u2(int u2){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->c_set_u2(u2); } /* c_set_u2 */ void c_set_u3_and_u4(int u3, int u4){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->c_set_u3_and_u4(u3, u4); } /* c_set_u3_and_u4 */ void c_set_u6(int u6){ - if(0 != mockup_global_ptr) + if(mockup_global_ptr) mockup_global_ptr->c_set_u6(u6); } /* c_set_u6 */ } diff --git a/tests/data/gmock_test/test_mini_c_gmock/mockup.h b/tests/data/gmock_test/test_mini_c_gmock/mockup.h index 2c91875..23f047b 100644 --- a/tests/data/gmock_test/test_mini_c_gmock/mockup.h +++ b/tests/data/gmock_test/test_mini_c_gmock/mockup.h @@ -8,21 +8,30 @@ extern "C" { #include "c.h" } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: - MOCK_METHOD((int), a_get_y2, ()); - MOCK_METHOD((int), a_get_y3_and_set_u5, (int)); - MOCK_METHOD((int), a_get_y5, ()); - MOCK_METHOD((void), a_get_y6, (int *)); - MOCK_METHOD((int), c_get_y3_and_set_u5, (int)); - MOCK_METHOD((void), c_set_u2, (int)); - MOCK_METHOD((void), c_set_u3_and_u4, (int, int)); - MOCK_METHOD((void), c_set_u6, (int)); + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } + MOCK_METHOD((int), a_get_y2, ()); + MOCK_METHOD((int), a_get_y3_and_set_u5, (int)); + MOCK_METHOD((int), a_get_y5, ()); + MOCK_METHOD((void), a_get_y6, (int *)); + MOCK_METHOD((int), c_get_y3_and_set_u5, (int)); + MOCK_METHOD((void), c_set_u2, (int)); + MOCK_METHOD((void), c_set_u3_and_u4, (int, int)); + MOCK_METHOD((void), c_set_u6, (int)); }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ diff --git a/tests/data/mini_c_test/b.c b/tests/data/mini_c_test/b.c index 4f30f79..5b8ad07 100644 --- a/tests/data/mini_c_test/b.c +++ b/tests/data/mini_c_test/b.c @@ -35,3 +35,10 @@ void b_step(void){ local_extern(2); } + +int x1 = 1; + +int get_x1(void) +{ + return x1; +} \ No newline at end of file diff --git a/tests/data/mini_c_test/b_test.cc b/tests/data/mini_c_test/b_test.cc index 61e5fe8..9a68765 100644 --- a/tests/data/mini_c_test/b_test.cc +++ b/tests/data/mini_c_test/b_test.cc @@ -31,28 +31,40 @@ TEST(b_test, TestSignalChain_3) b_step(); } -TEST(b_test, TestSignalChain_4) +/* Introducing a test fixture */ + +class B : public Test { + void SetUp() override { + mock = CREATE_PERSISTENT_MOCK(); // Create the mock handle in the fixture + // Now some generic reactions can be set up + ON_CALL(*mock, a_get_y5).WillByDefault(Return(13)); + } + void TearDown() override { + DESTROY_PERSISTENT_MOCK(); // Tear down the mock handle to finalize its expecations + } + +protected: + mock_ptr_t mock; +}; + +TEST_F(B, TestSignalChain_4) { - CREATE_MOCK(mymock); a_y4 = 13; - EXPECT_CALL(mymock, c_set_u3_and_u4(_, 13)); + EXPECT_CALL(*mock, c_set_u3_and_u4(_, 13)); b_step(); } -TEST(b_test, TestSignalChain_5) +TEST_F(B, TestSignalChain_5) { - CREATE_MOCK(mymock); - EXPECT_CALL(mymock, a_get_y5()) - .WillOnce(Return(13)); - EXPECT_CALL(mymock, c_get_y3_and_set_u5(13)); + // Makes use of a_get_y5 behavior from the fixture's setup + EXPECT_CALL(*mock, c_get_y3_and_set_u5(13)); b_step(); } -TEST(b_test, TestSignalChain_6) +TEST_F(B, TestSignalChain_6) { - CREATE_MOCK(mymock); - EXPECT_CALL(mymock, a_get_y6(_)) + EXPECT_CALL(*mock, a_get_y6(_)) .WillOnce(SetArgPointee<0>(13)); - EXPECT_CALL(mymock, c_set_u6(13)); + EXPECT_CALL(*mock, c_set_u6(13)); b_step(); } diff --git a/tests/hammocking_test.py b/tests/hammocking_test.py index 6ca4c89..485d57b 100644 --- a/tests/hammocking_test.py +++ b/tests/hammocking_test.py @@ -314,14 +314,23 @@ def test_add_header(self): #include "y.h" } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_h */ """ @@ -343,14 +352,23 @@ def test_add_variable(self): extern "C" { } /* extern "C" */ +class class_mockup; +typedef class_mockup* mock_ptr_t; +extern mock_ptr_t mockup_global_ptr; + class class_mockup { - public: + public: + class_mockup() { mockup_global_ptr = this; } + ~class_mockup() { mockup_global_ptr = nullptr; } }; /* class_mockup */ -extern class_mockup *mockup_global_ptr; +/* Version A: Create a local object that is destroyed when out of scope */ +#define CREATE_MOCK(name) class_mockup name -#define CREATE_MOCK(name) class_mockup name; mockup_global_ptr = &name; +/* Version B: Allocate an object that will be only explicitly deallocated */ +#define CREATE_PERSISTENT_MOCK() new class_mockup +#define DESTROY_PERSISTENT_MOCK() {if(mockup_global_ptr) delete mockup_global_ptr;} #endif /* mockup_new_h */ """ @@ -360,7 +378,7 @@ class class_mockup { writer.get_mockup('mockup.cc') == """#include "mockup_new.h" -class_mockup *mockup_global_ptr = 0; +mock_ptr_t mockup_global_ptr = nullptr; unsigned int a; int x;