static int send_command(int sd, int events, void *discard) { char buf[8192]; int ret; simple_worker *wp; struct kvvec *kvv; ret = read(sd, buf, sizeof(buf)); if (ret == 0) { iobroker_close(iobs, sd); return 0; } if (ret < 0) { printf("main: Failed to read() from fd %d: %s", sd, strerror(errno)); } /* this happens when we're reading from stdin */ buf[--ret] = 0; kvv = kvvec_create(5); wp = wps[wp_index++ % NWPS]; kvvec_addkv(kvv, "job_id", (char *)mkstr("%d", wp->job_index++)); kvvec_addkv_wlen(kvv, "command", sizeof("command") - 1, buf, ret); kvvec_addkv(kvv, "timeout", (char *)mkstr("%d", 10)); printf("Sending kvvec with %d pairs to worker %d\n", kvv->kv_pairs, wp->pid); worker_send_kvvec(wp->sd, kvv); kvvec_destroy(kvv, 0); return 0; }
END_TEST START_TEST( kvvec_test_lookup_sorted ) { struct kvvec *kvv; struct key_value *kv; kvv = kvvec_create(1); ck_assert(kvv != NULL); kvvec_addkv_str(kvv, "golf", "7"); kvvec_addkv_str(kvv, "alfa", "1"); kvvec_addkv_str(kvv, "echo", "5"); kvvec_addkv_str(kvv, "foxtrot", "6"); kvvec_addkv_str(kvv, "bravo", "2"); kvvec_addkv_str(kvv, "hotel", "8"); kvvec_addkv_str(kvv, "charlie", "3"); kvvec_addkv_str(kvv, "delta", "4"); kvvec_sort(kvv); ck_assert_int_eq(kvv->kv_pairs, 8); kv = kvvec_fetch(kvv, "foxtrot", strlen("foxtrot")); ck_assert(kv != NULL); ck_assert_str_eq(kv->key, "foxtrot"); ck_assert_str_eq(kv->value, "6"); kv = kvvec_fetch(kvv, "hotel", strlen("hotel")); ck_assert(kv != NULL); ck_assert_str_eq(kv->key, "hotel"); ck_assert_str_eq(kv->value, "8"); kv = kvvec_fetch(kvv, "delta", strlen("delta")); ck_assert(kv != NULL); ck_assert_str_eq(kv->key, "delta"); ck_assert_str_eq(kv->value, "4"); kv = kvvec_fetch(kvv, "golf", strlen("golf")); ck_assert(kv != NULL); ck_assert_str_eq(kv->key, "golf"); ck_assert_str_eq(kv->value, "7"); kv = kvvec_fetch(kvv, "fox", strlen("fox")); ck_assert(kv == NULL); kv = kvvec_fetch(kvv, "foxtrottrot", strlen("foxtrottrot")); ck_assert(kv == NULL); kvvec_destroy(kvv, 0); }
END_TEST /** * This test verifies that the is_sorted flag triggers a binary search, which * reduces the overall time. Forcing a unsorted list to be reduced means some * values shouldn't be found. * * This shouldn't happen, since is_sorted should only be set if the list is * sorted on key. */ START_TEST( kvvec_test_lookup_sorted_uses_binary ) { struct kvvec *kvv; struct key_value *kv; kvv = kvvec_create(1); ck_assert(kvv != NULL); kvvec_addkv_str(kvv, "bravo", "2"); kvvec_addkv_str(kvv, "charlie", "3"); kvvec_addkv_str(kvv, "delta", "4"); kvvec_addkv_str(kvv, "echo", "5"); kvvec_addkv_str(kvv, "foxtrot", "6"); kvvec_addkv_str(kvv, "golf", "7"); kvvec_addkv_str(kvv, "hotel", "8"); kvvec_addkv_str(kvv, "alfa", "1"); /* Using non-sorted lookup alfa should be found */ kv = kvvec_fetch(kvv, "alfa", strlen("alfa")); ck_assert(kv != NULL); ck_assert_str_eq(kv->key, "alfa"); ck_assert_str_eq(kv->value, "1"); /* Forcing sorted flag, binary search shoud be used */ kvv->kvv_sorted = 1; /* alfa shouldn't be found, since binary search reduces to first half */ kv = kvvec_fetch(kvv, "alfa", strlen("alfa")); ck_assert(kv == NULL); kvvec_destroy(kvv, 0); }
int main(int argc, char **argv) { int i, j; struct kvvec *kvv, *kvv2, *kvv3; struct kvvec_buf *kvvb, *kvvb2; struct kvvec k = KVVEC_INITIALIZER; t_set_colors(0); t_start("key/value vector tests"); kvv = kvvec_create(1); kvv2 = kvvec_create(1); kvv3 = kvvec_create(1); add_vars(kvv, test_data, 1239819); add_vars(kvv, (const char **)argv + 1, argc - 1); kvvec_sort(kvv); kvvec_foreach(kvv, NULL, walker); /* kvvec2buf -> buf2kvvec -> kvvec2buf -> buf2kvvec conversion */ kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC); kvv3 = buf2kvvec(kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_COPY); kvvb2 = kvvec2buf(kvv3, KVSEP, PAIRSEP, OVERALLOC); buf2kvvec_prealloc(kvv2, kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_ASSIGN); kvvec_foreach(kvv2, kvv, walker); kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC); test(kvv->kv_pairs == kvv2->kv_pairs, "pairs should be identical"); for (i = 0; i < kvv->kv_pairs; i++) { struct key_value *kv1, *kv2; kv1 = &kvv->kv[i]; if (i >= kvv2->kv_pairs) { t_fail("missing var %d in kvv2", i); printf("[%s=%s] (%d+%d)\n", kv1->key, kv1->value, kv1->key_len, kv1->value_len); continue; } kv2 = &kvv2->kv[i]; if (!test(!kv_compare(kv1, kv2), "kv pair %d must match", i)) { printf("%d failed: [%s=%s] (%d+%d) != [%s=%s (%d+%d)]\n", i, kv1->key, kv1->value, kv1->key_len, kv1->value_len, kv2->key, kv2->value, kv2->key_len, kv2->value_len); } } test(kvvb2->buflen == kvvb->buflen, "buflens must match"); test(kvvb2->bufsize == kvvb->bufsize, "bufsizes must match"); if (kvvb2->buflen == kvvb->buflen && kvvb2->bufsize == kvvb->bufsize && !memcmp(kvvb2->buf, kvvb->buf, kvvb->bufsize)) { t_pass("kvvec -> buf -> kvvec conversion works flawlessly"); } else { t_fail("kvvec -> buf -> kvvec conversion failed :'("); } free(kvvb->buf); free(kvvb); free(kvvb2->buf); free(kvvb2); kvvec_destroy(kvv, 1); kvvec_destroy(kvv3, KVVEC_FREE_ALL); for (j = 0; pair_term_missing[j]; j++) { buf2kvvec_prealloc(&k, strdup(pair_term_missing[j]), strlen(pair_term_missing[j]), '=', ';', KVVEC_COPY); for (i = 0; i < k.kv_pairs; i++) { struct key_value *kv = &k.kv[i]; test(kv->key_len == kv->value_len, "%d.%d; key_len=%d; value_len=%d (%s = %s)", j, i, kv->key_len, kv->value_len, kv->key, kv->value); test(kv->value_len == strlen(kv->value), "%d.%d; kv->value_len(%d) == strlen(%s)(%d)", j, i, kv->value_len, kv->value, (int)strlen(kv->value)); } } t_end(); return 0; }