41 std::cout << __PRETTY_FUNCTION__ << std::endl;
44 svf.
write(14,
"ABCDEF", 6);
47 svf.
read(16, 2, read_buffer);
51 auto need = svf.
need(8, 24);
54 for (
auto &val: need) {
55 std::cout <<
"(" << val.first <<
", " << val.second <<
"),";
57 std::cout <<
")" << std::endl;
58 std::cout << __PRETTY_FUNCTION__ <<
" DONE" << std::endl;
66 m_expected_blocks(m_expected_blocks) {}
73 size_t bytes_written = 0;
74 auto time_start = std::chrono::high_resolution_clock::now();
80 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
85 auto actual_blocks = svf.
blocks();
89 std::ostringstream os;
90 os <<
"Expected " <<
m_expected_blocks.size() <<
" blocks but got " << actual_blocks.size()
98 std::ostringstream os;
100 os <<
" but got " << actual_blocks[i].first <<
" (other blocks not tested)";
107 std::ostringstream os;
109 os <<
" but got " << actual_blocks[i].second <<
" (other blocks not tested)";
114 num_bytes += actual_blocks[i].second;
119 if (svf.
num_blocks() != actual_blocks.size()) {
121 std::ostringstream os;
122 os <<
"Found svf.num_blocks() " << svf.
num_blocks() <<
" but expected " << actual_blocks.size();
129 std::ostringstream os;
130 os <<
"Found svf.num_bytes() " << svf.
num_bytes() <<
" but expected " << num_bytes;
137 std::ostringstream os;
138 os <<
"Found svf.count_write()" << svf.
count_write() <<
" but expected " <<
m_writes.size();
144 std::ostringstream os;
145 os <<
"Found svf.bytes_write() " << svf.
bytes_write() <<
" but expected " << bytes_written;
152 std::ostringstream os;
153 os <<
"Count of reads is " << svf.
count_read() <<
" but should be 0";
159 std::ostringstream os;
160 os <<
"Count of read bytes is " << svf.
bytes_read() <<
" but should be 0";
221 {
"Write no blocks", {}, {}},
224 {
"Write single block", {{8, 4}}, {{8, 4}},},
229 {
"Overwrite single block", {{8, 4}, {8, 4}}, {{8, 4}},},
233 {
"Extend single block - a", {{8, 4}, {8, 5}}, {{8, 5}},},
237 {
"Extend single block - b", {{8, 4}, {9, 4}}, {{8, 5}},},
241 {
"Coalesce two blocks", {{8, 4}, {12, 5}}, {{8, 9}},},
244 {
"Insert a previous block", {{16, 4}, {8, 4}}, {{8, 4}, {16, 4}},},
246 {
"Insert a new block in the middle", {{16, 4}, {2, 4}, {8, 4}}, {{2, 4}, {8, 4}, {16, 4}},},
248 {
"Add second block", {{8, 4}, {16, 4}}, {{8, 4}, {16, 4}},},
251 {
"New joins two blocks", {{8, 4}, {16, 4}, {10, 8}}, {{8, 12}},},
257 {
"New just fills gap between two blocks", {{8, 4}, {16, 4}, {12, 4}}, {{8, 12}},},
261 {
"New overlaps two blocks exactly", {{8, 4}, {16, 4}, {8, 12}}, {{8, 12}},},
265 {
"New overlaps two blocks just short", {{8, 4}, {16, 4}, {9, 10}}, {{8, 12}},},
269 {
"New overlaps two blocks and adds", {{8, 4}, {16, 4}, {8, 14}}, {{8, 14}},},
275 {
"New appends old[0]", {{8, 4}, {4, 4}}, {{4, 8}},},
279 {
"New appends part of old[0]", {{8, 4}, {7, 3}}, {{7, 5}},},
283 {
"New overlaps end old[0] exactly", {{8, 4}, {7, 5}}, {{7, 5}},},
287 {
"New overlaps end old[0] and beyond", {{8, 4}, {7, 6}}, {{7, 6}},},
291 {
"New appends old[0] not [1] (a)", {{8, 4}, {16, 4}, {7, 7}}, {{7, 7}, {16, 4}},},
295 {
"New appends old[0] not [1] (b)", {{8, 4}, {16, 4}, {7, 8}}, {{7, 8}, {16, 4}},},
299 {
"New appends old[0] and [1] exactly", {{8, 4}, {16, 4}, {7, 9}}, {{7, 13}},},
303 {
"New appends old[0] and [1] - just", {{8, 4}, {16, 4}, {7, 10}}, {{7, 13}},},
307 {
"New appends old[0] and [1] - one byte", {{8, 4}, {16, 4}, {7, 11}}, {{7, 13}},},
311 {
"New appends old[0] and [1] - all", {{8, 4}, {16, 4}, {7, 13}}, {{7, 13}},},
315 {
"New appends old[0] and [1] overlapped", {{8, 4}, {16, 4}, {7, 14}}, {{7, 14}},},
321 {
"New appends part of old[0]", {{8, 4}, {7, 3}}, {{7, 5}},},
327 auto result = test_case.run();
329 results.push_back(result);
332 auto result = test_case.run();
334 results.push_back(result);
341 t_fpos fpos,
size_t len,
const char *data,
const std::string &message)
347 m_message(message) {}
360 std::ostringstream os;
361 os <<
"Error message \"" << err.
message() <<
"\" expected \"" <<
m_message <<
"\"";
371 "SparseVirtualFile::write(): Difference at position 65 'B' != 'A' Ordinal 66 != 65"
378 auto result = test_case.run();
380 results.push_back(result);
391 size_t block_size = 256;
394 auto time_start = std::chrono::high_resolution_clock::now();
395 for (
int i = 0; i < repeat; ++i) {
398 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
399 std::ostringstream os;
400 os << block_size <<
" block size, x" << repeat <<
", compare_for_diff=" << compare_for_diff;
401 auto result =
TestResult(__PRETTY_FUNCTION__, std::string(os.str()), 0,
"", time_exec.count(),
402 repeat * block_size);
404 results.push_back(result);
423 auto time_start = std::chrono::high_resolution_clock::now();
425 for (
size_t vr = 0; vr < 23831; ++vr) {
426 t_fpos fpos = 80 + vr * 8004;
429 for (
int lrsh = 0; lrsh < 10; ++lrsh) {
435 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
436 auto result =
TestResult(__PRETTY_FUNCTION__,
"Sim low level index", 0,
"", time_exec.count(),
439 results.push_back(result);
447 for (
size_t block_size = 1; block_size <= 256; block_size *= 2) {
450 auto time_start = std::chrono::high_resolution_clock::now();
451 for (
t_fpos i = 0; i < (1024 * 1024 * 1) / block_size; ++i) {
452 t_fpos fpos = i * block_size;
455 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
457 std::ostringstream os;
458 os <<
"1Mb, " << std::setw(3) << block_size <<
" sized blocks, coalesced";
459 auto result =
TestResult(__PRETTY_FUNCTION__, std::string(os.str()), 0,
"", time_exec.count(),
462 results.push_back(result);
471 for (
size_t block_size = 1; block_size <= 256; block_size *= 2) {
474 auto time_start = std::chrono::high_resolution_clock::now();
475 for (
t_fpos i = 0; i < (1024 * 1024 * 1) / block_size; ++i) {
476 t_fpos fpos = i * block_size + i;
479 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
481 std::ostringstream os;
482 os <<
"1Mb, " << std::setw(3) << block_size <<
" sized blocks, uncoalesced";
483 auto result =
TestResult(__PRETTY_FUNCTION__, std::string(os.str()), 0,
"", time_exec.count(),
486 results.push_back(result);
498 for (
size_t block_size = 1; block_size <= 256; block_size *= 2) {
501 size_t num_blocks = (1024 * 1024 * 1) / block_size;
503 auto time_start = std::chrono::high_resolution_clock::now();
504 for (
t_fpos i = 0; i < num_blocks; ++i) {
505 t_fpos fpos = i * block_size + i;
508 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
510 std::ostringstream os;
511 os <<
"1Mb, block size " << std::setw(3) << block_size <<
" sized blocks";
512 os <<
" num_blocks " << num_blocks;
513 os <<
" size_of " << svf.
size_of();
516 auto result =
TestResult(__PRETTY_FUNCTION__, std::string(os.str()), 0,
"", time_exec.count(),
519 results.push_back(result);
528 m_fpos(fpos), m_len(len) {}
546 char read_buffer[256];
548 auto time_start = std::chrono::high_resolution_clock::now();
554 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
557 for (
size_t i = 0; i <
m_len; ++i) {
560 std::ostringstream os;
561 os <<
"In position " <<
m_fpos + 1 <<
" expected fpos "
563 os <<
" but got " <<
static_cast<int>(read_buffer[i]) <<
" (other test_data_bytes_512 not tested)";
575 {
"Read exactly a block", {{8, 4}}, 8, 4},
578 {
"Read leading part of block", {{8, 4}}, 8, 3},
581 {
"Read trailing part of block", {{8, 4}}, 9, 3},
584 {
"Read mid part of block", {{8, 4}}, 9, 2},
591 {
"Read trailing part of block", {{8, 4}}, 9, 3},
594 {
"Read mid part of block", {{8, 4}}, 9, 2},
603 auto result = test_case.run();
605 results.push_back(result);
631 char read_buffer[256];
637 std::ostringstream os;
638 os <<
"Error message \"" << err.
message() <<
"\" expected \"" <<
m_message <<
"\"";
646 {
"Read empty SVF throws", {}, 8, 4,
"SparseVirtualFile::read(): Sparse virtual file is empty."},
653 {
"Read before block throws", {{8, 4}}, 2, 4,
654 "SparseVirtualFile::read(): Requested file position 2 precedes first block at 8"},
657 {
"Read prior to block throws", {{8, 4}}, 7, 4,
658 "SparseVirtualFile::read(): Requested file position 7 precedes first block at 8"},
661 {
"Read beyond block throws", {{8, 4}}, 9, 4,
662 "SparseVirtualFile::read(): Requested position 9 length 4 (end 13) overruns block that starts at 8 has size 4 (end 12). Offset into block is 1 overrun is 1 bytes"},
665 {
"Read beyond end throws", {{8, 4}}, 12, 4,
666 "SparseVirtualFile::read(): Requested position 12 length 4 (end 16) overruns block that starts at 8 has size 4 (end 12). Offset into block is 4 overrun is 4 bytes"},
674 auto result = test_case.run();
676 results.push_back(result);
685 const size_t SIZE = 1024 * 1024 * 1;
688 for (
t_fpos i = 0; i < (SIZE) / 256; ++i) {
694 auto time_start = std::chrono::high_resolution_clock::now();
695 svf.
read(0, SIZE, buffer);
696 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
698 std::ostringstream os;
699 auto result =
TestResult(__PRETTY_FUNCTION__,
"1Mb of 256 bytes in one block", 0,
"", time_exec.count(),
702 results.push_back(result);
708 const size_t SIZE = 1024 * 1024 * 1;
710 for (
size_t block_size = 1; block_size <= 512; block_size *= 2) {
712 for (
t_fpos i = 0; i < (SIZE) / block_size; ++i) {
713 t_fpos fpos = i * 512 * 2;
718 auto time_start = std::chrono::high_resolution_clock::now();
719 for (
t_fpos i = 0; i < (SIZE) / block_size; ++i) {
720 t_fpos fpos = i * 512 * 2;
721 svf.
read(fpos, block_size, buffer);
723 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
725 std::ostringstream os;
726 os <<
"1Mb " << block_size <<
" byte blocks " << svf.
num_blocks() <<
" blocks ";
727 auto result =
TestResult(__PRETTY_FUNCTION__, os.str(), 0,
"", time_exec.count(),
730 results.push_back(result);
737 m_fpos(fpos), m_len(len),
738 m_expected(expected) {}
756 auto time_start = std::chrono::high_resolution_clock::now();
758 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
762 std::ostringstream os;
763 os <<
"Expected has() in position " <<
m_fpos <<
" and length " <<
m_len;
776 {
"Has empty - false", {}, 8, 4,
false},
779 {
"Has an exact block", {{8, 4}}, 8, 4,
true},
782 {
"Has leading block", {{8, 4}}, 8, 3,
true},
785 {
"Has trailing block", {{8, 4}}, 9, 3,
true},
788 {
"Has mid block", {{8, 4}}, 9, 2,
true},
791 {
"Not has an exact block -1", {{8, 4}}, 7, 4,
false},
794 {
"Not has an exact block +1", {{8, 4}}, 9, 4,
false},
801 auto result = test_case.run();
803 results.push_back(result);
811 m_fpos(fpos), m_len(len),
828 auto time_start = std::chrono::high_resolution_clock::now();
830 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
833 if (need.size() !=
m_need.size()) {
834 std::ostringstream os;
835 os <<
"Found " << need.size() <<
" need pairs but expected " <<
m_need.size() <<
" need pairs";
838 for (
size_t i = 0; i < need.size(); ++i) {
839 if (need[i].first !=
m_need[i].first || need[i].second !=
m_need[i].second) {
840 std::ostringstream os;
841 os <<
"In position " << i <<
" expected fpos " <<
m_need[i].first <<
" and len "
843 os <<
" but got fpos " << need[i].first <<
" and len " << need[i].second;
854 {
"Need on empty SVF", {}, 8, 4, {{8, 4}}},
857 {
"Exactly one block", {{8, 4}}, 8, 4, {},},
860 {
"Inside one block", {{8, 4}}, 9, 2, {},},
863 {
"All before one block", {{8, 4}}, 4, 4, {{4, 4}},},
866 {
"All after one block", {{8, 4}}, 12, 4, {{12, 4}},},
869 {
"Before and part of one block", {{8, 4}}, 4, 7, {{4, 4}},},
872 {
"Before and all of one block", {{8, 4}}, 4, 8, {{4, 4}},},
875 {
"Before, all of one block and after", {{8, 4}}, 4, 15, {{4, 4}, {12, 7}},},
878 {
"Before, all and after one block", {{8, 4}}, 4, 9, {{4, 4}, {12, 1}},},
881 {
"Two blocks and in between (a)", {{8, 4}, {14, 4}}, 8, 10, {{12, 2}},},
884 {
"Two blocks and in between (b)", {{8, 4}, {14, 4}}, 8, 9, {{12, 2}},},
887 {
"Two blocks and in between (c)", {{8, 4}, {14, 4}}, 9, 9, {{12, 2}},},
890 {
"Two blocks and in between (d)", {{8, 4}, {14, 4}}, 9, 7, {{12, 2}},},
893 {
"Two blocks, under-run", {{8, 4}, {14, 4}}, 7, 11, {{7, 1}, {12, 2}},},
896 {
"Two blocks, over-run", {{8, 4}, {14, 4}}, 8, 11, {{12, 2}, {18, 1}},},
899 {
"Two blocks, under/over-run", {{8, 4}, {14, 4}}, 7, 12, {{7, 1}, {12, 2}, {18, 1}},},
905 {
"Two blocks and in between (a)", {{8, 4}, {14, 4}}, 8, 10, {{12, 2}},},
911 auto result = test_case.run();
913 results.push_back(result);
916 auto result = test_case.run();
918 results.push_back(result);
930 for (
size_t vr = 0; vr < 23831; ++vr) {
931 t_fpos fpos = 80 + vr * 8004;
934 for (
int lrsh = 0; lrsh < 10; ++lrsh) {
940 size_t data_size = 0;
941 size_t num_need_blocks = 0;
942 auto time_start = std::chrono::high_resolution_clock::now();
944 auto need = svf.
need(i, need_size);
945 num_need_blocks += need.size();
946 data_size += need_size;
948 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
949 std::ostringstream os;
950 os <<
"Sim need(" << need_size <<
") on index [" << num_need_blocks <<
"]";
951 auto result =
TestResult(__PRETTY_FUNCTION__, os.str(), 0,
"", time_exec.count(), data_size);
953 results.push_back(result);
959 for (
size_t need_size = 32; need_size < 8 * 4096; need_size *= 2) {
965 #pragma mark - Test need() with greedy value.
989 auto time_start = std::chrono::high_resolution_clock::now();
991 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
994 if (need.size() !=
m_need.size()) {
995 std::ostringstream os;
996 os <<
"Found " << need.size() <<
" need pairs but expected " <<
m_need.size() <<
" need pairs";
999 for (
size_t i = 0; i < need.size(); ++i) {
1000 if (need[i].first !=
m_need[i].first || need[i].second !=
m_need[i].second) {
1001 std::ostringstream os;
1002 os <<
"In position " << i <<
" expected fpos " <<
m_need[i].first <<
" and len "
1004 os <<
" but got fpos " << need[i].first <<
" and len " << need[i].second;
1017 "Need (greedy=0) on empty SVF",
1023 "Need 32 (greedy=4) on empty SVF",
1029 "Need (greedy=32) on empty SVF",
1055 "Need with write one byte un-coalesced (greedy=8)",
1077 auto result = test_case.run();
1079 results.push_back(result);
1085 #pragma mark - Test erase()
1108 auto time_start = std::chrono::high_resolution_clock::now();
1114 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1121 {
"Erase a block", {{8, 4}}, 8},
1129 auto result = test_case.run();
1131 results.push_back(result);
1140 m_message(message) {}
1158 std::ostringstream os;
1159 os <<
"Error message \"" << err.
message() <<
"\" expected \"" <<
m_message <<
"\"";
1168 {
"Erase empty SVF throws", {}, 8,
"SparseVirtualFile::erase(): Non-existent file position 8 at start of block."},
1171 {
"Erase before block throws", {{8, 4}}, 2,
1172 "SparseVirtualFile::erase(): Non-existent file position 2 at start of block."},
1175 {
"Erase within a block throws", {{8, 4}}, 9,
1176 "SparseVirtualFile::erase(): Non-existent file position 9 at start of block."},
1179 {
"Erase beyond end throws", {{8, 4}}, 12,
1180 "SparseVirtualFile::erase(): Non-existent file position 12 at start of block."},
1188 auto result = test_case.run();
1190 results.push_back(result);
1197 size_t block_size = 256;
1198 size_t total_size = 1024 * 1024 * 1;
1203 double time_total = 0.0;
1204 for (
int r = 0; r < repeat; ++r) {
1205 for (
t_fpos i = 0; i < total_size / block_size; ++i) {
1207 t_fpos fpos = i * block_size + 1;
1210 auto time_start = std::chrono::high_resolution_clock::now();
1212 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1213 time_total += time_exec.count();
1215 std::ostringstream os;
1216 os <<
"1Mb, " << std::setw(3) << block_size <<
"block size, x" << repeat <<
" overwrite=" << overwrite;
1217 auto result =
TestResult(__PRETTY_FUNCTION__, std::string(os.str()), 0,
"", time_total, total_size);
1219 results.push_back(result);
1231 #ifdef SVF_THREAD_SAFE
1237 for (
size_t fpos = 0; fpos < 1024 * 1024; fpos += 8) {
1242 std::cout << __FUNCTION__ <<
"(): Fails: " << err.
message() << std::endl;
1248 for (
size_t fpos = 0; fpos < 1024 * 1024 * 2; fpos += 16) {
1253 std::cout << __FUNCTION__ <<
"(): Fails: " << err.
message() << std::endl;
1260 std::vector<std::thread> threads;
1264 auto time_start = std::chrono::high_resolution_clock::now();
1265 for (
int i = 0; i < num_threads; ++i) {
1272 for (
size_t i = 0; i < threads.size(); ++i) {
1275 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1281 std::ostringstream os;
1282 os <<
"Multi threaded write [" << num_threads <<
"] Coalesced " << is_coalesced;
1283 auto result =
TestResult(__PRETTY_FUNCTION__, os.str(), 0,
"", time_exec.count() / num_threads, work_done);
1285 results.push_back(result);
1291 for (
int num_threads = 1; num_threads < 1 << 8; num_threads *= 2) {
1299 for (
int num_threads = 1; num_threads < 1 << 8; num_threads *= 2) {
1321 std::string test_name(__FUNCTION__);
1322 static char data[4096];
1325 svf.
write(0, data, 1024);
1326 svf.
write(291809396, data, 1024);
1327 auto blocks = svf.
blocks();
1333 auto time_start = std::chrono::high_resolution_clock::now();
1334 bool has = svf.
has(291810392, 2429);
1336 auto need = svf.
need(291810392, 2429, 1024);
1337 svf.
write(291810420, data, 2401);
1339 has = svf.
has(291810392, 2429);
1341 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1342 return TestResult(__PRETTY_FUNCTION__, test_name, result, err, time_exec.count(), svf.
num_bytes());
1347 std::string test_name(__FUNCTION__);
1348 static char data[4096];
1351 auto blocks = svf.
blocks();
1357 auto time_start = std::chrono::high_resolution_clock::now();
1358 auto need = svf.
need(0, 32, 1);
1359 svf.
write(0, data, 32);
1361 bool has = svf.
has(0, 32);
1364 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1365 return TestResult(__PRETTY_FUNCTION__, test_name, result, err, time_exec.count(), svf.
num_bytes());
1372 std::string test_name(__FUNCTION__);
1373 static char data[1 << 16];
1379 auto time_start = std::chrono::high_resolution_clock::now();
1381 needs = svf.
need(515'913'022, 6283);
1382 result |= needs.size() != 1;
1383 svf.
write(515'913'022, data, 1 << 16);
1385 result |= blocks.size() != 1;
1386 svf.
read(515'913'022, 6283, data);
1388 needs = svf.
need(515'919'305, 5873);
1389 result |= needs.size() != 0;
1390 svf.
read(515'919'305, 5873, data);
1392 needs = svf.
need(486'156'341, 6039);
1393 result |= needs.size() != 1;
1395 svf.
write(486'156'341, data, 1 << 16);
1397 result |= blocks.size() != 2;
1399 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1400 return TestResult(__PRETTY_FUNCTION__, test_name, result, err, time_exec.count(), svf.
num_bytes());
1404 std::string test_name(__FUNCTION__);
1409 auto time_start = std::chrono::high_resolution_clock::now();
1411 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1412 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1414 results.push_back(test_result);
1420 std::string test_name(__FUNCTION__);
1422 std::string test_error_message =
"";
1426 auto time_start = std::chrono::high_resolution_clock::now();
1430 std::string expected_message =
"SparseVirtualFile::block_size(): Requested file position 895 is not at the start of a block";
1431 if (err.
message() != expected_message) {
1432 std::ostringstream os;
1433 os <<
"Error message \"" << err.
message() <<
"\" expected \"" << expected_message <<
"\"";
1434 test_error_message = os.str();
1438 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1439 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result, test_error_message,
1442 results.push_back(test_result);
1448 std::string test_name(__FUNCTION__);
1452 auto time_start = std::chrono::high_resolution_clock::now();
1459 result |= block_touches.size() != 1;
1461 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1462 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1464 results.push_back(test_result);
1470 std::string test_name(__FUNCTION__);
1473 static char data[1 << 16];
1476 auto time_start = std::chrono::high_resolution_clock::now();
1483 result |= block_touches.size() != 1;
1484 result |= block_touches.begin()->first != 0;
1485 result |= block_touches.begin()->second != 894;
1488 svf.
read(900, 4, data);
1491 result |= block_touches.size() != 1;
1492 result |= block_touches.begin()->first != 1;
1493 result |= block_touches.begin()->second != 894;
1495 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1496 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1498 results.push_back(test_result);
1504 std::string test_name(__FUNCTION__);
1508 auto time_start = std::chrono::high_resolution_clock::now();
1518 result |= block_touches.size() != 2;
1520 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1521 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1523 results.push_back(test_result);
1530 std::string test_name(__FUNCTION__);
1534 auto time_start = std::chrono::high_resolution_clock::now();
1546 result |= block_touches.size() != 1;
1548 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1549 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1551 results.push_back(test_result);
1557 std::string test_name(__FUNCTION__);
1562 size_t block_size = 128;
1563 size_t block_count = 256;
1565 for (
size_t i = 0; i < block_count; ++i) {
1567 file_positon += block_size;
1573 result |= svf.
num_bytes() != (block_count * block_size);
1575 result |= svf.
num_blocks() == block_count ? 0 : 1 << 0;
1576 result |= svf.
num_bytes() == (block_count * block_size) ? 0 : 1 << 1;
1578 auto time_start = std::chrono::high_resolution_clock::now();
1580 size_t cache_upper_bound = 1024;
1581 result |= svf.
num_bytes() < cache_upper_bound;
1583 result |= svf.
num_bytes() >= cache_upper_bound ? 0 : 1 << 2;
1587 for (
const auto &iter: touch_fpos_map) {
1589 svf.
erase(iter.second);
1595 result |= svf.
num_bytes() >= cache_upper_bound;
1597 result |= svf.
num_bytes() < cache_upper_bound ? 0 : 1 << 3;;
1599 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1600 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1602 results.push_back(test_result);
1608 std::string test_name(__FUNCTION__);
1613 size_t block_size = 128;
1614 size_t block_count = 256;
1615 t_fpos file_position = 0;
1616 for (
size_t i = 0; i < block_count; ++i) {
1618 file_position += block_size;
1625 result |= svf.
num_blocks() == block_count ? 0 : 1 << error_bit;
1627 result |= svf.
num_bytes() == (block_count * block_size) ? 0 : 1 << error_bit;
1630 auto time_start = std::chrono::high_resolution_clock::now();
1632 size_t cache_upper_bound = 1024;
1635 result |= svf.
num_bytes() >= cache_upper_bound ? 0 : 1 << error_bit;
1638 size_t punted = svf.
lru_punt(cache_upper_bound);
1641 result |= svf.
num_bytes() == 7 * block_size ? 0 : 1 << error_bit;
1643 result |= punted == (block_size * block_count - 896) ? 0 : 1 << error_bit;
1647 result |= svf.
num_bytes() < cache_upper_bound ? 0 : 1 << error_bit;
1652 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1653 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1655 results.push_back(test_result);
1663 int result_code = 0;
1665 auto time_start = std::chrono::high_resolution_clock::now();
1671 result_code |= svf.
num_blocks() == 1 ? 0 : 1 << error_bit;
1673 result_code |= svf.
block_touch() == 2 ? 0 : 1 << error_bit;
1676 auto iter = block_touches.begin();
1677 result_code |= iter != block_touches.end() ? 0 : 1 << error_bit;
1679 result_code |= iter->first == 1 ? 0 : 1 << error_bit;
1681 result_code |= iter->second == 16 ? 0 : 1 << error_bit;
1684 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1685 auto result =
TestResult(__PRETTY_FUNCTION__,
"Sim low level index", result_code,
"", time_exec.count(),
1688 results.push_back(result);
1695 std::string test_name(__FUNCTION__);
1707 auto time_start = std::chrono::high_resolution_clock::now();
1709 result |= seek_reads_result.size() == 2 ? 0 : 1 << error_bit;
1711 result |= seek_reads_result[0].first == 0 ? 0 : 1 << error_bit;
1713 result |= seek_reads_result[0].second == 128 ? 0 : 1 << error_bit;
1715 result |= seek_reads_result[1].first == 256 ? 0 : 1 << error_bit;
1717 result |= seek_reads_result[1].second == 512 ? 0 : 1 << error_bit;
1719 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1721 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1723 results.push_back(test_result);
1729 std::string test_name(__FUNCTION__);
1741 auto time_start = std::chrono::high_resolution_clock::now();
1743 result |= seek_reads_result.size() == 1 ? 0 : 1 << error_bit++;
1744 result |= seek_reads_result[0].first == 0 ? 0 : 1 << error_bit++;
1745 result |= seek_reads_result[0].second == 64 + 512 ? 0 : 1 << error_bit++;
1746 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1748 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1750 results.push_back(test_result);
1756 std::string test_name(__FUNCTION__);
1768 auto time_start = std::chrono::high_resolution_clock::now();
1770 result |= seek_reads_result.size() == 1 ? 0 : 1 << error_bit++;
1771 result |= seek_reads_result[0].first == 0 ? 0 : 1 << error_bit++;
1772 result |= seek_reads_result[0].second == 256 + 512 ? 0 : 1 << error_bit++;
1773 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1775 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1777 results.push_back(test_result);
1784 std::string test_name(__FUNCTION__);
1796 auto time_start = std::chrono::high_resolution_clock::now();
1798 result |= seek_reads_result.size() == 2 ? 0 : 1 << error_bit;
1800 result |= seek_reads_result[0].first == 0 ? 0 : 1 << error_bit;
1802 result |= seek_reads_result[0].second == 64 ? 0 : 1 << error_bit;
1804 result |= seek_reads_result[1].first == 64 + 128 ? 0 : 1 << error_bit;
1806 result |= seek_reads_result[1].second == (64 + 256) - (64 + 128) ? 0 : 1 << error_bit;
1808 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1810 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1812 results.push_back(test_result);
1819 std::string test_name(__FUNCTION__);
1831 auto time_start = std::chrono::high_resolution_clock::now();
1833 result |= seek_reads_result.size() == 1 ? 0 : 1 << error_bit;
1835 result |= seek_reads_result[0].first == 0 ? 0 : 1 << error_bit;
1837 result |= seek_reads_result[0].second == 512 ? 0 : 1 << error_bit;
1839 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1841 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1843 results.push_back(test_result);
1851 std::string test_name(__FUNCTION__);
1855 auto time_start = std::chrono::high_resolution_clock::now();
1872 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1873 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1875 results.push_back(test_result);
1882 std::string test_name(__FUNCTION__);
1886 auto time_start = std::chrono::high_resolution_clock::now();
1903 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1904 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1906 results.push_back(test_result);
1913 std::string test_name(__FUNCTION__);
1917 auto time_start = std::chrono::high_resolution_clock::now();
1938 std::chrono::duration<double> time_exec = std::chrono::high_resolution_clock::now() - time_start;
1939 TestResult test_result =
TestResult(__PRETTY_FUNCTION__, test_name, result,
"", time_exec.count(),
1941 results.push_back(test_result);
1947 #define INCLUDE_TESTS 1
1988 #ifdef SVF_THREAD_SAFE
Might be thrown during a erase operation where the file position is not at the exact beginning of a b...
Exception specialisation for the SparseVirtualFile.
const std::string & message() const
Might be thrown during a write operation where the data differs.
Might be thrown during a write operation which fails.
Implementation of a Sparse Virtual File.
size_t bytes_read() const noexcept
Count of total bytes read with read() operations.
t_seek_reads need_many(t_seek_reads &seek_reads, size_t greedy_length=0) const noexcept
Given many [(file position, lengths), ...] what data do I need that I don't yet have?
size_t size_of() const noexcept
size_of() gives best guess of total memory usage.
size_t lru_punt(size_t cache_size_upper_bound)
size_t blocks_punted() const noexcept
Returns the The total count of blocks that have been erased by punting.
t_block_touches block_touches() const noexcept
Returns a std::map of latest touch value key and file position value.
size_t num_blocks() const noexcept
Number of blocks used.
size_t bytes_erased() const noexcept
Returns the The total count of bytes that have been erased either directly or by punting.
size_t num_bytes() const noexcept
Gives exact number of data bytes held.
t_block_touch block_touch() const noexcept
Return the latest value of the monotonically increasing block_touch value.
void write(t_fpos fpos, const char *data, size_t len)
Write the data a the given file position.
void clear() noexcept
Executes the data deletion strategy.
size_t bytes_punted() const noexcept
Returns the The total count of bytes that have been erased by punting.
size_t erase(t_fpos fpos)
Remove a particular block.
size_t blocks_erased() const noexcept
Returns the The total count of blocks that have been erased either directly or by punting.
size_t count_read() const noexcept
Count of read() operations.
bool has(t_fpos fpos, size_t len) const noexcept
Do I have the data at the given file position and length?
size_t block_size(t_fpos fpos) const
The length of the block at a specific file position.
size_t bytes_write() const noexcept
Count of total bytes written with write() operations.
size_t count_write() const noexcept
Count of write() operations.
t_fpos last_file_position() const noexcept
The position of the last byte.
void read(t_fpos fpos, size_t len, char *p)
Read data and write to the buffer provided by the caller. This is non-const as it updates the non-con...
t_seek_reads need(t_fpos fpos, size_t len, size_t greedy_length=0) const noexcept
Create a new fragmentation list of seek/read instructions.
t_seek_reads blocks() const noexcept
The existing blocks as a list of (file_position, size) pairs.
Abstract base class for tests cases.
size_t load_writes(SparseVirtualFile &svf, const char *data) const
Load all the specified write seek/write blocks from the data (assumed to be 512 bytes long).
Specialisation of a test case for erase() on a SVF.
TestResult run() const override
TestCaseErase(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos)
TestCaseEraseThrows(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, const std::string &message)
TestResult run() const override
TestCaseHas(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len, bool expected)
TestResult run() const override
Specialisation of a test case for a SVF need() with a greedy length.
TestResult run() const override
TestCaseNeedGreedy(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len, size_t greedy_length, const t_seek_reads &m_need)
TestResult run() const override
TestCaseNeed(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len, const t_seek_reads &m_need)
Specialisation of a test case for writing to a SVF.
TestCaseRead(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len)
TestResult run() const override
TestResult run() const override
TestCaseReadThrows(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len, const std::string &message)
TestCaseWrite(const std::string &m_test_name, const t_seek_reads &m_writes, const t_seek_reads &m_expected_blocks)
TestResult run() const override
Create a SVF, run the write tests and report the result.
t_seek_reads m_expected_blocks
TestResult run() const override
TestCaseWriteThrows(const std::string &m_test_name, const t_seek_reads &m_writes, t_fpos fpos, size_t len, const char *data, const std::string &message)
Count of tests taht pass and fail.
void add_result(int result)
Add a tests result.
TestCount test_perf_erase_overwrite_true(t_test_results &results)
const std::vector< TestCaseNeed > need_test_cases_special
TestCount test_block_size(t_test_results &results)
TestCount _test_perf_erase_overwrite(bool overwrite, t_test_results &results)
TestCount test_needs_many_empty_greedy_length(t_test_results &results)
const std::vector< TestCaseWrite > write_test_cases_special
TestCount test_block_touch_coalesced(t_test_results &results)
const std::vector< TestCaseRead > read_test_cases_special
TestCount test_needs_many_empty(t_test_results &results)
TestCount test_erase_updates_counters_not_punt(t_test_results &results)
TestCount test_perf_write_1M_uncoalesced_size_of(t_test_results &results)
TestCount test_lru_block_punting_a(t_test_results &results)
std::vector< TestResult > t_test_results
TestCount test_svf_all(t_test_results &results)
SparseVirtualFile g_svf_multithreaded("", 0.0)
const std::vector< TestCaseNeed > need_test_cases
TestCount test_perf_write_without_diff_check(t_test_results &results)
TestCount test_write_multithreaded_un_coalesced(t_test_results &results)
TestCount test_perf_write_1M_coalesced(t_test_results &results)
TestCount test_perf_erase_overwrite_false(t_test_results &results)
TestCount test_needs_many_empty_overlap(t_test_results &results)
const std::vector< TestCaseNeedGreedy > need_greedy_test_cases
TestCount test_needs_many_one_block(t_test_results &results)
TestCount test_perf_read_1M_un_coalesced(t_test_results &results)
TestCount test_perf_write_1M_uncoalesced(t_test_results &results)
TestCount test_need_greedy_all(t_test_results &results)
TestCount test_needs_many_one_block_greedy(t_test_results &results)
const std::vector< TestCaseWriteThrows > write_test_cases_throws
const std::vector< TestCaseReadThrows > read_test_cases_throw
TestCount test_lru_block_punting_b(t_test_results &results)
TestCount _test_perf_write_with_diff_check(bool compare_for_diff, t_test_results &results)
void _write_multithreaded_un_coalesced()
TestResult test_debug_need_read_special_B()
const std::vector< TestCaseHas > has_test_cases
const std::vector< TestCaseEraseThrows > erase_test_cases_throw
TestCount test_perf_need_sim_index(t_test_results &results)
TestCount test_lru_block_punting_c(t_test_results &results)
TestCount test_write_multithreaded(int num_threads, bool is_coalesced, t_test_results &results)
TestCount test_read_all(t_test_results &results)
TestCount test_write_all(t_test_results &results)
TestCount test_perf_write_sim_index_svf(t_test_results &results)
const std::vector< TestCaseErase > erase_test_cases
TestCount test_erase_all(t_test_results &results)
TestCount test_need_all(t_test_results &results)
TestCount test_perf_read_1M_coalesced(t_test_results &results)
TestCount test_erase_throws_all(t_test_results &results)
TestCount test_write_all_throws(t_test_results &results)
const char test_data_bytes_512[]
TestCount test_block_touch_two_blocks(t_test_results &results)
const std::vector< TestCaseRead > read_test_cases
TestResult test_debug_need_read_special_A()
TestCount _test_perf_need_sim_index(size_t need_size, t_test_results &results)
TestCount test_erase_updates_counters(t_test_results &results)
TestCount test_perf_write_with_diff_check(t_test_results &results)
TestCount test_write_multithreaded_coalesced(t_test_results &results)
void _write_multithreaded_coalesced()
TestCount test_block_touch_single_block_read_updates(t_test_results &results)
TestCount test_block_touch_single_block(t_test_results &results)
const std::vector< TestCaseWrite > write_test_cases
The actual write tests cases.
TestResult test_debug_need_read_special_C()
This is special test created to check the problem reading TUPAC-TR-004.svs.
TestCount test_block_size_throws(t_test_results &results)
TestCount test_punt_updates_counters(t_test_results &results)
TestCount test_has_all(t_test_results &results)
TestCount test_read_throws_all(t_test_results &results)
The namespace for all svfsc code.
std::vector< t_seek_read > t_seek_reads
std::map< t_block_touch, t_fpos > t_block_touches
Configuration for the Sparse Virtual File.
void test_example_code(void)