~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to solr/test-framework/src/java/org/apache/solr/util/AbstractSolrTestCase.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**
2
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 
 * contributor license agreements.  See the NOTICE file distributed with
4
 
 * this work for additional information regarding copyright ownership.
5
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 
 * (the "License"); you may not use this file except in compliance with
7
 
 * the License.  You may obtain a copy of the License at
8
 
 *
9
 
 *     http://www.apache.org/licenses/LICENSE-2.0
10
 
 *
11
 
 * Unless required by applicable law or agreed to in writing, software
12
 
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
 * See the License for the specific language governing permissions and
15
 
 * limitations under the License.
16
 
 */
17
 
 
18
 
 
19
 
package org.apache.solr.util;
20
 
 
21
 
 
22
 
import org.apache.lucene.util.LuceneTestCase;
23
 
import org.apache.solr.SolrTestCaseJ4;
24
 
import org.apache.solr.core.SolrConfig;
25
 
import org.apache.solr.common.SolrException;
26
 
import org.apache.solr.common.SolrInputDocument;
27
 
import org.apache.solr.common.SolrInputField;
28
 
import org.apache.solr.common.util.XML;
29
 
import org.apache.solr.request.*;
30
 
import org.junit.AfterClass;
31
 
import org.junit.BeforeClass;
32
 
 
33
 
import org.xml.sax.SAXException;
34
 
import org.slf4j.LoggerFactory;
35
 
import org.slf4j.Logger;
36
 
import javax.xml.xpath.XPathExpressionException;
37
 
 
38
 
import java.io.*;
39
 
import java.util.HashSet;
40
 
import java.util.List;
41
 
import java.util.ArrayList;
42
 
 
43
 
/**
44
 
 * An Abstract base class that makes writing Solr JUnit tests "easier"
45
 
 *
46
 
 * <p>
47
 
 * Test classes that subclass this need only specify the path to the
48
 
 * schema.xml file (:TODO: the solrconfig.xml as well) and write some
49
 
 * testMethods.  This class takes care of creating/destroying the index,
50
 
 * and provides several assert methods to assist you.
51
 
 * </p>
52
 
 *
53
 
 * @see #setUp
54
 
 * @see #tearDown
55
 
 */
56
 
public abstract class AbstractSolrTestCase extends LuceneTestCase {
57
 
    protected SolrConfig solrConfig;
58
 
  /**
59
 
   * Harness initialized by initTestHarness.
60
 
   *
61
 
   * <p>
62
 
   * For use in test methods as needed.
63
 
   * </p>
64
 
   */
65
 
  protected TestHarness h;
66
 
  /**
67
 
   * LocalRequestFactory initialized by initTestHarness using sensible
68
 
   * defaults.
69
 
   *
70
 
   * <p>
71
 
   * For use in test methods as needed.
72
 
   * </p>
73
 
   */
74
 
  protected TestHarness.LocalRequestFactory lrf;
75
 
    
76
 
  /**
77
 
   * Subclasses must define this method to return the name of the
78
 
   * schema.xml they wish to use.
79
 
   */
80
 
  public abstract String getSchemaFile();
81
 
    
82
 
  /**
83
 
   * Subclasses must define this method to return the name of the
84
 
   * solrconfig.xml they wish to use.
85
 
   */
86
 
  public abstract String getSolrConfigFile();
87
 
 
88
 
  /**
89
 
   * Subclasses can override this to change a test's solr home
90
 
   * (default is in test-files)
91
 
   */
92
 
  public String getSolrHome() {
93
 
    return SolrTestCaseJ4.TEST_HOME();
94
 
  }
95
 
  
96
 
  @BeforeClass
97
 
  public static void beforeClassAbstractSolrTestCase() throws Exception {
98
 
    SolrTestCaseJ4.startTrackingSearchers();
99
 
  }
100
 
  
101
 
  @AfterClass
102
 
  public static void afterClassAbstractSolrTestCase() throws Exception {
103
 
    SolrTestCaseJ4.endTrackingSearchers();
104
 
  }
105
 
  
106
 
  /**
107
 
   * The directory used to story the index managed by the TestHarness h
108
 
   */
109
 
  protected File dataDir;
110
 
    
111
 
