From d81b08b2ca43732601ddd3883db06a6977afb51a Mon Sep 17 00:00:00 2001 From: Florian Frank <flori@ping.de> Date: Thu, 12 Apr 2012 12:09:28 +0200 Subject: [PATCH] Avoid crashes during calculations Geocoder.coordinates sometimes returns nil which causes crashes in the distance and bearing calculations. By returning a point array of [ NaN, NaN ] this distances will be also NaN which seems to be a sensible result. If the argument to extract_coordinates has an unexpected form, also return [ NaN, NaN ]. --- lib/geocoder/calculations.rb | 24 +++++++++++++++++++++--- test/calculations_test.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/geocoder/calculations.rb b/lib/geocoder/calculations.rb index abc8b947..06beb8df 100644 --- a/lib/geocoder/calculations.rb +++ b/lib/geocoder/calculations.rb @@ -21,6 +21,9 @@ module Geocoder # KM_IN_MI = 0.621371192 + # Not a number constant + NAN = defined?(::Float::NAN) ? ::Float::NAN : 0 / 0.0 + ## # Distance spanned by one degree of latitude in the given units. # @@ -270,10 +273,25 @@ module Geocoder # def extract_coordinates(point) case point - when Array; point - when String; Geocoder.coordinates(point) - else point.to_coordinates + when Array + if point.size == 2 + lat, lon = point + if !lat.nil? && lat.respond_to?(:to_f) and + !lon.nil? && lon.respond_to?(:to_f) + then + return [ lat.to_f, lon.to_f ] + end + end + when String + point = Geocoder.coordinates(point) and return point + else + if point.respond_to?(:to_coordinates) + if Array === array = point.to_coordinates + return extract_coordinates(array) + end + end end + [ NAN, NAN ] end end end diff --git a/test/calculations_test.rb b/test/calculations_test.rb index 25343cb7..74816e20 100644 --- a/test/calculations_test.rb +++ b/test/calculations_test.rb @@ -144,4 +144,33 @@ class CalculationsTest < Test::Unit::TestCase l = Landmark.new(*landmark_params(:msg)) assert_equal l.bearing_from([50,-86.1]), l.bearing_to([50,-86.1]) - 180 end + + def test_extract_coordinates + result = Geocoder::Calculations.extract_coordinates([ nil, nil ]) + assert_equal [ Geocoder::Calculations::NAN ] * 2, result + + result = Geocoder::Calculations.extract_coordinates([ 1.0 / 3, 2.0 / 3 ]) + assert_in_delta 1.0 / 3, result.first, 1E-5 + assert_in_delta 2.0 / 3, result.last, 1E-5 + + result = Geocoder::Calculations.extract_coordinates(nil) + assert_equal [ Geocoder::Calculations::NAN ] * 2, result + + result = Geocoder::Calculations.extract_coordinates('') + assert_equal [ Geocoder::Calculations::NAN ] * 2, result + + result = Geocoder::Calculations.extract_coordinates([ 'nix' ]) + assert_equal [ Geocoder::Calculations::NAN ] * 2, result + + o = Object.new + result = Geocoder::Calculations.extract_coordinates(o) + assert_equal [ Geocoder::Calculations::NAN ] * 2, result + + def o.to_coordinates + [ 1.0 / 3, 2.0 / 3 ] + end + result = Geocoder::Calculations.extract_coordinates(o) + assert_in_delta 1.0 / 3, result.first, 1E-5 + assert_in_delta 2.0 / 3, result.last, 1E-5 + end end -- GitLab