Skip to content

Commit 6b74680

Browse files
committed
Add initial test, fix ragged lengths
1 parent f0fb42c commit 6b74680

File tree

2 files changed

+173
-11
lines changed

2 files changed

+173
-11
lines changed

c/tests/test_tables.c

+138
Original file line numberDiff line numberDiff line change
@@ -4049,6 +4049,143 @@ test_individual_table(void)
40494049
free(metadata_offset);
40504050
}
40514051

4052+
static void
4053+
test_individual_table_takeset(void)
4054+
{
4055+
int ret = 0;
4056+
tsk_id_t ret_id;
4057+
tsk_individual_table_t source_table, table;
4058+
tsk_size_t num_rows = 100;
4059+
tsk_id_t j;
4060+
tsk_size_t k;
4061+
tsk_flags_t *flags;
4062+
double *location;
4063+
tsk_id_t *parents;
4064+
char *metadata;
4065+
tsk_size_t *metadata_offset;
4066+
tsk_size_t *parents_offset;
4067+
tsk_size_t *location_offset;
4068+
tsk_size_t spatial_dimension = 2;
4069+
tsk_size_t num_parents = 3;
4070+
const char *test_metadata = "test";
4071+
tsk_size_t test_metadata_length = 4;
4072+
double test_location[spatial_dimension];
4073+
tsk_id_t test_parents[num_parents];
4074+
tsk_size_t zeros[num_rows + 1];
4075+
4076+
tsk_memset(zeros, 0, (num_rows + 1) * sizeof(tsk_size_t));
4077+
/* Make a table to copy from */
4078+
ret = tsk_individual_table_init(&source_table, 0);
4079+
CU_ASSERT_EQUAL_FATAL(ret, 0);
4080+
for (k = 0; k < spatial_dimension; k++) {
4081+
test_location[k] = (double) k;
4082+
}
4083+
for (k = 0; k < num_parents; k++) {
4084+
test_parents[k] = (tsk_id_t) k + 42;
4085+
}
4086+
for (j = 0; j < (tsk_id_t) num_rows; j++) {
4087+
ret_id = tsk_individual_table_add_row(&source_table, (tsk_flags_t) j,
4088+
test_location, spatial_dimension, test_parents, num_parents, test_metadata,
4089+
test_metadata_length);
4090+
CU_ASSERT_EQUAL_FATAL(ret_id, j);
4091+
}
4092+
4093+
/* Prepare arrays to be taken */
4094+
flags = tsk_malloc(num_rows * sizeof(tsk_flags_t));
4095+
CU_ASSERT_FATAL(flags != NULL);
4096+
tsk_memcpy(flags, source_table.flags, num_rows * sizeof(tsk_flags_t));
4097+
location = tsk_malloc(spatial_dimension * num_rows * sizeof(double));
4098+
CU_ASSERT_FATAL(location != NULL);
4099+
tsk_memcpy(
4100+
location, source_table.location, spatial_dimension * num_rows * sizeof(double));
4101+
location_offset = tsk_malloc((num_rows + 1) * sizeof(tsk_size_t));
4102+
CU_ASSERT_FATAL(location_offset != NULL);
4103+
tsk_memcpy(location_offset, source_table.location_offset,
4104+
(num_rows + 1) * sizeof(tsk_size_t));
4105+
parents = tsk_malloc(num_parents * num_rows * sizeof(tsk_id_t));
4106+
CU_ASSERT_FATAL(parents != NULL);
4107+
tsk_memcpy(parents, source_table.parents, num_parents * num_rows * sizeof(tsk_id_t));
4108+
parents_offset = tsk_malloc((num_rows + 1) * sizeof(tsk_size_t));
4109+
CU_ASSERT_FATAL(parents_offset != NULL);
4110+
tsk_memcpy(parents_offset, source_table.parents_offset,
4111+
(num_rows + 1) * sizeof(tsk_size_t));
4112+
metadata = tsk_malloc(num_rows * test_metadata_length * sizeof(char));
4113+
CU_ASSERT_FATAL(metadata != NULL);
4114+
tsk_memcpy(
4115+
metadata, source_table.metadata, num_rows * test_metadata_length * sizeof(char));
4116+
metadata_offset = tsk_malloc((num_rows + 1) * sizeof(tsk_size_t));
4117+
CU_ASSERT_FATAL(metadata_offset != NULL);
4118+
tsk_memcpy(metadata_offset, source_table.metadata_offset,
4119+
(num_rows + 1) * sizeof(tsk_size_t));
4120+
4121+
ret = tsk_individual_table_init(&table, 0);
4122+
CU_ASSERT_EQUAL_FATAL(ret, 0);
4123+
4124+
/* Add one row so that we can check takeset frees it */
4125+
ret_id = tsk_individual_table_add_row(&table, (tsk_flags_t) 1, test_location,
4126+
spatial_dimension, test_parents, num_parents, test_metadata,
4127+
test_metadata_length);
4128+
CU_ASSERT_EQUAL_FATAL(ret_id, 0);
4129+
4130+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location,
4131+
location_offset, parents, parents_offset, metadata, metadata_offset);
4132+
CU_ASSERT_EQUAL_FATAL(ret, 0);
4133+
CU_ASSERT_TRUE(tsk_individual_table_equals(&source_table, &table, 0));
4134+
4135+
/* Test error states, all of these must not take the array, or free existing */
4136+
/* location and location offset must be simultaneously NULL or not */
4137+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location, NULL,
4138+
parents, parents_offset, metadata, metadata_offset);
4139+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4140+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, NULL,
4141+
location_offset, NULL, NULL, metadata, metadata_offset);
4142+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4143+
/* parents and parents offset must be simultaneously NULL or not */
4144+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location,
4145+
location_offset, parents, NULL, metadata, metadata_offset);
4146+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4147+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location,
4148+
location_offset, NULL, parents_offset, metadata, metadata_offset);
4149+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4150+
/* metadata and metadata offset must be simultaneously NULL or not */
4151+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location,
4152+
location_offset, parents, parents_offset, NULL, metadata_offset);
4153+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4154+
ret = tsk_individual_table_takeset_columns(&table, num_rows, flags, location,
4155+
location_offset, parents, parents_offset, metadata, NULL);
4156+
CU_ASSERT_EQUAL(ret, TSK_ERR_BAD_PARAM_VALUE);
4157+
4158+
/* Truncation after takeset keeps memory and max_rows */
4159+
ret = tsk_individual_table_clear(&table);
4160+
CU_ASSERT_EQUAL_FATAL(ret, 0);
4161+
CU_ASSERT_EQUAL_FATAL(table.max_rows, num_rows);
4162+
4163+
/* if ragged array and offset are both null, all entries are zero length,
4164+
NULL flags mean all zero entries */
4165+
num_rows = 10;
4166+
ret = tsk_individual_table_takeset_columns(
4167+
&table, num_rows, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
4168+
CU_ASSERT_EQUAL(tsk_memcmp(table.flags, zeros, num_rows * sizeof(tsk_flags_t)), 0);
4169+
CU_ASSERT_EQUAL(ret, 0);
4170+
CU_ASSERT_EQUAL(table.num_rows, num_rows);
4171+
CU_ASSERT_EQUAL(
4172+
tsk_memcmp(table.location_offset, zeros, (num_rows + 1) * sizeof(tsk_size_t)),
4173+
0);
4174+
CU_ASSERT_EQUAL(table.location_length, 0);
4175+
CU_ASSERT_EQUAL(
4176+
tsk_memcmp(table.parents_offset, zeros, (num_rows + 1) * sizeof(tsk_size_t)), 0);
4177+
CU_ASSERT_EQUAL(table.parents_length, 0);
4178+
CU_ASSERT_EQUAL(
4179+
tsk_memcmp(table.metadata_offset, zeros, (num_rows + 1) * sizeof(tsk_size_t)),
4180+
0);
4181+
CU_ASSERT_EQUAL(table.metadata_length, 0);
4182+
4183+
ret = tsk_individual_table_free(&table);
4184+
CU_ASSERT_EQUAL(ret, 0);
4185+
ret = tsk_individual_table_free(&source_table);
4186+
CU_ASSERT_EQUAL(ret, 0);
4187+
}
4188+
40524189
static void
40534190
test_individual_table_update_row(void)
40544191
{
@@ -9235,6 +9372,7 @@ main(int argc, char **argv)
92359372
{ "test_migration_table", test_migration_table },
92369373
{ "test_migration_table_update_row", test_migration_table_update_row },
92379374
{ "test_individual_table", test_individual_table },
9375+
{ "test_individual_table_takeset", test_individual_table_takeset },
92389376
{ "test_individual_table_update_row", test_individual_table_update_row },
92399377
{ "test_population_table", test_population_table },
92409378
{ "test_population_table_update_row", test_population_table_update_row },

c/tskit/tables.c

+35-11
Original file line numberDiff line numberDiff line change
@@ -642,28 +642,38 @@ alloc_empty_ragged_column(tsk_size_t num_rows, void **data_col, tsk_size_t **off
642642
}
643643

644644
static int
645-
takeset_ragged_column(tsk_size_t num_rows, void *data, tsk_size_t *offset,
646-
void **data_dest, tsk_size_t **offset_dest)
645+
check_ragged_column(tsk_size_t num_rows, void *data, tsk_size_t *offset)
647646
{
648647
int ret = 0;
649-
650648
if ((data == NULL) != (offset == NULL)) {
651649
ret = TSK_ERR_BAD_PARAM_VALUE;
652650
goto out;
653651
}
654-
if (data == NULL) {
655-
ret = alloc_empty_ragged_column(num_rows, (void *) data_dest, offset_dest);
652+
if (data != NULL) {
653+
ret = check_offsets(num_rows, offset, 0, false);
656654
if (ret != 0) {
657655
goto out;
658656
}
659-
} else {
660-
ret = check_offsets(num_rows, offset, 0, false);
657+
}
658+
out:
659+
return ret;
660+
}
661+
662+
static int
663+
takeset_ragged_column(tsk_size_t num_rows, void *data, tsk_size_t *offset,
664+
void **data_dest, tsk_size_t **offset_dest, tsk_size_t *length_dest)
665+
{
666+
int ret = 0;
667+
if (data == NULL) {
668+
ret = alloc_empty_ragged_column(num_rows, (void *) data_dest, offset_dest);
661669
if (ret != 0) {
662670
goto out;
663671
}
672+
} else {
664673
*data_dest = data;
665674
*offset_dest = offset;
666675
}
676+
*length_dest = (*offset_dest)[num_rows];
667677
out:
668678
return ret;
669679
}
@@ -1070,6 +1080,20 @@ tsk_individual_table_takeset_columns(tsk_individual_table_t *self, tsk_size_t nu
10701080
{
10711081
int ret = 0;
10721082

1083+
/* We need to check all the inputs before we start freeing or taking memory */
1084+
ret = check_ragged_column(num_rows, location, location_offset);
1085+
if (ret != 0) {
1086+
goto out;
1087+
}
1088+
ret = check_ragged_column(num_rows, parents, parents_offset);
1089+
if (ret != 0) {
1090+
goto out;
1091+
}
1092+
ret = check_ragged_column(num_rows, metadata, metadata_offset);
1093+
if (ret != 0) {
1094+
goto out;
1095+
}
1096+
10731097
tsk_individual_table_free_columns(self);
10741098
self->num_rows = num_rows;
10751099
self->max_rows = num_rows;
@@ -1087,17 +1111,17 @@ tsk_individual_table_takeset_columns(tsk_individual_table_t *self, tsk_size_t nu
10871111
}
10881112

10891113
ret = takeset_ragged_column(num_rows, location, location_offset,
1090-
(void *) &self->location, &self->location_offset);
1114+
(void *) &self->location, &self->location_offset, &self->location_length);
10911115
if (ret != 0) {
10921116
goto out;
10931117
}
10941118
ret = takeset_ragged_column(num_rows, parents, parents_offset,
1095-
(void *) &self->parents, &self->parents_offset);
1119+
(void *) &self->parents, &self->parents_offset, &self->parents_length);
10961120
if (ret != 0) {
10971121
goto out;
10981122
}
10991123
ret = takeset_ragged_column(num_rows, metadata, metadata_offset,
1100-
(void *) &self->metadata, &self->metadata_offset);
1124+
(void *) &self->metadata, &self->metadata_offset, &self->metadata_length);
11011125
if (ret != 0) {
11021126
goto out;
11031127
}
@@ -1837,7 +1861,7 @@ tsk_node_table_takeset_columns(tsk_node_table_t *self, tsk_size_t num_rows,
18371861
goto out;
18381862
}
18391863
ret = takeset_ragged_column(num_rows, metadata, metadata_offset,
1840-
(void *) &self->metadata, &self->metadata_offset);
1864+
(void *) &self->metadata, &self->metadata_offset, &self->metadata_length);
18411865
if (ret != 0) {
18421866
goto out;
18431867
}

0 commit comments

Comments
 (0)