  /**
112
 
   * Initializes things your test might need
113
 
   *
114
 
   * <ul>
115
 
   * <li>Creates a dataDir in the "java.io.tmpdir"</li>
116
 
   * <li>initializes the TestHarness h using this data directory, and getSchemaPath()</li>
117
 
   * <li>initializes the LocalRequestFactory lrf using sensible defaults.</li>
118
 
   * </ul>
119
 
   *
120
 
   */
121
 
 
122
 
  public static Logger log = LoggerFactory.getLogger(AbstractSolrTestCase.class);
123
 
 
124
 
  private String factoryProp;
125
 
  @Override
126
 
  public void setUp() throws Exception {
127
 
    super.setUp();
128
 
    log.info("####SETUP_START " + getName());
129
 
    ignoreException("ignore_exception");
130
 
    factoryProp = System.getProperty("solr.directoryFactory");
131
 
    if (factoryProp == null) {
132
 
      System.setProperty("solr.directoryFactory","solr.RAMDirectoryFactory");
133
 
    }
134
 
    dataDir = new File(TEMP_DIR,
135
 
            getClass().getName() + "-" + System.currentTimeMillis());
136
 
    dataDir.mkdirs();
137
 
    String configFile = getSolrConfigFile();
138
 
    System.setProperty("solr.solr.home", getSolrHome());
139
 
    if (configFile != null) {
140
 
 
141
 
      solrConfig = h.createConfig(getSolrConfigFile());
142
 
      h = new TestHarness( dataDir.getAbsolutePath(),
143
 
              solrConfig,
144
 
              getSchemaFile());
145
 
      lrf = h.getRequestFactory
146
 
              ("standard",0,20,"version","2.2");
147
 
    }
148
 
    log.info("####SETUP_END " + getName());
149
 
  }
150
 
 
151
 
    /** Causes an exception matching the regex pattern to not be logged. */
152
 
  public static void ignoreException(String pattern) {
153
 
    if (SolrException.ignorePatterns == null)
154
 
      SolrException.ignorePatterns = new HashSet<String>();
155
 
    SolrException.ignorePatterns.add(pattern);
156
 
  }
157
 
 
158
 
  public static void resetExceptionIgnores() {
159
 
    SolrException.ignorePatterns = null;
160
 
    ignoreException("ignore_exception");  // always ignore "ignore_exception"
161
 
  }
162
 
 
163
 
  /** Subclasses that override setUp can optionally call this method
164
 
   * to log the fact that their setUp process has ended.
165
 
   */
166
 
  public void postSetUp() {
167
 
    log.info("####POSTSETUP " + getName());
168
 
  }
169
 
 
170
 
 
171
 
  /** Subclasses that override tearDown can optionally call this method
172
 
   * to log the fact that the tearDown process has started.  This is necessary
173
 
   * since subclasses will want to call super.tearDown() at the *end* of their
174
 
   * tearDown method.
175
 
   */
176
 
  public void preTearDown() {
177
 
    log.info("####PRETEARDOWN " + getName());      
178
 
  }
179
 
 
180
 
  /**
181
 
   * Shuts down the test harness, and makes the best attempt possible
182
 
   * to delete dataDir, unless the system property "solr.test.leavedatadir"
183
 
   * is set.
184
 
   */
185
 
  @Override
186
 
  public void tearDown() throws Exception {
187
 
    log.info("####TEARDOWN_START " + getName());
188
 
    if (factoryProp == null) {
189
 
      System.clearProperty("solr.directoryFactory");
190
 
    }
191
 
 
192
 
    if (h != null) { h.close(); }
193
 
    SolrTestCaseJ4.closeDirectories();
194
 
    String skip = System.getProperty("solr.test.leavedatadir");
195
 
    if (null != skip && 0 != skip.trim().length()) {
196
 
      System.err.println("NOTE: per solr.test.leavedatadir, dataDir will not be removed: " + dataDir.getAbsolutePath());
197
 
    } else {
198
 
      if (!recurseDelete(dataDir)) {
199
 
        System.err.println("!!!! WARNING: best effort to remove " + dataDir.getAbsolutePath() + " FAILED !!!!!");
200
 
      }
201
 
    }
202
 
 
203
 
    resetExceptionIgnores();  
204
 
    super.tearDown();
205
 
  }
206
 
 
207
 
  /** Validates an update XML String is successful
208
 
   */
209
 
  public void assertU(String update) {
210
 
    assertU(null, update);
211
 
  }
212
 
 
213
 
  /** Validates an update XML String is successful
214
 
   */
215
 
