X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tests%2Fdata%2Fdatasheet-test.c;h=f0384853e60ccde412a3633f08ca40dd0a698b9a;hb=refs%2Fheads%2Fctables10;hp=194f9223a00396801647f3372b4cd43d1ad0dce4;hpb=02a03f8e7a3bdb796974fa683a60d66fad37d3eb;p=pspp diff --git a/tests/data/datasheet-test.c b/tests/data/datasheet-test.c index 194f9223a0..f0384853e6 100644 --- a/tests/data/datasheet-test.c +++ b/tests/data/datasheet-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 2007, 2009, 2010, 2014 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include #include @@ -40,7 +42,6 @@ #include "error.h" #include "minmax.h" #include "progname.h" -#include "xalloc.h" /* lazy_casereader callback function to instantiate a casereader from the datasheet. */ @@ -65,12 +66,13 @@ struct datasheet_test_params int max_rows; /* Maximum number of rows. */ int max_cols; /* Maximum number of columns. */ int backing_rows; /* Number of rows of backing store. */ - int backing_cols; /* Number of columns of backing store. */ + int backing_widths[MAX_COLS]; /* Widths of columns of backing store. */ + int n_backing_cols; /* Number of columns of backing store. */ int widths[MAX_WIDTHS]; /* Allowed column widths. */ int n_widths; /* State. */ - int next_value; + unsigned int next_value; }; static bool @@ -115,15 +117,15 @@ check_datasheet_casereader (struct mc *mc, struct casereader *reader, if (!check_caseproto (mc, proto, casereader_get_proto (reader), "casereader")) return; - else if (casereader_get_case_cnt (reader) != n_rows) + else if (casereader_get_n_cases (reader) != n_rows) { - if (casereader_get_case_cnt (reader) == CASENUMBER_MAX + if (casereader_get_n_cases (reader) == CASENUMBER_MAX && casereader_count_cases (reader) == n_rows) mc_error (mc, "datasheet casereader has unknown case count"); else mc_error (mc, "casereader row count (%lu) does not match " "expected (%zu)", - (unsigned long int) casereader_get_case_cnt (reader), + (unsigned long int) casereader_get_n_cases (reader), n_rows); } else @@ -151,15 +153,16 @@ check_datasheet_casereader (struct mc *mc, struct casereader *reader, { if (width == 0) mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " - "%g != %g", + "%.*g != %.*g", row, col, n_rows, n_columns, - case_num_idx (c, col), array[row][col].f); + DBL_DIG + 1, case_num_idx (c, col), + DBL_DIG + 1, array[row][col].f); else mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " "'%.*s' != '%.*s'", row, col, n_rows, n_columns, width, case_str_idx (c, col), - width, value_str (&array[row][col], width)); + width, array[row][col].s); } } @@ -188,14 +191,6 @@ check_datasheet (struct mc *mc, struct datasheet *ds, assert (n_rows < MAX_ROWS); assert (n_columns < MAX_COLS); - /* If it is a duplicate hash, discard the state before checking - its consistency, to save time. */ - if (mc_discard_dup_state (mc, hash_datasheet (ds))) - { - datasheet_destroy (ds); - return; - } - /* Check contents of datasheet via datasheet functions. */ if (!check_caseproto (mc, proto, datasheet_get_proto (ds), "datasheet")) { @@ -223,14 +218,14 @@ check_datasheet (struct mc *mc, struct datasheet *ds, { if (width == 0) mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " - "%g != %g", row, col, n_rows, n_columns, - v.f, av->f); + "%.*g != %.*g", row, col, n_rows, n_columns, + DBL_DIG + 1, v.f, DBL_DIG + 1, av->f); else mc_error (mc, "element %zu,%zu (of %zu,%zu) differs: " "'%.*s' != '%.*s'", row, col, n_rows, n_columns, - width, value_str (&v, width), - width, value_str (av, width)); + width, v.s, + width, v.s); difference = true; } value_destroy (&v, width); @@ -253,7 +248,7 @@ check_datasheet (struct mc *mc, struct datasheet *ds, if (width == 0) ds_put_format (&s, " %g", v->f); else - ds_put_format (&s, " '%.*s'", width, value_str (v, width)); + ds_put_format (&s, " '%.*s'", width, v->s); } mc_error (mc, "%s", ds_cstr (&s)); } @@ -266,11 +261,15 @@ check_datasheet (struct mc *mc, struct datasheet *ds, ds_put_format (&s, "row %zu:", row); for (col = 0; col < n_columns; col++) { + int width = caseproto_get_width (proto, col); union value v; - value_init (&v, 0); + value_init (&v, width); if (!datasheet_get_value (ds, row, col, &v)) NOT_REACHED (); - ds_put_format (&s, " %g", v.f); + if (width == 0) + ds_put_format (&s, " %g", v.f); + else + ds_put_format (&s, " '%.*s'", width, v.s); } mc_error (mc, "%s", ds_cstr (&s)); } @@ -316,7 +315,10 @@ check_datasheet (struct mc *mc, struct datasheet *ds, "have been (size %zu,%zu)", n_rows, n_columns); } - mc_add_state (mc, ds); + if (mc_discard_dup_state (mc, hash_datasheet (ds))) + datasheet_destroy (ds); + else + mc_add_state (mc, ds); } /* Extracts the contents of DS into DATA. */ @@ -395,6 +397,22 @@ clone_model (const struct datasheet *ods, odata, data); } +static void +value_from_param (union value *value, int width, unsigned int idx) +{ + if (width == 0) + value->f = idx & 0xffff; + else + { + unsigned int hash = hash_int (idx, 0); + int offset; + + assert (width < 32); + for (offset = 0; offset < width; offset++) + value->s[offset] = "ABCDEFGHIJ"[(hash >> offset) % 10]; + } +} + /* "init" function for struct mc_class. */ static void datasheet_mc_init (struct mc *mc) @@ -402,12 +420,15 @@ datasheet_mc_init (struct mc *mc) struct datasheet_test_params *params = mc_get_aux (mc); struct datasheet *ds; - if (params->backing_rows == 0 && params->backing_cols == 0) + if (params->backing_rows == 0 && params->n_backing_cols == 0) { /* Create unbacked datasheet. */ + struct caseproto *proto; ds = datasheet_create (NULL); mc_name_operation (mc, "empty datasheet"); - check_datasheet (mc, ds, NULL, 0, caseproto_create ()); + proto = caseproto_create (); + check_datasheet (mc, ds, NULL, 0, proto); + caseproto_unref (proto); } else { @@ -419,12 +440,12 @@ datasheet_mc_init (struct mc *mc) int row, col; assert (params->backing_rows > 0 && params->backing_rows <= MAX_ROWS); - assert (params->backing_cols > 0 && params->backing_cols <= MAX_COLS); + assert (params->n_backing_cols > 0 + && params->n_backing_cols <= MAX_COLS); - /* XXX support different backing column widths */ proto = caseproto_create (); - for (col = 0; col < params->backing_cols; col++) - proto = caseproto_add_width (proto, 0); + for (col = 0; col < params->n_backing_cols; col++) + proto = caseproto_add_width (proto, params->backing_widths[col]); writer = mem_writer_create (proto); for (row = 0; row < params->backing_rows; row++) @@ -432,42 +453,43 @@ datasheet_mc_init (struct mc *mc) struct ccase *c; c = case_create (proto); - for (col = 0; col < params->backing_cols; col++) + for (col = 0; col < params->n_backing_cols; col++) { - double value = params->next_value++; - data[row][col].f = value; - case_data_rw_idx (c, col)->f = value; + int width = params->backing_widths[col]; + union value *value = &data[row][col]; + value_init (value, width); + value_from_param (value, width, params->next_value++); + value_copy (case_data_rw_idx (c, col), value, width); } casewriter_write (writer, c); } - caseproto_unref (proto); reader = casewriter_make_reader (writer); assert (reader != NULL); ds = datasheet_create (reader); mc_name_operation (mc, "datasheet with (%d,%d) backing", - params->backing_rows, params->backing_cols); + params->backing_rows, params->n_backing_cols); check_datasheet (mc, ds, data, params->backing_rows, proto); + release_data (params->backing_rows, proto, data); + caseproto_unref (proto); } } +struct resize_cb_aux + { + int old_width; + int new_width; + }; + static void -value_from_param (union value *value, int width, int idx) +resize_cb (const union value *old_value, union value *new_value, const void *aux_) { - if (width == 0) - value->f = idx; - else - { - unsigned int hash = hash_int (idx, 0); - char *string = value_str_rw (value, width); - int offset; + const struct resize_cb_aux *aux = aux_; - assert (width < 32); - for (offset = 0; offset < width; offset++) - string[offset] = "ABCDEFGHIJ"[(hash >> offset) % 10]; - } + value_from_param (new_value, aux->new_width, + value_hash (old_value, aux->old_width, 0)); } /* "mutate" function for struct mc_class. */ @@ -482,7 +504,7 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) const struct caseproto *oproto = datasheet_get_proto (ods); size_t n_columns = datasheet_get_n_columns (ods); size_t n_rows = datasheet_get_n_rows (ods); - size_t pos, new_pos, cnt, width_idx; + size_t pos, new_pos, n, width_idx; extract_data (ods, odata); @@ -524,10 +546,50 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) caseproto_unref (proto); } + /* Resize each column to each possible new size. */ + for (pos = 0; pos < n_columns; pos++) + for (width_idx = 0; width_idx < params->n_widths; width_idx++) + { + int owidth = caseproto_get_width (oproto, pos); + int width = params->widths[width_idx]; + if (mc_include_state (mc)) + { + struct resize_cb_aux aux; + struct caseproto *proto; + struct datasheet *ds; + size_t i; + + mc_name_operation (mc, "resize column %zu (of %zu) " + "from width %d to %d", + pos, n_columns, owidth, width); + clone_model (ods, odata, &ds, data); + + aux.old_width = owidth; + aux.new_width = width; + if (!datasheet_resize_column (ds, pos, width, resize_cb, &aux)) + NOT_REACHED (); + proto = caseproto_set_width (caseproto_ref (oproto), pos, width); + + for (i = 0; i < n_rows; i++) + { + union value *old_value = &data[i][pos]; + union value new_value; + value_init (&new_value, width); + resize_cb (old_value, &new_value, &aux); + value_swap (old_value, &new_value); + value_destroy (&new_value, owidth); + } + + check_datasheet (mc, ds, data, n_rows, proto); + release_data (n_rows, proto, data); + caseproto_unref (proto); + } + } + /* Delete all possible numbers of columns from all possible positions. */ for (pos = 0; pos < n_columns; pos++) - for (cnt = 1; cnt < n_columns - pos; cnt++) + for (n = 1; n < n_columns - pos; n++) if (mc_include_state (mc)) { struct caseproto *proto; @@ -536,17 +598,17 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) mc_name_operation (mc, "delete %zu columns at %zu " "(from %zu to %zu columns)", - cnt, pos, n_columns, n_columns - cnt); + n, pos, n_columns, n_columns - n); clone_model (ods, odata, &ds, data); - datasheet_delete_columns (ds, pos, cnt); - proto = caseproto_remove_widths (caseproto_ref (oproto), pos, cnt); + datasheet_delete_columns (ds, pos, n); + proto = caseproto_remove_widths (caseproto_ref (oproto), pos, n); for (i = 0; i < n_rows; i++) { - for (j = pos; j < pos + cnt; j++) + for (j = pos; j < pos + n; j++) value_destroy (&data[i][j], caseproto_get_width (oproto, j)); - remove_range (&data[i], n_columns, sizeof *data[i], pos, cnt); + remove_range (&data[i], n_columns, sizeof *data[i], pos, n); } check_datasheet (mc, ds, data, n_rows, proto); @@ -557,8 +619,8 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) /* Move all possible numbers of columns from all possible existing positions to all possible new positions. */ for (pos = 0; pos < n_columns; pos++) - for (cnt = 1; cnt < n_columns - pos; cnt++) - for (new_pos = 0; new_pos < n_columns - cnt; new_pos++) + for (n = 1; n < n_columns - pos; n++) + for (new_pos = 0; new_pos < n_columns - n; new_pos++) if (mc_include_state (mc)) { struct caseproto *proto; @@ -567,15 +629,15 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) clone_model (ods, odata, &ds, data); mc_name_operation (mc, "move %zu columns (of %zu) from %zu to %zu", - cnt, n_columns, pos, new_pos); + n, n_columns, pos, new_pos); - datasheet_move_columns (ds, pos, new_pos, cnt); + datasheet_move_columns (ds, pos, new_pos, n); for (i = 0; i < n_rows; i++) move_range (&data[i], n_columns, sizeof data[i][0], - pos, new_pos, cnt); + pos, new_pos, n); proto = caseproto_move_widths (caseproto_ref (oproto), - pos, new_pos, cnt); + pos, new_pos, n); check_datasheet (mc, ds, data, n_rows, proto); release_data (n_rows, proto, data); @@ -585,7 +647,7 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) /* Insert all possible numbers of rows in all possible positions. */ for (pos = 0; pos <= n_rows; pos++) - for (cnt = 1; cnt <= params->max_rows - n_rows; cnt++) + for (n = 1; n <= params->max_rows - n_rows; n++) if (mc_include_state (mc)) { struct datasheet *ds; @@ -595,9 +657,9 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) clone_model (ods, odata, &ds, data); mc_name_operation (mc, "insert %zu rows at %zu " "(from %zu to %zu rows)", - cnt, pos, n_rows, n_rows + cnt); + n, pos, n_rows, n_rows + n); - for (i = 0; i < cnt; i++) + for (i = 0; i < n; i++) { c[i] = case_create (oproto); for (j = 0; j < n_columns; j++) @@ -606,8 +668,8 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) params->next_value++); } - insert_range (data, n_rows, sizeof data[pos], pos, cnt); - for (i = 0; i < cnt; i++) + insert_range (data, n_rows, sizeof data[pos], pos, n); + for (i = 0; i < n; i++) for (j = 0; j < n_columns; j++) { int width = caseproto_get_width (oproto, j); @@ -615,17 +677,17 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) value_copy (&data[i + pos][j], case_data_idx (c[i], j), width); } - if (!datasheet_insert_rows (ds, pos, c, cnt)) + if (!datasheet_insert_rows (ds, pos, c, n)) mc_error (mc, "datasheet_insert_rows failed"); - check_datasheet (mc, ds, data, n_rows + cnt, oproto); - release_data (n_rows + cnt, oproto, data); + check_datasheet (mc, ds, data, n_rows + n, oproto); + release_data (n_rows + n, oproto, data); } /* Delete all possible numbers of rows from all possible positions. */ for (pos = 0; pos < n_rows; pos++) - for (cnt = 1; cnt < n_rows - pos; cnt++) + for (n = 1; n < n_rows - pos; n++) if (mc_include_state (mc)) { struct datasheet *ds; @@ -633,34 +695,34 @@ datasheet_mc_mutate (struct mc *mc, const void *ods_) clone_model (ods, odata, &ds, data); mc_name_operation (mc, "delete %zu rows at %zu " "(from %zu to %zu rows)", - cnt, pos, n_rows, n_rows - cnt); + n, pos, n_rows, n_rows - n); - datasheet_delete_rows (ds, pos, cnt); + datasheet_delete_rows (ds, pos, n); - release_data (cnt, oproto, &data[pos]); - remove_range (&data[0], n_rows, sizeof data[0], pos, cnt); + release_data (n, oproto, &data[pos]); + remove_range (&data[0], n_rows, sizeof data[0], pos, n); - check_datasheet (mc, ds, data, n_rows - cnt, oproto); - release_data (n_rows - cnt, oproto, data); + check_datasheet (mc, ds, data, n_rows - n, oproto); + release_data (n_rows - n, oproto, data); } /* Move all possible numbers of rows from all possible existing positions to all possible new positions. */ for (pos = 0; pos < n_rows; pos++) - for (cnt = 1; cnt < n_rows - pos; cnt++) - for (new_pos = 0; new_pos < n_rows - cnt; new_pos++) + for (n = 1; n < n_rows - pos; n++) + for (new_pos = 0; new_pos < n_rows - n; new_pos++) if (mc_include_state (mc)) { struct datasheet *ds; clone_model (ods, odata, &ds, data); mc_name_operation (mc, "move %zu rows (of %zu) from %zu to %zu", - cnt, n_rows, pos, new_pos); + n, n_rows, pos, new_pos); - datasheet_move_rows (ds, pos, new_pos, cnt); + datasheet_move_rows (ds, pos, new_pos, n); move_range (&data[0], n_rows, sizeof data[0], - pos, new_pos, cnt); + pos, new_pos, n); check_datasheet (mc, ds, data, n_rows, oproto); release_data (n_rows, oproto, data); @@ -682,18 +744,18 @@ enum OPT_MAX_ROWS, OPT_MAX_COLUMNS, OPT_BACKING_ROWS, - OPT_BACKING_COLUMNS, + OPT_BACKING_WIDTHS, OPT_WIDTHS, OPT_HELP, N_DATASHEET_OPTIONS }; -static struct argv_option datasheet_argv_options[N_DATASHEET_OPTIONS] = +static const struct argv_option datasheet_argv_options[N_DATASHEET_OPTIONS] = { {"max-rows", 0, required_argument, OPT_MAX_ROWS}, {"max-columns", 0, required_argument, OPT_MAX_COLUMNS}, {"backing-rows", 0, required_argument, OPT_BACKING_ROWS}, - {"backing-columns", 0, required_argument, OPT_BACKING_COLUMNS}, + {"backing-widths", 0, required_argument, OPT_BACKING_WIDTHS}, {"widths", 0, required_argument, OPT_WIDTHS}, {"help", 'h', no_argument, OPT_HELP}, }; @@ -718,8 +780,25 @@ datasheet_option_callback (int id, void *params_) params->backing_rows = atoi (optarg); break; - case OPT_BACKING_COLUMNS: - params->backing_cols = atoi (optarg); + case OPT_BACKING_WIDTHS: + { + char *w; + + params->n_backing_cols = 0; + for (w = strtok (optarg, ", "); w != NULL; w = strtok (NULL, ", ")) + { + int value = atoi (w); + + if (params->n_backing_cols >= MAX_COLS) + error (1, 0, "Too many widths on --backing-widths " + "(only %d are allowed)", MAX_COLS); + if (!isdigit (w[0]) || value < 0 || value > 31) + error (1, 0, "--backing-widths argument must be a list of 1 to " + "%d integers between 0 and 31 in increasing order", + MAX_COLS); + params->backing_widths[params->n_backing_cols++] = value; + } + } break; case OPT_WIDTHS: @@ -771,15 +850,14 @@ usage (void) " --max-rows=N Maximum number of rows (0...5, 3)\n" " --max-rows=N Maximum number of columns (0...5, 3)\n" " --backing-rows=N Rows of backing store (0...max_rows, 0)\n" - " --backing-columns=N Columns of backing store (0...max_cols, 0)\n" + " --backing-widths=W[,W]... Backing store widths to test (0=num)\n" " --widths=W[,W]... Column widths to test, where 0=numeric,\n" " other values are string widths (0,1,11)\n", program_name, program_name); mc_options_usage (); - fputs ("\nOther options:\n" - " --help Display this help message\n" - "\nReport bugs to \n", - stdout); + printf ("\nOther options:\n" + " --help Display this help message\n" + "\nReport bugs to <%s>\n", PACKAGE_BUGREPORT); exit (0); } @@ -806,14 +884,14 @@ main (int argc, char *argv[]) params.max_rows = 3; params.max_cols = 3; params.backing_rows = 0; - params.backing_cols = 0; + params.n_backing_cols = 0; params.widths[0] = 0; params.widths[1] = 1; params.widths[2] = 11; params.n_widths = 3; params.next_value = 1; - /* Parse comand line. */ + /* Parse command line. */ parser = argv_parser_create (); options = mc_options_create (); mc_options_register_argv_parser (options, parser); @@ -828,7 +906,7 @@ main (int argc, char *argv[]) params.max_rows = MIN (params.max_rows, MAX_ROWS); params.max_cols = MIN (params.max_cols, MAX_COLS); params.backing_rows = MIN (params.backing_rows, params.max_rows); - params.backing_cols = MIN (params.backing_cols, params.max_cols); + params.n_backing_cols = MIN (params.n_backing_cols, params.max_cols); mc_options_set_aux (options, ¶ms); results = mc_run (&datasheet_mc_class, options); @@ -839,11 +917,18 @@ main (int argc, char *argv[]) { int i; - printf ("Parameters: " - "--max-rows=%d --max-columns=%d " - "--backing-rows=%d --backing-columns=%d ", - params.max_rows, params.max_cols, - params.backing_rows, params.backing_cols); + printf ("Parameters: --max-rows=%d --max-columns=%d --backing-rows=%d ", + params.max_rows, params.max_cols, params.backing_rows); + + printf ("--backing-widths="); + for (i = 0; i < params.n_backing_cols; i++) + { + if (i > 0) + printf (","); + printf ("%d", params.backing_widths[i]); + } + printf (" "); + printf ("--widths="); for (i = 0; i < params.n_widths; i++) {