bw-geocoder 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +31 -0
  3. data/CHANGELOG.md +377 -0
  4. data/LICENSE +20 -0
  5. data/README.md +1041 -0
  6. data/Rakefile +25 -0
  7. data/bin/geocode +5 -0
  8. data/examples/autoexpire_cache_dalli.rb +62 -0
  9. data/examples/autoexpire_cache_redis.rb +28 -0
  10. data/examples/cache_bypass.rb +48 -0
  11. data/gemfiles/Gemfile.mongoid-2.4.x +16 -0
  12. data/lib/generators/geocoder/config/config_generator.rb +14 -0
  13. data/lib/generators/geocoder/config/templates/initializer.rb +21 -0
  14. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
  15. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -0
  16. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  17. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  18. data/lib/geocoder/cache.rb +90 -0
  19. data/lib/geocoder/calculations.rb +428 -0
  20. data/lib/geocoder/cli.rb +121 -0
  21. data/lib/geocoder/configuration.rb +124 -0
  22. data/lib/geocoder/configuration_hash.rb +11 -0
  23. data/lib/geocoder/exceptions.rb +21 -0
  24. data/lib/geocoder/ip_address.rb +21 -0
  25. data/lib/geocoder/lookup.rb +100 -0
  26. data/lib/geocoder/lookups/baidu.rb +55 -0
  27. data/lib/geocoder/lookups/baidu_ip.rb +54 -0
  28. data/lib/geocoder/lookups/base.rb +302 -0
  29. data/lib/geocoder/lookups/bing.rb +59 -0
  30. data/lib/geocoder/lookups/dstk.rb +20 -0
  31. data/lib/geocoder/lookups/esri.rb +48 -0
  32. data/lib/geocoder/lookups/freegeoip.rb +47 -0
  33. data/lib/geocoder/lookups/geocoder_ca.rb +54 -0
  34. data/lib/geocoder/lookups/geocoder_us.rb +39 -0
  35. data/lib/geocoder/lookups/geocodio.rb +42 -0
  36. data/lib/geocoder/lookups/google.rb +67 -0
  37. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  38. data/lib/geocoder/lookups/google_premier.rb +47 -0
  39. data/lib/geocoder/lookups/here.rb +62 -0
  40. data/lib/geocoder/lookups/ip_address_labs.rb +43 -0
  41. data/lib/geocoder/lookups/mapquest.rb +60 -0
  42. data/lib/geocoder/lookups/maxmind.rb +90 -0
  43. data/lib/geocoder/lookups/maxmind_local.rb +58 -0
  44. data/lib/geocoder/lookups/nominatim.rb +52 -0
  45. data/lib/geocoder/lookups/okf.rb +43 -0
  46. data/lib/geocoder/lookups/opencagedata.rb +58 -0
  47. data/lib/geocoder/lookups/ovi.rb +62 -0
  48. data/lib/geocoder/lookups/pointpin.rb +68 -0
  49. data/lib/geocoder/lookups/smarty_streets.rb +45 -0
  50. data/lib/geocoder/lookups/telize.rb +40 -0
  51. data/lib/geocoder/lookups/test.rb +44 -0
  52. data/lib/geocoder/lookups/yahoo.rb +88 -0
  53. data/lib/geocoder/lookups/yandex.rb +54 -0
  54. data/lib/geocoder/models/active_record.rb +50 -0
  55. data/lib/geocoder/models/base.rb +39 -0
  56. data/lib/geocoder/models/mongo_base.rb +64 -0
  57. data/lib/geocoder/models/mongo_mapper.rb +26 -0
  58. data/lib/geocoder/models/mongoid.rb +32 -0
  59. data/lib/geocoder/query.rb +111 -0
  60. data/lib/geocoder/railtie.rb +26 -0
  61. data/lib/geocoder/request.rb +25 -0
  62. data/lib/geocoder/results/baidu.rb +79 -0
  63. data/lib/geocoder/results/baidu_ip.rb +62 -0
  64. data/lib/geocoder/results/base.rb +67 -0
  65. data/lib/geocoder/results/bing.rb +48 -0
  66. data/lib/geocoder/results/dstk.rb +6 -0
  67. data/lib/geocoder/results/esri.rb +51 -0
  68. data/lib/geocoder/results/freegeoip.rb +45 -0
  69. data/lib/geocoder/results/geocoder_ca.rb +60 -0
  70. data/lib/geocoder/results/geocoder_us.rb +39 -0
  71. data/lib/geocoder/results/geocodio.rb +66 -0
  72. data/lib/geocoder/results/google.rb +124 -0
  73. data/lib/geocoder/results/google_places_details.rb +35 -0
  74. data/lib/geocoder/results/google_premier.rb +6 -0
  75. data/lib/geocoder/results/here.rb +62 -0
  76. data/lib/geocoder/results/ip_address_labs.rb +78 -0
  77. data/lib/geocoder/results/mapquest.rb +51 -0
  78. data/lib/geocoder/results/maxmind.rb +135 -0
  79. data/lib/geocoder/results/maxmind_local.rb +49 -0
  80. data/lib/geocoder/results/nominatim.rb +94 -0
  81. data/lib/geocoder/results/okf.rb +106 -0
  82. data/lib/geocoder/results/opencagedata.rb +82 -0
  83. data/lib/geocoder/results/ovi.rb +62 -0
  84. data/lib/geocoder/results/pointpin.rb +44 -0
  85. data/lib/geocoder/results/smarty_streets.rb +106 -0
  86. data/lib/geocoder/results/telize.rb +45 -0
  87. data/lib/geocoder/results/test.rb +33 -0
  88. data/lib/geocoder/results/yahoo.rb +55 -0
  89. data/lib/geocoder/results/yandex.rb +84 -0
  90. data/lib/geocoder/sql.rb +107 -0
  91. data/lib/geocoder/stores/active_record.rb +278 -0
  92. data/lib/geocoder/stores/base.rb +127 -0
  93. data/lib/geocoder/stores/mongo_base.rb +89 -0
  94. data/lib/geocoder/stores/mongo_mapper.rb +13 -0
  95. data/lib/geocoder/stores/mongoid.rb +13 -0
  96. data/lib/geocoder/version.rb +3 -0
  97. data/lib/geocoder.rb +47 -0
  98. data/lib/hash_recursive_merge.rb +74 -0
  99. data/lib/maxmind_database.rb +109 -0
  100. data/lib/oauth_util.rb +112 -0
  101. data/lib/tasks/geocoder.rake +29 -0
  102. data/lib/tasks/maxmind.rake +73 -0
  103. data/test/fixtures/baidu_invalid_key +1 -0
  104. data/test/fixtures/baidu_ip_202_198_16_3 +19 -0
  105. data/test/fixtures/baidu_ip_invalid_key +1 -0
  106. data/test/fixtures/baidu_ip_no_results +1 -0
  107. data/test/fixtures/baidu_no_results +1 -0
  108. data/test/fixtures/baidu_reverse +1 -0
  109. data/test/fixtures/baidu_shanghai_pearl_tower +12 -0
  110. data/test/fixtures/bing_invalid_key +1 -0
  111. data/test/fixtures/bing_madison_square_garden +40 -0
  112. data/test/fixtures/bing_no_results +16 -0
  113. data/test/fixtures/bing_reverse +42 -0
  114. data/test/fixtures/cloudmade_invalid_key +1 -0
  115. data/test/fixtures/cloudmade_madison_square_garden +1 -0
  116. data/test/fixtures/cloudmade_no_results +1 -0
  117. data/test/fixtures/esri_madison_square_garden +59 -0
  118. data/test/fixtures/esri_no_results +8 -0
  119. data/test/fixtures/esri_reverse +21 -0
  120. data/test/fixtures/freegeoip_74_200_247_59 +12 -0
  121. data/test/fixtures/freegeoip_no_results +1 -0
  122. data/test/fixtures/geocoder_ca_madison_square_garden +1 -0
  123. data/test/fixtures/geocoder_ca_no_results +1 -0
  124. data/test/fixtures/geocoder_ca_reverse +34 -0
  125. data/test/fixtures/geocoder_us_madison_square_garden +1 -0
  126. data/test/fixtures/geocoder_us_no_results +1 -0
  127. data/test/fixtures/geocodio_1101_pennsylvania_ave +1 -0
  128. data/test/fixtures/geocodio_bad_api_key +3 -0
  129. data/test/fixtures/geocodio_invalid +4 -0
  130. data/test/fixtures/geocodio_no_results +1 -0
  131. data/test/fixtures/geocodio_over_query_limit +4 -0
  132. data/test/fixtures/google_garbage +456 -0
  133. data/test/fixtures/google_madison_square_garden +57 -0
  134. data/test/fixtures/google_no_city_data +44 -0
  135. data/test/fixtures/google_no_locality +51 -0
  136. data/test/fixtures/google_no_results +4 -0
  137. data/test/fixtures/google_over_limit +4 -0
  138. data/test/fixtures/google_places_details_invalid_request +4 -0
  139. data/test/fixtures/google_places_details_madison_square_garden +120 -0
  140. data/test/fixtures/google_places_details_no_results +4 -0
  141. data/test/fixtures/google_places_details_no_reviews +60 -0
  142. data/test/fixtures/google_places_details_no_types +66 -0
  143. data/test/fixtures/here_madison_square_garden +72 -0
  144. data/test/fixtures/here_no_results +8 -0
  145. data/test/fixtures/mapquest_error +16 -0
  146. data/test/fixtures/mapquest_invalid_api_key +16 -0
  147. data/test/fixtures/mapquest_invalid_request +16 -0
  148. data/test/fixtures/mapquest_madison_square_garden +52 -0
  149. data/test/fixtures/mapquest_no_results +16 -0
  150. data/test/fixtures/maxmind_24_24_24_21 +1 -0
  151. data/test/fixtures/maxmind_24_24_24_22 +1 -0
  152. data/test/fixtures/maxmind_24_24_24_23 +1 -0
  153. data/test/fixtures/maxmind_24_24_24_24 +1 -0
  154. data/test/fixtures/maxmind_74_200_247_59 +1 -0
  155. data/test/fixtures/maxmind_invalid_key +1 -0
  156. data/test/fixtures/maxmind_no_results +1 -0
  157. data/test/fixtures/nominatim_madison_square_garden +150 -0
  158. data/test/fixtures/nominatim_no_results +1 -0
  159. data/test/fixtures/nominatim_over_limit +1 -0
  160. data/test/fixtures/okf_kirstinmaki +67 -0
  161. data/test/fixtures/okf_no_results +4 -0
  162. data/test/fixtures/opencagedata_invalid_api_key +25 -0
  163. data/test/fixtures/opencagedata_invalid_request +26 -0
  164. data/test/fixtures/opencagedata_madison_square_garden +73 -0
  165. data/test/fixtures/opencagedata_no_results +29 -0
  166. data/test/fixtures/opencagedata_over_limit +31 -0
  167. data/test/fixtures/ovi_madison_square_garden +72 -0
  168. data/test/fixtures/ovi_no_results +8 -0
  169. data/test/fixtures/pointpin_10_10_10_10 +1 -0
  170. data/test/fixtures/pointpin_555_555_555_555 +1 -0
  171. data/test/fixtures/pointpin_80_111_555_555 +1 -0
  172. data/test/fixtures/pointpin_no_results +1 -0
  173. data/test/fixtures/smarty_streets_11211 +1 -0
  174. data/test/fixtures/smarty_streets_madison_square_garden +47 -0
  175. data/test/fixtures/smarty_streets_no_results +1 -0
  176. data/test/fixtures/telize_10_10_10_10 +1 -0
  177. data/test/fixtures/telize_555_555_555_555 +4 -0
  178. data/test/fixtures/telize_74_200_247_59 +1 -0
  179. data/test/fixtures/telize_no_results +1 -0
  180. data/test/fixtures/yahoo_error +1 -0
  181. data/test/fixtures/yahoo_invalid_key +2 -0
  182. data/test/fixtures/yahoo_madison_square_garden +52 -0
  183. data/test/fixtures/yahoo_no_results +10 -0
  184. data/test/fixtures/yahoo_over_limit +2 -0
  185. data/test/fixtures/yandex_canada_rue_dupuis_14 +446 -0
  186. data/test/fixtures/yandex_invalid_key +1 -0
  187. data/test/fixtures/yandex_kremlin +48 -0
  188. data/test/fixtures/yandex_new_york +1 -0
  189. data/test/fixtures/yandex_no_city_and_town +112 -0
  190. data/test/fixtures/yandex_no_results +16 -0
  191. data/test/integration/http_client_test.rb +31 -0
  192. data/test/mongoid_test_helper.rb +43 -0
  193. data/test/test_helper.rb +386 -0
  194. data/test/unit/active_record_test.rb +16 -0
  195. data/test/unit/cache_test.rb +37 -0
  196. data/test/unit/calculations_test.rb +220 -0
  197. data/test/unit/configuration_test.rb +55 -0
  198. data/test/unit/error_handling_test.rb +56 -0
  199. data/test/unit/geocoder_test.rb +78 -0
  200. data/test/unit/https_test.rb +17 -0
  201. data/test/unit/ip_address_test.rb +27 -0
  202. data/test/unit/lookup_test.rb +153 -0
  203. data/test/unit/lookups/bing_test.rb +68 -0
  204. data/test/unit/lookups/dstk_test.rb +26 -0
  205. data/test/unit/lookups/esri_test.rb +48 -0
  206. data/test/unit/lookups/freegeoip_test.rb +27 -0
  207. data/test/unit/lookups/geocoder_ca_test.rb +17 -0
  208. data/test/unit/lookups/geocodio_test.rb +55 -0
  209. data/test/unit/lookups/google_places_details_test.rb +122 -0
  210. data/test/unit/lookups/google_premier_test.rb +22 -0
  211. data/test/unit/lookups/google_test.rb +84 -0
  212. data/test/unit/lookups/mapquest_test.rb +60 -0
  213. data/test/unit/lookups/maxmind_local_test.rb +28 -0
  214. data/test/unit/lookups/maxmind_test.rb +63 -0
  215. data/test/unit/lookups/nominatim_test.rb +31 -0
  216. data/test/unit/lookups/okf_test.rb +38 -0
  217. data/test/unit/lookups/opencagedata_test.rb +64 -0
  218. data/test/unit/lookups/pointpin_test.rb +30 -0
  219. data/test/unit/lookups/smarty_streets_test.rb +71 -0
  220. data/test/unit/lookups/telize_test.rb +36 -0
  221. data/test/unit/lookups/yahoo_test.rb +35 -0
  222. data/test/unit/method_aliases_test.rb +26 -0
  223. data/test/unit/model_test.rb +38 -0
  224. data/test/unit/mongoid_test.rb +47 -0
  225. data/test/unit/near_test.rb +87 -0
  226. data/test/unit/oauth_util_test.rb +31 -0
  227. data/test/unit/proxy_test.rb +37 -0
  228. data/test/unit/query_test.rb +52 -0
  229. data/test/unit/rake_task_test.rb +21 -0
  230. data/test/unit/request_test.rb +35 -0
  231. data/test/unit/result_test.rb +72 -0
  232. data/test/unit/test_mode_test.rb +70 -0
  233. metadata +281 -0
