Branch data Line data Source code
1 : : /* stemtest.cc
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002 Ananova Ltd
5 : : * Copyright 2002,2003,2004,2007,2008,2009 Olly Betts
6 : : *
7 : : * This program is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU General Public License as
9 : : * published by the Free Software Foundation; either version 2 of the
10 : : * License, or (at your option) any later version.
11 : : *
12 : : * This program is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this program; if not, write to the Free Software
19 : : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 : : * USA
21 : : */
22 : :
23 : : #include <config.h>
24 : :
25 : : #include <cstdlib>
26 : :
27 : : #include <string>
28 : : #include <fstream>
29 : : #include <iostream>
30 : :
31 : : #include <xapian/stem.h>
32 : : #include "testsuite.h"
33 : :
34 : : using namespace std;
35 : :
36 : : static const int JUNKSIZE = 2 * 1048576;
37 : :
38 : 1 : static string language;
39 : :
40 : 1 : static Xapian::Stem stemmer;
41 : :
42 : 1 : static string srcdir;
43 : :
44 : : static int seed;
45 : :
46 : : // run stemmers on random text
47 : : static bool
48 : 19 : test_stemrandom()
49 : : {
50 : : static const char wordchars[] =
51 : : "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789^\0";
52 : :
53 : 19 : tout << "Stemming random text... (seed " << seed << ")" << endl;
54 : 19 : srand(seed);
55 : :
56 : 19 : string word;
57 : 19 : int stemmed_size = 0;
58 [ + + ]: 39845907 : for (int c = JUNKSIZE; c; --c) {
59 : 39845888 : char ch = wordchars[(rand() >> 8) % sizeof wordchars];
60 [ + + ]: 39845888 : if (ch) {
61 : 38621718 : word += ch;
62 : 38621718 : continue;
63 : : }
64 : 1224170 : stemmed_size += stemmer(word).length();
65 : 1224170 : word.resize(0);
66 : : }
67 : 19 : stemmed_size += stemmer(word).length();
68 : : tout << "Input size " << JUNKSIZE << ", stemmed size " << stemmed_size
69 : 19 : << endl;
70 : :
71 [ - + ]: 19 : if (stemmed_size > JUNKSIZE * 101 / 100) {
72 [ # # ]: 0 : FAIL_TEST("Stemmed data is significantly bigger than input: "
73 : : << stemmed_size << " vs. " << JUNKSIZE);
74 : : }
75 [ - + ]: 19 : if (stemmed_size < JUNKSIZE / 2) {
76 [ # # ]: 0 : FAIL_TEST("Stemmed data is significantly smaller than input: "
77 : : << stemmed_size << " vs. " << JUNKSIZE);
78 : : }
79 : 19 : return true;
80 : : }
81 : :
82 : : // run stemmers on random junk
83 : : static bool
84 : 19 : test_stemjunk()
85 : : {
86 : 19 : tout << "Stemming random junk... (seed " << seed << ")" << endl;
87 : 19 : srand(seed);
88 : :
89 : 19 : string word;
90 : 19 : int stemmed_size = 0;
91 [ + + ]: 39845907 : for (int c = JUNKSIZE; c; --c) {
92 : 39845888 : char ch = rand() >> 8;
93 [ + + ]: 39845888 : if (ch) {
94 : 39690468 : word += ch;
95 : 39690468 : continue;
96 : : }
97 : 155420 : stemmed_size += stemmer(word).length();
98 : 155420 : word.resize(0);
99 : : }
100 : 19 : stemmed_size += stemmer(word).length();
101 : : tout << "Input size " << JUNKSIZE << ", stemmed size " << stemmed_size
102 : 19 : << endl;
103 : :
104 [ - + ]: 19 : if (stemmed_size > JUNKSIZE * 101 / 100) {
105 [ # # ]: 0 : FAIL_TEST("Stemmed data is significantly bigger than input ("
106 : : << stemmed_size << " vs. " << JUNKSIZE);
107 : : }
108 [ - + ]: 19 : if (stemmed_size < JUNKSIZE / 2) {
109 [ # # ]: 0 : FAIL_TEST("Stemmed data is significantly smaller than input ("
110 : : << stemmed_size << " vs. " << JUNKSIZE);
111 : : }
112 : 19 : return true;
113 : : }
114 : :
115 : : static bool
116 : 19 : test_stemdict()
117 : : {
118 : 19 : string dir = srcdir + "/../../xapian-data/stemming/";
119 : :
120 : 19 : ifstream voc((dir + language + "/voc.txt").c_str());
121 [ - + ]: 19 : if (!voc.is_open()) {
122 [ # # ]: 0 : SKIP_TEST(language + "/voc.txt not found");
123 : : }
124 : :
125 : 19 : ifstream st((dir + language + "/output.txt").c_str());
126 [ - + ]: 19 : if (!st.is_open()) {
127 : 0 : voc.close();
128 [ # # ]: 0 : FAIL_TEST(language + "/output.txt not found");
129 : : }
130 : :
131 : 19 : tout << "Testing " << language << " with Snowball dictionary..." << endl;
132 : :
133 : 19 : int pass = 1;
134 [ + + ][ + + ]: 20 : while (true) {
[ + + ]
135 : 20 : string word, stem, expect;
136 [ + + ][ + - ]: 742703 : while (!voc.eof() && !st.eof()) {
[ + + ]
137 : 742683 : getline(voc, word);
138 : 742683 : getline(st, expect);
139 : :
140 : 742683 : stem = stemmer(word);
141 : :
142 [ - + # # ]: 742683 : TEST_EQUAL(stem, expect);
143 : : }
144 : 20 : voc.close();
145 : 20 : st.close();
146 : :
147 [ + + ]: 20 : if (pass == 2) break;
148 : :
149 : 19 : voc.open((dir + language + "/voc2.txt").c_str());
150 [ + + ]: 19 : if (!voc.is_open()) break;
151 : :
152 : 1 : st.open((dir + language + "/output2.txt").c_str());
153 [ - + ]: 1 : if (!st.is_open()) {
154 : 0 : voc.close();
155 [ # # ]: 0 : FAIL_TEST(language + "/output2.txt not found");
156 : : }
157 : : tout << "Testing " << language << " with supplemental dictionary..."
158 : 1 : << endl;
159 : 1 : ++pass;
160 : : }
161 : :
162 : 19 : return true;
163 : : }
164 : :
165 : : // ##################################################################
166 : : // # End of actual tests #
167 : : // ##################################################################
168 : :
169 : : /// The lists of tests to perform
170 : : static const test_desc tests[] = {
171 : : {"stemrandom", test_stemrandom},
172 : : {"stemjunk", test_stemjunk},
173 : : {"stemdict", test_stemdict},
174 : : {0, 0}
175 : : };
176 : :
177 : 1 : int main(int argc, char **argv)
178 : : try {
179 : 1 : string langs = Xapian::Stem::get_available_languages();
180 : 1 : test_driver::add_command_line_option("languages", 'l', &langs);
181 : :
182 : 1 : seed = 42;
183 : 1 : string seed_str;
184 : 1 : test_driver::add_command_line_option("seed", 's', &seed_str);
185 : :
186 : 1 : test_driver::parse_command_line(argc, argv);
187 : 1 : srcdir = test_driver::get_srcdir();
188 : 1 : int result = 0;
189 : :
190 [ - + ]: 1 : if (!seed_str.empty()) seed = atoi(seed_str.c_str());
191 : 1 : cout << "The random seed is " << seed << endl;
192 : 1 : cout << "Please report the seed when reporting a test failure." << endl;
193 : :
194 : 1 : string::size_type b = 0;
195 [ + + ]: 20 : while (b != langs.size()) {
196 : 19 : string::size_type a = b;
197 [ + + ][ + + ]: 161 : while (b < langs.size() && langs[b] != ' ') ++b;
[ + + ]
198 : 19 : language = langs.substr(a, b - a);
199 [ + + ][ + + ]: 37 : while (b < langs.size() && langs[b] == ' ') ++b;
[ + + ]
200 : 19 : cout << "Running tests with " << language << " stemmer..." << endl;
201 : 19 : stemmer = Xapian::Stem(language);
202 : 19 : result = max(result, test_driver::run(tests));
203 : : }
204 : 1 : return result;
205 : 1 : } catch (const char * e) {
206 : 0 : cout << e << endl;
207 : 0 : return 1;
208 [ + - ][ + - ]: 3 : }
|