// Tries reading beyond pending write. void test_read_beyond_pending_record(void) { printf("Starting test: read beyond pending record\n"); setup_test(0); // Start a write. const size_t incomplete_record_size = 10; void* incomplete_record = census_log_start_write(incomplete_record_size); GPR_ASSERT(incomplete_record != NULL); const size_t complete_record_size = 20; void* complete_record = census_log_start_write(complete_record_size); GPR_ASSERT(complete_record != NULL); GPR_ASSERT(complete_record != incomplete_record); census_log_end_write(complete_record, complete_record_size); // Now iterate over blocks to read completed records. census_log_init_reader(); size_t bytes_available; const void* record_read = census_log_read_next(&bytes_available); GPR_ASSERT(complete_record == record_read); GPR_ASSERT(complete_record_size == bytes_available); // Complete first record. census_log_end_write(incomplete_record, incomplete_record_size); // Have read past the incomplete record, so read_next() should return NULL. // NB: this test also assumes our thread did not get switched to a different // CPU between the two start_write calls record_read = census_log_read_next(&bytes_available); GPR_ASSERT(record_read == NULL); // Reset reader to get the newly completed record. census_log_init_reader(); record_read = census_log_read_next(&bytes_available); GPR_ASSERT(incomplete_record == record_read); GPR_ASSERT(incomplete_record_size == bytes_available); assert_log_empty(); census_log_shutdown(); }
/* Fills the log and verifies data. If 'no fragmentation' is true, records are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record size. If not a circular log, verifies that the number of records written match the number of records read. */ static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { int size; int32_t records_written; int32_t usable_space; int32_t records_read; if (no_fragmentation) { int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); size = (1 << log2size); } else { while (1) { size = 1 + (rand() % CENSUS_LOG_MAX_RECORD_SIZE); if (CENSUS_LOG_MAX_RECORD_SIZE % size) { break; } } } printf(" Fill record size: %d\n", size); records_written = write_records_to_log( 0 /* writer id */, size, (log_size / size) * 2, 0 /* spin count */); usable_space = min_usable_space(log_size, size); GPR_ASSERT(records_written * size >= usable_space); records_read = perform_read_iteration(size); if (!circular_log) { GPR_ASSERT(records_written == records_read); } assert_log_empty(); }
// Tests end_write() with a different size than what was specified in // start_write(). void test_end_write_with_different_size(void) { static const size_t START_WRITE_SIZE = 10; static const size_t END_WRITE_SIZE = 7; printf("Starting test: end write with different size\n"); setup_test(0); void* record_written = census_log_start_write(START_WRITE_SIZE); GPR_ASSERT(record_written != NULL); census_log_end_write(record_written, END_WRITE_SIZE); census_log_init_reader(); size_t bytes_available; const void* record_read = census_log_read_next(&bytes_available); GPR_ASSERT(record_written == record_read); GPR_ASSERT(END_WRITE_SIZE == bytes_available); assert_log_empty(); census_log_shutdown(); }
// Verifies that pending records are not available via read_next(). void test_read_pending_record(void) { static const size_t PR_RECORD_SIZE = 1024; printf("Starting test: read pending record\n"); setup_test(0); // Start a write. void* record_written = census_log_start_write(PR_RECORD_SIZE); GPR_ASSERT(record_written != NULL); // As write is pending, read should fail. census_log_init_reader(); size_t bytes_available; const void* record_read = census_log_read_next(&bytes_available); GPR_ASSERT(record_read == NULL); // A read followed by end_write() should succeed. census_log_end_write(record_written, PR_RECORD_SIZE); census_log_init_reader(); record_read = census_log_read_next(&bytes_available); GPR_ASSERT(record_written == record_read); GPR_ASSERT(PR_RECORD_SIZE == bytes_available); assert_log_empty(); census_log_shutdown(); }
// Fills the log and verifies data. If 'no fragmentation' is true, records // are sized such that CENSUS_LOG_2_MAX_RECORD_SIZE is a multiple of record // size. If not a circular log, verifies that the number of records written // match the number of records read. static void fill_log(size_t log_size, int no_fragmentation, int circular_log) { size_t size; if (no_fragmentation) { int log2size = rand() % (CENSUS_LOG_2_MAX_RECORD_SIZE + 1); size = ((size_t)1 << log2size); } else { while (1) { size = 1 + ((size_t)rand() % CENSUS_LOG_MAX_RECORD_SIZE); if (CENSUS_LOG_MAX_RECORD_SIZE % size) { break; } } } int records_written = write_records_to_log(0 /* writer id */, size, (int)((log_size / size) * 2), 0 /* spin count */); int records_read = perform_read_iteration(size); if (!circular_log) { GPR_ASSERT(records_written == records_read); } assert_log_empty(); }