]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
11fdf7f2 TL |
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). | |
7c673cae FG |
5 | // |
6 | #ifndef ROCKSDB_LITE | |
7 | #include "utilities/geodb/geodb_impl.h" | |
8 | ||
9 | #include <cctype> | |
10 | #include "util/testharness.h" | |
11 | ||
12 | namespace rocksdb { | |
13 | ||
14 | class GeoDBTest : public testing::Test { | |
15 | public: | |
16 | static const std::string kDefaultDbName; | |
17 | static Options options; | |
18 | DB* db; | |
19 | GeoDB* geodb; | |
20 | ||
21 | GeoDBTest() { | |
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); | |
27 | } | |
28 | ||
29 | ~GeoDBTest() { | |
30 | delete geodb; | |
31 | } | |
32 | ||
33 | GeoDB* getdb() { | |
34 | return geodb; | |
35 | } | |
36 | }; | |
37 | ||
11fdf7f2 TL |
38 | const std::string GeoDBTest::kDefaultDbName = |
39 | test::PerThreadDBPath("geodb_test"); | |
7c673cae FG |
40 | Options GeoDBTest::options = Options(); |
41 | ||
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"); | |
47 | ||
48 | // insert first object into database | |
49 | GeoObject obj1(pos1, id1, value1); | |
50 | Status status = getdb()->Insert(obj1); | |
51 | ASSERT_TRUE(status.ok()); | |
52 | ||
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()); | |
60 | ||
61 | // retrieve first object using position | |
62 | std::string value; | |
63 | status = getdb()->GetByPosition(pos1, Slice(id1), &value); | |
64 | ASSERT_TRUE(status.ok()); | |
65 | ASSERT_EQ(value, value1); | |
66 | ||
67 | // retrieve first object using id | |
68 | GeoObject obj; | |
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); | |
75 | ||
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()); | |
83 | ||
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()); | |
90 | } | |
91 | ||
92 | // Search. | |
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"; | |
98 | ||
99 | // insert object at 45 degree latitude | |
100 | GeoObject obj1(pos1, id1, value1); | |
101 | Status status = getdb()->Insert(obj1); | |
102 | ASSERT_TRUE(status.ok()); | |
103 | ||
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"); | |
110 | uint32_t size = 0; | |
111 | while (iter1->Valid()) { | |
11fdf7f2 TL |
112 | GeoObject obj; |
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); | |
119 | ||
7c673cae FG |
120 | size++; |
121 | iter1->Next(); | |
11fdf7f2 | 122 | ASSERT_TRUE(!iter1->Valid()); |
7c673cae FG |
123 | } |
124 | ASSERT_EQ(size, 1U); | |
125 | delete iter1; | |
126 | ||
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()); | |
132 | delete iter2; | |
133 | } | |
134 | ||
11fdf7f2 TL |
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"); | |
140 | ||
141 | GeoObject obj1(pos1, id1, value1); | |
142 | Status status = getdb()->Insert(obj1); | |
143 | ASSERT_TRUE(status.ok()); | |
144 | ||
145 | // insert obj2 into database | |
146 | GeoPosition pos2(40.00002, 116.00002); | |
147 | std::string id2("123"); | |
148 | std::string value2 = "value2"; | |
149 | ||
150 | GeoObject obj2(pos2, id2, value2); | |
151 | status = getdb()->Insert(obj2); | |
152 | ASSERT_TRUE(status.ok()); | |
153 | ||
154 | // get obj1's quadkey | |
155 | ReadOptions opt; | |
156 | PinnableSlice quadkey1; | |
157 | status = getdb()->Get(opt, getdb()->DefaultColumnFamily(), "k:" + id1, &quadkey1); | |
158 | ASSERT_TRUE(status.ok()); | |
159 | ||
160 | // get obj2's quadkey | |
161 | PinnableSlice quadkey2; | |
162 | status = getdb()->Get(opt, getdb()->DefaultColumnFamily(), "k:" + id2, &quadkey2); | |
163 | ASSERT_TRUE(status.ok()); | |
164 | ||
165 | // obj1 and obj2 have the same quadkey | |
166 | ASSERT_EQ(quadkey1, quadkey2); | |
167 | ||
168 | // get obj1 by id, and check value | |
169 | GeoObject obj; | |
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); | |
176 | ||
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); | |
184 | } | |
185 | ||
7c673cae FG |
186 | } // namespace rocksdb |
187 | ||
188 | int main(int argc, char* argv[]) { | |
189 | ::testing::InitGoogleTest(&argc, argv); | |
190 | return RUN_ALL_TESTS(); | |
191 | } | |
192 | #else | |
193 | ||
194 | #include <stdio.h> | |
195 | ||
196 | int main() { | |
197 | fprintf(stderr, "SKIPPED\n"); | |
198 | return 0; | |
199 | } | |
200 | ||
201 | #endif // !ROCKSDB_LITE |