// passing over REPLICATION_LIST configuration parameter, turning all the // addresses into canonical <ip:port> form and inserting them all, except for // the address of local replication daemon, into 'm_replicationDaemonsList'. void AbstractReplicatorStateMachine::initializeReplicationList( char* buffer ) { StringList replicationAddressList; char* replicationAddress = NULL; bool isMyAddressPresent = false; Sinful my_addr( daemonCore->InfoCommandSinfulString( ) ); replicationAddressList.initializeFromString( buffer ); // initializing a list unrolls it, that's why the rewind is needed to bring // it to the beginning replicationAddressList.rewind( ); /* Passing through the REPLICATION_LIST configuration parameter, stripping * the optional <> brackets off, and extracting the host name out of * either ip:port or hostName:port entries */ while( (replicationAddress = replicationAddressList.next( )) ) { char* sinfulAddress = utilToSinful( replicationAddress ); if( sinfulAddress == NULL ) { char bufArray[BUFSIZ]; sprintf( bufArray, "AbstractReplicatorStateMachine::initializeReplicationList" " invalid address %s\n", replicationAddress ); utilCrucialError( bufArray ); continue; } if( my_addr.addressPointsToMe( Sinful(sinfulAddress) ) ) { isMyAddressPresent = true; } else { m_replicationDaemonsList.insert( sinfulAddress ); } // pay attention to release memory allocated by malloc with free and by // new with delete here utilToSinful returns memory allocated by malloc free( sinfulAddress ); } if( !isMyAddressPresent ) { utilCrucialError( "ReplicatorStateMachine::initializeReplicationList " "my address is not present in REPLICATION_LIST" ); } }
int main( int, char ** ) { Sinful s; Sinful t; // // Test, for 0, 1, 2, and 3 condor_sockaddrs: that the vector is not NULL, // that the vector has the correct number of elements, that the vector's // elements values are correct (and in the correct order); and that the // string form of the sinful is correct; and that the parser correctly // handles the sinful string (by repeating the vector tests); and that // the string->sinful->string loop also works (by repeating the string // test). Then repeat the 0 test after clearing the Sinful of addrs. // // We then also test adding three condor_sockaddrs in a row, just in // case one-at-a-time testing somehow hides a problem; this also tests // that adding condor_sockaddrs after clearing the Sinful works. // std::vector< condor_sockaddr > * v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); delete v; v = NULL; char const * sinfulString = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString == NULL ); REQUIRE( ! s.hasAddrs() ); condor_sockaddr sa; bool ok = sa.from_ip_and_port_string( "1.2.3.4:5" ); REQUIRE( ok ); s.addAddrToAddrs( sa ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 1 ); REQUIRE( (*v)[0] == sa ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 1 ); REQUIRE( (*v)[0] == sa ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5>" ) == 0 ); REQUIRE( s.hasAddrs() ); condor_sockaddr sa2; ok = sa2.from_ip_and_port_string( "5.6.7.8:9" ); REQUIRE( ok ); s.addAddrToAddrs( sa2 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 2 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 2 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9>" ) == 0 ); REQUIRE( s.hasAddrs() ); condor_sockaddr sa3; ok = sa3.from_ip_and_port_string( "[1:3:5:7::a]:13" ); REQUIRE( ok ); s.addAddrToAddrs( sa3 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); REQUIRE( s.hasAddrs() ); s.clearAddrs(); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 0 ); sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<>" ) == 0 ); REQUIRE( ! s.hasAddrs() ); s.addAddrToAddrs( sa ); s.addAddrToAddrs( sa2 ); s.addAddrToAddrs( sa3 ); v = s.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = s.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); t = Sinful( sinfulString ); v = t.getAddrs(); REQUIRE( v != NULL ); REQUIRE( v->size() == 3 ); REQUIRE( (*v)[0] == sa ); REQUIRE( (*v)[1] == sa2 ); REQUIRE( (*v)[2] == sa3 ); delete v; v = NULL; sinfulString = t.getSinful(); REQUIRE( sinfulString != NULL ); REQUIRE( strcmp( sinfulString, "<?addrs=1.2.3.4-5+5.6.7.8-9+[1-3-5-7--a]-13>" ) == 0 ); REQUIRE( s.hasAddrs() ); // In practice, all C++03 implementations are stable with respect // to insertion order; the C++11 standard requires that they are. // This is the unit test for the former. std::multimap< int, condor_sockaddr > sortedByDesire; sortedByDesire.insert(std::make_pair( 0, sa )); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 0, sa3 )); int i = 0; std::multimap< int, condor_sockaddr >::const_iterator iter; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa ); break; case 1: REQUIRE( (* iter).second == sa2 ); break; case 2: REQUIRE( (* iter).second == sa3 ); break; default: REQUIRE( false ); break; } } sortedByDesire.clear(); REQUIRE( sortedByDesire.size() == 0 ); sortedByDesire.insert(std::make_pair( 1, sa )); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 0, sa3 )); i = 0; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa2 ); break; case 1: REQUIRE( (* iter).second == sa3 ); break; case 2: REQUIRE( (* iter).second == sa ); break; default: REQUIRE( false ); break; } } sortedByDesire.clear(); REQUIRE( sortedByDesire.size() == 0 ); sortedByDesire.insert(std::make_pair( 0, sa2 )); sortedByDesire.insert(std::make_pair( 1, sa )); sortedByDesire.insert(std::make_pair( 0, sa3 )); i = 0; for( iter = sortedByDesire.begin(); iter != sortedByDesire.end(); ++iter, ++i ) { switch( i ) { case 0: REQUIRE( (* iter).second == sa2 ); break; case 1: REQUIRE( (* iter).second == sa3 ); break; case 2: REQUIRE( (* iter).second == sa ); break; default: REQUIRE( false ); break; } } return 0; }