-
Notifications
You must be signed in to change notification settings - Fork 43
CFSet: add a test suite for creation, lookup and mutation #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| #include "CoreFoundation/CFSet.h" | ||
| #include "../CFTesting.h" | ||
|
|
||
| static void | ||
| countApplier (const void *value, void *context) | ||
| { | ||
| (void)value; | ||
| *((CFIndex *)context) += 1; | ||
| } | ||
|
|
||
| int main (void) | ||
| { | ||
| CFSetRef set; | ||
| CFSetRef copy; | ||
| CFSetRef other; | ||
| CFSetRef empty; | ||
| const void *values[3]; | ||
| const void *out[3]; | ||
| const void *found; | ||
| const void *otherValues[2]; | ||
| CFIndex applied; | ||
| CFIndex i; | ||
| Boolean present; | ||
|
|
||
| values[0] = CFSTR("a"); | ||
| values[1] = CFSTR("b"); | ||
| values[2] = CFSTR("c"); | ||
|
|
||
| set = CFSetCreate (NULL, values, 3, &kCFTypeSetCallBacks); | ||
| PASS_CF(set != NULL, "CFSet created."); | ||
|
|
||
| PASS_CF(CFSetGetTypeID () != 0, "CFSet type ID is not zero."); | ||
| PASS_CF(CFGetTypeID (set) == CFSetGetTypeID (), | ||
| "CFSet has the CFSet type ID."); | ||
|
|
||
| PASS_CF(CFSetGetCount (set) == 3, "CFSetGetCount returns the value count."); | ||
|
|
||
| PASS_CF(CFSetContainsValue (set, CFSTR("b")), | ||
| "CFSetContainsValue finds a present value."); | ||
| PASS_CF(!CFSetContainsValue (set, CFSTR("z")), | ||
| "CFSetContainsValue rejects an absent value."); | ||
|
|
||
| PASS_CF(CFSetGetCountOfValue (set, CFSTR("b")) == 1, | ||
| "CFSetGetCountOfValue returns 1 for a present value."); | ||
| PASS_CF(CFSetGetCountOfValue (set, CFSTR("z")) == 0, | ||
| "CFSetGetCountOfValue returns 0 for an absent value."); | ||
|
|
||
| found = CFSetGetValue (set, CFSTR("c")); | ||
| PASS_CFEQ(found, CFSTR("c"), "CFSetGetValue returns the stored value."); | ||
| PASS_CF(CFSetGetValue (set, CFSTR("z")) == NULL, | ||
| "CFSetGetValue returns NULL for an absent value."); | ||
|
|
||
| found = NULL; | ||
| present = CFSetGetValueIfPresent (set, CFSTR("a"), &found); | ||
| PASS_CF(present && found != NULL, | ||
| "CFSetGetValueIfPresent reports a present value."); | ||
| present = CFSetGetValueIfPresent (set, CFSTR("z"), &found); | ||
| PASS_CF(!present, | ||
| "CFSetGetValueIfPresent reports an absent value."); | ||
|
|
||
| CFSetGetValues (set, out); | ||
| for (i = 0; i < 3; i++) | ||
| PASS_CF(CFSetContainsValue (set, out[i]), | ||
| "CFSetGetValues returns stored values."); | ||
|
|
||
| /* CFSetApplyFunction must visit every value exactly once. */ | ||
| applied = 0; | ||
| CFSetApplyFunction (set, countApplier, &applied); | ||
| PASS_CF(applied == 3, "CFSetApplyFunction visits every value."); | ||
|
|
||
| copy = CFSetCreateCopy (NULL, set); | ||
| PASS_CF(copy != NULL, "CFSetCreateCopy returns a set."); | ||
| PASS_CFEQ(copy, set, "A copy is equal to the original."); | ||
| PASS_CF(CFHash (copy) == CFHash (set), | ||
| "A copy hashes the same as the original."); | ||
| CFRelease (copy); | ||
|
|
||
| /* A set with different members is not equal. */ | ||
| otherValues[0] = CFSTR("a"); | ||
| otherValues[1] = CFSTR("x"); | ||
| other = CFSetCreate (NULL, otherValues, 2, &kCFTypeSetCallBacks); | ||
| PASS_CFNEQ(other, set, "Sets with different members are not equal."); | ||
| CFRelease (other); | ||
|
|
||
| /* An empty set. */ | ||
| empty = CFSetCreate (NULL, NULL, 0, &kCFTypeSetCallBacks); | ||
| PASS_CF(empty != NULL && CFSetGetCount (empty) == 0, | ||
| "An empty set has count 0."); | ||
| PASS_CF(!CFSetContainsValue (empty, CFSTR("a")), | ||
| "An empty set contains no value."); | ||
| PASS_CF(CFSetGetValue (empty, CFSTR("a")) == NULL, | ||
| "CFSetGetValue on an empty set returns NULL."); | ||
| CFRelease (empty); | ||
|
|
||
| CFRelease (set); | ||
|
|
||
| return 0; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe also add a brief test for empty sets.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| #include "CoreFoundation/CFSet.h" | ||
| #include "../CFTesting.h" | ||
|
|
||
| int main (void) | ||
| { | ||
| CFMutableSetRef set; | ||
| CFMutableSetRef copy; | ||
|
|
||
| set = CFSetCreateMutable (NULL, 0, &kCFTypeSetCallBacks); | ||
| PASS_CF(set != NULL, "CFMutableSet created."); | ||
| PASS_CF(CFSetGetCount (set) == 0, "A new mutable set is empty."); | ||
|
|
||
| CFSetAddValue (set, CFSTR("a")); | ||
| CFSetAddValue (set, CFSTR("b")); | ||
| PASS_CF(CFSetGetCount (set) == 2, "CFSetAddValue adds values."); | ||
|
|
||
| /* A set holds each value once: adding a present value is a no-op. */ | ||
| CFSetAddValue (set, CFSTR("a")); | ||
| PASS_CF(CFSetGetCount (set) == 2, | ||
| "CFSetAddValue does not duplicate a present value."); | ||
|
|
||
| /* CFSetSetValue adds a value that is not yet present. */ | ||
| CFSetSetValue (set, CFSTR("c")); | ||
| PASS_CF(CFSetGetCount (set) == 3 && CFSetContainsValue (set, CFSTR("c")), | ||
| "CFSetSetValue adds an absent value."); | ||
| CFSetSetValue (set, CFSTR("c")); | ||
| PASS_CF(CFSetGetCount (set) == 3, | ||
| "CFSetSetValue leaves an already-present value alone."); | ||
|
|
||
| /* CFSetReplaceValue only acts when the value is already present. */ | ||
| CFSetReplaceValue (set, CFSTR("a")); | ||
| PASS_CF(CFSetGetCount (set) == 3 && CFSetContainsValue (set, CFSTR("a")), | ||
| "CFSetReplaceValue keeps a present value."); | ||
| CFSetReplaceValue (set, CFSTR("z")); | ||
| PASS_CF(CFSetGetCount (set) == 3 && !CFSetContainsValue (set, CFSTR("z")), | ||
| "CFSetReplaceValue ignores an absent value."); | ||
|
|
||
| copy = CFSetCreateMutableCopy (NULL, 0, set); | ||
| PASS_CF(copy != NULL, "CFSetCreateMutableCopy returns a set."); | ||
| PASS_CFEQ(copy, set, "A mutable copy is equal to the original."); | ||
| CFRelease (copy); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also test whether removing an absent value is a no op.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
|
||
| CFSetRemoveValue (set, CFSTR("b")); | ||
| PASS_CF(CFSetGetCount (set) == 2, "CFSetRemoveValue removes a value."); | ||
| PASS_CF(!CFSetContainsValue (set, CFSTR("b")), | ||
| "A removed value is no longer present."); | ||
|
|
||
| CFSetRemoveValue (set, CFSTR("z")); | ||
| PASS_CF(CFSetGetCount (set) == 2, | ||
| "CFSetRemoveValue of an absent value is a no-op."); | ||
|
|
||
| CFSetRemoveAllValues (set); | ||
| PASS_CF(CFSetGetCount (set) == 0, | ||
| "CFSetRemoveAllValues empties the set."); | ||
|
|
||
| CFRelease (set); | ||
|
|
||
| return 0; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also have a test for sets created from an array of values with duplicates / NULLs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding that test surfaced a bug, so I've left it out of this suite rather than assert the broken behaviour:
CFSetCreatedoesn't de-duplicate. From{a, b, a}it returns count 3, andCFSetGetValuesthen hands back a garbage third pointer (segfault). Root cause isGSHashTableCreateincrementing_countper array element with no existing-key check, soCFDictionaryCreate/CFBagCreateare affected too. I'll fix that in a separate PR and add the de-dup test (and the NULL-callbacks case) there.