diff options
Diffstat (limited to 'test/core/statistics')
-rw-r--r-- | test/core/statistics/census_log_tests.cc | 576 | ||||
-rw-r--r-- | test/core/statistics/hash_table_test.cc | 286 | ||||
-rw-r--r-- | test/core/statistics/trace_test.cc | 239 | ||||
-rw-r--r-- | test/core/statistics/window_stats_test.cc | 304 |
4 files changed, 0 insertions, 1405 deletions
diff --git a/test/core/statistics/census_log_tests.cc b/test/core/statistics/census_log_tests.cc deleted file mode 100644 index e6eda5486c..0000000000 --- a/test/core/statistics/census_log_tests.cc +++ /dev/null @@ -1,576 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <grpc/support/cpu.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> -#include <grpc/support/time.h> -#include <grpc/support/useful.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "src/core/ext/census/census_log.h" -#include "test/core/util/test_config.h" - -/* Fills in 'record' of size 'size'. Each byte in record is filled in with the - same value. The value is extracted from 'record' pointer. */ -static void write_record(char* record, size_t size) { - char data = (uintptr_t)record % 255; - memset(record, data, size); -} - -/* Reads fixed size records. Returns the number of records read in - 'num_records'. */ -static void read_records(size_t record_size, const char* buffer, - size_t buffer_size, int32_t* num_records) { - int32_t ix; - GPR_ASSERT(buffer_size >= record_size); - GPR_ASSERT(buffer_size % record_size == 0); - *num_records = buffer_size / record_size; - for (ix = 0; ix < *num_records; ++ix) { - size_t jx; - const char* record = buffer + (record_size * ix); - char data = (uintptr_t)record % 255; - for (jx = 0; jx < record_size; ++jx) { - GPR_ASSERT(data == record[jx]); - } - } -} - -/* 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 size_t write_records_to_log(int writer_id, int32_t record_size, - int32_t num_records, - int32_t max_spin_count) { - int32_t ix; - int counter = 0; - for (ix = 0; ix < num_records; ++ix) { - int32_t jx; - int32_t spin_count = max_spin_count ? rand() % max_spin_count : 0; - char* record; - if (counter++ == num_records / 10) { - printf(" Writer %d: %d out of %d written\n", writer_id, ix, - num_records); - counter = 0; - } - record = (char*)(census_log_start_write(record_size)); - if (record == NULL) { - return ix; - } - write_record(record, record_size); - census_log_end_write(record, record_size); - for (jx = 0; jx < spin_count; ++jx) { - GPR_ASSERT(jx >= 0); - } - } - return num_records; -} - -/* Performs a single read iteration. Returns the number of records read. */ -static size_t perform_read_iteration(size_t record_size) { - const void* read_buffer = NULL; - size_t bytes_available; - size_t records_read = 0; - census_log_init_reader(); - while ((read_buffer = census_log_read_next(&bytes_available))) { - int32_t num_records = 0; - read_records(record_size, (const char*)read_buffer, bytes_available, - &num_records); - records_read += num_records; - } - return records_read; -} - -/* Asserts that the log is empty. */ -static void assert_log_empty(void) { - size_t bytes_available; - census_log_init_reader(); - GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); -} - -/* Given log size and record size, computes the minimum usable space. */ -static int32_t min_usable_space(size_t log_size, size_t record_size) { - int32_t usable_space; - int32_t num_blocks = - GPR_MAX(log_size / CENSUS_LOG_MAX_RECORD_SIZE, gpr_cpu_num_cores()); - int32_t waste_per_block = CENSUS_LOG_MAX_RECORD_SIZE % record_size; - /* In the worst case, all except one core-local block is full. */ - int32_t num_full_blocks = num_blocks - 1; - usable_space = (int32_t)log_size - - (num_full_blocks * CENSUS_LOG_MAX_RECORD_SIZE) - - ((num_blocks - num_full_blocks) * waste_per_block); - GPR_ASSERT(usable_space > 0); - return usable_space; -} - -/* 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(); -} - -/* Structure to pass args to writer_thread */ -typedef struct writer_thread_args { - /* Index of this thread in the writers vector. */ - int index; - /* Record size. */ - size_t record_size; - /* Number of records to write. */ - int32_t num_records; - /* Used to signal when writer is complete */ - gpr_cv* done; - gpr_mu* mu; - int* count; -} writer_thread_args; - -/* Writes the given number of records of random size (up to kMaxRecordSize) and - random data to the specified log. */ -static void writer_thread(void* arg) { - writer_thread_args* args = (writer_thread_args*)arg; - /* Maximum number of times to spin between writes. */ - static const int32_t MAX_SPIN_COUNT = 50; - int records_written = 0; - printf(" Writer: %d\n", args->index); - while (records_written < args->num_records) { - records_written += write_records_to_log(args->index, args->record_size, - args->num_records - records_written, - MAX_SPIN_COUNT); - if (records_written < args->num_records) { - /* Ran out of log space. Sleep for a bit and let the reader catch up. - This should never happen for circular logs. */ - printf(" Writer stalled due to out-of-space: %d out of %d written\n", - records_written, args->num_records); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(10)); - } - } - /* Done. Decrement count and signal. */ - gpr_mu_lock(args->mu); - (*args->count)--; - gpr_cv_broadcast(args->done); - printf(" Writer done: %d\n", args->index); - gpr_mu_unlock(args->mu); -} - -/* struct to pass args to reader_thread */ -typedef struct reader_thread_args { - /* Record size. */ - size_t record_size; - /* Interval between read iterations. */ - int32_t read_iteration_interval_in_msec; - /* Total number of records. */ - int32_t total_records; - /* Signalled when reader should stop. */ - gpr_cv stop; - int stop_flag; - /* Used to signal when reader has finished */ - gpr_cv* done; - gpr_mu* mu; - int running; -} reader_thread_args; - -/* Reads and verifies the specified number of records. Reader can also be - stopped via gpr_cv_signal(&args->stop). Sleeps for 'read_interval_in_msec' - between read iterations. */ -static void reader_thread(void* arg) { - int32_t records_read = 0; - reader_thread_args* args = (reader_thread_args*)arg; - int32_t num_iterations = 0; - gpr_timespec interval; - int counter = 0; - printf(" Reader starting\n"); - interval = gpr_time_from_micros( - (int64_t)args->read_iteration_interval_in_msec * 1000, GPR_TIMESPAN); - gpr_mu_lock(args->mu); - while (!args->stop_flag && records_read < args->total_records) { - gpr_cv_wait(&args->stop, args->mu, interval); - if (!args->stop_flag) { - records_read += perform_read_iteration(args->record_size); - GPR_ASSERT(records_read <= args->total_records); - if (counter++ == 100000) { - printf(" Reader: %d out of %d read\n", records_read, - args->total_records); - counter = 0; - } - ++num_iterations; - } - } - /* Done */ - args->running = 0; - gpr_cv_broadcast(args->done); - printf(" Reader: records: %d, iterations: %d\n", records_read, - num_iterations); - gpr_mu_unlock(args->mu); -} - -/* Creates NUM_WRITERS writers where each writer writes NUM_RECORDS_PER_WRITER - records. Also, starts a reader that iterates over and reads blocks every - READ_ITERATION_INTERVAL_IN_MSEC. */ -/* Number of writers. */ -#define NUM_WRITERS 5 -static void multiple_writers_single_reader(int circular_log) { - /* Sleep interval between read iterations. */ - static const int32_t READ_ITERATION_INTERVAL_IN_MSEC = 10; - /* Number of records written by each writer. */ - static const int32_t NUM_RECORDS_PER_WRITER = 10 * 1024 * 1024; - /* Maximum record size. */ - static const size_t MAX_RECORD_SIZE = 10; - int ix; - gpr_thd_id id; - gpr_cv writers_done; - int writers_count = NUM_WRITERS; - gpr_mu writers_mu; /* protects writers_done and writers_count */ - writer_thread_args writers[NUM_WRITERS]; - gpr_cv reader_done; - gpr_mu reader_mu; /* protects reader_done and reader.running */ - reader_thread_args reader; - int32_t record_size = 1 + rand() % MAX_RECORD_SIZE; - printf(" Record size: %d\n", record_size); - /* Create and start writers. */ - gpr_cv_init(&writers_done); - gpr_mu_init(&writers_mu); - for (ix = 0; ix < NUM_WRITERS; ++ix) { - writers[ix].index = ix; - writers[ix].record_size = record_size; - writers[ix].num_records = NUM_RECORDS_PER_WRITER; - writers[ix].done = &writers_done; - writers[ix].count = &writers_count; - writers[ix].mu = &writers_mu; - gpr_thd_new(&id, &writer_thread, &writers[ix], NULL); - } - /* Start reader. */ - reader.record_size = record_size; - reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; - reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; - reader.stop_flag = 0; - gpr_cv_init(&reader.stop); - gpr_cv_init(&reader_done); - reader.done = &reader_done; - gpr_mu_init(&reader_mu); - reader.mu = &reader_mu; - reader.running = 1; - gpr_thd_new(&id, &reader_thread, &reader, NULL); - /* Wait for writers to finish. */ - gpr_mu_lock(&writers_mu); - while (writers_count != 0) { - gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&writers_mu); - gpr_mu_destroy(&writers_mu); - gpr_cv_destroy(&writers_done); - gpr_mu_lock(&reader_mu); - if (circular_log) { - /* Stop reader. */ - reader.stop_flag = 1; - gpr_cv_signal(&reader.stop); - } - /* wait for reader to finish */ - while (reader.running) { - gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - if (circular_log) { - /* Assert that there were no out-of-space errors. */ - GPR_ASSERT(0 == census_log_out_of_space_count()); - } - gpr_mu_unlock(&reader_mu); - gpr_mu_destroy(&reader_mu); - gpr_cv_destroy(&reader_done); - printf(" Reader: finished\n"); -} - -/* Log sizes to use for all tests. */ -#define LOG_SIZE_IN_MB 1 -#define LOG_SIZE_IN_BYTES (LOG_SIZE_IN_MB << 20) - -static void setup_test(int circular_log) { - census_log_initialize(LOG_SIZE_IN_MB, circular_log); - GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); -} - -/* 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; - void* record; - printf("Starting test: invalid record size\n"); - setup_test(0); - 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(); -} - -/* 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; - void* record_written; - const void* record_read; - size_t bytes_available; - printf("Starting test: end write with different size\n"); - setup_test(0); - 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(); - 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; - size_t bytes_available; - const void* record_read; - void* record_written; - printf("Starting test: read pending record\n"); - setup_test(0); - /* Start a write. */ - 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(); - 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(); -} - -/* Tries reading beyond pending write. */ -void test_read_beyond_pending_record(void) { - /* Start a write. */ - uint32_t incomplete_record_size = 10; - uint32_t 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 scenario where block being read is detached from a core and put on the - dirty list. */ -void test_detached_while_reading(void) { - static const size_t DWR_RECORD_SIZE = 10; - size_t bytes_available; - const void* record_read; - void* record_written; - uint32_t block_read = 0; - printf("Starting test: detached while reading\n"); - setup_test(0); - /* Start a write. */ - record_written = census_log_start_write(DWR_RECORD_SIZE); - GPR_ASSERT(record_written != NULL); - census_log_end_write(record_written, DWR_RECORD_SIZE); - /* Read this record. */ - census_log_init_reader(); - record_read = census_log_read_next(&bytes_available); - GPR_ASSERT(record_read != NULL); - GPR_ASSERT(DWR_RECORD_SIZE == bytes_available); - /* Now fill the log. This will move the block being read from core-local - array to the dirty list. */ - while ((record_written = census_log_start_write(DWR_RECORD_SIZE))) { - census_log_end_write(record_written, DWR_RECORD_SIZE); - } - - /* In this iteration, read_next() should only traverse blocks in the - core-local array. Therefore, we expect at most gpr_cpu_num_cores() more - blocks. As log is full, if read_next() is traversing the dirty list, we - will get more than gpr_cpu_num_cores() blocks. */ - while ((record_read = census_log_read_next(&bytes_available))) { - ++block_read; - GPR_ASSERT(block_read <= gpr_cpu_num_cores()); - } - census_log_shutdown(); -} - -/* Fills non-circular log with records sized such that size is a multiple of - CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ -void test_fill_log_no_fragmentation(void) { - const int circular = 0; - printf("Starting test: fill log no fragmentation\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -/* Fills circular log with records sized such that size is a multiple of - CENSUS_LOG_MAX_RECORD_SIZE (no per-block fragmentation). */ -void test_fill_circular_log_no_fragmentation(void) { - const int circular = 1; - printf("Starting test: fill circular log no fragmentation\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 1 /* no fragmentation */, circular); - census_log_shutdown(); -} - -/* Fills non-circular log with records that may straddle end of a block. */ -void test_fill_log_with_straddling_records(void) { - const int circular = 0; - printf("Starting test: fill log with straddling records\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -/* Fills circular log with records that may straddle end of a block. */ -void test_fill_circular_log_with_straddling_records(void) { - const int circular = 1; - printf("Starting test: fill circular log with straddling records\n"); - setup_test(circular); - fill_log(LOG_SIZE_IN_BYTES, 0 /* block straddling records */, circular); - census_log_shutdown(); -} - -/* Tests scenario where multiple writers and a single reader are using a log - that is configured to discard old records. */ -void test_multiple_writers_circular_log(void) { - const int circular = 1; - printf("Starting test: multiple writers circular log\n"); - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -/* Tests scenario where multiple writers and a single reader are using a log - that is configured to discard old records. */ -void test_multiple_writers(void) { - const int circular = 0; - printf("Starting test: multiple writers\n"); - setup_test(circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -/* Repeat the straddling records and multiple writers tests with a small log. */ -void test_small_log(void) { - size_t log_size; - const int circular = 0; - printf("Starting test: small log\n"); - census_log_initialize(0, circular); - log_size = census_log_remaining_space(); - GPR_ASSERT(log_size > 0); - fill_log(log_size, 0, circular); - census_log_shutdown(); - census_log_initialize(0, circular); - multiple_writers_single_reader(circular); - census_log_shutdown(); -} - -void test_performance(void) { - int write_size = 1; - for (; write_size < CENSUS_LOG_MAX_RECORD_SIZE; write_size *= 2) { - gpr_timespec write_time; - gpr_timespec start_time; - double write_time_micro = 0.0; - int nrecords = 0; - setup_test(0); - start_time = gpr_now(GPR_CLOCK_REALTIME); - while (1) { - void* record = census_log_start_write(write_size); - if (record == NULL) { - break; - } - census_log_end_write(record, write_size); - nrecords++; - } - write_time = gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), start_time); - write_time_micro = write_time.tv_sec * 1000000 + write_time.tv_nsec / 1000; - census_log_shutdown(); - printf( - "Wrote %d %d byte records in %.3g microseconds: %g records/us " - "(%g ns/record), %g gigabytes/s\n", - nrecords, write_size, write_time_micro, nrecords / write_time_micro, - 1000 * write_time_micro / nrecords, - (write_size * nrecords) / write_time_micro / 1000); - } -} diff --git a/test/core/statistics/hash_table_test.cc b/test/core/statistics/hash_table_test.cc deleted file mode 100644 index b660006b8a..0000000000 --- a/test/core/statistics/hash_table_test.cc +++ /dev/null @@ -1,286 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "src/core/ext/census/hash_table.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include "src/core/lib/support/murmur_hash.h" -#include "src/core/lib/support/string.h" -#include "test/core/util/test_config.h" - -static uint64_t hash64(const void* k) { - size_t len = strlen(k); - uint64_t higher = gpr_murmur_hash3((const char*)k, len / 2, 0); - return higher << 32 | - gpr_murmur_hash3((const char*)(k) + len / 2, len - len / 2, 0); -} - -static int cmp_str_keys(const void* k1, const void* k2) { - return strcmp((const char*)k1, (const char*)k2); -} - -static uint64_t force_collision(const void* k) { - return (1997 + hash64(k) % 3); -} - -static void free_data(void* data) { gpr_free(data); } - -/* Basic tests that empty hash table can be created and destroyed. */ -static void test_create_table(void) { - /* Create table with uint64 key type */ - census_ht* ht = NULL; - census_ht_option ht_options = { - CENSUS_HT_UINT64, 1999, NULL, NULL, NULL, NULL}; - ht = census_ht_create(&ht_options); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_destroy(ht); - /* Create table with pointer key type */ - ht = NULL; - ht_options.key_type = CENSUS_HT_POINTER; - ht_options.hash = &hash64; - ht_options.compare_keys = &cmp_str_keys; - ht = census_ht_create(&ht_options); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_destroy(ht); -} - -static void test_table_with_int_key(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; - census_ht* ht = census_ht_create(&opt); - uint64_t i = 0; - uint64_t sum_of_keys = 0; - size_t num_elements; - census_ht_kv* elements = NULL; - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - elements = census_ht_get_all_elements(ht, &num_elements); - GPR_ASSERT(num_elements == 0); - GPR_ASSERT(elements == NULL); - for (i = 0; i < 20; ++i) { - census_ht_key key; - key.val = i; - census_ht_insert(ht, key, (void*)(intptr_t)i); - GPR_ASSERT(census_ht_get_size(ht) == i + 1); - } - for (i = 0; i < 20; i++) { - uint64_t* val = NULL; - census_ht_key key; - key.val = i; - val = static_cast<uint64_t*>(census_ht_find(ht, key)); - GPR_ASSERT(val == (void*)(intptr_t)i); - } - elements = census_ht_get_all_elements(ht, &num_elements); - GPR_ASSERT(elements != NULL); - GPR_ASSERT(num_elements == 20); - for (i = 0; i < num_elements; i++) { - sum_of_keys += elements[i].k.val; - } - GPR_ASSERT(sum_of_keys == 190); - gpr_free(elements); - census_ht_destroy(ht); -} - -/* Test that there is no memory leak when keys and values are owned by table. */ -static void test_value_and_key_deleter(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, - &cmp_str_keys, &free_data, &free_data}; - census_ht* ht = census_ht_create(&opt); - census_ht_key key; - char* val = NULL; - char* val2 = NULL; - key.ptr = gpr_malloc(100); - val = static_cast<char*>(gpr_malloc(10)); - strcpy(val, "value"); - strcpy(key.ptr, "some string as a key"); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - census_ht_insert(ht, key, val); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val = static_cast<char*>(census_ht_find(ht, key)); - GPR_ASSERT(val != NULL); - GPR_ASSERT(strcmp(val, "value") == 0); - /* Insert same key different value, old value is overwritten. */ - val2 = static_cast<char*>(gpr_malloc(10)); - strcpy(val2, "v2"); - census_ht_insert(ht, key, val2); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val2 = static_cast<char*>(census_ht_find(ht, key)); - GPR_ASSERT(val2 != NULL); - GPR_ASSERT(strcmp(val2, "v2") == 0); - census_ht_destroy(ht); -} - -/* Test simple insert and erase operations. */ -static void test_simple_add_and_erase(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 7, NULL, NULL, NULL, NULL}; - census_ht* ht = census_ht_create(&opt); - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - { - census_ht_key key; - int val = 3; - key.val = 2; - census_ht_insert(ht, key, (void*)&val); - GPR_ASSERT(census_ht_get_size(ht) == 1); - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 0); - /* Erasing a key from an empty table should be noop. */ - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 0); - /* Erasing a non-existant key from a table should be noop. */ - census_ht_insert(ht, key, (void*)&val); - key.val = 3; - census_ht_insert(ht, key, (void*)&val); - key.val = 9; - census_ht_insert(ht, key, (void*)&val); - GPR_ASSERT(census_ht_get_size(ht) == 3); - key.val = 1; - census_ht_erase(ht, key); - /* size unchanged after deleting non-existant key. */ - GPR_ASSERT(census_ht_get_size(ht) == 3); - /* size decrease by 1 after deleting an existant key. */ - key.val = 2; - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == 2); - } - census_ht_destroy(ht); -} - -static void test_insertion_and_deletion_with_high_collision_rate(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 13, &force_collision, - &cmp_str_keys, NULL, NULL}; - census_ht* ht = census_ht_create(&opt); - char key_str[1000][GPR_LTOA_MIN_BUFSIZE]; - uint64_t val = 0; - unsigned i = 0; - for (i = 0; i < 1000; i++) { - census_ht_key key; - key.ptr = key_str[i]; - gpr_ltoa(i, key_str[i]); - census_ht_insert(ht, key, (void*)(&val)); - gpr_log(GPR_INFO, "%d\n", i); - GPR_ASSERT(census_ht_get_size(ht) == (i + 1)); - } - for (i = 0; i < 1000; i++) { - census_ht_key key; - key.ptr = key_str[i]; - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == (999 - i)); - } - census_ht_destroy(ht); -} - -static void test_table_with_string_key(void) { - census_ht_option opt = {CENSUS_HT_POINTER, 7, &hash64, - &cmp_str_keys, NULL, NULL}; - census_ht* ht = census_ht_create(&opt); - const char* keys[] = { - "k1", "a", "000", "apple", "banana_a_long_long_long_banana", - "%$", "111", "foo", "b"}; - const int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - int i = 0; - GPR_ASSERT(ht != NULL); - GPR_ASSERT(census_ht_get_size(ht) == 0); - for (i = 0; i < 9; i++) { - census_ht_key key; - key.ptr = (void*)(keys[i]); - census_ht_insert(ht, key, (void*)(vals + i)); - } - GPR_ASSERT(census_ht_get_size(ht) == 9); - for (i = 0; i < 9; i++) { - census_ht_key key; - int* val_ptr; - key.ptr = (void*)(keys[i]); - val_ptr = static_cast<int*>(census_ht_find(ht, key)); - GPR_ASSERT(*val_ptr == vals[i]); - } - { - /* inserts duplicate keys */ - census_ht_key key; - int* val_ptr = NULL; - key.ptr = (void*)(keys[2]); - census_ht_insert(ht, key, (void*)(vals + 8)); - /* expect value to be over written by new insertion */ - GPR_ASSERT(census_ht_get_size(ht) == 9); - val_ptr = static_cast<int*>(census_ht_find(ht, key)); - GPR_ASSERT(*val_ptr == vals[8]); - } - for (i = 0; i < 9; i++) { - census_ht_key key; - int* val_ptr; - uint32_t expected_tbl_sz = 9 - i; - GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz); - key.ptr = (void*)(keys[i]); - val_ptr = static_cast<int*>(census_ht_find(ht, key)); - GPR_ASSERT(val_ptr != NULL); - census_ht_erase(ht, key); - GPR_ASSERT(census_ht_get_size(ht) == expected_tbl_sz - 1); - val_ptr = static_cast<int*>(census_ht_find(ht, key)); - GPR_ASSERT(val_ptr == NULL); - } - census_ht_destroy(ht); -} - -static void test_insertion_with_same_key(void) { - census_ht_option opt = {CENSUS_HT_UINT64, 11, NULL, NULL, NULL, NULL}; - census_ht* ht = census_ht_create(&opt); - census_ht_key key; - const char vals[] = {'a', 'b', 'c'}; - char* val_ptr; - key.val = 3; - census_ht_insert(ht, key, (void*)&(vals[0])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char*)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'a'); - key.val = 4; - val_ptr = (char*)census_ht_find(ht, key); - GPR_ASSERT(val_ptr == NULL); - key.val = 3; - census_ht_insert(ht, key, (void*)&(vals[1])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char*)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'b'); - census_ht_insert(ht, key, (void*)&(vals[2])); - GPR_ASSERT(census_ht_get_size(ht) == 1); - val_ptr = (char*)census_ht_find(ht, key); - GPR_ASSERT(val_ptr != NULL); - GPR_ASSERT(*val_ptr == 'c'); - census_ht_destroy(ht); -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - test_create_table(); - test_simple_add_and_erase(); - test_table_with_int_key(); - test_table_with_string_key(); - test_value_and_key_deleter(); - test_insertion_with_same_key(); - test_insertion_and_deletion_with_high_collision_rate(); - return 0; -} diff --git a/test/core/statistics/trace_test.cc b/test/core/statistics/trace_test.cc deleted file mode 100644 index ecbfed09ee..0000000000 --- a/test/core/statistics/trace_test.cc +++ /dev/null @@ -1,239 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <stdio.h> -#include <string.h> - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/port_platform.h> -#include <grpc/support/sync.h> -#include <grpc/support/thd.h> -#include <grpc/support/time.h> -#include <grpc/support/useful.h> -#include "src/core/ext/census/census_interface.h" -#include "src/core/ext/census/census_tracing.h" -#include "test/core/util/test_config.h" - -/* Ensure all possible state transitions are called without causing problem */ -static void test_init_shutdown(void) { - census_tracing_init(); - census_tracing_init(); - census_tracing_shutdown(); - census_tracing_shutdown(); - census_tracing_init(); -} - -static void test_start_op_generates_locally_unique_ids(void) { -/* Check that ids generated within window size of 1000 are unique. - TODO(hongyu): Replace O(n^2) duplicate detection algorithm with O(nlogn) - algorithm. Enhance the test to larger window size (>10^6) */ -#define WINDOW_SIZE 1000 - census_op_id ids[WINDOW_SIZE]; - int i; - census_init(); - for (i = 0; i < WINDOW_SIZE; i++) { - ids[i] = census_tracing_start_op(); - census_tracing_end_op(ids[i]); - } - for (i = 0; i < WINDOW_SIZE - 1; i++) { - int j; - for (j = i + 1; j < WINDOW_SIZE; j++) { - GPR_ASSERT(ids[i].upper != ids[j].upper || ids[i].lower != ids[j].lower); - } - } -#undef WINDOW_SIZE - census_shutdown(); -} - -static void test_get_trace_method_name(void) { - census_op_id id; - const char write_name[] = "service/method"; - census_tracing_init(); - id = census_tracing_start_op(); - census_add_method_tag(id, write_name); - census_internal_lock_trace_store(); - { - const char* read_name = - census_get_trace_method_name(census_get_trace_obj_locked(id)); - GPR_ASSERT(strcmp(read_name, write_name) == 0); - } - census_internal_unlock_trace_store(); - census_tracing_shutdown(); -} - -typedef struct thd_arg { - int num_done; - gpr_cv done; - gpr_mu mu; -} thd_arg; - -static void mimic_trace_op_sequences(void* arg) { - census_op_id id; - const char* method_name = "service_foo/method_bar"; - int i = 0; - const int num_iter = 200; - thd_arg* args = (thd_arg*)arg; - GPR_ASSERT(args != NULL); - gpr_log(GPR_INFO, "Start trace op sequence thread."); - for (i = 0; i < num_iter; i++) { - id = census_tracing_start_op(); - census_add_method_tag(id, method_name); - /* pretend doing 1us work. */ - gpr_sleep_until(GRPC_TIMEOUT_MICROS_TO_DEADLINE(1)); - census_tracing_end_op(id); - } - gpr_log(GPR_INFO, "End trace op sequence thread."); - gpr_mu_lock(&args->mu); - args->num_done += 1; - gpr_cv_broadcast(&args->done); - gpr_mu_unlock(&args->mu); -} - -static void test_concurrency(void) { -#define NUM_THREADS 1000 - gpr_thd_id tid[NUM_THREADS]; - int i = 0; - thd_arg arg; - arg.num_done = 0; - gpr_mu_init(&arg.mu); - gpr_cv_init(&arg.done); - census_tracing_init(); - for (i = 0; i < NUM_THREADS; ++i) { - gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); - } - gpr_mu_lock(&arg.mu); - while (arg.num_done < NUM_THREADS) { - gpr_log(GPR_INFO, "num done %d", arg.num_done); - gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } - gpr_mu_unlock(&arg.mu); - census_tracing_shutdown(); -#undef NUM_THREADS -} - -static void test_add_method_tag_to_unknown_op_id(void) { - census_op_id unknown_id = {0xDEAD, 0xBEEF}; - int ret = 0; - census_tracing_init(); - ret = census_add_method_tag(unknown_id, "foo"); - GPR_ASSERT(ret != 0); - census_tracing_shutdown(); -} - -static void test_trace_print(void) { - census_op_id id; - int i; - const char* annotation_txt[4] = {"abc", "", "$%^ *()_"}; - char long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 10]; - - memset(long_txt, 'a', GPR_ARRAY_SIZE(long_txt)); - long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 9] = '\0'; - annotation_txt[3] = long_txt; - - census_tracing_init(); - id = census_tracing_start_op(); - /* Adds large number of annotations to each trace */ - for (i = 0; i < 1000; i++) { - census_tracing_print(id, - annotation_txt[i % GPR_ARRAY_SIZE(annotation_txt)]); - } - census_tracing_end_op(id); - - census_tracing_shutdown(); -} - -/* Returns 1 if two ids are equal, otherwise returns 0. */ -static int ids_equal(census_op_id id1, census_op_id id2) { - return (id1.upper == id2.upper) && (id1.lower == id2.lower); -} - -static void test_get_active_ops(void) { - census_op_id id_1, id_2, id_3; - census_trace_obj** active_ops; - const char* annotation_txt[] = {"annotation 1", "a2"}; - int i = 0; - int n = 0; - - gpr_log(GPR_INFO, "test_get_active_ops"); - census_tracing_init(); - /* No active ops before calling start_op(). */ - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops == NULL); - GPR_ASSERT(n == 0); - - /* Starts one op */ - id_1 = census_tracing_start_op(); - census_add_method_tag(id_1, "foo_1"); - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops != NULL); - GPR_ASSERT(n == 1); - GPR_ASSERT(ids_equal(active_ops[0]->id, id_1)); - census_trace_obj_destroy(active_ops[0]); - gpr_free(active_ops); - active_ops = NULL; - - /* Start the second and the third ops */ - id_2 = census_tracing_start_op(); - census_add_method_tag(id_2, "foo_2"); - id_3 = census_tracing_start_op(); - census_add_method_tag(id_3, "foo_3"); - - active_ops = census_get_active_ops(&n); - GPR_ASSERT(n == 3); - for (i = 0; i < 3; i++) { - census_trace_obj_destroy(active_ops[i]); - } - gpr_free(active_ops); - active_ops = NULL; - - /* End the second op and add annotations to the third ops */ - census_tracing_end_op(id_2); - census_tracing_print(id_3, annotation_txt[0]); - census_tracing_print(id_3, annotation_txt[1]); - - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops != NULL); - GPR_ASSERT(n == 2); - for (i = 0; i < 2; i++) { - census_trace_obj_destroy(active_ops[i]); - } - gpr_free(active_ops); - active_ops = NULL; - - /* End all ops. */ - census_tracing_end_op(id_1); - census_tracing_end_op(id_3); - active_ops = census_get_active_ops(&n); - GPR_ASSERT(active_ops == NULL); - GPR_ASSERT(n == 0); - - census_tracing_shutdown(); -} - -int main(int argc, char** argv) { - grpc_test_init(argc, argv); - test_init_shutdown(); - test_start_op_generates_locally_unique_ids(); - test_get_trace_method_name(); - test_concurrency(); - test_add_method_tag_to_unknown_op_id(); - test_trace_print(); - test_get_active_ops(); - return 0; -} diff --git a/test/core/statistics/window_stats_test.cc b/test/core/statistics/window_stats_test.cc deleted file mode 100644 index b17c61a47b..0000000000 --- a/test/core/statistics/window_stats_test.cc +++ /dev/null @@ -1,304 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/ext/census/window_stats.h" -#include <grpc/support/log.h> -#include <grpc/support/time.h> -#include <stdlib.h> -#include "test/core/util/test_config.h" - -typedef struct test_stat { - double value1; - int value2; -} test_stat; - -void add_test_stat(void* base, const void* addme) { - test_stat* b = (test_stat*)base; - const test_stat* a = (const test_stat*)addme; - b->value1 += a->value1; - b->value2 += a->value2; -} - -void add_proportion_test_stat(double p, void* base, const void* addme) { - test_stat* b = (test_stat*)base; - const test_stat* a = (const test_stat*)addme; - b->value1 += p * a->value1; - b->value2 += p * a->value2 + 0.5; /* +0.5 is poor mans (no c99) round() */ -} - -const struct census_window_stats_stat_info kMyStatInfo = { - sizeof(test_stat), NULL, add_test_stat, add_proportion_test_stat}; - -const gpr_timespec kMilliSecInterval = {0, 1000000, GPR_CLOCK_MONOTONIC}; -const gpr_timespec kSecInterval = {1, 0, GPR_CLOCK_MONOTONIC}; -const gpr_timespec kMinInterval = {60, 0 GPR_CLOCK_MONOTONIC}; -const gpr_timespec kHourInterval = {3600, 0, GPR_CLOCK_MONOTONIC}; -const gpr_timespec kPrimeInterval = {0, 101, GPR_CLOCK_MONOTONIC}; - -static int compare_double(double a, double b, double epsilon) { - if (a >= b) { - return (a > b + epsilon) ? 1 : 0; - } else { - return (b > a + epsilon) ? -1 : 0; - } -} - -void empty_test(void) { - census_window_stats_sums result; - const gpr_timespec zero = {0, 0, GPR_CLOCK_MONOTONIC}; - test_stat sum; - struct census_window_stats* stats = - census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - result.statistic = ∑ - census_window_stats_get_sums(stats, zero, &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - census_window_stats_get_sums(stats, gpr_now(GPR_CLOCK_REALTIME), &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - census_window_stats_destroy(stats); -} - -void one_interval_test(void) { - const test_stat value = {0.1, 4}; - const double epsilon = 1e10 - 11; - gpr_timespec when = {0, 0, GPR_CLOCK_MONOTONIC}; - census_window_stats_sums result; - test_stat sum; - /* granularity == 5 so width of internal windows should be 12s */ - struct census_window_stats* stats = - census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - /* phase 1: insert a single value at t=0s, and check that various measurement - times result in expected output values */ - census_window_stats_add(stats, when, &value); - result.statistic = ∑ - /* when = 0s, values extracted should be everything */ - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when = 6,30,60s, should be all of the data */ - when.tv_sec = 6; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when == 30s,60s, should be all of the data */ - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - when.tv_sec = 60; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 1.0, epsilon) == 0 && - compare_double(sum.value1, value.value1, epsilon) == 0 && - sum.value2 == value.value2); - /* when = 66s, should be half (only take half of bottom bucket) */ - when.tv_sec = 66; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && - sum.value2 == value.value2 / 2); - /* when = 72s, should be completely out of window */ - when.tv_sec = 72; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && - compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); - - /* phase 2: tear down and do as before, but inserting two values */ - census_window_stats_destroy(stats); - stats = census_window_stats_create(1, &kMinInterval, 5, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - when.tv_sec = 0; - when.tv_nsec = 17; - census_window_stats_add(stats, when, &value); - when.tv_sec = 1; - census_window_stats_add(stats, when, &value); - when.tv_sec = 0; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 0, epsilon) == 0 && - compare_double(sum.value1, 0, epsilon) == 0 && sum.value2 == 0); - /* time = 3s, 30s, should get all data */ - when.tv_sec = 3; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && - sum.value2 == 2 * value.value2); - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, 2 * value.value1, epsilon) == 0 && - sum.value2 == 2 * value.value2); - - /* phase 3: insert into "middle" bucket, and force a shift, pushing out - the two values in bottom bucket */ - when.tv_sec = 30; - census_window_stats_add(stats, when, &value); - when.tv_sec = 76; - census_window_stats_add(stats, when, &value); - when.tv_sec = 0; - census_window_stats_get_sums(stats, when, &result); - GPR_ASSERT(result.count == 0 && sum.value1 == 0 && sum.value2 == 0); - when.tv_sec = 30; - census_window_stats_get_sums(stats, when, &result); - /* half of the single value in the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 0.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 / 2, epsilon) == 0 && - sum.value2 == value.value2 / 2); - when.tv_sec = 74; - census_window_stats_get_sums(stats, when, &result); - /* half of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 1.5, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 1.5, epsilon) == 0 && - sum.value2 == value.value2 / 2 * 3); - when.tv_sec = 76; - census_window_stats_get_sums(stats, when, &result); - /* >=76s, get all of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && - sum.value2 == value.value2 * 2); - when.tv_sec = 78; - census_window_stats_get_sums(stats, when, &result); - /* half of the 76 second bucket, all of the 30 second bucket */ - GPR_ASSERT(compare_double(result.count, 2, epsilon) == 0 && - compare_double(sum.value1, value.value1 * 2, epsilon) == 0 && - sum.value2 == value.value2 * 2); - census_window_stats_destroy(stats); -} - -void many_interval_test(void) { - gpr_timespec intervals[4]; - const test_stat value = {123.45, 8}; - const double epsilon = 1e10 - 11; - gpr_timespec when = {3600, 0, GPR_CLOCK_MONOTONIC}; /* one hour */ - census_window_stats_sums result[4]; - test_stat sums[4]; - int i; - struct census_window_stats* stats; - intervals[0] = kMilliSecInterval; - intervals[1] = kSecInterval; - intervals[2] = kMinInterval; - intervals[3] = kHourInterval; - for (i = 0; i < 4; i++) { - result[i].statistic = &sums[i]; - } - stats = census_window_stats_create(4, intervals, 100, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - /* add 10 stats within half of each time range */ - for (i = 0; i < 10; i++) { - when.tv_sec += 180; /* covers 30 min of one hour range */ - census_window_stats_add(stats, when, &value); - } - when.tv_sec += 120; - for (i = 0; i < 10; i++) { - when.tv_sec += 3; /* covers 30 sec of one minute range */ - census_window_stats_add(stats, when, &value); - } - when.tv_sec += 2; - for (i = 0; i < 10; i++) { - when.tv_nsec += 50000000; /* covers 0.5s of 1s range */ - census_window_stats_add(stats, when, &value); - } - when.tv_nsec += 2000000; - for (i = 0; i < 10; i++) { - when.tv_nsec += 50000; /* covers 0.5 ms of 1 ms range */ - census_window_stats_add(stats, when, &value); - } - when.tv_nsec += 20000; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[0].count, 10, epsilon) == 0 && - compare_double(sums[0].value1, value.value1 * 10, epsilon) == 0 && - sums[0].value2 == value.value2 * 10); - when.tv_nsec += 20000000; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[1].count, 20, epsilon) == 0 && - compare_double(sums[1].value1, value.value1 * 20, epsilon) == 0 && - sums[1].value2 == value.value2 * 20); - when.tv_sec += 2; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[2].count, 30, epsilon) == 0 && - compare_double(sums[2].value1, value.value1 * 30, epsilon) == 0 && - sums[2].value2 == value.value2 * 30); - when.tv_sec += 72; - census_window_stats_get_sums(stats, when, result); - GPR_ASSERT(compare_double(result[3].count, 40, epsilon) == 0 && - compare_double(sums[3].value1, value.value1 * 40, epsilon) == 0 && - sums[3].value2 == value.value2 * 40); - census_window_stats_destroy(stats); -} - -void rolling_time_test(void) { - const test_stat value = {0.1, 4}; - gpr_timespec when = {0, 0, GPR_CLOCK_MONOTONIC}; - census_window_stats_sums result; - test_stat sum; - int i; - gpr_timespec increment = {0, 0, GPR_CLOCK_MONOTONIC}; - struct census_window_stats* stats = - census_window_stats_create(1, &kMinInterval, 7, &kMyStatInfo); - GPR_ASSERT(stats != NULL); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - for (i = 0; i < 100000; i++) { - increment.tv_nsec = rand() % 100000000; /* up to 1/10th second */ - when = gpr_time_add(when, increment); - census_window_stats_add(stats, when, &value); - } - result.statistic = ∑ - census_window_stats_get_sums(stats, when, &result); - /* With 1/20th second average between samples, we expect 20*60 = 1200 - samples on average. Make sure we are within 100 of that. */ - GPR_ASSERT(compare_double(result.count, 1200, 100) == 0); - census_window_stats_destroy(stats); -} - -#include <stdio.h> -void infinite_interval_test(void) { - const test_stat value = {0.1, 4}; - gpr_timespec when = {0, 0, GPR_CLOCK_MONOTONIC}; - census_window_stats_sums result; - test_stat sum; - int i; - const int count = 100000; - gpr_timespec increment = {0, 0, GPR_CLOCK_MONOTONIC}; - gpr_timespec temp = gpr_inf_future(GPR_CLOCK_REALTIME); - struct census_window_stats* stats = census_window_stats_create( - 1, &gpr_inf_future(GPR_CLOCK_REALTIME), 10, &kMyStatInfo); - srand(gpr_now(GPR_CLOCK_REALTIME).tv_nsec); - for (i = 0; i < count; i++) { - increment.tv_sec = rand() % 21600; /* 6 hours */ - when = gpr_time_add(when, increment); - census_window_stats_add(stats, when, &value); - } - result.statistic = ∑ - census_window_stats_get_sums(stats, when, &result); - /* The only thing it makes sense to compare for "infinite" periods is the - total counts */ - GPR_ASSERT(result.count == count); - census_window_stats_destroy(stats); -} - -int main(int argc, char* argv[]) { - grpc_test_init(argc, argv); - empty_test(); - one_interval_test(); - many_interval_test(); - rolling_time_test(); - infinite_interval_test(); - return 0; -} |