TEST(SlottedPage, ReferenceRecords) { SlottedPage* slottedPage = static_cast<SlottedPage*>(malloc(kPageSize)); slottedPage->initialize(); TupleId tid = TupleId(8129); RecordId rid = slottedPage->insert(Record("most awesome paper ever: a system for visualizing human behavior based on car metaphors")); // Make reference and check slottedPage->updateToReference(rid, tid); ASSERT_EQ(tid, slottedPage->isReference(rid)); ASSERT_EQ(slottedPage->getAllRecords(kInvalidPageId).size(), 0u); ASSERT_EQ(slottedPage->countAllRecords(), 1u); // Remove reference slottedPage->remove(rid); ASSERT_EQ(slottedPage->getAllRecords(kInvalidPageId).size(), 0u); ASSERT_EQ(slottedPage->countAllRecords(), 0u); free(slottedPage); }
TEST(SlottedPage, ForeignRecords) { SlottedPage* slottedPage = static_cast<SlottedPage*>(malloc(kPageSize)); slottedPage->initialize(); // Make foreign record and check uint16_t freeBytes = slottedPage->getBytesFreeForRecord(); RecordId rid = slottedPage->insertForeigner(Record("fear not this night"), TupleId(8129)); ASSERT_EQ(slottedPage->lookup(rid), Record("fear not this night")); ASSERT_EQ(slottedPage->isReference(rid), kInvalidTupleId); ASSERT_EQ(1u, slottedPage->getAllRecords(kInvalidPageId).size()); ASSERT_EQ(TupleId(8129), slottedPage->getAllRecords(kInvalidPageId)[0].first); ASSERT_EQ(Record("fear not this night"), slottedPage->getAllRecords(kInvalidPageId)[0].second); // Update the foreign record slottedPage->updateForeigner(rid, TupleId(8129), Record("but i am afraid of the dark")); ASSERT_EQ(slottedPage->lookup(rid), Record("but i am afraid of the dark")); ASSERT_EQ(slottedPage->isReference(rid), kInvalidTupleId); ASSERT_EQ(1u, slottedPage->getAllRecords(kInvalidPageId).size()); ASSERT_EQ(TupleId(8129), slottedPage->getAllRecords(kInvalidPageId)[0].first); ASSERT_EQ(Record("but i am afraid of the dark"), slottedPage->getAllRecords(kInvalidPageId)[0].second); // Remove foreign record slottedPage->remove(rid); ASSERT_EQ(slottedPage->getBytesFreeForRecord(), freeBytes); ASSERT_EQ(slottedPage->countAllRecords(), 0u); free(slottedPage); }
TEST(SlottedPage, Randomized) { const uint32_t kTestScale = 1; const uint32_t iterations = 10000; util::Random ranny; for(uint32_t j=0; j<kTestScale; j++) { std::unordered_map<RecordId, std::string> reference; SlottedPage* slottedPage = static_cast<SlottedPage*>(malloc(kPageSize)); slottedPage->initialize(); // Add some initial data for(uint32_t i=0; i<kPageSize/3/32; i++) { std::string data = util::randomWord(ranny, 8, 64); if(slottedPage->getBytesFreeForRecord() < data.size()) continue; RecordId id = slottedPage->insert(Record(data)); // std::cout << "insert " << id << " -> " << data << std::endl; ASSERT_TRUE(reference.count(id) == 0); reference.insert(make_pair(id, data)); } // Work on it for(uint32_t i=0; i<iterations; i++) { int32_t operation = ranny.rand() % 100; // Do insert if(operation <= 40) { std::string data = util::randomWord(ranny, 8, 64); if(slottedPage->getBytesFreeForRecord() < data.size()) continue; RecordId id = slottedPage->insert(Record(data)); // std::cout << "insert " << id << " -> " << data << std::endl; ASSERT_TRUE(reference.count(id) == 0); reference.insert(make_pair(id, data)); } // Do remove else if(operation <= 80) { if(reference.empty()) continue; RecordId id = reference.begin()->first; // std::cout << "remove " << id << std::endl; Record record = slottedPage->lookup(id); ASSERT_EQ(slottedPage->isReference(id), kInvalidTupleId); ASSERT_EQ(std::string(record.data(), record.size()), reference.begin()->second); slottedPage->remove(id); reference.erase(reference.begin()); } // Do update else if(operation <= 98) { if(reference.empty()) continue; RecordId id = reference.begin()->first; Record record = slottedPage->lookup(id); ASSERT_EQ(slottedPage->isReference(id), kInvalidTupleId); ASSERT_EQ(std::string(record.data(), record.size()), reference.begin()->second); std::string data = util::randomWord(ranny, 8, 64); if(slottedPage->canUpdateRecord(id, Record(data))) { slottedPage->update(id, Record(data)); reference.erase(reference.begin()); reference.insert(make_pair(id, data)); } } // Do consistency check else if(operation<=99 || i==iterations-1 || i==0) { ASSERT_TRUE(slottedPage->isValid()); auto records = slottedPage->getAllRecords(kInvalidPageId); // page id does not matter ASSERT_EQ(records.size(), reference.size()); for(auto& iter : records) { ASSERT_TRUE(reference.count(iter.first.toRecordId()) > 0); ASSERT_EQ(string(iter.second.data(), iter.second.size()), reference.find(iter.first.toRecordId())->second); } continue; } } free(slottedPage); } }