Merge "Add more concurrent tests"

This commit is contained in:
Zuul
2026-03-06 20:48:36 +00:00
committed by Gerrit Code Review

View File

@@ -700,6 +700,291 @@ static void test_multi_thread_create_backend(
free(desc2);
}
struct decode_state {
int desc1;
int desc2;
char **available_fragments;
int num_fragments;
uint64_t fragment_len;
};
void* decode_in_thread(void* arg)
{
struct decode_state *s = arg;
int *rc = malloc(sizeof(int));
char *decoded_data = NULL;
uint64_t decoded_data_len = 0;
*rc = liberasurecode_decode(s->desc1, s->available_fragments,
s->num_fragments, s->fragment_len, 0, /* force_metadata_checks */
&decoded_data, &decoded_data_len);
assert(0 == *rc || -EBACKENDNOTAVAIL == *rc);
if (*rc == 0) {
assert(liberasurecode_decode_cleanup(s->desc2, decoded_data) == 0);
}
return rc;
}
static void test_multi_thread_decode_and_destroy_backend(
ec_backend_id_t be_id,
struct ec_args *args)
{
pthread_t tid1, tid2;
int *rc1, *rc2;
int desc = liberasurecode_instance_create(be_id, args);
if (-EBACKENDNOTAVAIL == desc) {
fprintf(stderr, "Backend library not available!\n");
return;
}
assert(desc > 0);
int orig_data_size = 1024 * 1024;
char *orig_data = create_buffer(orig_data_size, 'x');
assert(orig_data != NULL);
char **encoded_data = NULL, **encoded_parity = NULL;
uint64_t encoded_fragment_len = 0;
int rc = liberasurecode_encode(desc, orig_data, orig_data_size,
&encoded_data, &encoded_parity, &encoded_fragment_len);
assert(rc == 0);
/* Create available fragments array using the same method as existing tests */
char **available_fragments = NULL;
int *skip = create_skips_array(args, -1);
assert(skip != NULL);
int num_avail_frags = create_frags_array(&available_fragments, encoded_data,
encoded_parity, args, skip);
assert(num_avail_frags > 0);
struct decode_state s = {
desc,
/* need a second descriptor so we can clean up
* even after first descriptor is destroyed */
liberasurecode_instance_create(be_id, args),
available_fragments,
num_avail_frags,
encoded_fragment_len
};
assert(s.desc2 > 0);
pthread_create(&tid2, NULL, decode_in_thread, &s);
pthread_create(&tid1, NULL, destroy_backend_in_thread, &desc);
pthread_join(tid1, (void *) &rc1);
pthread_join(tid2, (void *) &rc2);
/* The threads race, but destroy always succeeds */
assert(*rc1 == 0);
liberasurecode_encode_cleanup(s.desc2, encoded_data, encoded_parity);
assert(liberasurecode_instance_destroy(s.desc2) == 0);
free(available_fragments);
free(skip);
free(rc1);
free(rc2);
free(orig_data);
}
struct reconstruct_state {
int desc1;
int desc2;
char **available_fragments;
int num_fragments;
uint64_t fragment_len;
int missing_idx;
char *out_fragment;
};
void* reconstruct_in_thread(void* arg)
{
struct reconstruct_state *s = arg;
int *rc = malloc(sizeof(int));
*rc = liberasurecode_reconstruct_fragment(s->desc1, s->available_fragments,
s->num_fragments, s->fragment_len, s->missing_idx, s->out_fragment);
assert(0 == *rc || -EBACKENDNOTAVAIL == *rc);
return rc;
}
static void test_multi_thread_reconstruct_and_destroy_backend(
ec_backend_id_t be_id,
struct ec_args *args)
{
pthread_t tid1, tid2;
int *rc1, *rc2;
int desc = liberasurecode_instance_create(be_id, args);
if (-EBACKENDNOTAVAIL == desc) {
fprintf(stderr, "Backend library not available!\n");
return;
}
assert(desc > 0);
int orig_data_size = 1024 * 1024;
char *orig_data = create_buffer(orig_data_size, 'x');
assert(orig_data != NULL);
char **encoded_data = NULL, **encoded_parity = NULL;
uint64_t encoded_fragment_len = 0;
int rc = liberasurecode_encode(desc, orig_data, orig_data_size,
&encoded_data, &encoded_parity, &encoded_fragment_len);
assert(rc == 0);
/* Create available fragments array with one missing fragment */
char **available_fragments = NULL;
int *skip = create_skips_array(args, -1);
assert(skip != NULL);
skip[0] = 1; /* skip first fragment */
int num_avail_frags = create_frags_array(&available_fragments, encoded_data,
encoded_parity, args, skip);
assert(num_avail_frags > 0);
/* Allocate output fragment buffer */
char *out_fragment = malloc(encoded_fragment_len);
assert(out_fragment != NULL);
struct reconstruct_state s = {
desc,
/* need a second descriptor so we can clean up
* even after first descriptor is destroyed */
liberasurecode_instance_create(be_id, args),
available_fragments,
num_avail_frags,
encoded_fragment_len,
0, /* missing fragment index */
out_fragment
};
assert(s.desc2 > 0);
pthread_create(&tid2, NULL, reconstruct_in_thread, &s);
pthread_create(&tid1, NULL, destroy_backend_in_thread, &desc);
pthread_join(tid1, (void *) &rc1);
pthread_join(tid2, (void *) &rc2);
/* The threads race, but destroy always succeeds */
assert(*rc1 == 0);
liberasurecode_encode_cleanup(s.desc2, encoded_data, encoded_parity);
assert(liberasurecode_instance_destroy(s.desc2) == 0);
free(available_fragments);
free(out_fragment);
free(skip);
free(rc1);
free(rc2);
free(orig_data);
}
struct fragments_needed_state {
int desc1;
int desc2;
int *fragments_to_reconstruct;
int *fragments_to_exclude;
int *fragments_needed;
};
void* fragments_needed_in_thread(void* arg)
{
struct fragments_needed_state *s = arg;
int *rc = malloc(sizeof(int));
*rc = liberasurecode_fragments_needed(s->desc1, s->fragments_to_reconstruct,
s->fragments_to_exclude, s->fragments_needed);
assert(0 == *rc || -EBACKENDNOTAVAIL == *rc);
return rc;
}
static void test_multi_thread_fragments_needed_and_destroy_backend(
ec_backend_id_t be_id,
struct ec_args *args)
{
pthread_t tid1, tid2;
int *rc1, *rc2;
int desc = liberasurecode_instance_create(be_id, args);
if (-EBACKENDNOTAVAIL == desc) {
fprintf(stderr, "Backend library not available!\n");
return;
}
assert(desc > 0);
int fragments_to_reconstruct[] = {0, -1};
int fragments_to_exclude[] = {-1};
int *fragments_needed = malloc(sizeof(int) * (args->k + args->m + 1));
assert(fragments_needed != NULL);
struct fragments_needed_state s = {
desc,
/* need a second descriptor so we can clean up
* even after first descriptor is destroyed */
liberasurecode_instance_create(be_id, args),
fragments_to_reconstruct,
fragments_to_exclude,
fragments_needed
};
assert(s.desc2 > 0);
pthread_create(&tid2, NULL, fragments_needed_in_thread, &s);
pthread_create(&tid1, NULL, destroy_backend_in_thread, &desc);
pthread_join(tid1, (void *) &rc1);
pthread_join(tid2, (void *) &rc2);
/* The threads race, but destroy always succeeds */
assert(*rc1 == 0);
assert(liberasurecode_instance_destroy(s.desc2) == 0);
free(fragments_needed);
free(rc1);
free(rc2);
}
struct get_fragment_size_state {
int desc1;
int desc2;
int data_len;
};
void* get_fragment_size_in_thread(void* arg)
{
struct get_fragment_size_state *s = arg;
int *rc = malloc(sizeof(int));
*rc = liberasurecode_get_fragment_size(s->desc1, s->data_len);
/* This function returns size on success or negative error code on failure */
assert(*rc > 0 || *rc == -EBACKENDNOTAVAIL);
return rc;
}
static void test_multi_thread_get_fragment_size_and_destroy_backend(
ec_backend_id_t be_id,
struct ec_args *args)
{
pthread_t tid1, tid2;
int *rc1, *rc2;
int desc = liberasurecode_instance_create(be_id, args);
if (-EBACKENDNOTAVAIL == desc) {
fprintf(stderr, "Backend library not available!\n");
return;
}
assert(desc > 0);
struct get_fragment_size_state s = {
desc,
/* need a second descriptor so we can clean up
* even after first descriptor is destroyed */
liberasurecode_instance_create(be_id, args),
1024 * 1024 /* data length */
};
assert(s.desc2 > 0);
pthread_create(&tid2, NULL, get_fragment_size_in_thread, &s);
pthread_create(&tid1, NULL, destroy_backend_in_thread, &desc);
pthread_join(tid1, (void *) &rc1);
pthread_join(tid2, (void *) &rc2);
/* The threads race, but destroy always succeeds */
assert(*rc1 == 0);
assert(liberasurecode_instance_destroy(s.desc2) == 0);
free(rc1);
free(rc2);
}
static void test_backend_available(void) {
assert(1 == liberasurecode_backend_available(EC_BACKEND_NULL));
}
@@ -2285,6 +2570,10 @@ static void test_metadata_crcs_be(void)
TEST({.with_args = test_multi_thread_create_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_simple_encode_decode}, backend, CHKSUM_NONE), \
TEST({.with_args = test_multi_thread_encode_and_destroy_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_multi_thread_decode_and_destroy_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_multi_thread_reconstruct_and_destroy_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_multi_thread_fragments_needed_and_destroy_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_multi_thread_get_fragment_size_and_destroy_backend}, backend, CHKSUM_NONE), \
TEST({.with_args = test_decode_with_missing_data}, backend, CHKSUM_NONE), \
TEST({.with_args = test_decode_with_missing_parity}, backend, CHKSUM_NONE), \
TEST({.with_args = test_decode_with_missing_multi_data}, backend, CHKSUM_NONE), \