/* * xml_behavior_test.c * * Tests XML parser behavior for correctness and specification compliance: * * 1) A element must contain exactly one root value node. * Any additional value nodes after the first root object must * cause parsing to fail. * * 2) Dictionaries of the form: * * CF$UID * ... * * must be converted to PLIST_UID nodes during XML parsing, * including when they appear nested inside other containers. * * These tests ensure proper root handling and UID node conversion * when parsing XML property lists. */ #include #include #include #include #include "plist/plist.h" static int test_nested_cfuid_converts_to_uid(void) { const char *xml = "" "" "" " " " obj" " " " CF$UID" " 7" " " " " ""; plist_t root = NULL; plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root); if (err != PLIST_ERR_SUCCESS || !root) { fprintf(stderr, "nested CF$UID: plist_from_xml failed (err=%d)\n", err); plist_free(root); return 0; } if (plist_get_node_type(root) != PLIST_DICT) { fprintf(stderr, "nested CF$UID: root is not dict\n"); plist_free(root); return 0; } plist_t obj = plist_dict_get_item(root, "obj"); if (!obj) { fprintf(stderr, "nested CF$UID: missing key 'obj'\n"); plist_free(root); return 0; } if (plist_get_node_type(obj) != PLIST_UID) { fprintf(stderr, "nested CF$UID: expected PLIST_UID, got %d\n", plist_get_node_type(obj)); plist_free(root); return 0; } uint64_t uid = 0; plist_get_uid_val(obj, &uid); if (uid != 7) { fprintf(stderr, "nested CF$UID: expected uid=7, got %" PRIu64 "\n", uid); plist_free(root); return 0; } plist_free(root); return 1; } static int test_extra_root_value_is_rejected(void) { /* Two root values inside must be rejected */ const char *xml = "" "" " one" " two" ""; plist_t root = NULL; plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root); /* Must fail, and root must be NULL (consistent with other parsers) */ if (err == PLIST_ERR_SUCCESS || root != NULL) { fprintf(stderr, "extra root value: expected failure, got err=%d root=%p\n", err, (void*)root); plist_free(root); return 0; } return 1; } static int test_scalar_then_extra_node_is_rejected(void) { /* Scalar root followed by another node must be rejected */ const char *xml = "" "" " " " Ax" ""; plist_t root = NULL; plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root); if (err == PLIST_ERR_SUCCESS || root != NULL) { fprintf(stderr, "scalar then extra node: expected failure, got err=%d root=%p\n", err, (void*)root); plist_free(root); return 0; } return 1; } static int test_scalar_with_comment_is_ok(void) { /* Comment after the single root value is not an extra value node */ const char *xml = "" "" " ok" " " ""; plist_t root = NULL; plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root); if (err != PLIST_ERR_SUCCESS || !root) { fprintf(stderr, "scalar + comment: expected success, got err=%d\n", err); plist_free(root); return 0; } if (plist_get_node_type(root) != PLIST_STRING) { fprintf(stderr, "scalar + comment: expected root string, got %d\n", plist_get_node_type(root)); plist_free(root); return 0; } plist_free(root); return 1; } int main(void) { int ok = 1; ok &= test_nested_cfuid_converts_to_uid(); ok &= test_extra_root_value_is_rejected(); ok &= test_scalar_then_extra_node_is_rejected(); ok &= test_scalar_with_comment_is_ok(); return ok ? 0 : 1; }