@@ -0,0 +1,220 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class CalculationsTest < GeocoderTestCase
6
+ def setup
7
+ Geocoder.configure(
8
+ :units => :mi,
9
+ :distances => :linear
10
+ )
11
+ end
12
+
13
+ # --- degree distance ---
14
+
15
+ def test_longitude_degree_distance_at_equator
16
+ assert_equal 69, Geocoder::Calculations.longitude_degree_distance(0).round
17
+ end
18
+
19
+ def test_longitude_degree_distance_at_new_york
20
+ assert_equal 53, Geocoder::Calculations.longitude_degree_distance(40).round
21
+ end
22
+
23
+ def test_longitude_degree_distance_at_north_pole
24
+ assert_equal 0, Geocoder::Calculations.longitude_degree_distance(89.98).round
25
+ end
26
+
27
+
28
+ # --- distance between ---
29
+
30
+ def test_distance_between_in_miles
31
+ assert_equal 69, Geocoder::Calculations.distance_between([0,0], [0,1]).round
32
+ la_to_ny = Geocoder::Calculations.distance_between([34.05,-118.25], [40.72,-74]).round
33
+ assert (la_to_ny - 2444).abs < 10
34
+ end
35
+
36
+ def test_distance_between_in_kilometers
37
+ assert_equal 111, Geocoder::Calculations.distance_between([0,0], [0,1], :units => :km).round
38
+ la_to_ny = Geocoder::Calculations.distance_between([34.05,-118.25], [40.72,-74], :units => :km).round
39
+ assert (la_to_ny - 3942).abs < 10
40
+ end
41
+
42
+ def test_distance_between_in_nautical_miles
43
+ assert_equal 60, Geocoder::Calculations.distance_between([0,0], [0,1], :units => :nm).round
44
+ la_to_ny = Geocoder::Calculations.distance_between([34.05,-118.25], [40.72,-74], :units => :nm).round
45
+ assert (la_to_ny - 2124).abs < 10
46
+ end
47
+
48
+
49
+ # --- geographic center ---
50
+
51
+ def test_geographic_center_with_arrays
52
+ assert_equal [0.0, 0.5],
53
+ Geocoder::Calculations.geographic_center([[0,0], [0,1]])
54
+ assert_equal [0.0, 1.0],
55
+ Geocoder::Calculations.geographic_center([[0,0], [0,1], [0,2]])
56
+ end
57
+
58
+ def test_geographic_center_with_mixed_arguments
59
+ p1 = [0, 0]
60
+ p2 = PlaceReverseGeocoded.new("Some Cold Place", 0, 1)
61
+ assert_equal [0.0, 0.5], Geocoder::Calculations.geographic_center([p1, p2])
62
+ end
63
+
64
+
65
+ # --- bounding box ---
66
+
67
+ def test_bounding_box_calculation_in_miles
68
+ center = [51, 7] # Cologne, DE
69
+ radius = 10 # miles
70
+ corners = [50.86, 6.77, 51.14, 7.23]
71
+ assert_equal corners.map{ |i| (i * 100).round },
72
+ Geocoder::Calculations.bounding_box(center, radius).map{ |i| (i * 100).round }
73
+ end
74
+
75
+ def test_bounding_box_calculation_in_kilometers
76
+ center = [51, 7] # Cologne, DE
77
+ radius = 111 # kilometers (= 1 degree latitude)
78
+ corners = [50, 5.41, 52, 8.59]
79
+ assert_equal corners.map{ |i| (i * 100).round },
80
+ Geocoder::Calculations.bounding_box(center, radius, :units => :km).map{ |i| (i * 100).round }
81
+ end
82
+
83
+ def test_bounding_box_calculation_with_object
84
+ center = [51, 7] # Cologne, DE
85
+ radius = 10 # miles
86
+ corners = [50.86, 6.77, 51.14, 7.23]
87
+ obj = PlaceReverseGeocoded.new("Cologne", center[0], center[1])
88
+ assert_equal corners.map{ |i| (i * 100).round },
89
+ Geocoder::Calculations.bounding_box(obj, radius).map{ |i| (i * 100).round }
90
+ end
91
+
92
+ def test_bounding_box_calculation_with_address_string
93
+ assert_nothing_raised do
94
+ Geocoder::Calculations.bounding_box("4893 Clay St, San Francisco, CA", 50)
95
+ end
96
+ end
97
+
98
+ # --- random point ---
99
+
100
+ def test_random_point_within_radius
101
+ 20.times do
102
+ center = [51, 7] # Cologne, DE
103
+ radius = 10 # miles
104
+ random_point = Geocoder::Calculations.random_point_near(center, radius)
105
+ distance = Geocoder::Calculations.distance_between(center, random_point)
106
+ assert distance <= radius
107
+ end
108
+ end
109
+
110
+ # --- bearing ---
111
+
112
+ def test_compass_points
113
+ assert_equal "N", Geocoder::Calculations.compass_point(0)
114
+ assert_equal "N", Geocoder::Calculations.compass_point(1.0)
115
+ assert_equal "N", Geocoder::Calculations.compass_point(360)
116
+ assert_equal "N", Geocoder::Calculations.compass_point(361)
117
+ assert_equal "N", Geocoder::Calculations.compass_point(-22)
118
+ assert_equal "NW", Geocoder::Calculations.compass_point(-23)
119
+ assert_equal "S", Geocoder::Calculations.compass_point(180)
120
+ assert_equal "S", Geocoder::Calculations.compass_point(181)
121
+ end
122
+
123
+ def test_bearing_between
124
+ bearings = {
125
+ :n => 0,
126
+ :e => 90,
127
+ :s => 180,
128
+ :w => 270
129
+ }
130
+ points = {
131
+ :n => [41, -75],
132
+ :e => [40, -74],
133
+ :s => [39, -75],
134
+ :w => [40, -76]
135
+ }
136
+ directions = [:n, :e, :s, :w]
137
+ methods = [:linear, :spherical]
138
+
139
+ methods.each do |m|
140
+ directions.each_with_index do |d,i|
141
+ opp = directions[(i + 2) % 4] # opposite direction
142
+ b = Geocoder::Calculations.bearing_between(
143
+ points[d], points[opp], :method => m)
144
+ assert (b - bearings[opp]).abs < 1,
145
+ "Bearing (#{m}) should be close to #{bearings[opp]} but was #{b}."
146
+ end
147
+ end
148
+ end
149
+
150
+ def test_spherical_bearing_to
151
+ l = PlaceReverseGeocoded.new(*reverse_geocoded_object_params(:msg))
152
+ assert_equal 324, l.bearing_to([50,-85], :method => :spherical).round
153
+ end
154
+
155
+ def test_spherical_bearing_from
156
+ l = PlaceReverseGeocoded.new(*reverse_geocoded_object_params(:msg))
157
+ assert_equal 136, l.bearing_from([50,-85], :method => :spherical).round
158
+ end
159
+
160
+ def test_linear_bearing_from_and_to_are_exactly_opposite
161
+ l = PlaceReverseGeocoded.new(*reverse_geocoded_object_params(:msg))
162
+ assert_equal l.bearing_from([50,-86.1]), l.bearing_to([50,-86.1]) - 180
163
+ end
164
+
165
+ def test_extract_coordinates
166
+ coords = [-23,47]
167
+ l = PlaceReverseGeocoded.new("Madagascar", coords[0], coords[1])
168
+ assert_equal coords, Geocoder::Calculations.extract_coordinates(l)
169
+ assert_equal coords, Geocoder::Calculations.extract_coordinates(coords)
170
+ end
171
+
172
+ def test_extract_nan_coordinates
173
+ result = Geocoder::Calculations.extract_coordinates([ nil, nil ])
174
+ assert_nan_coordinates?(result)
175
+
176
+ result = Geocoder::Calculations.extract_coordinates(nil)
177
+ assert_nan_coordinates?(result)
178
+
179
+ result = Geocoder::Calculations.extract_coordinates('')
180
+ assert_nan_coordinates?(result)
181
+
182
+ result = Geocoder::Calculations.extract_coordinates([ 'nix' ])
183
+ assert_nan_coordinates?(result)
184
+
185
+ o = Object.new
186
+ result = Geocoder::Calculations.extract_coordinates(o)
187
+ assert_nan_coordinates?(result)
188
+ end
189
+
190
+ def test_coordinates_present
191
+ assert Geocoder::Calculations.coordinates_present?(3.23)
192
+ assert !Geocoder::Calculations.coordinates_present?(nil)
193
+ assert !Geocoder::Calculations.coordinates_present?(Geocoder::Calculations::NAN)
194
+ assert !Geocoder::Calculations.coordinates_present?(3.23, nil)
195
+ end
196
+
197
+ private # ------------------------------------------------------------------
198
+
199
+ def assert_nan_coordinates?(value)
200
+ assert value.is_a?(Array) &&
201
+ value.size == 2 &&
202
+ value[0].nan? &&
203
+ value[1].nan?,
204
+ "Expected value to be [NaN, NaN] but was #{value}"
205
+ end
206
+
207
+ def test_endpoint
208
+ # test 5 time with random coordinates and headings
209
+ [0..5].each do |i|
210
+ rheading = [*0..359].sample
211
+ rdistance = [*0..100].sample
212
+ startpoint = [45.0906, 7.6596]
213
+ endpoint = Geocoder::Calculations.endpoint(startpoint, rheading, rdistance)
214
+ assert_in_delta rdistance,
215
+ Geocoder::Calculations.distance_between(startpoint, endpoint, :method => :spherical), 1E-5
216
+ assert_in_delta rheading,
217
+ Geocoder::Calculations.bearing_between(startpoint, endpoint, :method => :spherical), 1E-2
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class ConfigurationTest < GeocoderTestCase
6
+ def setup
7
+ Geocoder::Configuration.set_defaults
8
+ end
9
+
10
+ def test_exception_raised_on_bad_lookup_config
11
+ Geocoder.configure(:lookup => :stoopid)
12
+ assert_raises Geocoder::ConfigurationError do
13
+ Geocoder.search "something dumb"
14
+ end
15
+ end
16
+
17
+ def test_setting_with_class_method
18
+ Geocoder::Configuration.units = :test
19
+ assert_equal :test, Geocoder.config.units
20
+ end
21
+
22
+ def test_setting_with_configure_method
23
+ Geocoder.configure(:units => :test)
24
+ assert_equal :test, Geocoder.config.units
25
+ end
26
+
27
+ def test_config_for_lookup
28
+ Geocoder.configure(
29
+ :timeout => 5,
30
+ :api_key => "aaa",
31
+ :google => {
32
+ :timeout => 2
33
+ }
34
+ )
35
+ assert_equal 2, Geocoder.config_for_lookup(:google).timeout
36
+ assert_equal "aaa", Geocoder.config_for_lookup(:google).api_key
37
+ end
38
+
39
+ def test_configuration_chain
40
+ v = PlaceReverseGeocoded.new(*reverse_geocoded_object_params(:msg))
41
+ v.latitude = 0
42
+ v.longitude = 0
43
+
44
+ # method option > global configuration
45
+ Geocoder.configure(:units => :km)
46
+ assert_equal 69, v.distance_to([0,1], :mi).round
47
+
48
+ # per-model configuration > global configuration
49
+ PlaceReverseGeocoded.reverse_geocoded_by :latitude, :longitude, method: :spherical, units: :mi
50
+ assert_equal 69, v.distance_to([0,1]).round
51
+
52
+ # method option > per-model configuration
53
+ assert_equal 111, v.distance_to([0,1], :km).round
54
+ end
55
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class ErrorHandlingTest < GeocoderTestCase
6
+
7
+ def teardown
8
+ Geocoder.configure(:always_raise => [])
9
+ end
10
+
11
+ def test_does_not_choke_on_timeout
12
+ silence_warnings do
13
+ Geocoder::Lookup.all_services_except_test.each do |l|
14
+ Geocoder.configure(:lookup => l)
15
+ set_api_key!(l)
16
+ assert_nothing_raised { Geocoder.search("timeout") }
17
+ end
18
+ end
19
+ end
20
+
21
+ def test_always_raise_timeout_error
22
+ Geocoder.configure(:always_raise => [TimeoutError])
23
+ Geocoder::Lookup.all_services_except_test.each do |l|
24
+ next if l == :maxmind_local # local, does not raise timeout
25
+ lookup = Geocoder::Lookup.get(l)
26
+ set_api_key!(l)
27
+ assert_raises TimeoutError do
28
+ lookup.send(:results, Geocoder::Query.new("timeout"))
29
+ end
30
+ end
31
+ end
32
+
33
+ def test_always_raise_socket_error
34
+ Geocoder.configure(:always_raise => [SocketError])
35
+ Geocoder::Lookup.all_services_except_test.each do |l|
36
+ next if l == :maxmind_local # local, does not raise timeout
37
+ lookup = Geocoder::Lookup.get(l)
38
+ set_api_key!(l)
39
+ assert_raises SocketError do
40
+ lookup.send(:results, Geocoder::Query.new("socket_error"))
41
+ end
42
+ end
43
+ end
44
+
45
+ def test_always_raise_connection_refused_error
46
+ Geocoder.configure(:always_raise => [Errno::ECONNREFUSED])
47
+ Geocoder::Lookup.all_services_except_test.each do |l|
48
+ next if l == :maxmind_local # local, does not raise timeout
49
+ lookup = Geocoder::Lookup.get(l)
50
+ set_api_key!(l)
51
+ assert_raises Errno::ECONNREFUSED do
52
+ lookup.send(:results, Geocoder::Query.new("connection_refused"))
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class GeocoderTest < GeocoderTestCase
6
+
7
+ def test_distance_to_returns_float
8
+ v = Place.new(*geocoded_object_params(:msg))
9
+ v.latitude, v.longitude = [40.750354, -73.993371]
10
+ assert (v.distance_to([30, -94])).is_a?(Float)
11
+ end
12
+
13
+ def test_coordinates_method_returns_array
14
+ assert Geocoder.coordinates("Madison Square Garden, New York, NY").is_a?(Array)
15
+ end
16
+
17
+ def test_address_method_returns_string
18
+ assert Geocoder.address([40.750354, -73.993371]).is_a?(String)
19
+ end
20
+
21
+ def test_geographic_center_doesnt_overwrite_argument_value
22
+ # test for the presence of a bug that was introduced in version 0.9.11
23
+ orig_points = [[52,8], [46,9], [42,5]]
24
+ points = orig_points.clone
25
+ Geocoder::Calculations.geographic_center(points)
26
+ assert_equal orig_points, points
27
+ end
28
+
29
+ def test_geocode_assigns_and_returns_coordinates
30
+ v = Place.new(*geocoded_object_params(:msg))
31
+ coords = [40.750354, -73.993371]
32
+ assert_equal coords, v.geocode
33
+ assert_equal coords, [v.latitude, v.longitude]
34
+ end
35
+
36
+ def test_geocode_block_executed_when_no_results
37
+ v = PlaceWithCustomResultsHandling.new("Nowhere", "no results")
38
+ v.geocode
39
+ assert_equal "NOT FOUND", v.coords_string
40
+ end
41
+
42
+ def test_reverse_geocode_assigns_and_returns_address
43
+ v = PlaceReverseGeocoded.new(*reverse_geocoded_object_params(:msg))
44
+ address = "4 Penn Plaza, New York, NY 10001, USA"
45
+ assert_equal address, v.reverse_geocode
46
+ assert_equal address, v.address
47
+ end
48
+
49
+ def test_forward_and_reverse_geocoding_on_same_model_works
50
+ g = PlaceWithForwardAndReverseGeocoding.new("Exxon")
51
+ g.address = "404 New St, Middletown, CT"
52
+ g.geocode
53
+ assert_not_nil g.lat
54
+ assert_not_nil g.lon
55
+
56
+ assert_nil g.location
57
+ g.reverse_geocode
58
+ assert_not_nil g.location
59
+ end
60
+
61
+ def test_geocode_with_custom_lookup_param
62
+ v = PlaceWithCustomLookup.new(*geocoded_object_params(:msg))
63
+ v.geocode
64
+ assert_equal Geocoder::Result::Nominatim, v.result_class
65
+ end
66
+
67
+ def test_geocode_with_custom_lookup_proc_param
68
+ v = PlaceWithCustomLookupProc.new(*geocoded_object_params(:msg))
69
+ v.geocode
70
+ assert_equal Geocoder::Result::Nominatim, v.result_class
71
+ end
72
+
73
+ def test_reverse_geocode_with_custom_lookup_param
74
+ v = PlaceReverseGeocodedWithCustomLookup.new(*reverse_geocoded_object_params(:msg))
75
+ v.reverse_geocode
76
+ assert_equal Geocoder::Result::Nominatim, v.result_class
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class HttpsTest < GeocoderTestCase
6
+
7
+ def test_uses_https_for_secure_query
8
+ Geocoder.configure(:use_https => true)
9
+ g = Geocoder::Lookup::Google.new
10
+ assert_match(/^https:/, g.query_url(Geocoder::Query.new("test")))
11
+ end
12
+
13
+ def test_uses_http_by_default
14
+ g = Geocoder::Lookup::Google.new
15
+ assert_match(/^http:/, g.query_url(Geocoder::Query.new("test")))
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class IpAddressTest < GeocoderTestCase
6
+
7
+ def test_valid
8
+ assert Geocoder::IpAddress.new("232.65.123.94").valid?
9
+ assert Geocoder::IpAddress.new("666.65.123.94").valid? # technically invalid
10
+ assert Geocoder::IpAddress.new("::ffff:12.34.56.78").valid?
11
+ assert Geocoder::IpAddress.new("3ffe:0b00:0000:0000:0001:0000:0000:000a").valid?
12
+ assert Geocoder::IpAddress.new("::1").valid?
13
+ assert !Geocoder::IpAddress.new("232.65.123.94.43").valid?
14
+ assert !Geocoder::IpAddress.new("232.65.123").valid?
15
+ assert !Geocoder::IpAddress.new("::ffff:123.456.789").valid?
16
+ assert !Geocoder::IpAddress.new("Test\n232.65.123.94").valid?
17
+ end
18
+
19
+ def test_loopback
20
+ assert Geocoder::IpAddress.new("0.0.0.0").loopback?
21
+ assert Geocoder::IpAddress.new("127.0.0.1").loopback?
22
+ assert Geocoder::IpAddress.new("::1").loopback?
23
+ assert !Geocoder::IpAddress.new("232.65.123.234").loopback?
24
+ assert !Geocoder::IpAddress.new("127 Main St.").loopback?
25
+ assert !Geocoder::IpAddress.new("John Doe\n127 Main St.\nAnywhere, USA").loopback?
26
+ end
27
+ end
@@ -0,0 +1,153 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..")
3
+ require 'test_helper'
4
+
5
+ class LookupTest < GeocoderTestCase
6
+
7
+ def test_responds_to_name_method
8
+ Geocoder::Lookup.all_services.each do |l|
9
+ lookup = Geocoder::Lookup.get(l)
10
+ assert lookup.respond_to?(:name),
11
+ "Lookup #{l} does not respond to #name method."
12
+ end
13
+ end
14
+
15
+ def test_search_returns_empty_array_when_no_results
16
+ Geocoder::Lookup.all_services_except_test.each do |l|
17
+ lookup = Geocoder::Lookup.get(l)
18
+ set_api_key!(l)
19
+ assert_equal [], lookup.send(:results, Geocoder::Query.new("no results")),
20
+ "Lookup #{l} does not return empty array when no results."
21
+ end
22
+ end
23
+
24
+ def test_query_url_contains_values_in_params_hash
25
+ Geocoder::Lookup.all_services_except_test.each do |l|
26
+ next if [:freegeoip, :maxmind_local, :telize, :pointpin].include? l # does not use query string
27
+ set_api_key!(l)
28
+ url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new(
29
+ "test", :params => {:one_in_the_hand => "two in the bush"}
30
+ ))
31
+ # should be "+"s for all lookups except Yahoo
32
+ assert_match(/one_in_the_hand=two(%20|\+)in(%20|\+)the(%20|\+)bush/, url,
33
+ "Lookup #{l} does not appear to support arbitrary params in URL")
34
+ end
35
+ end
36
+
37
+ {
38
+ :esri => :l,
39
+ :bing => :key,
40
+ :geocoder_ca => :auth,
41
+ :google => :language,
42
+ :google_premier => :language,
43
+ :mapquest => :key,
44
+ :maxmind => :l,
45
+ :nominatim => :"accept-language",
46
+ :yahoo => :locale,
47
+ :yandex => :plng
48
+ }.each do |l,p|
49
+ define_method "test_passing_param_to_#{l}_query_overrides_configuration_value" do
50
+ set_api_key!(l)
51
+ url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new(
52
+ "test", :params => {p => "xxxx"}
53
+ ))
54
+ assert_match(/#{p}=xxxx/, url,
55
+ "Param passed to #{l} lookup does not override configuration value")
56
+ end
57
+ end
58
+
59
+ {
60
+ :google => :language,
61
+ :google_premier => :language,
62
+ :nominatim => :"accept-language",
63
+ :yahoo => :locale,
64
+ :yandex => :plng
65
+ }.each do |l,p|
66
+ define_method "test_passing_language_to_#{l}_query_overrides_configuration_value" do
67
+ set_api_key!(l)
68
+ url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new(
69
+ "test", :language => 'xxxx'
70
+ ))
71
+ assert_match(/#{p}=xxxx/, url,
72
+ "Param passed to #{l} lookup does not override configuration value")
73
+ end
74
+ end
75
+
76
+ def test_raises_exception_on_invalid_key
77
+ Geocoder.configure(:always_raise => [Geocoder::InvalidApiKey])
78
+ #Geocoder::Lookup.all_services_except_test.each do |l|
79
+ [:bing, :yahoo, :yandex, :maxmind, :baidu, :baidu_ip].each do |l|
80
+ lookup = Geocoder::Lookup.get(l)
81
+ assert_raises Geocoder::InvalidApiKey do
82
+ lookup.send(:results, Geocoder::Query.new("invalid key"))
83
+ end
84
+ end
85
+ end
86
+
87
+ def test_returns_empty_array_on_invalid_key
88
+ silence_warnings do
89
+ #Geocoder::Lookup.all_services_except_test.each do |l|
90
+ [:bing, :yahoo, :yandex, :maxmind, :baidu, :baidu_ip].each do |l|
91
+ Geocoder.configure(:lookup => l)
92
+ set_api_key!(l)
93
+ assert_equal [], Geocoder.search("invalid key")
94
+ end
95
+ end
96
+ end
97
+
98
+ def test_does_not_choke_on_nil_address
99
+ Geocoder::Lookup.all_services.each do |l|
100
+ Geocoder.configure(:lookup => l)
101
+ assert_nothing_raised { Place.new("Place", nil).geocode }
102
+ end
103
+ end
104
+
105
+ def test_hash_to_query
106
+ g = Geocoder::Lookup::Google.new
107
+ assert_equal "a=1&b=2", g.send(:hash_to_query, {:a => 1, :b => 2})
108
+ end
109
+
110
+ def test_baidu_api_key
111
+ Geocoder.configure(:api_key => "MY_KEY")
112
+ g = Geocoder::Lookup::BaiduIp.new
113
+ assert_match "ak=MY_KEY", g.query_url(Geocoder::Query.new("232.65.123.94"))
114
+ end
115
+
116
+ def test_baidu_ip_api_key
117
+ Geocoder.configure(:api_key => "MY_KEY")
118
+ g = Geocoder::Lookup::Baidu.new
119
+ assert_match "ak=MY_KEY", g.query_url(Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States"))
120
+ end
121
+
122
+ def test_pointpin_api_key
123
+ Geocoder.configure(:api_key => "MY_KEY")
124
+ g = Geocoder::Lookup::Pointpin.new
125
+ assert_match "/MY_KEY/", g.query_url(Geocoder::Query.new("232.65.123.94"))
126
+ end
127
+
128
+ def test_google_api_key
129
+ Geocoder.configure(:api_key => "MY_KEY")
130
+ g = Geocoder::Lookup::Google.new
131
+ assert_match "key=MY_KEY", g.query_url(Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States"))
132
+ end
133
+
134
+ def test_geocoder_ca_showpostal
135
+ Geocoder.configure(:api_key => "MY_KEY")
136
+ g = Geocoder::Lookup::GeocoderCa.new
137
+ assert_match "showpostal=1", g.query_url(Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States"))
138
+ end
139
+
140
+ def test_raises_configuration_error_on_missing_key
141
+ [:bing, :baidu].each do |l|
142
+ assert_raises Geocoder::ConfigurationError do
143
+ Geocoder.configure(:lookup => l, :api_key => nil)
144
+ Geocoder.search("Madison Square Garden, New York, NY 10001, United States")
145
+ end
146
+ end
147
+ end
148
+
149
+ def test_handle
150
+ assert_equal :google, Geocoder::Lookup::Google.new.handle
151
+ assert_equal :geocoder_ca, Geocoder::Lookup::GeocoderCa.new.handle
152
+ end
153
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..", "..")
3
+ require 'test_helper'
4
+
5
+ class BingTest < GeocoderTestCase
6
+
7
+ def setup
8
+ Geocoder.configure(lookup: :bing)
9
+ set_api_key!(:bing)
10
+ end
11
+
12
+ def test_query_for_reverse_geocode
13
+ lookup = Geocoder::Lookup::Bing.new
14
+ url = lookup.query_url(Geocoder::Query.new([45.423733, -75.676333]))
15
+ assert_match(/Locations\/45.423733/, url)
16
+ end
17
+
18
+ def test_result_components
19
+ result = Geocoder.search("Madison Square Garden, New York, NY").first
20
+ assert_equal "Madison Square Garden, NY", result.address
21
+ assert_equal "NY", result.state
22
+ assert_equal "New York", result.city
23
+ end
24
+
25
+ def test_no_results
26
+ results = Geocoder.search("no results")
27
+ assert_equal 0, results.length
28
+ end
29
+
30
+ def test_query_url_contains_region
31
+ lookup = Geocoder::Lookup::Bing.new
32
+ url = lookup.query_url(Geocoder::Query.new(
33
+ "manchester",
34
+ :region => "uk"
35
+ ))
36
+ assert_match(/Locations\/uk\?q=manchester/, url)
37
+ assert_no_match(/query/, url)
38
+ end
39
+
40
+ def test_query_url_without_region
41
+ lookup = Geocoder::Lookup::Bing.new
42
+ url = lookup.query_url(Geocoder::Query.new(
43
+ "manchester"
44
+ ))
45
+ assert_match(/Locations\?q=manchester/, url)
46
+ assert_no_match(/query/, url)
47
+ end
48
+
49
+ def test_query_url_contains_address_with_spaces
50
+ lookup = Geocoder::Lookup::Bing.new
51
+ url = lookup.query_url(Geocoder::Query.new(
52
+ "manchester, lancashire",
53
+ :region => "uk"
54
+ ))
55
+ assert_match(/Locations\/uk\?q=manchester,%20lancashire/, url)
56
+ assert_no_match(/query/, url)
57
+ end
58
+
59
+ def test_query_url_contains_address_with_trailing_and_leading_spaces
60
+ lookup = Geocoder::Lookup::Bing.new
61
+ url = lookup.query_url(Geocoder::Query.new(
62
+ " manchester, lancashire ",
63
+ :region => "uk"
64
+ ))
65
+ assert_match(/Locations\/uk\?q=manchester,%20lancashire/, url)
66
+ assert_no_match(/query/, url)
67
+ end
68
+ end