#include <stdint.h>
#include <OpenDirectory/OpenDirectory.h>
#include <DirectoryService/DirectoryService.h>
#include <unistd.h>
#include <pthread.h>
uint32_t gTestCase = 0;
bool gLogErrors = false;
bool gVerbose = false;
char *gLogPath = NULL;
char *gAdminAccount = NULL;
char *gAdminPassword = NULL;
char *gProxyHost = NULL;
char *gProxyPassword = NULL;
char *gProxyUser = NULL;
uint32_t gTestTimes = 1;
uint32_t gCopies = 1;
void usage( char *argv[] )
{
fprintf( stderr, "Usage: TestAppCF -a adminPass -p adminPass [-v] [-e] [-l path] [-N runNumber]\n", argv[0] );
fprintf( stderr, " [-c copies] [-t times] [-u proxyUser -P proxyPass -h proxyHost]\n" );
fprintf( stderr, " -v verbose output\n" );
fprintf( stderr, " -e output error log\n" );
fprintf( stderr, " -l log path (default \"./Logs/<runNumber>/\"\n" );
fprintf( stderr, " -N test run number\n" );
fprintf( stderr, " -c number of copies to fork for stress testing\n" );
fprintf( stderr, " -t number of times to run the test\n" );
fprintf( stderr, " -u Proxy username\n" );
fprintf( stderr, " -P Proxy username password\n" );
fprintf( stderr, " -h Proxy host\n" );
fprintf( stderr, " -a local admin account\n" );
fprintf( stderr, " -p local admin password\n" );
}
void parseOptions( int argc, char *argv[] )
{
int ch;
gTestCase = (uint32_t) CFAbsoluteTimeGetCurrent();
while ((ch = getopt(argc, argv, "vel:N:c:t:u:P:h:a:p:")) != -1)
{
switch (ch)
{
case 'v':
gVerbose = true;
break;
case 'e':
gLogErrors = true;
break;
case 'l':
gLogPath = optarg;
break;
case 'N':
gTestCase = strtol( optarg, NULL, 10 );
break;
case 'c':
if( NULL != optarg )
{
gCopies = strtol( optarg, NULL, 10 );
if( gCopies > 1024 )
gCopies = 1024;
}
else
usage( argv );
break;
case 't':
if( NULL != optarg )
{
gTestTimes = strtol( optarg, NULL, 10 );
if( 0 == gTestTimes )
gTestTimes = 1;
}
else
usage( argv );
break;
case 'u': gProxyUser = optarg;
break;
case 'P': gProxyPassword = optarg;
break;
case 'h': gProxyHost = optarg;
break;
case 'a': gAdminAccount = optarg;
break;
case 'p': gAdminPassword = optarg;
break;
case '?':
default:
usage( argv );
exit(1);
}
}
if( NULL == gAdminAccount || NULL == gAdminPassword )
{
usage( argv );
exit( 1 );
}
else if( NULL != gProxyHost || NULL != gProxyUser || NULL != gProxyHost )
{
if( NULL == gProxyHost || NULL == gProxyUser || NULL == gProxyHost )
{
usage( argv );
exit( 1 );
}
}
}
void searchCallback( ODContextRef inContext, CFMutableArrayRef inResults, CFErrorRef inResultCode )
{
if( NULL != inResults )
{
printf( "Got %d results\n", (int) CFArrayGetCount(inResults) );
}
else
{
printf( "Got no more results\n" );
}
}
bool doTestMembership( ODNodeRef inNodeRef, ODRecordType inGroupType, ODRecordType inMemberType )
{
CFErrorRef error = NULL;
ODRecordRef testmember = NULL;
ODRecordRef testcontainer = NULL;
bool bReturn = false;
CFArrayRef emptyValue = CFArrayCreateMutable( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks );
bool (^testFailure)( bool, const char *, CFErrorRef *) = ^( bool bSuccess, const char *testCase, CFErrorRef *inError )
{
bool bFailed = true;
CFErrorRef theError = (*inError);
if ( theError != NULL ) {
if ( bSuccess == false ) {
printf( "%s - FAIL", testCase );
}
else {
printf( "%s - FAIL (error but status says success)", testCase );
}
CFStringRef errorDesc = CFErrorCopyDescription( theError );
const char *errorStr = "no error details";
char buffer[512];
if ( errorDesc != NULL ) {
CFStringGetCString( errorDesc, buffer, sizeof(buffer), kCFStringEncodingUTF8 );
errorStr = buffer;
}
printf( " - (%d) - %s\n", (int) CFErrorGetCode(theError), errorStr );
}
else {
if ( bSuccess == false ) {
printf( "%s - FAIL - failed but no Error\n", testCase );
}
else {
printf( "%s - SUCCESS\n", testCase );
bFailed = false;
}
}
return bFailed;
};
char groupType[64];
char memberType[64];
CFStringGetCString( inGroupType, groupType, sizeof(groupType), kCFStringEncodingUTF8 );
if ( inMemberType != NULL ) {
CFStringGetCString( inMemberType, memberType, sizeof(memberType), kCFStringEncodingUTF8 );
printf( "\n-- Container '%s' - Member '%s'\n", groupType, memberType );
testmember = ODNodeCreateRecord( inNodeRef, inMemberType, CFSTR("testmember"), NULL, &error );
if ( testFailure(testmember != NULL, "ODNodeCreateRecord 'testmember'", &error) == true ) {
goto fail;
}
}
else {
printf( "\n-- Container '%s' - Member 'NULL'\n", groupType );
}
testcontainer = ODNodeCreateRecord( inNodeRef, inGroupType, CFSTR("testcontainer"), NULL, &error );
if ( testFailure(testcontainer != NULL, "ODNodeCreateRecord 'testcontainer'", &error) == true ) {
goto fail;
}
if ( inMemberType == NULL )
{
if ( ODRecordAddMember(testcontainer, NULL, &error) == true ) {
printf( "ODRecordAddMember (add NULL member) - FAIL (succeeded)\n" );
}
else {
printf( "ODRecordAddMember (add NULL member) - SUCCESS (got error)\n" );
}
goto finish;
}
bool (^badMixture)( void ) = ^(void) {
if ( (inGroupType == kODRecordTypeGroups && (inMemberType == kODRecordTypeUsers || inMemberType == kODRecordTypeGroups)) ||
(inGroupType == kODRecordTypeComputerGroups && (inMemberType == kODRecordTypeComputers || inMemberType == kODRecordTypeComputerGroups)) ||
(inGroupType == kODRecordTypeComputerLists && (inMemberType == kODRecordTypeComputers || inMemberType == kODRecordTypeComputerLists)) )
{
return (bool) false;
}
return (bool) true;
};
bool (^addMember)(const char *) = ^(const char *testCase) {
char errorStr[256];
CFErrorRef localErr = NULL;
snprintf( errorStr, sizeof(errorStr), "ODRecordAddMember (%s)", testCase );
if ( ODRecordAddMember(testcontainer, testmember, &localErr) == false )
{
if ( badMixture() == false )
{
if ( testFailure(false, errorStr, &localErr) == true ) {
return (bool) false;
}
}
else {
printf( "%s - SUCCESS (got error)\n", errorStr );
CFRelease( localErr );
localErr = NULL;
}
}
else {
printf( "%s - SUCCESS\n", errorStr );
}
return (bool) true;
};
if ( addMember("has UUID") == false ) goto fail;
if ( testFailure(ODRecordSetValue(testmember, kODAttributeTypeGUID, emptyValue, &error),
"ODRecordSetValue testmember (remove GUID)", &error) == true )
{
goto fail;
}
if ( inMemberType == kODRecordTypeUsers && addMember("no UUID nor UID/GID, if applicable") == false ) goto fail;
ODAttributeType idAttr = NULL;
if ( inMemberType == kODRecordTypeUsers ) {
idAttr = kODAttributeTypeUniqueID;
}
else if ( inMemberType == kODRecordTypeGroups ) {
idAttr = kODAttributeTypePrimaryGroupID;
}
if ( idAttr != NULL )
{
if ( testFailure(ODRecordSetValue(testmember, idAttr, CFSTR("199"), &error),
"ODRecordSetValue testmember (set UID)", &error) == true )
{
goto fail;
}
if ( addMember("synthetic UUID") == false ) goto fail;
}
ODAttributeType mbrAttrib = NULL;
ODAttributeType clearAttrib = NULL;
if ( inMemberType == kODRecordTypeUsers || inMemberType == kODRecordTypeComputers ) {
if ( inGroupType == kODRecordTypeComputerLists ) mbrAttrib = kODAttributeTypeComputers;
else mbrAttrib = kODAttributeTypeGroupMembers;
}
else if ( inMemberType == kODRecordTypeGroups || inMemberType == kODRecordTypeComputerGroups ) {
mbrAttrib = kODAttributeTypeNestedGroups;
}
else if ( inMemberType == kODRecordTypeComputerLists ) {
mbrAttrib = kODAttributeTypeGroup;
}
else {
goto finish;
}
if ( testFailure(ODRecordSetValue(testmember, kODAttributeTypeGUID, CFSTR("12345678-1234-1234-123456789011"), &error),
"ODRecordSetValue testmember (put a UUID back)", &error) == true )
{
goto fail;
}
CFTypeRef values[] = { CFSTR("12345678-1234-1234-123456789012"), CFSTR("12345678-1234-1234-123456789013"), CFSTR("12345678-1234-1234-123456789014") };
CFArrayRef cfGUIDList = CFArrayCreate( kCFAllocatorDefault, values, sizeof(values) / sizeof(CFTypeRef), &kCFTypeArrayCallBacks );
if ( testFailure(ODRecordSetValue(testcontainer, mbrAttrib, cfGUIDList, &error),
"ODRecordSetValue testcontainer (adding fake values)", &error) == true )
{
goto fail;
}
if ( inGroupType == kODRecordTypeGroups &&
inMemberType == kODRecordTypeUsers &&
testFailure(ODRecordSetValue(testcontainer, kODAttributeTypeGroupMembership, emptyValue, &error),
"ODRecordSetValue testcontainer (removing name list)", &error) == true )
{
goto fail;
}
if ( addMember("adding member (missing legacy membership, if applicable)") == false ) goto fail;
else if ( badMixture() == true ){
printf( "Stopping test because incompatible mix to do addition validation\n" );
goto finish;
}
CFArrayRef groupMembers = ODRecordCopyValues( testcontainer, mbrAttrib, &error );
if ( testFailure(groupMembers != NULL, "ODRecordCopyValues testcontainer", &error) == true ) {
goto fail;
}
CFIndex count = CFArrayGetCount( groupMembers );
printf( "ODRecordCopyValues testcontainer (expected 4 got %d) - %s\n", (int) count, (count == 4 ? "SUCCESS" : "FAIL") );
if ( count != 4 ) {
goto fail;
}
if ( addMember("adding member (twice)") == false ) goto fail;
groupMembers = ODRecordCopyValues( testcontainer, mbrAttrib, &error );
if ( testFailure(groupMembers != NULL, "ODRecordCopyValues testcontainer", &error) == true ) {
goto fail;
}
count = CFArrayGetCount( groupMembers );
printf( "ODRecordCopyValues testcontainer (expected 4 got %d) - %s\n", (int) count, (count == 4 ? "SUCCESS" : "FAIL") );
if ( count != 4 ) goto fail;
finish:
bReturn = true;
fail:
ODRecordDelete( testmember, NULL );
ODRecordDelete( testcontainer, NULL );
return bReturn;
};
void *doTest( void *inData )
{
ODSessionRef cfRef = NULL;
ODContextRef cfContext = 0;
ODQueryRef cfQuery = NULL;
CFArrayRef cfResults = NULL;
CFStringRef cfProxyHost = NULL;
CFStringRef cfProxyUser = NULL;
CFStringRef cfProxyPassword = NULL;
int ii;
CFErrorRef cfError;
ODNodeRef cfNodeRef = NULL;
ODNodeRef cfLocalNodeRef = (ODNodeRef) inData;
CFStringRef cfRecordName = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("TestCFFramework%ld"), (long) pthread_self() );
CFStringRef cfGroupName = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("TestGroup%ld"), (long) pthread_self() );
CFStringRef cfAddRecordName = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("TestAddRecord%ld"), (long) pthread_self() );
CFStringRef cfAddRecordAlias = CFStringCreateWithFormat( kCFAllocatorDefault, NULL, CFSTR("TestAddRecordAlias%ld"), (long) pthread_self() );
if( NULL != gProxyHost )
{
cfProxyHost = CFStringCreateWithCString( kCFAllocatorDefault, gProxyHost, kCFStringEncodingUTF8 );
cfProxyUser = CFStringCreateWithCString( kCFAllocatorDefault, gProxyUser, kCFStringEncodingUTF8 );
cfProxyPassword = CFStringCreateWithCString( kCFAllocatorDefault, gProxyPassword, kCFStringEncodingUTF8 );
}
CFStringRef cfAdminAccount = CFStringCreateWithCString( kCFAllocatorDefault, gAdminAccount, kCFStringEncodingUTF8 );
CFStringRef cfAdminPassword = CFStringCreateWithCString( kCFAllocatorDefault, gAdminPassword, kCFStringEncodingUTF8 );
for( ii = 0; ii < gTestTimes; ii++ )
{
if( NULL != gProxyHost )
{
CFMutableDictionaryRef cfOptions = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
CFDictionarySetValue( cfOptions, kODSessionProxyAddress, cfProxyHost );
CFDictionarySetValue( cfOptions, kODSessionProxyUsername, cfProxyUser );
CFDictionarySetValue( cfOptions, kODSessionProxyPassword, cfProxyPassword );
cfRef = ODSessionCreate( kCFAllocatorDefault, cfOptions, NULL );
if( NULL != cfRef )
{
printf("ODSessionCreate (with options) proxy - PASS\n");
CFRelease( cfRef );
cfRef = NULL;
}
else
{
printf( "ODSessionCreate (with options) proxy - FAIL\n" );
}
CFRelease( cfOptions );
}
else
{
printf("ODSessionCreate (with options) proxy - SKIP\n");
}
cfRef = ODSessionCreate( kCFAllocatorDefault, NULL, NULL );
if( NULL != cfRef )
{
printf( "ODSessionCreate - PASS\n" );
CFRelease( cfRef );
cfRef = NULL;
}
cfNodeRef = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODNodeTypeAuthentication, &cfError );
if( NULL != cfNodeRef )
{
printf( "ODNodeCreate - PASS\n" );
CFArrayRef cfNodes = ODNodeCopySubnodeNames( cfNodeRef, NULL );
if( NULL != cfNodes )
{
printf( "ODNodeCopySubnodeNames (Auth search node) - PASS\n" );
CFArrayRef cfUnreachable = ODNodeCopyUnreachableSubnodeNames( cfNodeRef, NULL );
if ( cfUnreachable != NULL )
{
printf( "ODNodeCopyUnreachableSubnodeNames - FAIL - returned %d\n", (int) CFArrayGetCount(cfUnreachable) );
CFRelease( cfUnreachable );
cfUnreachable = NULL;
}
else
{
printf( "ODNodeCopyUnreachableSubnodeNames - PASS\n" );
}
CFRelease( cfNodes );
cfNodes = NULL;
}
else
{
printf( "ODNodeCopySubnodeNames (Auth search node) - FAIL\n" );
}
CFRelease( cfNodeRef );
cfNodeRef = NULL;
}
else
{
printf( "ODNodeCreateWithNodeType with kODTypeAuthenticationSearchNode - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
cfNodeRef = ODNodeCreateWithName( kCFAllocatorDefault, kODSessionDefault, CFSTR("/LDAPv3/od.apple.com"), &cfError );
if( NULL != cfNodeRef )
{
printf( "ODNodeCreateWithName with /LDAPv3/od.apple.com - PASS\n" );
ODNodeRef cfNodeRef2 = ODNodeCreateCopy( kCFAllocatorDefault, cfNodeRef, NULL );
if( NULL != cfNodeRef2 )
{
printf( "ODNodeCreateCopy - PASS\n" );
CFRelease( cfNodeRef2 );
cfNodeRef2 = NULL;
}
else
{
printf( "ODNodeCreateCopy - FAIL\n" );
}
CFRelease( cfNodeRef );
cfNodeRef = NULL;
}
else
{
printf( "ODNodeCreateWithName with /LDAPv3/od.apple.com - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
cfLocalNodeRef = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODNodeTypeLocalNodes, &cfError );
if( NULL != cfLocalNodeRef )
{
CFTypeRef cfValues[] = { cfAdminAccount };
CFArrayRef cfSearchValue = CFArrayCreate( kCFAllocatorDefault, cfValues, 1, &kCFTypeArrayCallBacks );
printf( "ODNodeCreateWithNodeType with kODTypeLocalNode - PASS\n" );
cfQuery = ODQueryCreateWithNode( kCFAllocatorDefault, cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), CFSTR(kDSNAttrRecordName),
kODMatchEqualTo, cfSearchValue, NULL, 0, NULL );
if( NULL != cfQuery )
{
printf( "ODQueryCreateWithNode - PASS\n" );
cfResults = ODQueryCopyResults( cfQuery, false, NULL );
if( NULL != cfResults )
{
printf( "ODQueryCopyResults returned non-NULL - PASS\n" );
if( CFArrayGetCount( cfResults ) != 0 )
{
printf( "ODQueryCopyResults returned results (%d) - PASS\n", (int) CFArrayGetCount(cfResults) );
}
else
{
printf( "ODQueryCopyResults returned results - FAIL\n" );
}
CFRelease( cfResults );
cfResults = NULL;
}
else
{
printf( "ODQueryCopyResults returned non-NULL - FAIL\n" );
}
CFRelease( cfQuery );
cfQuery = NULL;
}
ODRecordRef cfRecord = ODNodeCopyRecord( cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), cfAdminAccount, NULL, NULL );
if( NULL != cfRecord )
{
printf( "ODNodeCopyRecord - PASS\n" );
CFDictionaryRef cfPolicy = ODRecordCopyPasswordPolicy( kCFAllocatorDefault, cfRecord, NULL );
if( NULL != cfPolicy )
{
printf( "ODNodeCopyUserPolicy - PASS\n" );
CFRelease( cfPolicy );
cfPolicy = NULL;
}
else
{
printf( "ODNodeCopyUserPolicy - FAIL\n" );
}
if( ODRecordVerifyPassword(cfRecord, cfAdminPassword, NULL) == true )
{
printf( "ODNodeVerifyCredentials - PASS\n" );
}
else
{
printf( "ODNodeVerifyCredentials - FAIL\n" );
}
CFStringRef cfAttribute = CFSTR(kDSAttributesAll);
CFArrayRef cfAttribs = CFArrayCreate( kCFAllocatorDefault, (const void **) &cfAttribute, 1, &kCFTypeArrayCallBacks );
CFDictionaryRef cfValues = ODRecordCopyDetails( cfRecord, cfAttribs, NULL );
if( NULL != cfValues )
{
printf( "ODRecordCopyDetails (kDSAttributesAll) - non-NULL - PASS\n" );
if( CFDictionaryGetCount(cfValues) != 0 )
{
printf( "ODRecordCopyDetails (kDSAttributesAll) - has values - PASS\n" );
}
else
{
printf( "ODRecordCopyDetails (kDSAttributesAll) - has values - FAIL\n" );
}
CFRelease( cfValues );
cfValues = NULL;
}
else
{
printf( "ODRecordCopyAllAttributes - FAIL\n" );
}
CFArrayRef cfAttribValues = ODRecordCopyValues( cfRecord, CFSTR(kDS1AttrNFSHomeDirectory), NULL );
if( NULL != cfAttribValues )
{
printf( "ODRecordCopyValues - PASS\n" );
CFRelease( cfAttribValues );
cfAttribValues = NULL;
}
else
{
printf( "ODRecordCopyAttribute - FAIL\n" );
}
#warning needs ODNodeAuthenticateExtended
if( ODRecordSetNodeCredentials(cfRecord, cfAdminAccount, cfAdminPassword, NULL) )
{
printf( "ODRecordSetNodeCredentials - PASS\n" );
}
else
{
printf( "ODRecordSetNodeCredentials - FAIL\n" );
}
}
else
{
printf( "ODNodeCopyRecord - FAIL\n" );
}
CFStringRef cfNodeName = ODNodeGetName( cfLocalNodeRef );
if( NULL != cfNodeName )
{
printf( "ODNodeGetName - PASS\n" );
}
else
{
printf( "ODNodeGetName - FAIL\n" );
}
CFDictionaryRef cfNodeInfo = ODNodeCopyDetails( cfLocalNodeRef, NULL, NULL );
if( NULL != cfNodeInfo )
{
printf( "ODNodeCopyDetails - PASS\n" );
CFRelease( cfNodeInfo );
cfNodeInfo = NULL;
}
else
{
printf( "ODNodeCopyDetails - FAIL\n" );
}
CFArrayRef cfRecTypes = ODNodeCopySupportedRecordTypes( cfLocalNodeRef, NULL );
if( NULL != cfRecTypes )
{
printf( "ODNodeCopySupportedRecordTypes - PASS\n" );
CFRelease( cfRecTypes );
cfRecTypes = NULL;
}
else
{
printf( "ODNodeCopySupportedRecordTypes - FAIL\n" );
}
CFArrayRef cfAttribTypes = ODNodeCopySupportedAttributes( cfLocalNodeRef, NULL, NULL );
if( NULL != cfAttribTypes )
{
printf( "ODNodeCopySupportedAttributes - PASS\n" );
CFRelease( cfAttribTypes );
cfAttribTypes = NULL;
}
else
{
printf( "ODNodeCopySupportedAttributes - FAIL\n" );
}
if( ODNodeSetCredentials(cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), cfAdminAccount, cfAdminPassword, NULL) )
{
ODRecordRef cfRecord = NULL;
printf( "ODNodeSetCredentials - PASS\n" );
cfRecord = ODNodeCreateRecord( cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), cfRecordName, NULL, NULL );
if( NULL != cfRecord )
{
printf( "ODNodeCreateRecord - PASS\n" );
ODRecordRef cfRecordTemp = ODNodeCreateRecord( cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), cfRecordName, NULL, &cfError );
if( NULL != cfRecordTemp )
{
printf( "ODNodeCreateRecord (create duplicate) - FAIL record returned\n" );
}
else
{
CFIndex errCode = CFErrorGetCode( cfError );
if( errCode == kODErrorRecordAlreadyExists )
{
printf( "ODNodeCreateRecord (create duplicate) - PASS\n" );
}
else
{
printf( "ODNodeCreateRecord (create duplicate) - FAIL (%d)\n", (int) errCode );
CFRelease( cfError );
}
}
if( ODRecordDelete(cfRecord, &cfError) )
{
printf( "ODRecordDelete - PASS\n" );
}
else
{
printf( "ODRecordDelete - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
}
CFRelease( cfRecord );
cfRecord = NULL;
}
else
{
printf( "ODNodeCreateRecord - FAIL\n" );
}
CFMutableDictionaryRef cfAttributes = CFDictionaryCreateMutable( NULL, 0, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks );
CFStringRef cfHome[] = { CFSTR("/Users/blah"), NULL };
CFStringRef cfNames[] = { cfAddRecordName, cfAddRecordAlias, NULL };
CFArrayRef cfHomeAttrib = CFArrayCreate( kCFAllocatorDefault, (const void **) &cfHome, 1, &kCFTypeArrayCallBacks );
CFArrayRef cfNamesAttrib = CFArrayCreate( kCFAllocatorDefault, (const void **) &cfNames, 2, &kCFTypeArrayCallBacks );
CFDictionarySetValue( cfAttributes, CFSTR(kDS1AttrNFSHomeDirectory), cfHomeAttrib );
CFDictionarySetValue( cfAttributes, CFSTR(kDSNAttrRecordName), cfNamesAttrib );
CFRelease( cfNamesAttrib );
CFRelease( cfHomeAttrib );
cfRecord = ODNodeCreateRecord( cfLocalNodeRef, CFSTR(kDSStdRecordTypeUsers), cfAddRecordName, cfAttributes, &cfError );
if( NULL != cfRecord )
{
printf( "ODNodeCreateRecord (with attributes) - PASS\n" );
if( NULL != cfRecord )
{
printf( "ODNodeAddRecordWithAttributes (record returned) - PASS\n" );
CFArrayRef cfValue = ODRecordCopyValues( cfRecord, CFSTR(kDS1AttrNFSHomeDirectory), NULL );
if( NULL != cfValue && CFArrayGetCount(cfValue) == 1 )
{
printf( "ODNodeAddRecordWithAttributes (value exist) - PASS\n" );
}
else
{
printf( "ODNodeAddRecordWithAttributes (value exist) - FAIL\n" );
}
if( NULL != cfValue )
CFRelease( cfValue );
if( ODRecordChangePassword(cfRecord, NULL, CFSTR("test"), &cfError) )
{
printf( "ODNodeSetPassword - PASS\n" );
}
else
{
printf( "ODNodeSetPassword - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
if( ODRecordChangePassword(cfRecord, CFSTR("test"), CFSTR("test2"), &cfError) )
{
printf( "ODNodeChangePassword - PASS\n" );
}
else
{
printf( "ODNodeChangePassword - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
if( ODRecordSetValue( cfRecord, CFSTR(kDSNAttrState), CFSTR("Test street"), &cfError ) )
{
printf( "ODRecordSetValueOrValues - PASS\n" );
}
else
{
printf( "ODRecordSetValueOrValues - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
if( ODRecordAddValue( cfRecord, CFSTR(kDSNAttrState), CFSTR("Test street 2"), &cfError ) )
{
printf( "ODRecordAddValue - PASS\n" );
}
else
{
printf( "ODRecordAddValue - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
if( ODRecordRemoveValue(cfRecord, CFSTR(kDSNAttrState), CFSTR("Test street 2"), &cfError) )
{
printf( "ODRecordRemoveValue - PASS\n" );
}
else
{
printf( "ODRecordRemoveValue - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
}
CFArrayRef cfArray = CFArrayCreate( kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks );
if( ODRecordSetValue(cfRecord, CFSTR(kDSNAttrState), cfArray, &cfError) )
{
printf( "ODRecordSetValue (remove attribute) - PASS\n" );
CFArrayRef cfValues = ODRecordCopyValues( cfRecord, CFSTR(kDSNAttrState), NULL );
if( NULL == cfValues || CFArrayGetCount(cfValues) == 0 )
{
printf( "ODRecordSetValue (attrib gone) - PASS\n" );
}
else
{
printf( "ODRecordSetValue (attrib gone) - FAIL\n" );
}
if( NULL != cfValues )
CFRelease( cfValues );
}
else
{
printf( "ODRecordSetValue (deleting attrib) - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
}
CFRelease( cfArray );
ODRecordDelete( cfRecord, NULL );
}
else
{
printf( "ODNodeAddRecordWithAttributes (record returned) - FAIL\n" );
}
CFRelease( cfRecord );
cfRecord = NULL;
}
else
{
printf( "ODNodeCreateRecord (with attributes) - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
CFRelease( cfAttributes );
cfAttributes = NULL;
ODRecordType groupTypes[] = { kODRecordTypeConfiguration, kODRecordTypeUsers, kODRecordTypeGroups, kODRecordTypeComputerGroups, kODRecordTypeComputerLists };
ODRecordType userTypes[] = { NULL, kODRecordTypeUsers, kODRecordTypeComputers, kODRecordTypeGroups,
kODRecordTypeComputerGroups, kODRecordTypeComputerLists, kODRecordTypeConfiguration };
int groupX;
int userX;
bool bSuccess = true;
for ( groupX = 0; bSuccess == true && groupX < (sizeof(groupTypes) / sizeof(ODRecordType)); groupX++ )
{
for ( userX = 0; bSuccess == true && userX < (sizeof(userTypes) / sizeof(ODRecordType)); userX++ )
{
bSuccess = doTestMembership( cfLocalNodeRef, groupTypes[groupX], userTypes[userX] );
}
}
if ( bSuccess == false ) return NULL;
ODRecordRef cfGroup = ODNodeCopyRecord( cfLocalNodeRef, kODRecordTypeGroups, CFSTR("admin"), NULL, NULL );
if( NULL != cfGroup )
{
printf( "\n--Test Memberships\n" );
printf( "ODNodeCopyRecord (admin) - PASS\n" );
cfRecord = ODNodeCopyRecord( cfLocalNodeRef, kODRecordTypeUsers, cfAdminAccount, NULL, NULL );
if ( ODRecordContainsMember( cfGroup, cfRecord, NULL ) == true )
{
printf( "ODRecordContainsMember - PASS\n" );
}
else
{
printf( "ODRecordContainsMember - FAIL\n" );
}
if ( ODRecordContainsMember(cfRecord, cfGroup, NULL) == false ) {
printf( "ODRecordContainsMember (group is member of user (failure)) - PASS (got error)\n" );
}
else {
printf( "ODRecordContainsMember (group is member of user (failure)) - FAIL (no error)\n" );
}
if ( ODRecordContainsMember(cfRecord, cfGroup, NULL) == false ) {
printf( "ODRecordContainsMember (group is member of group (failure)) - PASS (got error)\n" );
}
else {
printf( "ODRecordContainsMember (group is member of group (failure)) - FAIL (no error)\n" );
}
CFRelease( cfGroup );
cfGroup = NULL;
}
else
{
printf( "ODNodeCopyRecord (admin) - FAIL\n" );
}
}
else
{
printf( "ODNodeSetCredentials - FAIL\n" );
}
CFRelease( cfLocalNodeRef );
cfLocalNodeRef = NULL;
}
else
{
printf( "ODNodeCreateWithNodeType with kODTypeLocalNode - FAIL (%d)\n", (int) CFErrorGetCode(cfError) );
CFRelease( cfError );
}
}
CFRelease( cfRecordName );
CFRelease( cfGroupName );
CFRelease( cfAddRecordName );
CFRelease( cfAddRecordAlias );
return NULL;
}
int main( int argc, char *argv[] )
{
parseOptions( argc, argv );
argc -= optind;
argv += optind;
ODNodeRef cfLocalNodeRef = ODNodeCreateWithNodeType( kCFAllocatorDefault, kODSessionDefault, kODNodeTypeLocalNodes, NULL );
if ( gCopies > 0 ) {
int ii;
void *junk;
pthread_t *threads = (pthread_t *) calloc( gCopies, sizeof(pthread_t) );
for ( ii = 0; ii < gCopies; ii++ )
{
while( pthread_create( &threads[ii], NULL, doTest, cfLocalNodeRef ) != 0 )
{
usleep( 1000 );
}
}
for ( ii = 0; ii < gCopies; ii++ ) {
pthread_join( threads[ii], &junk );
}
} else {
doTest( cfLocalNodeRef );
}
return 0;
}