/* Copyright (c) 2019 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "str.h" #include "array.h" #include "istream.h" #include "solr-response.h" #include "test-common.h" #include static bool debug = FALSE; struct solr_response_test_result { const char *box_id; struct fts_score_map *scores; }; struct solr_response_test { const char *input; struct solr_response_test_result *results; }; struct fts_score_map test_results1_scores[] = { { .score = 0.042314477, .uid = 1 }, { .score = 0.06996078, .uid = 2, }, { .score = 0.020381179, .uid = 3 }, { .score = 0.020381179, .uid = 4 }, { .score = 5.510487E-4, .uid = 6 }, { .score = 0.0424253, .uid = 7 }, { .score = 0.04215967, .uid = 8 }, { .score = 0.02470572, .uid = 9 }, { .score = 0.05936369, .uid = 10 }, { .score = 0.048221838, .uid = 11 }, { .score = 7.793006E-4, .uid = 12 }, { .score = 2.7900032E-4, .uid = 13 }, { .score = 0.02088323, .uid = 14 }, { .score = 0.011646388, .uid = 15 }, { .score = 1.3776218E-4, .uid = 17 }, { .score = 2.386111E-4, .uid = 19 }, { .score = 2.7552436E-4, .uid = 20 }, { .score = 4.772222E-4, .uid = 23 }, { .score = 4.772222E-4, .uid = 24 }, { .score = 5.965277E-4, .uid = 25 }, { .score = 0.0471366, .uid = 26 }, { .score = 0.0471366, .uid = 50 }, { .score = 0.047274362, .uid = 51 }, { .score = 0.053303234, .uid = 56 }, { .score = 5.445528E-4, .uid = 62 }, { .score = 2.922377E-4, .uid = 66 }, { .score = 0.02623833, .uid = 68 }, { .score = 3.4440547E-4, .uid = 70 }, { .score = 2.922377E-4, .uid = 74 }, { .score = 2.7552436E-4, .uid = 76 }, { .score = 1.3776218E-4, .uid = 77 }, { .score = 0, .uid = 0 }, }; struct solr_response_test_result test_results1[] = { { .box_id = "", .scores = test_results1_scores, }, { .box_id = NULL } }; static const struct solr_response_test tests[] = { { .input = "\n" "\n" "03xmluid,score4023uid asc{!luc" "ene q.op=AND}subject:pierreserveur OR from:pierre" "serveur OR to:pierreserveur OR cc:pierreserveur O" "R bcc:pierreserveur OR body:pierreserveur+box:fa74101044cb607d5f0900001de14" "712 +user:jpierreserveur" "0.04231447710.06996078<" "long name=\"uid\">20.0203811793" "0.0203811" "794<" "float name=\"score\">5.510487E-460.042425370.0421596780.0247057290.05936369100.048221838117" ".793006E-4122.7900032E-4130.02088323140.0116" "46388151.3776218E-4172.386111E-419<" "/long>2.7552436E" "-420" "4.772222E-4234.772222E-4245.965277E-4250.0471366260.0" "47136650<" "doc>0.047274362510.05330323456<" "/long>5.445528E-" "462<" "float name=\"score\">2.922377E-4660.0262383368" "3.4440547E-4702.922377E-4742." "7552436E-4761.3776218E-477\n" "\n", .results = test_results1, }, }; static const unsigned tests_count = N_ELEMENTS(tests); static void test_solr_result(const struct solr_response_test_result *test_results, struct solr_result **parse_results) { unsigned int rcount, i; for (i = 0; test_results[i].box_id != NULL; i++); rcount = i; for (i = 0; parse_results[i] != NULL; i++); test_out_quiet("result count equal", i == rcount); if (test_has_failed()) return; for (i = 0; i < rcount && parse_results[i] != NULL; i++) { unsigned int scount, j; const struct fts_score_map *tscores = test_results[i].scores; const struct fts_score_map *pscores = array_get(&parse_results[i]->scores, &scount); test_out_quiet(t_strdup_printf("box id equal[%u]", i), strcmp(test_results[i].box_id, parse_results[i]->box_id) == 0); for (j = 0; tscores[j].uid != 0; j++); test_out_quiet(t_strdup_printf("scores count equal[%u]", i), j == scount); if (j != scount) continue; for (j = 0; j < scount; j++) { test_out_quiet( t_strdup_printf("score uid equal[%u/%u]", i, j), pscores[j].uid == tscores[j].uid); test_out_quiet( t_strdup_printf("score value equal[%u/%u]", i, j), pscores[j].score == tscores[j].score); } } } static void test_solr_response_parser(void) { unsigned int i; for (i = 0; i < tests_count; i++) T_BEGIN { const struct solr_response_test *test; const char *text; unsigned int pos, text_len; struct istream *input; struct solr_response_parser *parser; struct solr_result **box_results; const char *error = NULL; pool_t pool; int ret = 0; test = &tests[i]; text = test->input; text_len = strlen(text); test_begin(t_strdup_printf("solr response [%d]", i)); input = test_istream_create_data(text, text_len); pool = pool_alloconly_create("solr response", 4096); parser = solr_response_parser_init(pool, input); ret = solr_response_parse(parser, &box_results); test_out_reason("parse ok (buffer)", ret > 0, error); if (ret > 0) test_solr_result(test->results, box_results); solr_response_parser_deinit(&parser); pool_unref(&pool); i_stream_unref(&input); input = test_istream_create_data(text, text_len); pool = pool_alloconly_create("solr response", 4096); parser = solr_response_parser_init(pool, input); ret = 0; for (pos = 0; pos <= text_len && ret == 0; pos++) { test_istream_set_size(input, pos); ret = solr_response_parse(parser, &box_results); } test_out_reason("parse ok (trickle)", ret > 0, error); if (ret > 0) test_solr_result(test->results, box_results); solr_response_parser_deinit(&parser); pool_unref(&pool); i_stream_unref(&input); test_end(); } T_END; } static void test_solr_response_file(const char *file) { pool_t pool; struct istream *input; struct solr_response_parser *parser; struct solr_result **box_results; int ret = 0; pool = pool_alloconly_create("solr response", 4096); input = i_stream_create_file(file, 1024); parser = solr_response_parser_init(pool, input); while ((ret = solr_response_parse(parser, &box_results)) == 0); if (ret < 0) i_fatal("Failed to read response"); solr_response_parser_deinit(&parser); i_stream_unref(&input); pool_unref(&pool); } int main(int argc, char *argv[]) { int c; static void (*test_functions[])(void) = { test_solr_response_parser, NULL }; while ((c = getopt(argc, argv, "D")) > 0) { switch (c) { case 'D': debug = TRUE; break; default: i_fatal("Usage: %s [-D]", argv[0]); } } argc -= optind; argv += optind; if (argc > 0) { test_solr_response_file(argv[0]); return 0; } return test_run(test_functions); }