18 static std::string BigString(
const std::string& partial_string,
size_t n) {
20 while (result.size() < n) {
21 result.append(partial_string);
28 static std::string NumberString(
int n) {
30 snprintf(buf,
sizeof(buf),
"%d.", n);
31 return std::string(buf);
35 static std::string RandomSkewedString(
int i, Random* rnd) {
36 return BigString(NumberString(i), rnd->Skewed(17));
49 contents_.append(slice.
data(), slice.
size());
62 ASSERT_TRUE(!returned_partial_) <<
"must not Read() after eof/error";
66 returned_partial_ =
true;
70 if (contents_.
size() < n) {
72 returned_partial_ =
true;
80 if (n > contents_.
size()) {
98 dropped_bytes_ += bytes;
117 reader_(&source_, &report_, true,
121 void Write(
const std::string& msg) {
122 ASSERT_TRUE(!reading_) <<
"Write() after starting to read";
177 if (report_.
message_.find(msg) == std::string::npos) {
185 for (
int i = 0; i < 4; i++) {
186 std::string record(initial_offset_record_sizes_[i],
187 static_cast<char>(
'a' + i));
196 Reader* offset_reader =
new Reader(&source_, &report_,
true,
201 delete offset_reader;
205 int expected_record_offset) {
209 Reader* offset_reader =
new Reader(&source_, &report_,
true,
214 ASSERT_EQ(initial_offset_record_sizes_[expected_record_offset],
216 ASSERT_EQ(initial_offset_last_record_offsets_[expected_record_offset],
218 ASSERT_EQ((
char)(
'a' + expected_record_offset), record.
data()[0]);
219 delete offset_reader;
227 2 * log::kBlockSize - 1000,
233 2 * (kHeaderSize + 10000),
234 2 * (kHeaderSize + 10000) +
235 (2 * log::kBlockSize - 1000) + 3 * kHeaderSize};
256 for (
int i = 0; i < 100000; i++) {
257 Write(NumberString(i));
259 for (
int i = 0; i < 100000; i++) {
267 Write(BigString(
"medium", 50000));
268 Write(BigString(
"large", 100000));
270 ASSERT_EQ(BigString(
"medium", 50000), Read());
271 ASSERT_EQ(BigString(
"large", 100000), Read());
277 const int n = kBlockSize - 2*kHeaderSize;
278 Write(BigString(
"foo", n));
279 ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes());
290 const int n = kBlockSize - 2*kHeaderSize;
291 Write(BigString(
"foo", n));
292 ASSERT_EQ(kBlockSize - kHeaderSize, WrittenBytes());
302 const int n = kBlockSize - 2*kHeaderSize + 4;
303 Write(BigString(
"foo", n));
304 ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes());
314 const int n = kBlockSize - 2*kHeaderSize + 4;
315 Write(BigString(
"foo", n));
316 ASSERT_EQ(kBlockSize - kHeaderSize + 4, WrittenBytes());
324 for (
int i = 0; i < N; i++) {
325 Write(RandomSkewedString(i, &write_rnd));
328 for (
int i = 0; i < N; i++) {
329 ASSERT_EQ(RandomSkewedString(i, &read_rnd), Read());
341 ASSERT_EQ(
"OK", MatchError(
"read error"));
347 IncrementByte(6, 100);
351 ASSERT_EQ(
"OK", MatchError(
"unknown record type"));
358 ASSERT_EQ(kHeaderSize - 1, DroppedBytes());
359 ASSERT_EQ(
"OK", MatchError(
"truncated record at end of file"));
366 ASSERT_EQ(kHeaderSize + 2, DroppedBytes());
367 ASSERT_EQ(
"OK", MatchError(
"bad record length"));
372 IncrementByte(0, 10);
375 ASSERT_EQ(
"OK", MatchError(
"checksum mismatch"));
384 ASSERT_EQ(
"OK", MatchError(
"missing start"));
393 ASSERT_EQ(
"OK", MatchError(
"missing start"));
404 ASSERT_EQ(
"OK", MatchError(
"partial record without end"));
409 Write(BigString(
"bar", 100000));
412 ASSERT_EQ(BigString(
"bar", 100000), Read());
415 ASSERT_EQ(
"OK", MatchError(
"partial record without end"));
425 Write(BigString(
"foo", kBlockSize));
426 Write(BigString(
"bar", kBlockSize));
430 for (
int offset = kBlockSize; offset < 2*kBlockSize; offset++) {
431 SetByte(offset,
'x');
436 const int dropped = DroppedBytes();
442 CheckInitialOffsetRecord(0, 0);
446 CheckInitialOffsetRecord(1, 1);
450 CheckInitialOffsetRecord(10000, 1);
454 CheckInitialOffsetRecord(10007, 1);
458 CheckInitialOffsetRecord(10008, 2);
462 CheckInitialOffsetRecord(20014, 2);
466 CheckInitialOffsetRecord(20015, 3);
470 CheckInitialOffsetRecord(log::kBlockSize - 4, 3);
474 CheckInitialOffsetRecord(log::kBlockSize + 1, 3);
478 CheckInitialOffsetRecord(2 * log::kBlockSize + 1, 3);
482 CheckInitialOffsetRecord(
483 2 * (kHeaderSize + 1000) + (2 * log::kBlockSize - 1000) + 3 * kHeaderSize,
488 CheckOffsetPastEndReturnsNoRecords(0);
492 CheckOffsetPastEndReturnsNoRecords(5);
498 int main(
int argc,
char** argv) {
virtual Status Append(const Slice &slice)
virtual Status Skip(uint64_t n)
void SetByte(int offset, char new_byte)
bool ReadRecord(Slice *record, std::string *scratch)
const char * data() const
uint64_t LastRecordOffset()
static Status Corruption(const Slice &msg, const Slice &msg2=Slice())
void CheckOffsetPastEndReturnsNoRecords(uint64_t offset_past_end)
int main(int argc, char **argv)
void EncodeFixed32(char *buf, uint32_t value)
Status AddRecord(const Slice &slice)
virtual Status Read(size_t n, Slice *result, char *scratch)
void CheckInitialOffsetRecord(uint64_t initial_offset, int expected_record_offset)
uint32_t Mask(uint32_t crc)
void remove_prefix(size_t n)
virtual void Corruption(size_t bytes, const Status &status)
unsigned long long uint64_t
size_t WrittenBytes() const
static Status NotFound(const Slice &msg, const Slice &msg2=Slice())
void ShrinkSize(int bytes)
void IncrementByte(int offset, int delta)
void FixChecksum(int header_offset, int len)
static uint64_t initial_offset_last_record_offsets_[]
void Write(const std::string &msg)
std::string ReportMessage() const
uint32_t Value(const char *data, size_t n)
size_t DroppedBytes() const
void WriteInitialOffsetLog()
static size_t initial_offset_record_sizes_[]
std::string ToString() const
std::string ToString() const
std::string MatchError(const std::string &msg) const