#include "unittest/TestSuite.h" #include "stemobject/StemObject.h" #include typedef struct TestObject1 TestObject1; #define TestObject1_superclass StemObject #define TestObject1_ivars \ StemObject_ivars \ int ivar1; #define TestObject1_vtable(self_type) \ StemObject_vtable(self_type) \ void (* function1)(self_type * self, int amount); stemobject_declare(TestObject1); TestObject1 * TestObject1_create(void); bool TestObject1_init(TestObject1 * self); void TestObject1_initCopy(TestObject1 * self, TestObject1 * original); void TestObject1_dispose(TestObject1 * self); TestObject1 * TestObject1_copy(TestObject1 * self); void TestObject1_function1(TestObject1 * self, int amount); #define stemobject_implementation TestObject1 stemobject_vtable_begin(); stemobject_vtable_entry(dispose); stemobject_vtable_entry(function1); stemobject_vtable_end(); TestObject1 * TestObject1_create(void) { stemobject_create_implementation(init) } bool TestObject1_init(TestObject1 * self) { call_super(init, self); self->ivar1 = 10; return true; } void TestObject1_initCopy(TestObject1 * self, TestObject1 * original) { call_super(init, self); self->ivar1 = original->ivar1; } void TestObject1_dispose(TestObject1 * self) { call_super(dispose, self); } TestObject1 * TestObject1_copy(TestObject1 * self) { stemobject_copy_implementation(initCopy) } void TestObject1_function1(TestObject1 * self, int amount) { self->ivar1 += amount; } #undef stemobject_implementation typedef struct TestObject2 TestObject2; #define TestObject2_superclass TestObject1 #define TestObject2_ivars \ TestObject1_ivars \ int ivar2; #define TestObject2_vtable(self_type) \ TestObject1_vtable(self_type) \ void (* function2)(self_type * self); stemobject_declare(TestObject2); TestObject2 * TestObject2_create(void); bool TestObject2_init(TestObject2 * self); void TestObject2_initCopy(TestObject2 * self, TestObject2 * original); void TestObject2_dispose(TestObject2 * self); TestObject2 * TestObject2_copy(TestObject2 * self); void TestObject2_function1(TestObject2 * self, int amount); void TestObject2_function2(TestObject2 * self); #define stemobject_implementation TestObject2 stemobject_vtable_begin(); stemobject_vtable_entry(dispose); stemobject_vtable_entry(function1); stemobject_vtable_entry(function2); stemobject_vtable_end(); TestObject2 * TestObject2_create(void) { stemobject_create_implementation(init) } bool TestObject2_init(TestObject2 * self) { call_super(init, self); self->ivar2 = 20; return true; } void TestObject2_initCopy(TestObject2 * self, TestObject2 * original) { call_super(initCopy, self, (TestObject1 *) original); self->ivar2 = original->ivar2; } void TestObject2_dispose(TestObject2 * self) { call_super(dispose, self); } TestObject2 * TestObject2_copy(TestObject2 * self) { stemobject_copy_implementation(initCopy) } void TestObject2_function1(TestObject2 * self, int amount) { self->ivar1 += amount * 5; call_super(function1, self, amount); } void TestObject2_function2(TestObject2 * self) { self->ivar2++; } #undef stemobject_implementation static void testInit(void) { StemObject objectStruct; bool success; stemobject_assign_vtable(objectStruct, StemObject); success = StemObject_init(&objectStruct); TestCase_assert(success, "Expected true but got false"); TestCase_assert(!objectStruct.protected_ivar(allocated), "Expected false but got true"); TestCase_assert(objectStruct.vtable == &StemObject_class, "Expected %p but got %p", &StemObject_class, objectStruct.vtable); call_virtual(dispose, &objectStruct); } static void assertObject1(TestObject1 * object1) { TestCase_assert(object1 != NULL, "Expected non-NULL but got NULL"); TestCase_assert(object1->vtable == &TestObject1_class, "Expected %p but got %p", &TestObject1_class, object1->vtable); TestCase_assert(object1->ivar1 == 10, "Expected 10 but got %d", object1->ivar1); call_virtual(function1, object1, 1); TestCase_assert(object1->ivar1 == 11, "Expected 11 but got %d", object1->ivar1); } static void assertObject2(TestObject2 * object2) { TestCase_assert(object2 != NULL, "Expected non-NULL but got NULL"); TestCase_assert(object2->vtable == &TestObject2_class, "Expected %p but got %p", &TestObject2_class, object2->vtable); TestCase_assert(object2->ivar1 == 10, "Expected 10 but got %d", object2->ivar1); TestCase_assert(object2->ivar2 == 20, "Expected 20 but got %d", object2->ivar2); call_virtual(function1, object2, 1); TestCase_assert(object2->ivar1 == 16, "Expected 16 but got %d", object2->ivar1); call_virtual(function2, object2); TestCase_assert(object2->ivar2 == 21, "Expected 21 but got %d", object2->ivar2); } static void testVtable(void) { TestObject1 object1, * object1Ptr; TestObject2 object2, * object2Ptr; stemobject_assign_vtable(object1, TestObject1); TestObject1_init(&object1); assertObject1(&object1); call_virtual(dispose, &object1); object1Ptr = TestObject1_create(); assertObject1(object1Ptr); call_virtual(dispose, object1Ptr); stemobject_assign_vtable(object2, TestObject2); TestObject2_init(&object2); assertObject2(&object2); call_virtual(dispose, &object2); object2Ptr = TestObject2_create(); assertObject2(object2Ptr); call_virtual(dispose, object2Ptr); } static void testReflection(void) { StemObject stemObject; TestObject1 testObject1; TestObject2 testObject2; stemobject_assign_vtable(stemObject, StemObject); StemObject_init(&stemObject); stemobject_assign_vtable(testObject1, TestObject1); TestObject1_init(&testObject1); stemobject_assign_vtable(testObject2, TestObject2); TestObject2_init(&testObject2); TestCase_assert(StemObject_isExactClass(&stemObject, &StemObject_class), "Expected true but got false"); TestCase_assert(!StemObject_isExactClass(&stemObject, &TestObject1_class), "Expected false but got true"); TestCase_assert(!StemObject_isExactClass(&stemObject, &TestObject2_class), "Expected false but got true"); TestCase_assert(StemObject_isClassOrSubclass(&stemObject, &StemObject_class), "Expected true but got false"); TestCase_assert(!StemObject_isClassOrSubclass(&stemObject, &TestObject1_class), "Expected false but got true"); TestCase_assert(!StemObject_isClassOrSubclass(&stemObject, &TestObject2_class), "Expected false but got true"); TestCase_assert(!StemObject_isExactClass(&testObject1, &StemObject_class), "Expected false but got true"); TestCase_assert(StemObject_isExactClass(&testObject1, &TestObject1_class), "Expected true but got false"); TestCase_assert(!StemObject_isExactClass(&testObject1, &TestObject2_class), "Expected false but got true"); TestCase_assert(StemObject_isClassOrSubclass(&testObject1, &StemObject_class), "Expected true but got false"); TestCase_assert(StemObject_isClassOrSubclass(&testObject1, &TestObject1_class), "Expected true but got false"); TestCase_assert(!StemObject_isClassOrSubclass(&testObject1, &TestObject2_class), "Expected false but got true"); TestCase_assert(!StemObject_isExactClass(&testObject2, &StemObject_class), "Expected false but got true"); TestCase_assert(!StemObject_isExactClass(&testObject2, &TestObject1_class), "Expected false but got true"); TestCase_assert(StemObject_isExactClass(&testObject2, &TestObject2_class), "Expected true but got false"); TestCase_assert(StemObject_isClassOrSubclass(&testObject2, &StemObject_class), "Expected true but got false"); TestCase_assert(StemObject_isClassOrSubclass(&testObject2, &TestObject1_class), "Expected true but got false"); TestCase_assert(StemObject_isClassOrSubclass(&testObject2, &TestObject2_class), "Expected true but got false"); } static void testCopy(void) { TestObject1 * original1, * copy1; TestObject2 * original2, * copy2; original1 = TestObject1_create(); original1->ivar1 = 123; copy1 = TestObject1_copy(original1); TestCase_assert(copy1 != NULL, "Expected non-NULL but got NULL"); TestCase_assert(copy1->ivar1 == 123, "Expected 123 but got %d", copy1->ivar1); call_virtual(dispose, copy1); call_virtual(dispose, original1); original2 = TestObject2_create(); original2->ivar1 = 456; original2->ivar2 = 789; copy2 = TestObject2_copy(original2); TestCase_assert(copy2 != NULL, "Expected non-NULL but got NULL"); TestCase_assert(copy2->ivar1 == 456, "Expected 456 but got %d", copy2->ivar1); TestCase_assert(copy2->ivar2 == 789, "Expected 789 but got %d", copy2->ivar2); call_virtual(dispose, copy2); call_virtual(dispose, original2); } TEST_SUITE(StemObjectTest, testInit, testVtable, testReflection, testCopy)