OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * |
| 3 * Copyright 2015, Google Inc. |
| 4 * All rights reserved. |
| 5 * |
| 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are |
| 8 * met: |
| 9 * |
| 10 * * Redistributions of source code must retain the above copyright |
| 11 * notice, this list of conditions and the following disclaimer. |
| 12 * * Redistributions in binary form must reproduce the above |
| 13 * copyright notice, this list of conditions and the following disclaimer |
| 14 * in the documentation and/or other materials provided with the |
| 15 * distribution. |
| 16 * * Neither the name of Google Inc. nor the names of its |
| 17 * contributors may be used to endorse or promote products derived from |
| 18 * this software without specific prior written permission. |
| 19 * |
| 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 * |
| 32 */ |
| 33 |
| 34 #include <string.h> |
| 35 #include <stdio.h> |
| 36 |
| 37 #include "src/core/statistics/census_interface.h" |
| 38 #include "src/core/statistics/census_tracing.h" |
| 39 #include "src/core/statistics/census_tracing.h" |
| 40 #include <grpc/support/alloc.h> |
| 41 #include <grpc/support/log.h> |
| 42 #include <grpc/support/port_platform.h> |
| 43 #include <grpc/support/sync.h> |
| 44 #include <grpc/support/thd.h> |
| 45 #include <grpc/support/time.h> |
| 46 #include <grpc/support/useful.h> |
| 47 #include "test/core/util/test_config.h" |
| 48 |
| 49 /* Ensure all possible state transitions are called without causing problem */ |
| 50 static void test_init_shutdown(void) { |
| 51 census_tracing_init(); |
| 52 census_tracing_init(); |
| 53 census_tracing_shutdown(); |
| 54 census_tracing_shutdown(); |
| 55 census_tracing_init(); |
| 56 } |
| 57 |
| 58 static void test_start_op_generates_locally_unique_ids(void) { |
| 59 /* Check that ids generated within window size of 1000 are unique. |
| 60 TODO(hongyu): Replace O(n^2) duplicate detection algorithm with O(nlogn) |
| 61 algorithm. Enhance the test to larger window size (>10^6) */ |
| 62 #define WINDOW_SIZE 1000 |
| 63 census_op_id ids[WINDOW_SIZE]; |
| 64 int i; |
| 65 census_init(); |
| 66 for (i = 0; i < WINDOW_SIZE; i++) { |
| 67 ids[i] = census_tracing_start_op(); |
| 68 census_tracing_end_op(ids[i]); |
| 69 } |
| 70 for (i = 0; i < WINDOW_SIZE - 1; i++) { |
| 71 int j; |
| 72 for (j = i + 1; j < WINDOW_SIZE; j++) { |
| 73 GPR_ASSERT(ids[i].upper != ids[j].upper || ids[i].lower != ids[j].lower); |
| 74 } |
| 75 } |
| 76 #undef WINDOW_SIZE |
| 77 census_shutdown(); |
| 78 } |
| 79 |
| 80 static void test_get_trace_method_name(void) { |
| 81 census_op_id id; |
| 82 const char write_name[] = "service/method"; |
| 83 census_tracing_init(); |
| 84 id = census_tracing_start_op(); |
| 85 census_add_method_tag(id, write_name); |
| 86 census_internal_lock_trace_store(); |
| 87 { |
| 88 const char *read_name = |
| 89 census_get_trace_method_name(census_get_trace_obj_locked(id)); |
| 90 GPR_ASSERT(strcmp(read_name, write_name) == 0); |
| 91 } |
| 92 census_internal_unlock_trace_store(); |
| 93 census_tracing_shutdown(); |
| 94 } |
| 95 |
| 96 typedef struct thd_arg { |
| 97 int num_done; |
| 98 gpr_cv done; |
| 99 gpr_mu mu; |
| 100 } thd_arg; |
| 101 |
| 102 static void mimic_trace_op_sequences(void *arg) { |
| 103 census_op_id id; |
| 104 const char *method_name = "service_foo/method_bar"; |
| 105 int i = 0; |
| 106 const int num_iter = 200; |
| 107 thd_arg *args = (thd_arg *)arg; |
| 108 GPR_ASSERT(args != NULL); |
| 109 gpr_log(GPR_INFO, "Start trace op sequence thread."); |
| 110 for (i = 0; i < num_iter; i++) { |
| 111 id = census_tracing_start_op(); |
| 112 census_add_method_tag(id, method_name); |
| 113 /* pretend doing 1us work. */ |
| 114 gpr_sleep_until(GRPC_TIMEOUT_MICROS_TO_DEADLINE(1)); |
| 115 census_tracing_end_op(id); |
| 116 } |
| 117 gpr_log(GPR_INFO, "End trace op sequence thread."); |
| 118 gpr_mu_lock(&args->mu); |
| 119 args->num_done += 1; |
| 120 gpr_cv_broadcast(&args->done); |
| 121 gpr_mu_unlock(&args->mu); |
| 122 } |
| 123 |
| 124 static void test_concurrency(void) { |
| 125 #define NUM_THREADS 1000 |
| 126 gpr_thd_id tid[NUM_THREADS]; |
| 127 int i = 0; |
| 128 thd_arg arg; |
| 129 arg.num_done = 0; |
| 130 gpr_mu_init(&arg.mu); |
| 131 gpr_cv_init(&arg.done); |
| 132 census_tracing_init(); |
| 133 for (i = 0; i < NUM_THREADS; ++i) { |
| 134 gpr_thd_new(tid + i, mimic_trace_op_sequences, &arg, NULL); |
| 135 } |
| 136 gpr_mu_lock(&arg.mu); |
| 137 while (arg.num_done < NUM_THREADS) { |
| 138 gpr_log(GPR_INFO, "num done %d", arg.num_done); |
| 139 gpr_cv_wait(&arg.done, &arg.mu, gpr_inf_future(GPR_CLOCK_REALTIME)); |
| 140 } |
| 141 gpr_mu_unlock(&arg.mu); |
| 142 census_tracing_shutdown(); |
| 143 #undef NUM_THREADS |
| 144 } |
| 145 |
| 146 static void test_add_method_tag_to_unknown_op_id(void) { |
| 147 census_op_id unknown_id = {0xDEAD, 0xBEEF}; |
| 148 int ret = 0; |
| 149 census_tracing_init(); |
| 150 ret = census_add_method_tag(unknown_id, "foo"); |
| 151 GPR_ASSERT(ret != 0); |
| 152 census_tracing_shutdown(); |
| 153 } |
| 154 |
| 155 static void test_trace_print(void) { |
| 156 census_op_id id; |
| 157 int i; |
| 158 const char *annotation_txt[4] = {"abc", "", "$%^ *()_"}; |
| 159 char long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 10]; |
| 160 |
| 161 memset(long_txt, 'a', GPR_ARRAY_SIZE(long_txt)); |
| 162 long_txt[CENSUS_MAX_ANNOTATION_LENGTH + 9] = '\0'; |
| 163 annotation_txt[3] = long_txt; |
| 164 |
| 165 census_tracing_init(); |
| 166 id = census_tracing_start_op(); |
| 167 /* Adds large number of annotations to each trace */ |
| 168 for (i = 0; i < 1000; i++) { |
| 169 census_tracing_print(id, |
| 170 annotation_txt[i % GPR_ARRAY_SIZE(annotation_txt)]); |
| 171 } |
| 172 census_tracing_end_op(id); |
| 173 |
| 174 census_tracing_shutdown(); |
| 175 } |
| 176 |
| 177 /* Returns 1 if two ids are equal, otherwise returns 0. */ |
| 178 static int ids_equal(census_op_id id1, census_op_id id2) { |
| 179 return (id1.upper == id2.upper) && (id1.lower == id2.lower); |
| 180 } |
| 181 |
| 182 static void test_get_active_ops(void) { |
| 183 census_op_id id_1, id_2, id_3; |
| 184 census_trace_obj **active_ops; |
| 185 const char *annotation_txt[] = {"annotation 1", "a2"}; |
| 186 int i = 0; |
| 187 int n = 0; |
| 188 |
| 189 gpr_log(GPR_INFO, "test_get_active_ops"); |
| 190 census_tracing_init(); |
| 191 /* No active ops before calling start_op(). */ |
| 192 active_ops = census_get_active_ops(&n); |
| 193 GPR_ASSERT(active_ops == NULL); |
| 194 GPR_ASSERT(n == 0); |
| 195 |
| 196 /* Starts one op */ |
| 197 id_1 = census_tracing_start_op(); |
| 198 census_add_method_tag(id_1, "foo_1"); |
| 199 active_ops = census_get_active_ops(&n); |
| 200 GPR_ASSERT(active_ops != NULL); |
| 201 GPR_ASSERT(n == 1); |
| 202 GPR_ASSERT(ids_equal(active_ops[0]->id, id_1)); |
| 203 census_trace_obj_destroy(active_ops[0]); |
| 204 gpr_free(active_ops); |
| 205 active_ops = NULL; |
| 206 |
| 207 /* Start the second and the third ops */ |
| 208 id_2 = census_tracing_start_op(); |
| 209 census_add_method_tag(id_2, "foo_2"); |
| 210 id_3 = census_tracing_start_op(); |
| 211 census_add_method_tag(id_3, "foo_3"); |
| 212 |
| 213 active_ops = census_get_active_ops(&n); |
| 214 GPR_ASSERT(n == 3); |
| 215 for (i = 0; i < 3; i++) { |
| 216 census_trace_obj_destroy(active_ops[i]); |
| 217 } |
| 218 gpr_free(active_ops); |
| 219 active_ops = NULL; |
| 220 |
| 221 /* End the second op and add annotations to the third ops */ |
| 222 census_tracing_end_op(id_2); |
| 223 census_tracing_print(id_3, annotation_txt[0]); |
| 224 census_tracing_print(id_3, annotation_txt[1]); |
| 225 |
| 226 active_ops = census_get_active_ops(&n); |
| 227 GPR_ASSERT(active_ops != NULL); |
| 228 GPR_ASSERT(n == 2); |
| 229 for (i = 0; i < 2; i++) { |
| 230 census_trace_obj_destroy(active_ops[i]); |
| 231 } |
| 232 gpr_free(active_ops); |
| 233 active_ops = NULL; |
| 234 |
| 235 /* End all ops. */ |
| 236 census_tracing_end_op(id_1); |
| 237 census_tracing_end_op(id_3); |
| 238 active_ops = census_get_active_ops(&n); |
| 239 GPR_ASSERT(active_ops == NULL); |
| 240 GPR_ASSERT(n == 0); |
| 241 |
| 242 census_tracing_shutdown(); |
| 243 } |
| 244 |
| 245 int main(int argc, char **argv) { |
| 246 grpc_test_init(argc, argv); |
| 247 test_init_shutdown(); |
| 248 test_start_op_generates_locally_unique_ids(); |
| 249 test_get_trace_method_name(); |
| 250 test_concurrency(); |
| 251 test_add_method_tag_to_unknown_op_id(); |
| 252 test_trace_print(); |
| 253 test_get_active_ops(); |
| 254 return 0; |
| 255 } |
OLD | NEW |