static void test_partial_freeze() { /* Test that freeze of only part of the graph correctly adjusts objects that * point to the newly-frozen objects. */ upb_msgdef *m1 = upb_msgdef_newnamed("M1", &m1); upb_msgdef *m2 = upb_msgdef_newnamed("M2", &m2); upb_msgdef *m3 = upb_msgdef_newnamed("M3", &m3); upb_fielddef *f1 = upb_fielddef_new(&f1); upb_fielddef *f2 = upb_fielddef_new(&f2); upb_def *defs[2]; defs[0] = upb_msgdef_upcast_mutable(m1); defs[1] = upb_msgdef_upcast_mutable(m2); upb_fielddef_settype(f1, UPB_TYPE_MESSAGE); ASSERT(upb_fielddef_setnumber(f1, 1, NULL)); ASSERT(upb_fielddef_setname(f1, "f1", NULL)); ASSERT(upb_fielddef_setmsgsubdef(f1, m1, NULL)); upb_fielddef_settype(f2, UPB_TYPE_MESSAGE); ASSERT(upb_fielddef_setnumber(f2, 2, NULL)); ASSERT(upb_fielddef_setname(f2, "f2", NULL)); ASSERT(upb_fielddef_setmsgsubdef(f2, m2, NULL)); ASSERT(upb_msgdef_addfield(m3, f1, &f1, NULL)); ASSERT(upb_msgdef_addfield(m3, f2, &f2, NULL)); /* Freeze M1 and M2, which should cause the group to be split * and m3 (left mutable) to take references on m1 and m2. */ ASSERT(upb_def_freeze(defs, 2, NULL)); ASSERT(upb_msgdef_isfrozen(m1)); ASSERT(upb_msgdef_isfrozen(m2)); ASSERT(!upb_msgdef_isfrozen(m3)); upb_msgdef_unref(m1, &m1); upb_msgdef_unref(m2, &m2); upb_msgdef_unref(m3, &m3); }
static void test_noreftracking() { /* Reftracking is not required; clients can pass UPB_UNTRACKED_REF for owner. */ upb_msgdef *md = upb_msgdef_new(UPB_UNTRACKED_REF); upb_msgdef_ref(md, UPB_UNTRACKED_REF); /* Clients can mix tracked and untracked refs. */ upb_msgdef_ref(md, &md); upb_msgdef_unref(md, UPB_UNTRACKED_REF); upb_msgdef_unref(md, UPB_UNTRACKED_REF); /* Call some random function on the messagedef to test that it is alive. */ ASSERT(!upb_msgdef_isfrozen(md)); upb_msgdef_unref(md, &md); }
upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { assert(upb_msgdef_isfrozen(md)); int extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); upb_handlers *h = calloc(sizeof(*h) + extra, 1); if (!h) return NULL; h->msg = md; upb_msgdef_ref(h->msg, h); upb_status_clear(&h->status_); h->sub = calloc(md->submsg_field_count, sizeof(*h->sub)); if (!h->sub) goto oom; if (!upb_refcounted_init(UPB_UPCAST(h), &vtbl, owner)) goto oom; // calloc() above initialized all handlers to NULL. return h; oom: freehandlers(UPB_UPCAST(h)); return NULL; }