1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
7 #include "utilities/geodb/geodb_impl.h"
10 #include "util/testharness.h"
14 class GeoDBTest
: public testing::Test
{
16 static const std::string kDefaultDbName
;
17 static Options options
;
22 GeoDBOptions geodb_options
;
23 EXPECT_OK(DestroyDB(kDefaultDbName
, options
));
24 options
.create_if_missing
= true;
25 Status status
= DB::Open(options
, kDefaultDbName
, &db
);
26 geodb
= new GeoDBImpl(db
, geodb_options
);
38 const std::string
GeoDBTest::kDefaultDbName
=
39 test::PerThreadDBPath("geodb_test");
40 Options
GeoDBTest::options
= Options();
42 // Insert, Get and Remove
43 TEST_F(GeoDBTest
, SimpleTest
) {
44 GeoPosition
pos1(100, 101);
45 std::string
id1("id1");
46 std::string
value1("value1");
48 // insert first object into database
49 GeoObject
obj1(pos1
, id1
, value1
);
50 Status status
= getdb()->Insert(obj1
);
51 ASSERT_TRUE(status
.ok());
53 // insert second object into database
54 GeoPosition
pos2(200, 201);
55 std::string
id2("id2");
56 std::string value2
= "value2";
57 GeoObject
obj2(pos2
, id2
, value2
);
58 status
= getdb()->Insert(obj2
);
59 ASSERT_TRUE(status
.ok());
61 // retrieve first object using position
63 status
= getdb()->GetByPosition(pos1
, Slice(id1
), &value
);
64 ASSERT_TRUE(status
.ok());
65 ASSERT_EQ(value
, value1
);
67 // retrieve first object using id
69 status
= getdb()->GetById(Slice(id1
), &obj
);
70 ASSERT_TRUE(status
.ok());
71 ASSERT_EQ(obj
.position
.latitude
, 100);
72 ASSERT_EQ(obj
.position
.longitude
, 101);
73 ASSERT_EQ(obj
.id
.compare(id1
), 0);
74 ASSERT_EQ(obj
.value
, value1
);
76 // delete first object
77 status
= getdb()->Remove(Slice(id1
));
78 ASSERT_TRUE(status
.ok());
79 status
= getdb()->GetByPosition(pos1
, Slice(id1
), &value
);
80 ASSERT_TRUE(status
.IsNotFound());
81 status
= getdb()->GetById(id1
, &obj
);
82 ASSERT_TRUE(status
.IsNotFound());
84 // check that we can still find second object
85 status
= getdb()->GetByPosition(pos2
, id2
, &value
);
86 ASSERT_TRUE(status
.ok());
87 ASSERT_EQ(value
, value2
);
88 status
= getdb()->GetById(id2
, &obj
);
89 ASSERT_TRUE(status
.ok());
93 // Verify distances via http://www.stevemorse.org/nearest/distance.php
94 TEST_F(GeoDBTest
, Search
) {
95 GeoPosition
pos1(45, 45);
96 std::string
id1("mid1");
97 std::string value1
= "midvalue1";
99 // insert object at 45 degree latitude
100 GeoObject
obj1(pos1
, id1
, value1
);
101 Status status
= getdb()->Insert(obj1
);
102 ASSERT_TRUE(status
.ok());
104 // search all objects centered at 46 degree latitude with
105 // a radius of 200 kilometers. We should find the one object that
106 // we inserted earlier.
107 GeoIterator
* iter1
= getdb()->SearchRadial(GeoPosition(46, 46), 200000);
108 ASSERT_TRUE(status
.ok());
109 ASSERT_EQ(iter1
->geo_object().value
, "midvalue1");
111 while (iter1
->Valid()) {
113 status
= getdb()->GetById(Slice(id1
), &obj
);
114 ASSERT_TRUE(status
.ok());
115 ASSERT_EQ(iter1
->geo_object().position
.latitude
, pos1
.latitude
);
116 ASSERT_EQ(iter1
->geo_object().position
.longitude
, pos1
.longitude
);
117 ASSERT_EQ(iter1
->geo_object().id
.compare(id1
), 0);
118 ASSERT_EQ(iter1
->geo_object().value
, value1
);
122 ASSERT_TRUE(!iter1
->Valid());
127 // search all objects centered at 46 degree latitude with
128 // a radius of 2 kilometers. There should be none.
129 GeoIterator
* iter2
= getdb()->SearchRadial(GeoPosition(46, 46), 2);
130 ASSERT_TRUE(status
.ok());
131 ASSERT_FALSE(iter2
->Valid());
135 TEST_F(GeoDBTest
, DifferentPosInSameQuadkey
) {
136 // insert obj1 into database
137 GeoPosition
pos1(40.00001, 116.00001);
138 std::string
id1("12");
139 std::string
value1("value1");
141 GeoObject
obj1(pos1
, id1
, value1
);
142 Status status
= getdb()->Insert(obj1
);
143 ASSERT_TRUE(status
.ok());
145 // insert obj2 into database
146 GeoPosition
pos2(40.00002, 116.00002);
147 std::string
id2("123");
148 std::string value2
= "value2";
150 GeoObject
obj2(pos2
, id2
, value2
);
151 status
= getdb()->Insert(obj2
);
152 ASSERT_TRUE(status
.ok());
154 // get obj1's quadkey
156 PinnableSlice quadkey1
;
157 status
= getdb()->Get(opt
, getdb()->DefaultColumnFamily(), "k:" + id1
, &quadkey1
);
158 ASSERT_TRUE(status
.ok());
160 // get obj2's quadkey
161 PinnableSlice quadkey2
;
162 status
= getdb()->Get(opt
, getdb()->DefaultColumnFamily(), "k:" + id2
, &quadkey2
);
163 ASSERT_TRUE(status
.ok());
165 // obj1 and obj2 have the same quadkey
166 ASSERT_EQ(quadkey1
, quadkey2
);
168 // get obj1 by id, and check value
170 status
= getdb()->GetById(Slice(id1
), &obj
);
171 ASSERT_TRUE(status
.ok());
172 ASSERT_EQ(obj
.position
.latitude
, pos1
.latitude
);
173 ASSERT_EQ(obj
.position
.longitude
, pos1
.longitude
);
174 ASSERT_EQ(obj
.id
.compare(id1
), 0);
175 ASSERT_EQ(obj
.value
, value1
);
177 // get obj2 by id, and check value
178 status
= getdb()->GetById(Slice(id2
), &obj
);
179 ASSERT_TRUE(status
.ok());
180 ASSERT_EQ(obj
.position
.latitude
, pos2
.latitude
);
181 ASSERT_EQ(obj
.position
.longitude
, pos2
.longitude
);
182 ASSERT_EQ(obj
.id
.compare(id2
), 0);
183 ASSERT_EQ(obj
.value
, value2
);
186 } // namespace rocksdb
188 int main(int argc
, char* argv
[]) {
189 ::testing::InitGoogleTest(&argc
, argv
);
190 return RUN_ALL_TESTS();
197 fprintf(stderr
, "SKIPPED\n");
201 #endif // !ROCKSDB_LITE