/* Tries reading beyond pending write. */ void test_read_beyond_pending_record(void) { /* Start a write. */ gpr_uint32 incomplete_record_size = 10; gpr_uint32 complete_record_size = 20; size_t bytes_available; void* complete_record; const void* record_read; void* incomplete_record; printf("Starting test: read beyond pending record\n"); setup_test(0); incomplete_record = census_log_start_write(incomplete_record_size); GPR_ASSERT(incomplete_record != NULL); 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(); 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(); }
// 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(); }
// Attempts to create a record of invalid size (size > // CENSUS_LOG_MAX_RECORD_SIZE). void test_invalid_record_size(void) { static const size_t INVALID_SIZE = CENSUS_LOG_MAX_RECORD_SIZE + 1; static const size_t VALID_SIZE = 1; printf("Starting test: invalid record size\n"); setup_test(0); void* record = census_log_start_write(INVALID_SIZE); GPR_ASSERT(record == NULL); // Now try writing a valid record. record = census_log_start_write(VALID_SIZE); GPR_ASSERT(record != NULL); census_log_end_write(record, VALID_SIZE); // Verifies that available space went down by one block. In theory, this // check can fail if the thread is context switched to a new CPU during the // start_write execution (multiple blocks get allocated), but this has not // been observed in practice. // GPR_ASSERT(LOG_SIZE_IN_BYTES - CENSUS_LOG_MAX_RECORD_SIZE == // census_log_remaining_space()); census_log_shutdown(); }
// Tries to write the specified number of records. Stops when the log gets // full. Returns the number of records written. Spins for random // number of times, up to 'max_spin_count', between writes. static int write_records_to_log(int writer_id, size_t record_size, int num_records, int max_spin_count) { int counter = 0; for (int i = 0; i < num_records; ++i) { int spin_count = max_spin_count ? rand() % max_spin_count : 0; if (VERBOSE && (counter++ == num_records / 10)) { printf(" Writer %d: %d out of %d written\n", writer_id, i, num_records); counter = 0; } char* record = (char*)(census_log_start_write(record_size)); if (record == NULL) { return i; } write_record(record, record_size); census_log_end_write(record, record_size); for (int j = 0; j < spin_count; ++j) { GPR_ASSERT(j >= 0); } } return num_records; }
// 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(); }