/* TEST_BUILD_OUTPUT .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] .*propertyDesc.m:\d+:\d+: warning: null passed to a callee that requires a non-null argument \[-Wnonnull\] END */ #include "test.h" #include "testroot.i" #include #include #include struct objc_property { const char *name; const char *attr; }; #define checkattrlist(attrs, attrcount, target) \ do { \ if (target > 0) { \ testassert(attrs); \ testassert(attrcount == target); \ testassert(malloc_size(attrs) >= \ (1+target) * sizeof(objc_property_attribute_t)); \ testassert(attrs[target].name == NULL); \ testassert(attrs[target].value == NULL); \ } else { \ testassert(!attrs); \ testassert(attrcount == 0); \ } \ } while (0) #define checkattr(attrs, i, n, v) \ do { \ char *attrsstart = (char *)attrs; \ char *attrsend = (char *)attrs + malloc_size(attrs); \ testassert((char*)(attrs+i+1) <= attrsend); \ testassert(attrs[i].name >= attrsstart); \ testassert(attrs[i].value >= attrsstart); \ testassert(attrs[i].name + strlen(attrs[i].name) + 1 <= attrsend); \ testassert(attrs[i].value + strlen(attrs[i].value) + 1 <= attrsend); \ if (n) testassert(0 == strcmp(attrs[i].name, n)); \ else testassert(attrs[i].name == NULL); \ if (v) testassert(0 == strcmp(attrs[i].value, v)); \ else testassert(attrs[i].value == NULL); \ } while (0) int main() { char *value; objc_property_attribute_t *attrs; unsigned int attrcount; // STRING TO ATTRIBUTE LIST (property_copyAttributeList) struct objc_property prop; prop.name = "test"; // null property attrcount = 42; attrs = property_copyAttributeList(NULL, &attrcount); testassert(!attrs); testassert(attrcount == 0); attrs = property_copyAttributeList(NULL, NULL); testassert(!attrs); // null attributes attrcount = 42; prop.attr = NULL; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 0); attrs = property_copyAttributeList(&prop, NULL); testassert(!attrs); // empty attributes attrcount = 42; prop.attr = ""; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 0); attrs = property_copyAttributeList(&prop, NULL); testassert(!attrs); // commas only attrcount = 42; prop.attr = ",,,"; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 0); attrs = property_copyAttributeList(&prop, NULL); testassert(!attrs); // long and short names, with and without values attrcount = 42; prop.attr = "?XX,',\"?!?!\"YY,\"''''\""; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 4); checkattr(attrs, 0, "?", "XX"); checkattr(attrs, 1, "'", ""); checkattr(attrs, 2, "?!?!", "YY"); checkattr(attrs, 3, "''''", ""); free(attrs); // all recognized attributes simultaneously, values with quotes attrcount = 42; prop.attr = "T11,V2222,S333333\",G\"44444444,W,P,D,R,N,C,&"; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 11); checkattr(attrs, 0, "T", "11"); checkattr(attrs, 1, "V", "2222"); checkattr(attrs, 2, "S", "333333\""); checkattr(attrs, 3, "G", "\"44444444"); checkattr(attrs, 4, "W", ""); checkattr(attrs, 5, "P", ""); checkattr(attrs, 6, "D", ""); checkattr(attrs, 7, "R", ""); checkattr(attrs, 8, "N", ""); checkattr(attrs, 9, "C", ""); checkattr(attrs,10, "&", ""); free(attrs); // kitchen sink attrcount = 42; prop.attr = "W,T11,P,?XX,D,V2222,R,',N,S333333\",C,\"?!?!\"YY,&,G\"44444444,\"''''\""; attrs = property_copyAttributeList(&prop, &attrcount); checkattrlist(attrs, attrcount, 15); checkattr(attrs, 0, "W", ""); checkattr(attrs, 1, "T", "11"); checkattr(attrs, 2, "P", ""); checkattr(attrs, 3, "?", "XX"); checkattr(attrs, 4, "D", ""); checkattr(attrs, 5, "V", "2222"); checkattr(attrs, 6, "R", ""); checkattr(attrs, 7, "'", ""); checkattr(attrs, 8, "N", ""); checkattr(attrs, 9, "S", "333333\""); checkattr(attrs,10, "C", ""); checkattr(attrs,11, "?!?!", "YY"); checkattr(attrs,12, "&", ""); checkattr(attrs,13, "G", "\"44444444"); checkattr(attrs,14, "''''", ""); free(attrs); // SEARCH ATTRIBUTE LIST (property_copyAttributeValue) // null property, null name, empty name value = property_copyAttributeValue(NULL, NULL); testassert(!value); value = property_copyAttributeValue(NULL, "foo"); testassert(!value); value = property_copyAttributeValue(NULL, ""); testassert(!value); value = property_copyAttributeValue(&prop, NULL); testassert(!value); value = property_copyAttributeValue(&prop, ""); testassert(!value); // null attributes, empty attributes prop.attr = NULL; value = property_copyAttributeValue(&prop, "foo"); testassert(!value); prop.attr = ""; value = property_copyAttributeValue(&prop, "foo"); testassert(!value); // long and short names, with and without values prop.attr = "?XX,',\"?!?!\"YY,\"''''\""; value = property_copyAttributeValue(&prop, "missing"); testassert(!value); value = property_copyAttributeValue(&prop, "X"); testassert(!value); value = property_copyAttributeValue(&prop, "\""); testassert(!value); value = property_copyAttributeValue(&prop, "'''"); testassert(!value); value = property_copyAttributeValue(&prop, "'''''"); testassert(!value); value = property_copyAttributeValue(&prop, "?"); testassert(0 == strcmp(value, "XX")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "'"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "?!?!"); testassert(0 == strcmp(value, "YY")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "''''"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); // all recognized attributes simultaneously, values with quotes prop.attr = "T11,V2222,S333333\",G\"44444444,W,P,D,R,N,C,&"; value = property_copyAttributeValue(&prop, "T"); testassert(0 == strcmp(value, "11")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "V"); testassert(0 == strcmp(value, "2222")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "S"); testassert(0 == strcmp(value, "333333\"")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "G"); testassert(0 == strcmp(value, "\"44444444")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "W"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "P"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "D"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "R"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "N"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "C"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); value = property_copyAttributeValue(&prop, "&"); testassert(0 == strcmp(value, "")); testassert(malloc_size(value) >= 1 + strlen(value)); free(value); // ATTRIBUTE LIST TO STRING (class_addProperty) BOOL ok; objc_property_t prop2; // null name ok = class_addProperty([TestRoot class], NULL, (objc_property_attribute_t *)1, 1); testassert(!ok); // null description ok = class_addProperty([TestRoot class], "test-null-desc", NULL, 0); testassert(ok); prop2 = class_getProperty([TestRoot class], "test-null-desc"); testassert(prop2); testassert(0 == strcmp(property_getAttributes(prop2), "")); // empty description ok = class_addProperty([TestRoot class], "test-empty-desc", (objc_property_attribute_t*)1, 0); testassert(ok); prop2 = class_getProperty([TestRoot class], "test-empty-desc"); testassert(prop2); testassert(0 == strcmp(property_getAttributes(prop2), "")); // long and short names, with and without values objc_property_attribute_t attrs2[] = { { "!", NULL }, { "?", "XX" }, { "'", "" }, { "?!?!", "YY" }, { "''''", "" } }; ok = class_addProperty([TestRoot class], "test-unrecognized", attrs2, 5); testassert(ok); prop2 = class_getProperty([TestRoot class], "test-unrecognized"); testassert(prop2); testassert(0 == strcmp(property_getAttributes(prop2), "?XX,',\"?!?!\"YY,\"''''\"")); // all recognized attributes simultaneously, values with quotes objc_property_attribute_t attrs3[] = { { "&", "" }, { "C", "" }, { "N", "" }, { "R", "" }, { "D", "" }, { "P", "" }, { "W", "" }, { "G", "\"44444444" }, { "S", "333333\"" }, { "V", "2222" }, { "T", "11" }, }; ok = class_addProperty([TestRoot class], "test-recognized", attrs3, 11); testassert(ok); prop2 = class_getProperty([TestRoot class], "test-recognized"); testassert(prop2); testassert(0 == strcmp(property_getAttributes(prop2), "&,C,N,R,D,P,W,G\"44444444,S333333\",V2222,T11")); // kitchen sink objc_property_attribute_t attrs4[] = { { "&", "" }, { "C", "" }, { "N", "" }, { "R", "" }, { "D", "" }, { "P", "" }, { "W", "" }, { "!", NULL }, { "G", "\"44444444" }, { "S", "333333\"" }, { "V", "2222" }, { "T", "11" }, { "?", "XX" }, { "'", "" }, { "?!?!", "YY" }, { "''''", "" } }; ok = class_addProperty([TestRoot class], "test-sink", attrs4, 16); testassert(ok); prop2 = class_getProperty([TestRoot class], "test-sink"); testassert(prop2); testassert(0 == strcmp(property_getAttributes(prop2), "&,C,N,R,D,P,W,G\"44444444,S333333\",V2222,T11," "?XX,',\"?!?!\"YY,\"''''\"")); succeed(__FILE__); }