"Fossies" - the Fresh Open Source Software Archive

Member "xapian-core-1.4.14/tests/api_geospatial.cc" (23 Nov 2019, 12194 Bytes) of package /linux/www/xapian-core-1.4.14.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /** @file api_geospatial.cc
    2  * @brief Tests of geospatial functionality.
    3  */
    4 /* Copyright 2008 Lemur Consulting Ltd
    5  * Copyright 2010,2011 Richard Boulton
    6  * Copyright 2012,2016 Olly Betts
    7  *
    8  * This program is free software; you can redistribute it and/or
    9  * modify it under the terms of the GNU General Public License as
   10  * published by the Free Software Foundation; either version 2 of the
   11  * License, or (at your option) any later version.
   12  *
   13  * This program is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  * GNU General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU General Public License
   19  * along with this program; if not, write to the Free Software
   20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
   21  * USA
   22  */
   23 
   24 #include <config.h>
   25 #include "api_geospatial.h"
   26 #include <xapian.h>
   27 
   28 #include "apitest.h"
   29 #include "testsuite.h"
   30 #include "testutils.h"
   31 
   32 using namespace std;
   33 using namespace Xapian;
   34 
   35 // #######################################################################
   36 // # Tests start here
   37 
   38 static void
   39 builddb_coords1(Xapian::WritableDatabase &db, const string &)
   40 {
   41     Xapian::LatLongCoord coord1(10, 10);
   42     Xapian::LatLongCoord coord2(20, 10);
   43     Xapian::LatLongCoord coord3(30, 10);
   44 
   45     Xapian::Document doc;
   46     doc.add_value(0, coord1.serialise());
   47     db.add_document(doc);
   48 
   49     doc = Xapian::Document();
   50     doc.add_value(0, coord2.serialise());
   51     db.add_document(doc);
   52 
   53     doc = Xapian::Document();
   54     doc.add_value(0, coord3.serialise());
   55     db.add_document(doc);
   56 }
   57 
   58 /// Test behaviour of the LatLongDistancePostingSource
   59 DEFINE_TESTCASE(latlongpostingsource1, generated && !remote && !inmemory) {
   60     Xapian::Database db = get_database("coords1", builddb_coords1, "");
   61     Xapian::LatLongCoord coord1(10, 10);
   62     Xapian::LatLongCoord coord2(20, 10);
   63     Xapian::LatLongCoord coord3(30, 10);
   64 
   65     Xapian::GreatCircleMetric metric;
   66     Xapian::LatLongCoords centre;
   67     centre.append(coord1);
   68     double coorddist = metric(coord1, coord2);
   69     TEST_EQUAL_DOUBLE(coorddist, metric(coord2, coord3));
   70 
   71     // Test a search with no range restriction.
   72     {
   73     Xapian::LatLongDistancePostingSource ps(0, coord1, metric);
   74     ps.init(db);
   75 
   76     ps.next(0.0);
   77     TEST_EQUAL(ps.at_end(), false);
   78     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
   79     TEST_EQUAL(ps.get_docid(), 1);
   80 
   81     ps.next(0.0);
   82     TEST_EQUAL(ps.at_end(), false);
   83     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
   84     TEST_EQUAL(ps.get_docid(), 2);
   85 
   86     ps.next(0.0);
   87     TEST_EQUAL(ps.at_end(), false);
   88     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist * 2));
   89     TEST_EQUAL(ps.get_docid(), 3);
   90 
   91     ps.next(0.0);
   92     TEST_EQUAL(ps.at_end(), true);
   93     }
   94 
   95     // Test a search with no range restriction and implicit metric.
   96     {
   97     Xapian::LatLongDistancePostingSource ps(0, coord1);
   98     ps.init(db);
   99 
  100     ps.next(0.0);
  101     TEST_EQUAL(ps.at_end(), false);
  102     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  103     TEST_EQUAL(ps.get_docid(), 1);
  104 
  105     ps.next(0.0);
  106     TEST_EQUAL(ps.at_end(), false);
  107     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  108     TEST_EQUAL(ps.get_docid(), 2);
  109 
  110     ps.next(0.0);
  111     TEST_EQUAL(ps.at_end(), false);
  112     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist * 2));
  113     TEST_EQUAL(ps.get_docid(), 3);
  114 
  115     ps.next(0.0);
  116     TEST_EQUAL(ps.at_end(), true);
  117     }
  118 
  119     // Test a search with a tight range restriction
  120     {
  121     Xapian::LatLongDistancePostingSource ps(0, centre, metric, coorddist * 0.5);
  122     ps.init(db);
  123 
  124     ps.next(0.0);
  125     TEST_EQUAL(ps.at_end(), false);
  126     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  127 
  128     ps.next(0.0);
  129     TEST_EQUAL(ps.at_end(), true);
  130     }
  131 
  132     // Test a search with a tight range restriction and implicit metric.
  133     {
  134     Xapian::LatLongDistancePostingSource ps(0, centre, coorddist * 0.5);
  135     ps.init(db);
  136 
  137     ps.next(0.0);
  138     TEST_EQUAL(ps.at_end(), false);
  139     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  140 
  141     ps.next(0.0);
  142     TEST_EQUAL(ps.at_end(), true);
  143     }
  144 
  145     // Test a search with a looser range restriction
  146     {
  147     Xapian::LatLongDistancePostingSource ps(0, centre, metric, coorddist);
  148     ps.init(db);
  149 
  150     ps.next(0.0);
  151     TEST_EQUAL(ps.at_end(), false);
  152     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  153 
  154     ps.next(0.0);
  155     TEST_EQUAL(ps.at_end(), false);
  156     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  157     TEST_EQUAL(ps.get_docid(), 2);
  158 
  159     ps.next(0.0);
  160     TEST_EQUAL(ps.at_end(), true);
  161     }
  162 
  163     // Test a search with a looser range restriction and implicit metric.
  164     {
  165     Xapian::LatLongDistancePostingSource ps(0, centre, coorddist);
  166     ps.init(db);
  167 
  168     ps.next(0.0);
  169     TEST_EQUAL(ps.at_end(), false);
  170     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  171 
  172     ps.next(0.0);
  173     TEST_EQUAL(ps.at_end(), false);
  174     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  175     TEST_EQUAL(ps.get_docid(), 2);
  176 
  177     ps.next(0.0);
  178     TEST_EQUAL(ps.at_end(), true);
  179     }
  180 
  181     // Test a search with a looser range restriction, but not enough to return
  182     // the next document.
  183     {
  184     Xapian::LatLongDistancePostingSource ps(0, centre, metric, coorddist * 1.5);
  185     ps.init(db);
  186 
  187     ps.next(0.0);
  188     TEST_EQUAL(ps.at_end(), false);
  189     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  190 
  191     ps.next(0.0);
  192     TEST_EQUAL(ps.at_end(), false);
  193     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  194     TEST_EQUAL(ps.get_docid(), 2);
  195 
  196     ps.next(0.0);
  197     TEST_EQUAL(ps.at_end(), true);
  198     }
  199 
  200     // Test a search with a looser range restriction, but not enough to return
  201     // the next document and implicit metric.
  202     {
  203     Xapian::LatLongDistancePostingSource ps(0, centre, coorddist * 1.5);
  204     ps.init(db);
  205 
  206     ps.next(0.0);
  207     TEST_EQUAL(ps.at_end(), false);
  208     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  209 
  210     ps.next(0.0);
  211     TEST_EQUAL(ps.at_end(), false);
  212     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  213     TEST_EQUAL(ps.get_docid(), 2);
  214 
  215     ps.next(0.0);
  216     TEST_EQUAL(ps.at_end(), true);
  217     }
  218 
  219     // Test a search with a loose enough range restriction that all docs should
  220     // be returned.
  221     {
  222     Xapian::LatLongDistancePostingSource ps(0, centre, metric, coorddist * 2.5);
  223     ps.init(db);
  224 
  225     ps.next(0.0);
  226     TEST_EQUAL(ps.at_end(), false);
  227     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  228 
  229     ps.next(0.0);
  230     TEST_EQUAL(ps.at_end(), false);
  231     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  232     TEST_EQUAL(ps.get_docid(), 2);
  233 
  234     ps.next(0.0);
  235     TEST_EQUAL(ps.at_end(), false);
  236     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist * 2));
  237     TEST_EQUAL(ps.get_docid(), 3);
  238 
  239     ps.next(0.0);
  240     TEST_EQUAL(ps.at_end(), true);
  241     }
  242 
  243     // Test a search with a loose enough range restriction that all docs should
  244     // be returned and implicit metric.
  245     {
  246     Xapian::LatLongDistancePostingSource ps(0, centre, coorddist * 2.5);
  247     ps.init(db);
  248 
  249     ps.next(0.0);
  250     TEST_EQUAL(ps.at_end(), false);
  251     TEST_EQUAL_DOUBLE(ps.get_weight(), 1.0);
  252 
  253     ps.next(0.0);
  254     TEST_EQUAL(ps.at_end(), false);
  255     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist));
  256     TEST_EQUAL(ps.get_docid(), 2);
  257 
  258     ps.next(0.0);
  259     TEST_EQUAL(ps.at_end(), false);
  260     TEST_EQUAL_DOUBLE(ps.get_weight(), 1000.0 / (1000.0 + coorddist * 2));
  261     TEST_EQUAL(ps.get_docid(), 3);
  262 
  263     ps.next(0.0);
  264     TEST_EQUAL(ps.at_end(), true);
  265     }
  266 
  267     return true;
  268 }
  269 
  270 // Test various methods of LatLongCoord and LatLongCoords
  271 DEFINE_TESTCASE(latlongcoords1, !backend) {
  272     LatLongCoord c1(0, 0);
  273     LatLongCoord c2(1, 0);
  274     LatLongCoord c3(1, 0);
  275     LatLongCoord c4(0, 1);
  276 
  277     // Test comparison
  278     TEST_NOT_EQUAL(c1.get_description(), c2.get_description());
  279     // Exactly one of these inequalities should be true.
  280     TEST((c1 < c2) ^ (c2 < c1));
  281     TEST_EQUAL(c2.get_description(), c3.get_description());
  282     TEST(!(c2 < c3) && !(c3 < c2));
  283     TEST_NOT_EQUAL(c3.get_description(), c4.get_description());
  284     // Exactly one of these inequalities should be true.  This is a regression
  285     // test for bug found prior to 1.3.0.
  286     TEST((c3 < c4) ^ (c4 < c3));
  287 
  288     // Test serialisation
  289     std::string s1 = c1.serialise();
  290     LatLongCoord c5;
  291     c4.unserialise(s1);
  292     TEST(!(c1 < c4 || c4 < c1));
  293     const char * ptr = s1.data();
  294     const char * end = ptr + s1.size();
  295     c5.unserialise(&ptr, end);
  296     TEST_EQUAL(c1.get_description(), c4.get_description());
  297     TEST_EQUAL(c1.get_description(), "Xapian::LatLongCoord(0, 0)");
  298     TEST_EQUAL(ptr, end);
  299 
  300     // Test uninitialised iterator constructor
  301     LatLongCoordsIterator i1;
  302 
  303     // Test building a set of LatLongCoords
  304     LatLongCoords g1(c1);
  305     TEST(!g1.empty());
  306     TEST_EQUAL(g1.size(), 1);
  307     TEST_EQUAL(g1.get_description(), "Xapian::LatLongCoords((0, 0))");
  308     g1.append(c2);
  309     TEST_EQUAL(g1.size(), 2);
  310     TEST_EQUAL(g1.get_description(), "Xapian::LatLongCoords((0, 0), (1, 0))");
  311 
  312     // Test iterating through a set of LatLongCoords
  313     i1 = g1.begin();
  314     TEST(i1 != g1.end());
  315     TEST_EQUAL((*i1).serialise(), c1.serialise());
  316     TEST_EQUAL((*i1).serialise(), c1.serialise());
  317     ++i1;
  318     TEST(i1 != g1.end());
  319     TEST_EQUAL((*i1).serialise(), c2.serialise());
  320     i1 = g1.begin();
  321     ++i1;
  322     TEST_EQUAL((*i1).serialise(), c2.serialise());
  323     TEST(i1 != g1.end());
  324     ++i1;
  325     TEST(i1 == g1.end());
  326 
  327     // Test that duplicates are allowed in the list of coordinates, now.
  328     g1.append(c3);
  329     TEST_EQUAL(g1.size(), 3);
  330     TEST_EQUAL(g1.get_description(), "Xapian::LatLongCoords((0, 0), (1, 0), (1, 0))");
  331 
  332     // Test building an empty LatLongCoords
  333     LatLongCoords g2;
  334     TEST(g2.empty());
  335     TEST_EQUAL(g2.size(), 0);
  336     TEST_EQUAL(g2.get_description(), "Xapian::LatLongCoords()");
  337     TEST(g2.begin() == g2.end());
  338 
  339     return true;
  340 }
  341 
  342 // Test various methods of LatLongMetric
  343 DEFINE_TESTCASE(latlongmetric1, !backend) {
  344     LatLongCoord c1(0, 0);
  345     LatLongCoord c2(1, 0);
  346     Xapian::GreatCircleMetric m1;
  347     double d1 = m1(c1, c2);
  348     TEST_REL(d1, >, 111226.0);
  349     TEST_REL(d1, <, 111227.0);
  350 
  351     // Let's make another metric, this time using the radius of mars, so
  352     // distances should be quite a bit smaller.
  353     Xapian::GreatCircleMetric m2(3310000);
  354     double d2 = m2(c1, c2);
  355     TEST_REL(d2, >, 57770.0);
  356     TEST_REL(d2, <, 57771.0);
  357 
  358     // Check serialise and unserialise.
  359     Xapian::Registry registry;
  360     std::string s1 = m2.serialise();
  361     const Xapian::LatLongMetric * m3;
  362     m3 = registry.get_lat_long_metric(m2.name());
  363     TEST(m3 != NULL);
  364     m3 = m3->unserialise(s1);
  365     double d3 = (*m3)(c1, c2);
  366     TEST_EQUAL_DOUBLE(d2, d3);
  367 
  368     delete m3;
  369 
  370     return true;
  371 }
  372 
  373 // Test LatLongMetric on lists of coords.
  374 DEFINE_TESTCASE(latlongmetric2, !backend) {
  375     LatLongCoord c1(0, 0);
  376     LatLongCoord c2(1, 0);
  377     LatLongCoords cl1(c1);
  378     LatLongCoords cl2(c2);
  379     string c2_str = c2.serialise();
  380     string cl2_str = cl2.serialise();
  381     TEST_EQUAL(c2_str, cl2_str);
  382 
  383     LatLongCoord c2_check(5, 5);
  384     c2_check.unserialise(c2_str);
  385     TEST_EQUAL(c2_check.latitude, c2.latitude);
  386     TEST_EQUAL(c2_check.longitude, c2.longitude);
  387 
  388     Xapian::GreatCircleMetric m1;
  389     double d1 = m1(c1, c2);
  390     double dl1 = m1(cl1, cl2);
  391     TEST_EQUAL(d1, dl1);
  392     double d1_str = m1(cl1, c2_str);
  393     TEST_EQUAL(d1, d1_str);
  394 
  395     return true;
  396 }
  397 
  398 // Test a LatLongDistanceKeyMaker directly.
  399 DEFINE_TESTCASE(latlongkeymaker1, !backend) {
  400     Xapian::GreatCircleMetric m1(3310000);
  401     LatLongCoord c1(0, 0);
  402     LatLongCoord c2(1, 0);
  403     LatLongCoord c3(2, 0);
  404     LatLongCoord c4(3, 0);
  405 
  406     LatLongCoords g1(c1);
  407     g1.append(c2);
  408 
  409     LatLongDistanceKeyMaker keymaker(0, g1, m1);
  410     Xapian::Document doc1;
  411     doc1.add_value(0, g1.serialise());
  412     Xapian::Document doc2;
  413     doc2.add_value(0, c3.serialise());
  414     Xapian::Document doc3;
  415     doc3.add_value(0, c4.serialise());
  416     Xapian::Document doc4;
  417 
  418     std::string k1 = keymaker(doc1);
  419     std::string k2 = keymaker(doc2);
  420     std::string k3 = keymaker(doc3);
  421     std::string k4 = keymaker(doc4);
  422     TEST_REL(k1, <, k2);
  423     TEST_REL(k2, <, k3);
  424     TEST_REL(k3, <, k4);
  425 
  426     LatLongDistanceKeyMaker keymaker2(0, g1, m1, 0);
  427     std::string k3b = keymaker2(doc3);
  428     std::string k4b = keymaker2(doc4);
  429     TEST_EQUAL(k3, k3b);
  430     TEST_REL(k3b, >, k4b);
  431 
  432     return true;
  433 }