TEST_F( SegmentTest, Remove ) { std::unordered_map<TID, uint32_t> values; // TID -> testData entry // Insert some records for ( uint32_t i = 0; i < 500; ++i ) { // Select string/record to insert uint64_t r = rand() % testData.size(); const std::string s = testData[r]; // Insert record TID tid = segment->Insert( Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); EXPECT_EQ( values.find( tid ), values.end() ); // TIDs should not be overwritten values[tid] = static_cast<uint32_t>(r); } std::unordered_map<TID, bool> removed; // TID -> is removed // Remove records for ( std::pair<TID, uint32_t> tidValue : values ) { if ( rand() > RAND_MAX * 0.5 ) { bool removeSuccess = segment->Remove( tidValue.first ); EXPECT_EQ( true, removeSuccess ); removed.insert( std::make_pair( tidValue.first, true ) ); } else { removed.insert( std::make_pair( tidValue.first, false ) ); } } // Check over every record if it was correctly removed/kept for ( std::pair<TID, uint32_t> tidValue : values ) { if ( removed[tidValue.first] ) { Record rec = segment->Lookup( tidValue.first ); EXPECT_EQ( 0, rec.GetLen() ); EXPECT_EQ( nullptr, rec.GetData() ); } else { const std::string& value = testData[tidValue.second]; uint32_t len = static_cast<uint32_t>(value.size()); Record rec = segment->Lookup( tidValue.first ); EXPECT_EQ( len, rec.GetLen() ); EXPECT_EQ( 0, memcmp( rec.GetData(), value.c_str(), len ) ); } } };
TEST_F(SegmentTest, InsertLookup ) { std::unordered_map<TID, uint32_t> values; // TID -> testData entry // Insert some records for ( uint32_t i = 0; i < 500; ++i ) { // Select string/record to insert uint64_t r = rand() % testData.size(); const std::string s = testData[r]; // Insert record TID tid = segment->Insert( Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); EXPECT_EQ( values.find( tid ), values.end() ); // TIDs should not be overwritten values[tid] = static_cast<uint32_t>(r); } // Every value has to be the same as it was inserted for ( std::pair<TID, uint32_t> tidValue : values ) { const std::string& value = testData[tidValue.second]; uint32_t len = static_cast<uint32_t>(value.size()); Record rec = segment->Lookup( tidValue.first ); EXPECT_EQ( len, rec.GetLen() ); EXPECT_EQ( 0, memcmp( rec.GetData(), value.c_str(), len ) ); } };
XnStatus PlayerNode::ReadRecordFields(Record &record) { XnUInt32 nBytesToRead = record.GetSize() - Record::HEADER_SIZE; XnUInt32 nBytesRead = 0; XnStatus nRetVal = Read(record.GetData() + Record::HEADER_SIZE, nBytesToRead, nBytesRead); XN_IS_STATUS_OK(nRetVal); if (nBytesRead < nBytesToRead) { XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Incorrect number of bytes read"); } return XN_STATUS_OK; }
XnStatus PlayerNode::ReadRecordHeader(Record &record) { XnUInt32 nBytesRead = 0; XnStatus nRetVal = Read(record.GetData(), Record::HEADER_SIZE, nBytesRead); if (nBytesRead != Record::HEADER_SIZE) { XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Incorrect number of bytes read"); } if (!record.IsHeaderValid()) { XN_ASSERT(FALSE); XN_LOG_ERROR_RETURN(XN_STATUS_CORRUPT_FILE, XN_MASK_OPEN_NI, "Invalid record header"); } return XN_STATUS_OK; }
TEST_F( SegmentTest, Update ) { std::unordered_map<TID, uint32_t> values; // TID -> testData entry std::vector<TID> tids; // Insert some records for ( uint32_t i = 0; i < 500; ++i ) { // Select string/record to insert uint64_t r = rand() % testData.size(); const std::string s = testData[r]; // Insert record TID tid = segment->Insert( Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); tids.push_back( tid ); EXPECT_EQ( values.find( tid ), values.end() ); // TIDs should not be overwritten values[tid] = static_cast<uint32_t>(r); } // Update random records for ( uint32_t i = 0; i < 1000; ++i ) { // Select new string / record TID target = tids[rand() % tids.size()]; uint32_t r = rand() % testData.size(); const std::string s = testData[r]; // Replace old with new value bool success = segment->Update( target, Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); EXPECT_EQ( true, success ); values[target] = static_cast<uint32_t>(r); } // Every value has to be the same as it was inserted/updated to for ( std::pair<TID, uint32_t> tidValue : values ) { const std::string& value = testData[tidValue.second]; uint32_t len = static_cast<uint32_t>(value.size()); Record rec = segment->Lookup( tidValue.first ); EXPECT_EQ( len, rec.GetLen() ); EXPECT_EQ( 0, memcmp( rec.GetData(), value.c_str(), len ) ); } };
inline RETCODE RecordFileScan::GetNextRec (Record & rec) { if ( _scanInfo.state != ScanState::Open ) return RETCODE::INVALIDSCAN; else if ( _scanInfo.state == End ) return RETCODE::EOFSCAN; Record tmpRec; RETCODE result; DataPtr recData; for ( ;; ) { if ( result = _recFile->GetRec (RecordIdentifier{ _scanInfo.scanedPage, _scanInfo.scanedSlot }, tmpRec) ) { Utils::PrintRetcode (result, __FUNCTION__, __LINE__); if ( result == RETCODE::EOFFILE ) { _scanInfo.state = End; return RETCODE::EOFSCAN; } return result; } if ( ++_scanInfo.scanedSlot == _scanInfo.recordsPerPage ) { _scanInfo.scanedPage++; _scanInfo.scanedSlot = 0; } if ( result = tmpRec.GetData (recData) ) { Utils::PrintRetcode (result, __FUNCTION__, __LINE__); return result; } if ( _comp == nullptr || _comp (recData.get ( ), _attrValue.get(), _attrType, _attrLength) ) { // if satisfies the condition rec = tmpRec; break; } } return RETCODE::COMPLETE; }
TEST_F( SegmentTest, RandomOperations ) { // Random interspersed operations std::unordered_map<TID, uint32_t> values; // TID -> testData entry std::vector<TID> tids; // Insert some baseline records for ( uint32_t i = 0; i < 100; ++i ) { // Select string/record to insert uint64_t r = rand() % testData.size(); const std::string s = testData[r]; // Insert record TID tid = segment->Insert( Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); tids.push_back( tid ); EXPECT_EQ( values.find( tid ), values.end() ); // TIDs should not be overwritten values[tid] = static_cast<uint32_t>(r); } // Random ops for ( uint32_t i = 0; i < 10000; ++i ) { float chance = static_cast<float>(rand()) / RAND_MAX; if (chance < 0.70) { // Insert // Select string/record to insert uint64_t r = rand() % testData.size(); const std::string s = testData[r]; // Insert record TID tid = segment->Insert( Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); EXPECT_EQ( values.find( tid ), values.end() ); // TIDs should not be overwritten tids.push_back( tid ); values[tid] = static_cast<uint32_t>(r); } else if (chance < 0.9) { // Update // Select new string / record TID target = tids[rand() % tids.size()]; uint32_t r = rand() % testData.size(); const std::string s = testData[r]; // Replace old with new value bool success = segment->Update( target, Record( static_cast<uint32_t>(s.size()), reinterpret_cast<const uint8_t*>(s.c_str()) ) ); EXPECT_EQ( true, success ); values[target] = static_cast<uint32_t>(r); } else { // Remove uint32_t inTid = rand() % tids.size(); TID target = tids[inTid]; bool removeSuccess = segment->Remove( target ); EXPECT_EQ( true, removeSuccess ); // Remove from our tid map and tid vector as well values.erase( target ); tids[inTid] = tids[tids.size() - 1]; tids.pop_back(); } } // Every value has to be the same as it was inserted/updated to for ( std::pair<TID, uint32_t> tidValue : values ) { // Not removed, normal check const std::string& value = testData[tidValue.second]; uint32_t len = static_cast<uint32_t>(value.size()); Record rec = segment->Lookup( tidValue.first ); EXPECT_EQ( len, rec.GetLen() ); EXPECT_EQ( 0, memcmp( rec.GetData(), value.c_str(), len ) ); } };
// Helper Funcitons void Socket::ClientHandshake() { std::cout << "Client Handshake" << std::endl; unsigned char previous = 0; bool bEncrypted = false; std::vector<unsigned char> handshakeData; bool bDone = false; while( !bDone ) { Record *record; if( !bEncrypted ) { record = new Record(); }else{ record = new Record( mClient ); } record->Read( *mSocket ); // Alert if( record->GetType() == Record::Alert ){ std::vector<unsigned char> data = record->GetData(); std::cerr << "Alert: " << std::hex << std::setw( 2 ) << std::setfill('0') << (int)data[0] << ", " << std::hex << std::setw( 2 ) << std::setfill('0') << (int)data[1] << std::endl; exit( EXIT_FAILURE ); } // Cipher if( record->GetType() == Record::Cipher ){ if( previous == Handshake::Type::ClientKey ){ bEncrypted = true; } previous = Record::Cipher; } // Handshake if( record->GetType() == Record::Handshake ){ std::vector<unsigned char> data = record->GetData(); if( previous == 0 ){ if( data[0] == Handshake::Type::ClientHello ){ Handshake::ClientHello hClientHello; hClientHello.Deserialize( std::vector<unsigned char>( data.begin() + 4, data.end() ) ); ClientRandom = hClientHello.Random(); handshakeData.insert( handshakeData.end(), data.begin(), data.end() ); Handshake::ServerHello hServerHello( 0x00, 0x35, 0x00 ); Record rServerHello( Record::Handshake, hServerHello.Serialize() ); rServerHello.Write( *mSocket ); ServerRandom = hServerHello.Random(); std::vector<unsigned char> dServerHello = hServerHello.Serialize(); handshakeData.insert( handshakeData.end(), dServerHello.begin(), dServerHello.end() ); Handshake::Certificate hCertificate( mCertificatePath ); Record rCertificate( Record::Handshake, hCertificate.Serialize() ); rCertificate.Write( *mSocket ); std::vector<unsigned char> dCertificate = hCertificate.Serialize(); handshakeData.insert( handshakeData.end(), dCertificate.begin(), dCertificate.end() ); std::vector<unsigned char> dServerDone; // Insert Size unsigned int size = htonl( dServerDone.size() ); unsigned char* cSize = (unsigned char*)&size; dServerDone.insert( dServerDone.begin(), cSize[3] ); dServerDone.insert( dServerDone.begin(), cSize[2] ); dServerDone.insert( dServerDone.begin(), cSize[1] ); // Insert Type dServerDone.insert( dServerDone.begin(), Handshake::Type::ServerDone ); Record rServerDone( Record::Handshake, dServerDone ); rServerDone.Write( *mSocket ); handshakeData.insert( handshakeData.end(), dServerDone.begin(), dServerDone.end() ); } previous = data[0]; } if( previous == Handshake::Type::ClientHello ){ if( data[0] == Handshake::Type::ClientKey ){ Handshake::ClientKeyExchange hClientKeyExchange( mKeyPath ); hClientKeyExchange.Deserialize( std::vector<unsigned char>( data.begin() + 4, data.end() ) ); handshakeData.insert( handshakeData.end(), data.begin(), data.end() ); DataArray secret = hClientKeyExchange.Secret(); MasterKey = PRF( 48, secret, "master secret", Concatonate( ClientRandom, ServerRandom ) ); KeyBlock = PRF( 136, MasterKey, "key expansion", Concatonate( ServerRandom, ClientRandom ) ); DataArray ClientMAC( KeyBlock.begin(), KeyBlock.begin() + 20 ); DataArray ServerMAC( KeyBlock.begin() + 20, KeyBlock.begin() + 40 ); DataArray ClientKey( KeyBlock.begin() + 40, KeyBlock.begin() + 72 ); DataArray ClientIV( KeyBlock.begin() + 104, KeyBlock.begin() + 120 ); mClient->Initialise( ClientMAC, ClientKey , ClientIV ); DataArray ServerKey( KeyBlock.begin() + 72, KeyBlock.begin() + 104 ); DataArray ServerIV( KeyBlock.begin() + 120, KeyBlock.begin() + 136 ); mServer->Initialise( ServerMAC, ServerKey , ServerIV ); } previous = data[0]; } if( previous == Record::Cipher ){ if( data[0] == Handshake::Type::Finished ){ Handshake::Finished hFinished; hFinished.Deserialize( std::vector<unsigned char>( data.begin() + 4, data.end() ) ); unsigned char md5hash[MD5_DIGEST_LENGTH]; unsigned char shahash[SHA_DIGEST_LENGTH]; MD5( &handshakeData[0], handshakeData.size(), md5hash ); SHA1( &handshakeData[0], handshakeData.size(), shahash ); std::vector<unsigned char> signiture; signiture.insert( signiture.end(), md5hash, md5hash + 16 ); signiture.insert( signiture.end(), shahash, shahash + 20 ); DataArray clientprf = PRF( 12, MasterKey, "client finished", signiture ); DataArray clientfin = std::vector<unsigned char>( data.begin() + 4, data.end() ); bool bDiff = false; for( unsigned int i = 0; i < clientfin.size(); i++ ){ if( clientfin[i] != clientprf[i] ) { bDiff = true; break; } } if( bDiff ) { std::cout << "Finished Different" << std::endl; std::cout << "Finish Should Be: " << std::dec << (int)clientprf.size() << std::endl; for( unsigned int i = 0 ; i < clientprf.size(); i++ ){ std::cout << std::hex << std::setw( 2 ) << std::setfill('0') << (int) clientprf[i] << " ";; if( (i + 1) % 16 == 0 ) std::cout << std::endl; } std::cout << std::endl; std::cout << "Finish Is: " << std::dec << (int)clientfin.size() << std::endl; for( unsigned int i = 0 ; i < clientfin.size(); i++ ){ std::cout << std::hex << std::setw( 2 ) << std::setfill('0') << (int) clientfin[i] << " ";; if( (i + 1) % 16 == 0 ) std::cout << std::endl; } std::cout << std::endl; } handshakeData.insert( handshakeData.end(), data.begin(), data.end() ); std::vector<unsigned char> dChangeCipher; dChangeCipher.push_back( 1 ); Record rChangeCipher( Record::Cipher, dChangeCipher ); rChangeCipher.Write( *mSocket ); MD5( &handshakeData[0], handshakeData.size(), md5hash ); SHA1( &handshakeData[0], handshakeData.size(), shahash ); std::vector<unsigned char> finSig; finSig.insert( finSig.end(), md5hash, md5hash + 16 ); finSig.insert( finSig.end(), shahash, shahash + 20 ); DataArray serverprf = PRF( 12, MasterKey, "server finished", finSig ); Record rServerFinished( Record::Handshake, Handshake::Finished( serverprf ).Serialize(), mServer ); rServerFinished.Write( *mSocket ); bDone = true; } previous = data[0]; } } } std::cout << "Finished " << this << " " << mSocket << std::endl; }