null+****@clear*****
null+****@clear*****
2010年 8月 2日 (月) 15:20:03 JST
Kouhei Sutou 2010-08-02 06:20:03 +0000 (Mon, 02 Aug 2010) New Revision: bf7a82d44fcb9e7df10f1b4e18370b0a06015aae Log: add a test for patricia trie cursor with GRN_CURSOR_SIZE_BY_BIT. Modified files: test/unit/core/test-table-patricia-trie-cursor.c Modified: test/unit/core/test-table-patricia-trie-cursor.c (+319 -30) =================================================================== --- test/unit/core/test-table-patricia-trie-cursor.c 2010-07-30 08:16:33 +0000 (dc99e44) +++ test/unit/core/test-table-patricia-trie-cursor.c 2010-08-02 06:20:03 +0000 (fe27d26) @@ -41,6 +41,8 @@ void data_prefix_short_text(void); void test_prefix_short_text(gpointer data); +void data_prefix_geo_point(void); +void test_prefix_geo_point(gpointer data); void data_near_uint32(void); void test_near_uint32(gpointer data); void data_near_geo_point(void); @@ -161,45 +163,20 @@ create_uint32_table(void) } static void -create_geo_point_table(void) +create_geo_point_table(const gchar *data) { const char *table_name = "GeoPointPat"; assert_send_commands( - cut_take_printf("table_create %s TABLE_PAT_KEY UInt32", table_name)); + cut_take_printf("table_create %s TABLE_PAT_KEY WGS84GeoPoint", table_name)); assert_send_commands( cut_take_printf("load --table %s\n" "[\n" " [\"_key\"],\n" - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]," - " [\"%s\"]" + "%s" "]", table_name, - TAKEN_POINT(1, 2, 3, - 4, 5, 6), - TAKEN_POINT(1, 2, 3, - 7, 8, 9), - TAKEN_POINT(7, 8, 9, - 4, 5, 6), - TAKEN_POINT(89, 59, 59, - 179, 59, 59), - TAKEN_POINT(89, 59, 59, - 179, -59, -59), - TAKEN_POINT(88, 58, 58, - 178, 58, 58), - TAKEN_POINT(-89, -59, -59, - -179, -59, -59), - TAKEN_POINT(-89, -59, -59, - 179, 59, 59), - TAKEN_POINT(-88, -58, -58, - -178, -58, -58))); + data)); table = grn_ctx_get(context, table_name, strlen(table_name)); } @@ -309,6 +286,291 @@ test_prefix_short_text(gpointer data) gcut_assert_equal_list_string(expected_keys, actual_keys); } +static void +grn_gton(uint8_t *keybuf, const void *key, uint32_t size) +{ + int la = ((grn_geo_point *)key)->latitude; + int lo = ((grn_geo_point *)key)->longitude; + uint8_t *p = keybuf; + int i = 32; + while (i) { + i -= 4; + *p++ = ((((la >> i) & 8) << 4) + (((lo >> i) & 8) << 3) + + (((la >> i) & 4) << 3) + (((lo >> i) & 4) << 2) + + (((la >> i) & 2) << 2) + (((lo >> i) & 2) << 1) + + (((la >> i) & 1) << 1) + (((lo >> i) & 1) << 0)); + } +} + +static void +grn_ntog(uint8_t *keybuf, uint8_t *key, uint32_t size) +{ + int la = 0, lo = 0; + uint8_t v, *p = key; + int i = 32; + while (size--) { + i -= 4; + v = *p++; + la += (((v & 128) >> 4) + ((v & 32) >> 3) + + ((v & 8) >> 2) + ((v & 2) >> 1)) << i; + lo += (((v & 64) >> 3) + ((v & 16) >> 2) + + ((v & 4) >> 1) + ((v & 1) >> 0)) << i; + } + ((grn_geo_point *)keybuf)->latitude = la; + ((grn_geo_point *)keybuf)->longitude = lo; +} + +static const gchar * +geo_byte_parse(const gchar *geo_byte_string) +{ + gint i = 0; + uint8_t geo_byte[sizeof(grn_geo_point)]; + grn_geo_point geo_point; + + while (geo_byte_string[0]) { + switch (geo_byte_string[0]) { + case '0': + geo_byte[i / 8] &= ~(1 << (7 - (i % 8))); + i++; + break; + case '1': + geo_byte[i / 8] |= 1 << (7 - (i % 8)); + i++; + break; + default: + break; + } + geo_byte_string++; + } + grn_ntog((uint8_t *)(&geo_point), geo_byte, sizeof(grn_geo_point)); + return cut_take_printf("%dx%d", + geo_point.latitude, + geo_point.longitude); +} + +static GList * +geo_byte_list_new_va_list(const gchar *value, va_list args) +{ + GList *list = NULL; + + while (value) { + list = g_list_prepend(list, g_strdup(geo_byte_parse(value))); + value = va_arg(args, const gchar *); + } + + return g_list_reverse(list); +} + +static GList * +geo_byte_list_new(const gchar *value, ...) +{ + GList *list = NULL; + va_list args; + + va_start(args, value); + list = geo_byte_list_new_va_list(value, args); + va_end(args); + + return list; +} + +static const gchar * +geo_byte_load_data(const gchar *value, ...) +{ + GString *data; + GList *list, *node; + va_list args; + + va_start(args, value); + list = geo_byte_list_new_va_list(value, args); + va_end(args); + + data = g_string_new(NULL); + for (node = list; node; node = g_list_next(node)) { + const gchar *point = node->data; + g_string_append_printf(data, "[\"%s\"]", point); + if (g_list_next(node)) { + g_string_append_printf(data, ",\n"); + } + } + gcut_list_string_free(list); + + return cut_take_string(g_string_free(data, FALSE)); +} + +void +data_prefix_geo_point(void) +{ +#define ADD_DATA(label, expected, min, min_size, offset, limit, flags) \ + gcut_add_datum(label, \ + "expected", G_TYPE_POINTER, \ + expected, gcut_list_string_free, \ + "min", G_TYPE_STRING, min, \ + "min-size", G_TYPE_UINT, min_size, \ + "offset", G_TYPE_INT, offset, \ + "limit", G_TYPE_INT, limit, \ + "flags", G_TYPE_INT, flags, \ + NULL) + + ADD_DATA( + "bit - ascending", + gcut_list_string_new( + "00000000 00111111 01010000 00000000 01111101 00010000 00011101 00001111", + "00000000 00111111 01010000 00000001 00011110 01010001 01101001 00110000", + "00000000 00111111 01010000 00001101 01011101 01011011 01011001 01010011", + "00000000 00111111 01010000 00001111 00101011 00011111 00110011 00001001", + "00000000 00111111 01010000 00010010 00110001 00001000 00001010 00110011", + "00000000 00111111 01010000 00010010 00110001 00110111 01111000 01110000", + "00000000 00111111 01010000 00011000 01110000 00001011 00101110 01001010", + "00000000 00111111 01010000 00100000 00010111 01000111 00110100 00101010", + "00000000 00111111 01010000 00100010 00100111 01000011 00000010 01101001", + "00000000 00111111 01010000 00100010 00111011 01000000 00111000 01100100", + "00000000 00111111 01010000 00100011 00000001 00000111 01011100 01110011", + "00000000 00111111 01010000 00100011 00001010 00000000 00001101 00111010", + "00000000 00111111 01010000 00100011 01100100 01011000 00000111 01110010", + "00000000 00111111 01010000 00101101 00101000 00111111 01010110 00010110", + "00000000 00111111 01010000 00101101 01111100 01101100 00111000 01111001", + "00000000 00111111 01010000 00101110 01010011 00101001 00101001 00100011", + "00000000 00111111 01010000 00101110 01110010 00111001 00011011 01101010", + "00000000 00111111 01010000 00101111 00011000 01000110 00100101 01011110", + "00000000 00111111 01010000 00101111 01001010 01101000 01000100 01100011", + "00000000 00111111 01010000 00110000 01001010 01011100 01101010 00010001", + "00000000 00111111 01010000 00111000 01100100 01101011 01111100 01111011", + "00000000 00111111 01010000 00111001 00111101 00001001 00001011 01010011", + "00000000 00111111 01010000 00111010 01011111 00000010 00101001 01010000", + NULL), + "00000000 00111111 01010000 00000000 00000000 00000000 00000000 00000000", + 26, + 0, -1, + GRN_CURSOR_SIZE_BY_BIT); + ADD_DATA( + "bit - descending", + gcut_list_string_new( + "00000000 00111111 01010000 00111010 01011111 00000010 00101001 01010000", + "00000000 00111111 01010000 00111001 00111101 00001001 00001011 01010011", + "00000000 00111111 01010000 00111000 01100100 01101011 01111100 01111011", + "00000000 00111111 01010000 00110000 01001010 01011100 01101010 00010001", + "00000000 00111111 01010000 00101111 01001010 01101000 01000100 01100011", + "00000000 00111111 01010000 00101111 00011000 01000110 00100101 01011110", + "00000000 00111111 01010000 00101110 01110010 00111001 00011011 01101010", + "00000000 00111111 01010000 00101110 01010011 00101001 00101001 00100011", + "00000000 00111111 01010000 00101101 01111100 01101100 00111000 01111001", + "00000000 00111111 01010000 00101101 00101000 00111111 01010110 00010110", + "00000000 00111111 01010000 00100011 01100100 01011000 00000111 01110010", + "00000000 00111111 01010000 00100011 00001010 00000000 00001101 00111010", + "00000000 00111111 01010000 00100011 00000001 00000111 01011100 01110011", + "00000000 00111111 01010000 00100010 00111011 01000000 00111000 01100100", + "00000000 00111111 01010000 00100010 00100111 01000011 00000010 01101001", + "00000000 00111111 01010000 00100000 00010111 01000111 00110100 00101010", + "00000000 00111111 01010000 00011000 01110000 00001011 00101110 01001010", + "00000000 00111111 01010000 00010010 00110001 00110111 01111000 01110000", + "00000000 00111111 01010000 00010010 00110001 00001000 00001010 00110011", + "00000000 00111111 01010000 00001111 00101011 00011111 00110011 00001001", + "00000000 00111111 01010000 00001101 01011101 01011011 01011001 01010011", + "00000000 00111111 01010000 00000001 00011110 01010001 01101001 00110000", + "00000000 00111111 01010000 00000000 01111101 00010000 00011101 00001111", + NULL), + "00000000 00111111 01010000 00000000 00000000 00000000 00000000 00000000", + 26, + 0, -1, + GRN_CURSOR_SIZE_BY_BIT | GRN_CURSOR_DESCENDING); + +#undef ADD_DATA +} + +void +test_prefix_geo_point(gpointer data) +{ + grn_id id; + grn_obj min, min_string; + int offset, limit, flags; + unsigned min_size; + const GList *expected_keys; + GList *actual_keys = NULL; + + create_geo_point_table( + geo_byte_load_data( + "00000000 00111111 01010000 00110000 01001010 01011100 01101010 00010001", + "00000000 00111111 01010000 00001101 01011101 01011011 01011001 01010011", + "00000000 00111111 01010000 00000001 00011110 01010001 01101001 00110000", + "00000000 00111111 01010000 00011000 01110000 00001011 00101110 01001010", + "00000000 00111111 01010000 00010010 00110001 00110111 01111000 01110000", + "00000000 00111111 01010000 00010010 00110001 00001000 00001010 00110011", + "00000000 00111111 01010000 00101110 01110010 00111001 00011011 01101010", + "00000000 00111111 01010000 00101101 00101000 00111111 01010110 00010110", + "00000000 00111111 01010000 00101111 01001010 01101000 01000100 01100011", + "00000000 00111111 01010000 00101111 00011000 01000110 00100101 01011110", + "00000000 00111111 01000101 01011001 01010110 00000111 00110100 01111111", + "00000000 00111111 01000101 01010010 01100101 01100110 00010111 01111110", + "00000000 00111111 01000101 01111111 01011011 01111101 00001001 01100001", + "00000000 00111111 01010000 00100011 00001010 00000000 00001101 00111010", + "00000000 00111111 01010000 00101110 01010011 00101001 00101001 00100011", + "00000000 00111111 01010000 00111010 01011111 00000010 00101001 01010000", + "00000000 00111111 01010000 00111001 00111101 00001001 00001011 01010011", + "00000000 00111111 01000101 01011100 00001100 01000001 01011010 00010011", + "00000000 00111111 01010000 00100011 00000001 00000111 01011100 01110011", + "00000000 00111111 01010000 00100011 01100100 01011000 00000111 01110010", + "00000000 00111111 01010000 00111000 01100100 01101011 01111100 01111011", + "00000000 00111111 01010000 00001111 00101011 00011111 00110011 00001001", + "00000000 00111111 01000101 01111011 01001011 01101011 00001001 00000001", + "00000000 00111111 01000101 01011010 00110100 00000010 01111010 00000000", + "00000000 00111111 01000101 01011011 00011010 00010111 00011000 00100000", + "00000000 00111111 01010000 00100000 00010111 01000111 00110100 00101010", + "00000000 00111111 01010000 00000000 01111101 00010000 00011101 00001111", + "00000000 00111111 01000101 01000100 01010010 00100100 01100011 00111011", + "00000000 00111111 01000101 01010001 00011100 01010110 00100110 00000110", + "00000000 00111111 01010000 00101101 01111100 01101100 00111000 01111001", + "00000000 00111111 01000101 01001101 00111110 00000101 00101010 01000101", + "00000000 00111111 01000101 01000100 01111100 01101011 01101111 00010101", + "00000000 00111111 01000101 01110111 01010100 01110100 01111000 01111000", + "00000000 00111111 01010000 00100010 00111011 01000000 00111000 01100100", + "00000000 00111111 01010000 00100010 00100111 01000011 00000010 01101001", + "00000000 00111111 01000101 01011100 00110110 00100010 00111000 01100001", + NULL)); + + GRN_TEXT_INIT(&min_string, 0); + GRN_TEXT_PUTS(context, &min_string, + geo_byte_parse(gcut_data_get_string(data, "min"))); + GRN_WGS84_GEO_POINT_INIT(&min, 0); + grn_obj_cast(context, &min_string, &min, FALSE); + grn_obj_unlink(context, &min_string); + + min_size = gcut_data_get_uint(data, "min-size"); + offset = gcut_data_get_int(data, "offset"); + limit = gcut_data_get_int(data, "limit"); + flags = gcut_data_get_int(data, "flags"); + cursor = grn_table_cursor_open(context, table, + GRN_BULK_HEAD(&min), min_size, + NULL, 0, + offset, limit, + flags | GRN_CURSOR_PREFIX); + grn_obj_unlink(context, &min); + grn_test_assert_context(context); + while ((id = grn_table_cursor_next(context, cursor))) { + grn_geo_point *key; + int i, j, key_size; + uint8_t encoded_key[sizeof(grn_geo_point)]; + GString *geo_byte; + + key_size = grn_table_cursor_get_key(context, cursor, (void **)&key); + grn_gton(encoded_key, key, key_size); + geo_byte = g_string_new(NULL); + for (i = 0; i < sizeof(grn_geo_point); i++) { + if (i != 0) { + g_string_append(geo_byte, " "); + } + for (j = 0; j < 8; j++) { + g_string_append_printf(geo_byte, "%d", (encoded_key[i] >> (7 - j)) & 1); + } + } + actual_keys = g_list_append(actual_keys, g_string_free(geo_byte, FALSE)); + } + gcut_take_list(actual_keys, g_free); + + expected_keys = gcut_data_get_pointer(data, "expected"); + gcut_assert_equal_list_string(expected_keys, actual_keys); +} + static GList * uint_list_new(gint n, guint value, ...) { @@ -468,7 +730,34 @@ test_near_geo_point(gpointer data) const GList *expected_keys; GList *actual_keys = NULL; - create_geo_point_table(); + create_geo_point_table( + cut_take_printf(" [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]," + " [\"%s\"]", + TAKEN_POINT(1, 2, 3, + 4, 5, 6), + TAKEN_POINT(1, 2, 3, + 7, 8, 9), + TAKEN_POINT(7, 8, 9, + 4, 5, 6), + TAKEN_POINT(89, 59, 59, + 179, 59, 59), + TAKEN_POINT(89, 59, 59, + 179, -59, -59), + TAKEN_POINT(88, 58, 58, + 178, 58, 58), + TAKEN_POINT(-89, -59, -59, + -179, -59, -59), + TAKEN_POINT(-89, -59, -59, + 179, 59, 59), + TAKEN_POINT(-88, -58, -58, + -178, -58, -58))); min_size = gcut_data_get_int(data, "min-size"); GRN_TEXT_INIT(&max_string, 0);