Skip to content

Commit 6b48475

Browse files
author
chenglong
committed
test(object): cover realize failure rollback
1 parent bd89c3a commit 6b48475

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

src/qom/object.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ bool object_is_realized(const Object *obj)
7777
bool object_realize(Object *obj, Error *err)
7878
{
7979
Type *chain[16];
80+
Type *realized_types[16];
8081
size_t depth;
82+
size_t realized_count = 0;
8183

8284
if (!obj)
8385
{
@@ -101,8 +103,25 @@ bool object_realize(Object *obj, Error *err)
101103
if (info->instance_realize &&
102104
!info->instance_realize(obj, err))
103105
{
106+
while (realized_count)
107+
{
108+
Type *realized_type = realized_types[--realized_count];
109+
const TypeInfo *realized_info =
110+
type_get_info(realized_type);
111+
112+
if (realized_info->instance_unrealize)
113+
{
114+
realized_info->instance_unrealize(obj);
115+
}
116+
}
117+
104118
return false;
105119
}
120+
121+
if (info->instance_realize)
122+
{
123+
realized_types[realized_count++] = type;
124+
}
106125
}
107126

108127
obj->state = OBJECT_STATE_REALIZED;

tests/test_qom.c

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#define TYPE_TEST_LIFECYCLE_PARENT "test-lifecycle-parent"
1010
#define TYPE_TEST_LIFECYCLE_CHILD "test-lifecycle-child"
11+
#define TYPE_TEST_LIFECYCLE_FAILING_CHILD \
12+
"test-lifecycle-failing-child"
1113

1214
typedef struct TestLifecycleObject
1315
{
@@ -63,6 +65,22 @@ static void test_child_unrealize(Object *obj)
6365
lifecycle_event_add('c');
6466
}
6567

68+
static bool test_failing_child_realize(Object *obj, Error *err)
69+
{
70+
(void)obj;
71+
72+
lifecycle_event_add('F');
73+
error_set(err, "child realize failed");
74+
return false;
75+
}
76+
77+
static void test_failing_child_unrealize(Object *obj)
78+
{
79+
(void)obj;
80+
81+
lifecycle_event_add('x');
82+
}
83+
6684
static const TypeInfo test_lifecycle_parent_info = {
6785
.name = TYPE_TEST_LIFECYCLE_PARENT,
6886
.parent = "object",
@@ -79,10 +97,19 @@ static const TypeInfo test_lifecycle_child_info = {
7997
.instance_unrealize = test_child_unrealize,
8098
};
8199

100+
static const TypeInfo test_lifecycle_failing_child_info = {
101+
.name = TYPE_TEST_LIFECYCLE_FAILING_CHILD,
102+
.parent = TYPE_TEST_LIFECYCLE_PARENT,
103+
.instance_size = sizeof(TestLifecycleObject),
104+
.instance_realize = test_failing_child_realize,
105+
.instance_unrealize = test_failing_child_unrealize,
106+
};
107+
82108
static void test_lifecycle_register_types(void)
83109
{
84110
type_register_static(&test_lifecycle_parent_info);
85111
type_register_static(&test_lifecycle_child_info);
112+
type_register_static(&test_lifecycle_failing_child_info);
86113
}
87114

88115
int main(void)
@@ -158,9 +185,8 @@ int main(void)
158185

159186
assert(backend->parent_obj.size == 2ULL * 1024 * 1024 * 1024);
160187
assert(!strcmp(backend->parent_obj.swap_storage, "file:///swap"));
161-
object_free(root);
162188

163-
// ===============
189+
// ====== Test realize callbacks ======
164190
error_clear(&err);
165191

166192
Object *lifecycle_object;
@@ -181,5 +207,24 @@ int main(void)
181207
assert(!strcmp(lifecycle_events, "cp"));
182208

183209
object_free(lifecycle_object);
210+
211+
// ===== Test realize failed ======
212+
Object *failing_object;
213+
214+
failing_object = object_new(TYPE_TEST_LIFECYCLE_FAILING_CHILD);
215+
assert(failing_object != NULL);
216+
217+
lifecycle_events_rest();
218+
error_clear(&err);
219+
220+
assert(!object_realize(failing_object, &err));
221+
assert(!strcmp(err.message, "child realize failed"));
222+
assert(!object_is_realized(failing_object));
223+
assert(!strcmp(lifecycle_events, "PFp"));
224+
225+
object_free(failing_object);
226+
227+
// ======= Release test resources ======
228+
object_free(root);
184229
return 0;
185230
}

0 commit comments

Comments
 (0)