  public void assertU(String message, String update) {
216
 
    checkUpdateU(message, update, true);
217
 
  }
218
 
 
219
 
  /** Validates an update XML String failed
220
 
   */
221
 
  public void assertFailedU(String update) {
222
 
    assertFailedU(null, update);
223
 
  }
224
 
 
225
 
  /** Validates an update XML String failed
226
 
   */
227
 
  public void assertFailedU(String message, String update) {
228
 
    checkUpdateU(message, update, false);
229
 
  }
230
 
 
231
 
  /** Checks the success or failure of an update message
232
 
   */
233
 
  private void checkUpdateU(String message, String update, boolean shouldSucceed) {
234
 
    try {
235
 
      String m = (null == message) ? "" : message + " ";
236
 
      if (shouldSucceed) {
237
 
           String res = h.validateUpdate(update);
238
 
         if (res != null) fail(m + "update was not successful: " + res);
239
 
      } else {
240
 
           String res = h.validateErrorUpdate(update);
241
 
         if (res != null) fail(m + "update succeeded, but should have failed: " + res);        
242
 
      }
243
 
    } catch (SAXException e) {
244
 
      throw new RuntimeException("Invalid XML", e);
245
 
    }
246
 
  }
247
 
 
248
 
  /** Validates a query matches some XPath test expressions and closes the query */
249
 
  public void assertQ(SolrQueryRequest req, String... tests) {
250
 
    assertQ(null, req, tests);
251
 
  }
252
 
  
253
 
  /** Validates a query matches some XPath test expressions and closes the query */
254
 
  public void assertQ(String message, SolrQueryRequest req, String... tests) {
255
 
    try {
256
 
      String m = (null == message) ? "" : message + " ";
257
 
      String response = h.query(req);
258
 
      String results = h.validateXPath(response, tests);
259
 
      if (null != results) {
260
 
        fail(m + "query failed XPath: " + results +
261
 
             "\n xml response was: " + response +
262
 
             "\n request was: " + req.getParamString());
263
 
      }
264
 
    } catch (XPathExpressionException e1) {
265
 
      throw new RuntimeException("XPath is invalid", e1);
266
 
    } catch (Exception e2) {
267
 
      throw new RuntimeException("Exception during query", e2);
268
 
    }
269
 
  }
270
 
 
271
 
  /** Makes sure a query throws a SolrException with the listed response code */
272
 
  public void assertQEx(String message, SolrQueryRequest req, int code ) {
273
 
    try {
274
 
      h.query(req);
275
 
      fail( message );
276
 
    } catch (SolrException sex) {
277
 
      assertEquals( code, sex.code() );
278
 
    } catch (Exception e2) {
279
 
      throw new RuntimeException("Exception during query", e2);
280
 
    }
281
 
  }
282
 
 
283
 
  public void assertQEx(String message, SolrQueryRequest req, SolrException.ErrorCode code ) {
284
 
    try {
285
 
      h.query(req);
286
 
      fail( message );
287
 
    } catch (SolrException e) {
288
 
      assertEquals( code.code, e.code() );
289
 
    } catch (Exception e2) {
290
 
      throw new RuntimeException("Exception during query", e2);
291
 
    }
292
 
  }
293
 
 
294
 
  
295
 
  /**
296
 
   * @see TestHarness#optimize
297
 
   */
298
 
  public String optimize(String... args) {
299
 
    return h.optimize(args);
300
 
  }
301
 
  /**
302
 
   * @see TestHarness#commit
303
 
   */
304
 
  public String commit(String... args) {
305
 
    return h.commit(args);
306
 
  }
307
 
 
308
 
  /**
309
 
   * Generates a simple &lt;add&gt;&lt;doc&gt;... XML String with no options
310
 
   *
311
 
   * @param fieldsAndValues 0th and Even numbered args are fields names odds are field values.
312
 
   * @see #add
313
 
   * @see #doc
314
 
   */
315
 
  public String adoc(String... fieldsAndValues) {
316
 
    Doc d = doc(fieldsAndValues);
317
 
    return add(d);
318
 
  }
319
 
 
320
 
  /**
321
 
   * Generates a simple &lt;add&gt;&lt;doc&gt;... XML String with no options
322
 
   */
323
 
