From 482887bdc36506a39416ca5d8e371ce2455165a9 Mon Sep 17 00:00:00 2001 From: Alex Reisner <alex@alexreisner.com> Date: Sun, 2 Sep 2012 14:01:35 -0400 Subject: [PATCH] Introduce Geocoder::Query object. Also move some lookup-related methods to Geocoder::Lookup module. --- lib/geocoder.rb | 101 +++---------------------- lib/geocoder/cli.rb | 6 +- lib/geocoder/lookup.rb | 62 +++++++++++++++ lib/geocoder/lookups/base.rb | 42 +++------- lib/geocoder/lookups/bing.rb | 10 +-- lib/geocoder/lookups/freegeoip.rb | 10 +-- lib/geocoder/lookups/geocoder_ca.rb | 12 +-- lib/geocoder/lookups/google.rb | 8 +- lib/geocoder/lookups/google_premier.rb | 4 +- lib/geocoder/lookups/mapquest.rb | 16 ++-- lib/geocoder/lookups/nominatim.rb | 16 ++-- lib/geocoder/lookups/test.rb | 14 ++-- lib/geocoder/lookups/yahoo.rb | 10 +-- lib/geocoder/lookups/yandex.rb | 14 ++-- lib/geocoder/query.rb | 88 +++++++++++++++++++++ lib/geocoder/version.rb | 2 +- test/calculations_test.rb | 7 ++ test/error_handling_test.rb | 14 ++-- test/https_test.rb | 4 +- test/input_handling_test.rb | 43 ----------- test/lookup_test.rb | 19 +++-- test/query_test.rb | 34 +++++++++ test/result_test.rb | 2 +- test/services_test.rb | 2 +- test/test_helper.rb | 80 +++++++++----------- 25 files changed, 332 insertions(+), 288 deletions(-) create mode 100644 lib/geocoder/lookup.rb create mode 100644 lib/geocoder/query.rb delete mode 100644 test/input_handling_test.rb create mode 100644 test/query_test.rb diff --git a/lib/geocoder.rb b/lib/geocoder.rb index 196cf75d..4019e845 100644 --- a/lib/geocoder.rb +++ b/lib/geocoder.rb @@ -1,8 +1,10 @@ require "geocoder/configuration" +require "geocoder/query" require "geocoder/calculations" require "geocoder/exceptions" require "geocoder/cache" require "geocoder/request" +require "geocoder/lookup" require "geocoder/models/active_record" if defined?(::ActiveRecord) require "geocoder/models/mongoid" if defined?(::Mongoid) require "geocoder/models/mongo_mapper" if defined?(::MongoMapper) @@ -13,15 +15,16 @@ module Geocoder ## # Search for information about an address or a set of coordinates. # - def search(query) - blank_query?(query) ? [] : lookup(query).search(query) + def search(query, options = {}) + query = Geocoder::Query.new(query, options) unless query.is_a?(Geocoder::Query) + query.blank? ? [] : query.execute end ## # Look up the coordinates of the given street or IP address. # - def coordinates(address) - if (results = search(address)).size > 0 + def coordinates(address, options = {}) + if (results = search(address, options)).size > 0 results.first.coordinates end end @@ -30,8 +33,8 @@ module Geocoder # Look up the address of the given coordinates ([lat,lon]) # or IP address (string). # - def address(query) - if (results = search(query)).size > 0 + def address(query, options = {}) + if (results = search(query, options)).size > 0 results.first.address end end @@ -45,92 +48,6 @@ module Geocoder end @cache end - - ## - # Array of valid Lookup names. - # - def valid_lookups - street_lookups + ip_lookups - end - - ## - # Array of valid Lookup names, excluding :test. - # - def valid_lookups_except_test - valid_lookups - [:test] - end - - ## - # All street address lookups, default first. - # - def street_lookups - [:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim, :mapquest, :test] - end - - ## - # All IP address lookups, default first. - # - def ip_lookups - [:freegeoip] - end - - - private # ----------------------------------------------------------------- - - ## - # Get a Lookup object (which communicates with the remote geocoding API). - # Takes a search query and returns an IP or street address Lookup - # depending on the query contents. - # - def lookup(query) - if ip_address?(query) - get_lookup(Configuration.ip_lookup || ip_lookups.first) - else - get_lookup(Configuration.lookup || street_lookups.first) - end - end - - ## - # Retrieve a Lookup object from the store. - # - def get_lookup(name) - @lookups = {} unless defined?(@lookups) - @lookups[name] = spawn_lookup(name) unless @lookups.include?(name) - @lookups[name] - end - - ## - # Spawn a Lookup of the given name. - # - def spawn_lookup(name) - if valid_lookups.include?(name) - name = name.to_s - require "geocoder/lookups/#{name}" - klass = name.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join - Geocoder::Lookup.const_get(klass).new - else - valids = valid_lookups.map(&:inspect).join(", ") - raise ConfigurationError, "Please specify a valid lookup for Geocoder " + - "(#{name.inspect} is not one of: #{valids})." - end - end - - ## - # Does the given value look like an IP address? - # - # Does not check for actual validity, just the appearance of four - # dot-delimited numbers. - # - def ip_address?(value) - !!value.to_s.match(/^(::ffff:)?(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) - end - - ## - # Is the given search query blank? (ie, should we not bother searching?) - # - def blank_query?(value) - !!value.to_s.match(/^\s*$/) - end end # load Railtie if Rails exists diff --git a/lib/geocoder/cli.rb b/lib/geocoder/cli.rb index 9a7fa13b..a5648631 100644 --- a/lib/geocoder/cli.rb +++ b/lib/geocoder/cli.rb @@ -32,8 +32,8 @@ module Geocoder Geocoder::Configuration.http_proxy = proxy end - opts.on("-s <service>", Geocoder.valid_lookups_except_test, "--service <service>", - "Geocoding service: #{Geocoder.valid_lookups_except_test * ', '}") do |service| + opts.on("-s <service>", Geocoder::Lookup.all_services_except_test, "--service <service>", + "Geocoding service: #{Geocoder::Lookup.all_services_except_test * ', '}") do |service| Geocoder::Configuration.lookup = service.to_sym Geocoder::Configuration.ip_lookup = service.to_sym end @@ -93,7 +93,7 @@ module Geocoder end if (result = Geocoder.search(query).first) - lookup = Geocoder.send(:get_lookup, :google) + lookup = Geocoder::Lookup.get(:google) lines = [ ["Latitude", result.latitude], ["Longitude", result.longitude], diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb new file mode 100644 index 00000000..11d0a8a2 --- /dev/null +++ b/lib/geocoder/lookup.rb @@ -0,0 +1,62 @@ +module Geocoder + module Lookup + + ## + # Array of valid Lookup service names. + # + def self.all_services + street_services + ip_services + end + + ## + # Array of valid Lookup service names, excluding :test. + # + def self.all_services_except_test + all_services - [:test] + end + + ## + # All street address lookup services, default first. + # + def self.street_services + [:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim, :mapquest, :test] + end + + ## + # All IP address lookup services, default first. + # + def self.ip_services + [:freegeoip] + end + + ## + # Retrieve a Lookup object from the store. + # Use this instead of Geocoder::Lookup::X.new to get an + # already-configured Lookup object. + # + def self.get(name) + @services = {} unless defined?(@services) + @services[name] = spawn(name) unless @services.include?(name) + @services[name] + end + + + private # ----------------------------------------------------------------- + + ## + # Spawn a Lookup of the given name. + # + def self.spawn(name) + if all_services.include?(name) + name = name.to_s + require "geocoder/lookups/#{name}" + klass = name.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join + Geocoder::Lookup.const_get(klass).new + else + valids = all_services.map(&:inspect).join(", ") + raise ConfigurationError, "Please specify a valid lookup for Geocoder " + + "(#{name.inspect} is not one of: #{valids})." + end + end + end +end diff --git a/lib/geocoder/lookups/base.rb b/lib/geocoder/lookups/base.rb index 3665e954..a770f97f 100644 --- a/lib/geocoder/lookups/base.rb +++ b/lib/geocoder/lookups/base.rb @@ -13,6 +13,7 @@ end module Geocoder module Lookup + class Base ## @@ -23,18 +24,9 @@ module Geocoder # "205.128.54.202") for geocoding, or coordinates (latitude, longitude) # for reverse geocoding. Returns an array of <tt>Geocoder::Result</tt>s. # - def search(query) - - # if coordinates given as string, turn into array - query = query.split(/\s*,\s*/) if coordinates?(query) - - if query.is_a?(Array) - reverse = true - query = query.join(',') - else - reverse = false - end - results(query, reverse).map{ |r| + def search(query, options = {}) + query = Geocoder::Query.new(query, options) unless query.is_a?(Geocoder::Query) + results(query).map{ |r| result = result_class.new(r) result.cache_hit = @cache_hit if cache result @@ -77,14 +69,14 @@ module Geocoder ## # Geocoder::Result object or nil on timeout or other error. # - def results(query, reverse = false) + def results(query) fail end ## # URL to use for querying the geocoding engine. # - def query_url(query, reverse = false) + def query_url(query) fail end @@ -111,8 +103,8 @@ module Geocoder ## # Returns a parsed search result (Ruby hash). # - def fetch_data(query, reverse = false) - parse_raw_data fetch_raw_data(query, reverse) + def fetch_data(query) + parse_raw_data fetch_raw_data(query) rescue SocketError => err raise_error(err) or warn "Geocoding API connection cannot be established." rescue TimeoutError => err @@ -144,9 +136,9 @@ module Geocoder ## # Fetches a raw search result (JSON string). # - def fetch_raw_data(query, reverse = false) + def fetch_raw_data(query) timeout(Geocoder::Configuration.timeout) do - url = query_url(query, reverse) + url = query_url(query) uri = URI.parse(url) if cache and body = cache[url] @cache_hit = true @@ -171,20 +163,6 @@ module Geocoder Geocoder.cache end - ## - # Is the given string a loopback IP address? - # - def loopback_address?(ip) - !!(ip == "0.0.0.0" or ip.to_s.match(/^127/)) - end - - ## - # Does the given string look like latitude/longitude coordinates? - # - def coordinates?(value) - value.is_a?(String) and !!value.to_s.match(/^-?[0-9\.]+, *-?[0-9\.]+$/) - end - ## # Simulate ActiveSupport's Object#to_query. # Removes any keys with nil value. diff --git a/lib/geocoder/lookups/bing.rb b/lib/geocoder/lookups/bing.rb index 2bec5a4f..a5d254c3 100644 --- a/lib/geocoder/lookups/bing.rb +++ b/lib/geocoder/lookups/bing.rb @@ -10,8 +10,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) if doc['statusDescription'] == "OK" return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : [] @@ -21,12 +21,12 @@ module Geocoder::Lookup end end - def query_url(query, reverse = false) + def query_url(query) params = {:key => Geocoder::Configuration.api_key} - params[:query] = query unless reverse + params[:query] = query.sanitized_text unless query.reverse_geocode? base_url = "http://dev.virtualearth.net/REST/v1/Locations" - url_tail = reverse ? "/#{query}?" : "?" + url_tail = query.reverse_geocode? ? "/#{query.sanitized_text}?" : "?" base_url + url_tail + hash_to_query(params) end end diff --git a/lib/geocoder/lookups/freegeoip.rb b/lib/geocoder/lookups/freegeoip.rb index a5526667..a3f6dc91 100644 --- a/lib/geocoder/lookups/freegeoip.rb +++ b/lib/geocoder/lookups/freegeoip.rb @@ -10,11 +10,11 @@ module Geocoder::Lookup raw_data.match(/^<html><title>404/) ? nil : super(raw_data) end - def results(query, reverse = false) + def results(query) # don't look up a loopback address, just return the stored result - return [reserved_result(query)] if loopback_address?(query) + return [reserved_result(query)] if query.loopback_ip_address? begin - return (doc = fetch_data(query, reverse)) ? [doc] : [] + return (doc = fetch_data(query)) ? [doc] : [] rescue StandardError => err # Freegeoip.net returns HTML on bad request raise_error(err) return [] @@ -36,8 +36,8 @@ module Geocoder::Lookup } end - def query_url(query, reverse = false) - "http://freegeoip.net/json/#{query}" + def query_url(query) + "http://freegeoip.net/json/#{query.sanitized_text}" end end end diff --git a/lib/geocoder/lookups/geocoder_ca.rb b/lib/geocoder/lookups/geocoder_ca.rb index 32ea293a..379d0fd4 100644 --- a/lib/geocoder/lookups/geocoder_ca.rb +++ b/lib/geocoder/lookups/geocoder_ca.rb @@ -6,8 +6,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) if doc['error'].nil? return [doc] elsif doc['error']['code'] == "005" @@ -18,21 +18,21 @@ module Geocoder::Lookup return [] end - def query_url(query, reverse = false) + def query_url(query) params = { :geoit => "xml", :jsonp => 1, :callback => "test", :auth => Geocoder::Configuration.api_key } - if reverse - lat,lon = query.split(',') + if query.reverse_geocode? + lat,lon = query.coordinates params[:latt] = lat params[:longt] = lon params[:corner] = 1 params[:reverse] = 1 else - params[:locate] = query + params[:locate] = query.sanitized_text params[:showpostal] = 1 end "http://geocoder.ca/?" + hash_to_query(params) diff --git a/lib/geocoder/lookups/google.rb b/lib/geocoder/lookups/google.rb index 6898c267..ed7f1cd3 100644 --- a/lib/geocoder/lookups/google.rb +++ b/lib/geocoder/lookups/google.rb @@ -10,8 +10,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) case doc['status']; when "OK" # OK status implies >0 results return doc['results'] when "OVER_QUERY_LIMIT" @@ -27,9 +27,9 @@ module Geocoder::Lookup return [] end - def query_url(query, reverse = false) + def query_url(query) params = { - (reverse ? :latlng : :address) => query, + (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text, :sensor => "false", :language => Geocoder::Configuration.language, :key => Geocoder::Configuration.api_key diff --git a/lib/geocoder/lookups/google_premier.rb b/lib/geocoder/lookups/google_premier.rb index 6befdddf..14cbdac8 100644 --- a/lib/geocoder/lookups/google_premier.rb +++ b/lib/geocoder/lookups/google_premier.rb @@ -8,9 +8,9 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def query_url(query, reverse = false) + def query_url(query) params = { - (reverse ? :latlng : :address) => query, + (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text, :sensor => 'false', :language => Geocoder::Configuration.language, :client => Geocoder::Configuration.api_key[1], diff --git a/lib/geocoder/lookups/mapquest.rb b/lib/geocoder/lookups/mapquest.rb index 08cd31d8..08bdaaeb 100644 --- a/lib/geocoder/lookups/mapquest.rb +++ b/lib/geocoder/lookups/mapquest.rb @@ -6,26 +6,26 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) doc.is_a?(Array) ? doc : [doc] end - def query_url(query, reverse = false) + def query_url(query) params = { :format => "json", :polygon => "1", :addressdetails => "1", :"accept-language" => Geocoder::Configuration.language } - if (reverse) + if (query.reverse_geocode?) method = 'reverse' - parts = query.split(/\s*,\s*/); - params[:lat] = parts[0] - params[:lon] = parts[1] + lat,lon = query.coordinates + params[:lat] = lat + params[:lon] = lon else method = 'search' - params[:q] = query + params[:q] = query.sanitized_text end "http://open.mapquestapi.com/#{method}?" + hash_to_query(params) end diff --git a/lib/geocoder/lookups/nominatim.rb b/lib/geocoder/lookups/nominatim.rb index 12f2c151..4ded59b1 100644 --- a/lib/geocoder/lookups/nominatim.rb +++ b/lib/geocoder/lookups/nominatim.rb @@ -10,26 +10,26 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) doc.is_a?(Array) ? doc : [doc] end - def query_url(query, reverse = false) + def query_url(query) params = { :format => "json", :polygon => "1", :addressdetails => "1", :"accept-language" => Geocoder::Configuration.language } - if (reverse) + if (query.reverse_geocode?) method = 'reverse' - parts = query.split(/\s*,\s*/); - params[:lat] = parts[0] - params[:lon] = parts[1] + lat,lon = query.coordinates + params[:lat] = lat + params[:lon] = lon else method = 'search' - params[:q] = query + params[:q] = query.sanitized_text end "http://nominatim.openstreetmap.org/#{method}?" + hash_to_query(params) end diff --git a/lib/geocoder/lookups/test.rb b/lib/geocoder/lookups/test.rb index e06171c9..89aa97f4 100644 --- a/lib/geocoder/lookups/test.rb +++ b/lib/geocoder/lookups/test.rb @@ -5,12 +5,14 @@ module Geocoder module Lookup class Test < Base - def self.add_stub(query, results) - stubs[query] = results + def self.add_stub(query_text, results) + stubs[query_text] = results end - def self.read_stub(query) - stubs.fetch(query) { raise ArgumentError, "unknown stub request #{query}" } + def self.read_stub(query_text) + stubs.fetch(query_text) { + raise ArgumentError, "unknown stub request #{query_text}" + } end def self.stubs @@ -23,8 +25,8 @@ module Geocoder private - def results(query, reverse = false) - Geocoder::Lookup::Test.read_stub(query) + def results(query) + Geocoder::Lookup::Test.read_stub(query.text) end end diff --git a/lib/geocoder/lookups/yahoo.rb b/lib/geocoder/lookups/yahoo.rb index 1ce523ec..e240fb4a 100644 --- a/lib/geocoder/lookups/yahoo.rb +++ b/lib/geocoder/lookups/yahoo.rb @@ -10,8 +10,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) if doc = doc['ResultSet'] and doc['Error'] == 0 return doc['Found'] > 0 ? doc['Results'] : [] else @@ -20,11 +20,11 @@ module Geocoder::Lookup end end - def query_url(query, reverse = false) + def query_url(query) params = { - :location => query, + :location => query.sanitized_text, :flags => "JXTSR", - :gflags => "AC#{'R' if reverse}", + :gflags => "AC#{'R' if query.reverse_geocode?}", :locale => "#{Geocoder::Configuration.language}_US", :appid => Geocoder::Configuration.api_key } diff --git a/lib/geocoder/lookups/yandex.rb b/lib/geocoder/lookups/yandex.rb index 452d2769..11f092d7 100644 --- a/lib/geocoder/lookups/yandex.rb +++ b/lib/geocoder/lookups/yandex.rb @@ -10,8 +10,8 @@ module Geocoder::Lookup private # --------------------------------------------------------------- - def results(query, reverse = false) - return [] unless doc = fetch_data(query, reverse) + def results(query) + return [] unless doc = fetch_data(query) if err = doc['error'] warn "Yandex Geocoding API error: #{err['status']} (#{err['message']})." return [] @@ -25,10 +25,14 @@ module Geocoder::Lookup end end - def query_url(query, reverse = false) - query = query.split(",").reverse.join(",") if reverse + def query_url(query) + if query.reverse_geocode? + q = query.coordinates.reverse.join(",") + else + q = query.sanitized_text + end params = { - :geocode => query, + :geocode => q, :format => "json", :plng => "#{Geocoder::Configuration.language}", # supports ru, uk, be :key => Geocoder::Configuration.api_key diff --git a/lib/geocoder/query.rb b/lib/geocoder/query.rb new file mode 100644 index 00000000..3da86ef1 --- /dev/null +++ b/lib/geocoder/query.rb @@ -0,0 +1,88 @@ +module Geocoder + class Query + attr_accessor :text, :options + + def initialize(text, options = {}) + self.text = text + self.options = options + end + + def execute + lookup.search(text, options) + end + + def to_s + text + end + + def sanitized_text + if coordinates? + text.split(/\s*,\s*/).join(',') + else + text + end + end + + ## + # Get a Lookup object (which communicates with the remote geocoding API) + # appropriate to the Query text. + # + def lookup + if ip_address? + name = Configuration.ip_lookup || Geocoder::Lookup.ip_services.first + else + name = Configuration.lookup || Geocoder::Lookup.street_services.first + end + Lookup.get(name) + end + + ## + # Is the Query text blank? (ie, should we not bother searching?) + # + def blank? + !!text.to_s.match(/^\s*$/) + end + + ## + # Does the Query text look like an IP address? + # + # Does not check for actual validity, just the appearance of four + # dot-delimited numbers. + # + def ip_address? + !!text.to_s.match(/^(::ffff:)?(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) + end + + ## + # Is the Query text a loopback IP address? + # + def loopback_ip_address? + !!(text == "0.0.0.0" or text.to_s.match(/^127/)) + end + + ## + # Does the given string look like latitude/longitude coordinates? + # + def coordinates? + text.is_a?(Array) or ( + text.is_a?(String) and + !!text.to_s.match(/^-?[0-9\.]+, *-?[0-9\.]+$/) + ) + end + + ## + # Return the latitude/longitude coordinates specified in the query, + # or nil if none. + # + def coordinates + sanitized_text.split(',') if coordinates? + end + + ## + # Should reverse geocoding be performed for this query? + # + def reverse_geocode? + coordinates? + end + end +end diff --git a/lib/geocoder/version.rb b/lib/geocoder/version.rb index 0eb5a042..3416c7e7 100644 --- a/lib/geocoder/version.rb +++ b/lib/geocoder/version.rb @@ -1,3 +1,3 @@ module Geocoder - VERSION = "1.1.3" + VERSION = "1.2.0" end diff --git a/test/calculations_test.rb b/test/calculations_test.rb index 4f9fef0d..902d8d68 100644 --- a/test/calculations_test.rb +++ b/test/calculations_test.rb @@ -185,4 +185,11 @@ class CalculationsTest < Test::Unit::TestCase assert !Geocoder::Calculations.coordinates_present?(Geocoder::Calculations::NAN) assert !Geocoder::Calculations.coordinates_present?(3.23, nil) end + + def test_extract_coordinates + coords = [-23,47] + l = Landmark.new("Madagascar", coords[0], coords[1]) + assert_equal coords, Geocoder::Calculations.extract_coordinates(l) + assert_equal coords, Geocoder::Calculations.extract_coordinates(coords) + end end diff --git a/test/error_handling_test.rb b/test/error_handling_test.rb index 9d84bdfd..369613e6 100644 --- a/test/error_handling_test.rb +++ b/test/error_handling_test.rb @@ -10,7 +10,7 @@ class ErrorHandlingTest < Test::Unit::TestCase def test_does_not_choke_on_timeout # keep test output clean: suppress timeout warning orig = $VERBOSE; $VERBOSE = nil - all_lookups_except_test.each do |l| + Geocoder::Lookup.all_services_except_test.each do |l| Geocoder::Configuration.lookup = l assert_nothing_raised { Geocoder.search("timeout") } end @@ -19,20 +19,20 @@ class ErrorHandlingTest < Test::Unit::TestCase def test_always_raise_timeout_error Geocoder::Configuration.always_raise = [TimeoutError] - all_lookups_except_test.each do |l| - lookup = Geocoder.send(:get_lookup, l) + Geocoder::Lookup.all_services_except_test.each do |l| + lookup = Geocoder::Lookup.get(l) assert_raises TimeoutError do - lookup.send(:results, "timeout") + lookup.send(:results, Geocoder::Query.new("timeout")) end end end def test_always_raise_socket_error Geocoder::Configuration.always_raise = [SocketError] - all_lookups_except_test.each do |l| - lookup = Geocoder.send(:get_lookup, l) + Geocoder::Lookup.all_services_except_test.each do |l| + lookup = Geocoder::Lookup.get(l) assert_raises SocketError do - lookup.send(:results, "socket_error") + lookup.send(:results, Geocoder::Query.new("socket_error")) end end end diff --git a/test/https_test.rb b/test/https_test.rb index 58219d33..aba96acf 100644 --- a/test/https_test.rb +++ b/test/https_test.rb @@ -6,11 +6,11 @@ class HttpsTest < Test::Unit::TestCase def test_uses_https_for_secure_query Geocoder::Configuration.use_https = true g = Geocoder::Lookup::Google.new - assert_match /^https:/, g.send(:query_url, {:a => 1, :b => 2}) + assert_match /^https:/, g.send(:query_url, Geocoder::Query.new("test")) end def test_uses_http_by_default g = Geocoder::Lookup::Google.new - assert_match /^http:/, g.send(:query_url, {:a => 1, :b => 2}) + assert_match /^http:/, g.send(:query_url, Geocoder::Query.new("test")) end end diff --git a/test/input_handling_test.rb b/test/input_handling_test.rb deleted file mode 100644 index f5da1f13..00000000 --- a/test/input_handling_test.rb +++ /dev/null @@ -1,43 +0,0 @@ -# encoding: utf-8 -require 'test_helper' - -class InputHandlingTest < Test::Unit::TestCase - - def test_ip_address_detection - assert Geocoder.send(:ip_address?, "232.65.123.94") - assert Geocoder.send(:ip_address?, "666.65.123.94") # technically invalid - assert Geocoder.send(:ip_address?, "::ffff:12.34.56.78") - assert !Geocoder.send(:ip_address?, "232.65.123.94.43") - assert !Geocoder.send(:ip_address?, "232.65.123") - assert !Geocoder.send(:ip_address?, "::ffff:123.456.789") - end - - def test_blank_query_detection - assert Geocoder.send(:blank_query?, nil) - assert Geocoder.send(:blank_query?, "") - assert Geocoder.send(:blank_query?, "\t ") - assert !Geocoder.send(:blank_query?, "a") - assert !Geocoder.send(:blank_query?, "МоÑква") # no ASCII characters - end - - def test_coordinates_detection - lookup = Geocoder::Lookup::Google.new - assert lookup.send(:coordinates?, "51.178844,5") - assert lookup.send(:coordinates?, "51.178844, -1.826189") - assert !lookup.send(:coordinates?, "232.65.123") - end - - def test_does_not_choke_on_nil_address - all_lookups.each do |l| - Geocoder::Configuration.lookup = l - assert_nothing_raised { Venue.new("Venue", nil).geocode } - end - end - - def test_extract_coordinates - coords = [-23,47] - l = Landmark.new("Madagascar", coords[0], coords[1]) - assert_equal coords, Geocoder::Calculations.extract_coordinates(l) - assert_equal coords, Geocoder::Calculations.extract_coordinates(coords) - end -end diff --git a/test/lookup_test.rb b/test/lookup_test.rb index 9cce80b7..5b4550c6 100644 --- a/test/lookup_test.rb +++ b/test/lookup_test.rb @@ -4,13 +4,20 @@ require 'test_helper' class LookupTest < Test::Unit::TestCase def test_search_returns_empty_array_when_no_results - all_lookups_except_test.each do |l| - lookup = Geocoder.send(:get_lookup, l) - assert_equal [], lookup.send(:results, "no results"), + Geocoder::Lookup.all_services_except_test.each do |l| + lookup = Geocoder::Lookup.get(l) + assert_equal [], lookup.send(:results, Geocoder::Query.new("no results")), "Lookup #{l} does not return empty array when no results." end end + def test_does_not_choke_on_nil_address + Geocoder::Lookup.all_services.each do |l| + Geocoder::Configuration.lookup = l + assert_nothing_raised { Venue.new("Venue", nil).geocode } + end + end + def test_hash_to_query g = Geocoder::Lookup::Google.new assert_equal "a=1&b=2", g.send(:hash_to_query, {:a => 1, :b => 2}) @@ -19,19 +26,19 @@ class LookupTest < Test::Unit::TestCase def test_google_api_key Geocoder::Configuration.api_key = "MY_KEY" g = Geocoder::Lookup::Google.new - assert_match "key=MY_KEY", g.send(:query_url, "Madison Square Garden, New York, NY 10001, United States") + assert_match "key=MY_KEY", g.send(:query_url, Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States")) end def test_yahoo_app_id Geocoder::Configuration.api_key = "MY_KEY" g = Geocoder::Lookup::Yahoo.new - assert_match "appid=MY_KEY", g.send(:query_url, "Madison Square Garden, New York, NY 10001, United States") + assert_match "appid=MY_KEY", g.send(:query_url, Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States")) end def test_geocoder_ca_showpostal Geocoder::Configuration.api_key = "MY_KEY" g = Geocoder::Lookup::GeocoderCa.new - assert_match "showpostal=1", g.send(:query_url, "Madison Square Garden, New York, NY 10001, United States") + assert_match "showpostal=1", g.send(:query_url, Geocoder::Query.new("Madison Square Garden, New York, NY 10001, United States")) end end diff --git a/test/query_test.rb b/test/query_test.rb new file mode 100644 index 00000000..22a90b5c --- /dev/null +++ b/test/query_test.rb @@ -0,0 +1,34 @@ +# encoding: utf-8 +require 'test_helper' + +class QueryTest < Test::Unit::TestCase + + def test_ip_address_detection + assert Geocoder::Query.new("232.65.123.94").ip_address? + assert Geocoder::Query.new("666.65.123.94").ip_address? # technically invalid + assert Geocoder::Query.new("::ffff:12.34.56.78").ip_address? + assert !Geocoder::Query.new("232.65.123.94.43").ip_address? + assert !Geocoder::Query.new("232.65.123").ip_address? + assert !Geocoder::Query.new("::ffff:123.456.789").ip_address? + end + + def test_blank_query_detection + assert Geocoder::Query.new(nil).blank? + assert Geocoder::Query.new("").blank? + assert Geocoder::Query.new("\t ").blank? + assert !Geocoder::Query.new("a").blank? + assert !Geocoder::Query.new("МоÑква").blank? # no ASCII characters + end + + def test_coordinates_detection + assert Geocoder::Query.new("51.178844,5").coordinates? + assert Geocoder::Query.new("51.178844, -1.826189").coordinates? + assert !Geocoder::Query.new("232.65.123").coordinates? + end + + def test_loopback_ip_address + assert Geocoder::Query.new("0.0.0.0").loopback_ip_address? + assert Geocoder::Query.new("127.0.0.1").loopback_ip_address? + assert !Geocoder::Query.new("232.65.123.234").loopback_ip_address? + end +end diff --git a/test/result_test.rb b/test/result_test.rb index 85bb0f4f..ab207c5f 100644 --- a/test/result_test.rb +++ b/test/result_test.rb @@ -4,7 +4,7 @@ require 'test_helper' class ResultTest < Test::Unit::TestCase def test_result_has_required_attributes - all_lookups_except_test.each do |l| + Geocoder::Lookup.all_services_except_test.each do |l| Geocoder::Configuration.lookup = l result = Geocoder.search([45.423733, -75.676333]).first assert_result_has_required_attributes(result) diff --git a/test/services_test.rb b/test/services_test.rb index 83fe571a..ef701510 100644 --- a/test/services_test.rb +++ b/test/services_test.rb @@ -41,7 +41,7 @@ class ServicesTest < Test::Unit::TestCase def test_google_premier_query_url Geocoder::Configuration.api_key = ["deadbeef", "gme-test", "test-dev"] assert_equal "http://maps.googleapis.com/maps/api/geocode/json?address=Madison+Square+Garden%2C+New+York%2C+NY&channel=test-dev&client=gme-test&language=en&sensor=false&signature=doJvJqX7YJzgV9rJ0DnVkTGZqTg=", - Geocoder::Lookup::GooglePremier.new.send(:query_url, "Madison Square Garden, New York, NY", false) + Geocoder::Lookup::GooglePremier.new.send(:query_url, Geocoder::Query.new("Madison Square Garden, New York, NY")) end diff --git a/test/test_helper.rb b/test/test_helper.rb index a9cf367f..aa7d6d7a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -60,10 +60,10 @@ module Geocoder class Google < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results when "no locality"; :no_locality when "no city data"; :no_city_data @@ -78,10 +78,10 @@ module Geocoder class Yahoo < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results else :madison_square_garden end @@ -91,10 +91,10 @@ module Geocoder class Yandex < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results when "invalid key"; :invalid_key else :kremlin @@ -105,13 +105,13 @@ module Geocoder class GeocoderCa < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - if reverse + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + if query.reverse_geocode? read_fixture "geocoder_ca_reverse.json" else - file = case query + file = case query.text when "no results"; :no_results else :madison_square_garden end @@ -122,10 +122,10 @@ module Geocoder class Freegeoip < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results else "74_200_247_59" end @@ -135,13 +135,13 @@ module Geocoder class Bing < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - if reverse + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + if query.reverse_geocode? read_fixture "bing_reverse.json" else - file = case query + file = case query.text when "no results"; :no_results else :madison_square_garden end @@ -152,10 +152,10 @@ module Geocoder class Nominatim < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results else :madison_square_garden end @@ -165,10 +165,10 @@ module Geocoder class Mapquest < Base private #----------------------------------------------------------------- - def fetch_raw_data(query, reverse = false) - raise TimeoutError if query == "timeout" - raise SocketError if query == "socket_error" - file = case query + def fetch_raw_data(query) + raise TimeoutError if query.text == "timeout" + raise SocketError if query.text == "socket_error" + file = case query.text when "no results"; :no_results else :madison_square_garden end @@ -277,18 +277,6 @@ class Test::Unit::TestCase }[abbrev] end - def all_lookups - Geocoder.valid_lookups - end - - def all_lookups_except_test - Geocoder.valid_lookups_except_test - end - - def street_lookups - Geocoder.street_lookups - end - def is_nan_coordinates?(coordinates) return false unless coordinates.respond_to? :size # Should be an array return false unless coordinates.size == 2 # Should have dimension 2 -- GitLab