  public String adoc(SolrInputDocument sdoc) {
324
 
    List<String> fields = new ArrayList<String>();
325
 
    for (SolrInputField sf : sdoc) {
326
 
      for (Object o : sf.getValues()) {
327
 
        fields.add(sf.getName());
328
 
        fields.add(o.toString());
329
 
      }
330
 
    }
331
 
    return adoc(fields.toArray(new String[fields.size()]));
332
 
  }
333
 
 
334
 
    
335
 
  /**
336
 
   * Generates an &lt;add&gt;&lt;doc&gt;... XML String with options
337
 
   * on the add.
338
 
   *
339
 
   * @param doc the Document to add
340
 
   * @param args 0th and Even numbered args are param names, Odds are param values.
341
 
   * @see #add
342
 
   * @see #doc
343
 
   */
344
 
  public String add(Doc doc, String... args) {
345
 
    try {
346
 
      StringWriter r = new StringWriter();
347
 
            
348
 
      // this is anoying
349
 
      if (null == args || 0 == args.length) {
350
 
        r.write("<add>");
351
 
        r.write(doc.xml);
352
 
        r.write("</add>");
353
 
      } else {
354
 
        XML.writeUnescapedXML(r, "add", doc.xml, (Object[])args);
355
 
      }
356
 
            
357
 
      return r.getBuffer().toString();
358
 
    } catch (IOException e) {
359
 
      throw new RuntimeException
360
 
        ("this should never happen with a StringWriter", e);
361
 
    }
362
 
  }
363
 
 
364
 
  /**
365
 
   * Generates a &lt;delete&gt;... XML string for an ID
366
 
   *
367
 
   * @see TestHarness#deleteById
368
 
   */
369
 
  public String delI(String id) {
370
 
    return h.deleteById(id);
371
 
  }
372
 
  /**
373
 
   * Generates a &lt;delete&gt;... XML string for an query
374
 
   *
375
 
   * @see TestHarness#deleteByQuery
376
 
   */
377
 
  public String delQ(String q) {
378
 
    return h.deleteByQuery(q);
379
 
  }
380
 
  
381
 
  /**
382
 
   * Generates a simple &lt;doc&gt;... XML String with no options
383
 
   *
384
 
   * @param fieldsAndValues 0th and Even numbered args are fields names, Odds are field values.
385
 
   * @see TestHarness#makeSimpleDoc
386
 
   */
387
 
  public Doc doc(String... fieldsAndValues) {
388
 
    Doc d = new Doc();
389
 
    d.xml = h.makeSimpleDoc(fieldsAndValues).toString();
390
 
    return d;
391
 
  }
392
 
 
393
 
  /**
394
 
   * Generates a SolrQueryRequest using the LocalRequestFactory
395
 
   * @see #lrf
396
 
   */
397
 
  public SolrQueryRequest req(String... q) {
398
 
    return lrf.makeRequest(q);
399
 
  }
400
 
 
401
 
  /**
402
 
   * Generates a SolrQueryRequest using the LocalRequestFactory
403
 
   * @see #lrf
404
 
   */
405
 
  public SolrQueryRequest req(String[] params, String... moreParams) {
406
 
    String[] allParams = moreParams;
407
 
    if (params.length!=0) {
408
 
      int len = params.length + moreParams.length;
409
 
      allParams = new String[len];
410
 
      System.arraycopy(params,0,allParams,0,params.length);
411
 
      System.arraycopy(moreParams,0,allParams,params.length,moreParams.length);
412
 
    }
413
 
 
414
 
    return lrf.makeRequest(allParams);
415
 
  }
416
 
 
417
 
  /** Neccessary to make method signatures un-ambiguous */
418
 
  public static class Doc {
419
 
    public String xml;
420
 
    @Override
421
 
    public String toString() { return xml; }
422
 
  }
423
 
 
424
 
  public static boolean recurseDelete(File f) {
425
 
    if (f.isDirectory()) {
426
 
      for (File sub : f.listFiles()) {
427
 
        if (!recurseDelete(sub)) {
428
 
          System.err.println("!!!! WARNING: best effort to remove " + sub.getAbsolutePath() + " FAILED !!!!!");
429
 
          return false;
430
 
        }
431
 
      }
432
 
    }
433
 
    return f.delete();
434
 
  }
435
 
 
436
 
  /** @see SolrTestCaseJ4#getFile */
437
 
  public static File getFile(String name) throws IOException {
438
 
    return SolrTestCaseJ4.getFile(name);
439
 
  }
440
 
}