require 'helper' class GeoipFilterTest < Test::Unit::TestCase def setup omit_unless(Fluent.const_defined?(:Filter)) Fluent::Test.setup @time = Fluent::Engine.now end def create_driver(conf='', tag='test', use_v1=false) Fluent::Test::FilterTestDriver.new(Fluent::GeoipFilter, tag).configure(conf, use_v1) end def filter(config, messages, use_v1=false) d = create_driver(config, 'test', use_v1) yield d if block_given? d.run { messages.each {|message| d.filter(message, @time) } } filtered = d.filtered_as_array filtered.map {|m| m[2] } end def setup_geoip_mock(d) geoip = d.instance.instance_variable_get(:@geoip) db = Object.new def db.lookup(ip) {} end geoip.instance_variable_set(:@geoip, db) end sub_test_case "configure" do test "empty" do assert_nothing_raised { create_driver('') } end test "missing required parameters" do assert_raise(Fluent::ConfigError) { create_driver('enable_key_cities') } end test "minimum" do d = create_driver %[ enable_key_city geoip_city ] assert_equal 'geoip_city', d.instance.config['enable_key_city'] end test "multiple key config" do d = create_driver %[ geoip_lookup_key from.ip, to.ip enable_key_city from_city, to_city ] assert_equal 'from_city, to_city', d.instance.config['enable_key_city'] end test "multiple key config (bad configure)" do assert_raise(Fluent::ConfigError) { create_driver %[ geoip_lookup_key from.ip, to.ip enable_key_city from_city enable_key_region from_region ] } end test "invalid json structure w/ Ruby hash like" do assert_raise(Fluent::ConfigError) { create_driver %[ geoip_lookup_key host invalid_json {"foo" => 123} ] } end test "invalid json structure w/ unquoted string literal" do assert_raise(Fluent::ConfigError) { create_driver %[ geoip_lookup_key host invalid_json {"foo" : string, "bar" : 123} ] } end data(geoip: "geoip", geoip2_compat: "geoip2_compat") test "unsupported key" do |backend| assert_raise(Fluent::ConfigError.new("#{backend}: unsupported key unknown")) do create_driver %[ backend_library #{backend} city ${unknown["host"]} ] end end data(geoip: ["geoip", '${city["host"]}'], geoip2_compat: ["geoip2_compat", '${city["host"]}'], geoip2_c: ["geoip2_c", '${city.names.en["host"]}']) test "supported backend" do |(backend, placeholder)| create_driver %[ backend_library #{backend} city #{placeholder} ] end test "unsupported backend" do assert_raise(Fluent::ConfigError) do create_driver %[ backend_library hive_geoip2 city ${city["host"]} ] end end end sub_test_case "geoip2_c" do def test_filter_with_include_tag_key config = %[ backend_library geoip2_c geoip_lookup_key ip.origin, ip.dest origin_country ${country.iso_code['ip.origin']} dest_country ${country.iso_code['ip.dest']} include_tag_key true ] messages = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'} ] expected = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8', 'origin_country' => 'US', 'dest_country' => 'US', 'tag' => 'test' } ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_dot_key config = %[ backend_library geoip2_c geoip_lookup_key ip.origin, ip.dest origin_country ${country.iso_code['ip.origin']} dest_country ${country.iso_code['ip.dest']} ] messages = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'} ] expected = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8', 'origin_country' => 'US', 'dest_country' => 'US'} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_unknown_address config = %[ backend_library geoip2_c geoip_lookup_key host geoip_city ${city.names.en['host']} geopoint [${location.longitude['host']}, ${location.latitude['host']}] skip_adding_null_record false ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]}, {'host' => '0', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_skip_unknown_address config = %[ backend_library geoip2_c geoip_lookup_key host geoip_city ${city.names.en['host']} geopoint [${location.longitude['host']}, ${location.latitude['host']}] skip_adding_null_record true ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot', 'geoip_city' => 'Mountain View', 'geopoint' => [-122.0574, 37.419200000000004]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_record_directive config = %[ backend_library geoip2_c geoip_lookup_key from.ip from_city ${city.names.en['from.ip']} from_country ${country.names.en['from.ip']} latitude ${location.latitude['from.ip']} longitude ${location.longitude['from.ip']} float_concat ${location.latitude['from.ip']},${location.longitude['from.ip']} float_array [${location.longitude['from.ip']}, ${location.latitude['from.ip']}] float_nest { "lat" : ${location.latitude['from.ip']}, "lon" : ${location.longitude['from.ip']}} string_concat ${city.names.en['from.ip']},${country.names.en['from.ip']} string_array [${city.names.en['from.ip']}, ${country.names.en['from.ip']}] string_nest { "city" : ${city.names.en['from.ip']}, "country_name" : ${country.names.en['from.ip']}} unknown_city ${city.names.en['unknown_key']} undefined ${city.names.en['undefined']} broken_array1 [${location.longitude['from.ip']}, ${location.latitude['undefined']}] broken_array2 [${location.longitude['undefined']}, ${location.latitude['undefined']}] ] messages = [ { 'from' => {'ip' => '66.102.3.80'} }, { 'message' => 'missing field' }, ] expected = [ { 'from' => {'ip' => '66.102.3.80'}, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'latitude' => 37.419200000000004, 'longitude' => -122.0574, 'float_concat' => '37.419200000000004,-122.0574', 'float_array' => [-122.0574, 37.419200000000004], 'float_nest' => { 'lat' => 37.4192000000000004, 'lon' => -122.0574 }, 'string_concat' => 'Mountain View,United States', 'string_array' => ["Mountain View", "United States"], 'string_nest' => {"city" => "Mountain View", "country_name" => "United States"}, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [-122.0574, nil], 'broken_array2' => [nil, nil] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'latitude' => nil, 'longitude' => nil, 'float_concat' => ',', 'float_array' => [nil, nil], 'float_nest' => { 'lat' => nil, 'lon' => nil }, 'string_concat' => ',', 'string_array' => [nil, nil], 'string_nest' => { "city" => nil, "country_name" => nil }, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [nil, nil], 'broken_array2' => [nil, nil] }, ] filtered = filter(config, messages) # test-unit cannot calculate diff between large Array assert_equal(expected[0], filtered[0]) assert_equal(expected[1], filtered[1]) end def test_filter_record_directive_multiple_record config = %[ backend_library geoip2_c geoip_lookup_key from.ip, to.ip from_city ${city.names.en['from.ip']} to_city ${city.names.en['to.ip']} from_country ${country.names.en['from.ip']} to_country ${country.names.en['to.ip']} string_array [${country.names.en['from.ip']}, ${country.names.en['to.ip']}] ] messages = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}}, {'message' => 'missing field'} ] expected = [ { 'from' => { 'ip' => '66.102.3.80' }, 'to' => { 'ip' => '125.54.15.42' }, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'to_city' => 'Tokorozawa', 'to_country' => 'Japan', 'string_array' => ['United States', 'Japan'] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'to_city' => nil, 'to_country' => nil, 'string_array' => [nil, nil] } ] filtered = filter(config, messages) assert_equal(expected, filtered) end def config_quoted_record %[ backend_library geoip2_c geoip_lookup_key host location_properties '{ "country_code" : "${country.iso_code["host"]}", "lat": ${location.latitude["host"]}, "lon": ${location.longitude["host"]} }' location_string ${location.latitude['host']},${location.longitude['host']} location_string2 ${country.iso_code["host"]} location_array "[${location.longitude['host']},${location.latitude['host']}]" location_array2 '[${location.longitude["host"]},${location.latitude["host"]}]' peculiar_pattern '[GEOIP] message => {"lat":${location.latitude["host"]}, "lon":${location.longitude["host"]}}' ] end def test_filter_quoted_record messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.419200000000004, 'lon' => -122.0574 }, 'location_string' => '37.419200000000004,-122.0574', 'location_string2' => 'US', 'location_array' => [-122.0574, 37.419200000000004], 'location_array2' => [-122.0574, 37.419200000000004], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}' } ] filtered = filter(config_quoted_record, messages) assert_equal(expected, filtered) end def test_filter_v1_config_compatibility messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.419200000000004, 'lon' => -122.0574 }, 'location_string' => '37.419200000000004,-122.0574', 'location_string2' => 'US', 'location_array' => [-122.0574, 37.419200000000004], 'location_array2' => [-122.0574, 37.419200000000004], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}' } ] filtered = filter(config_quoted_record, messages, true) assert_equal(expected, filtered) end def test_filter_multiline_v1_config config = %[ backend_library geoip2_c geoip_lookup_key host location_properties { "city": "${city.names.en['host']}", "country_code": "${country.iso_code['host']}", "latitude": "${location.latitude['host']}", "longitude": "${location.longitude['host']}" } ] messages = [ { 'host' => '66.102.3.80', 'message' => 'valid ip' } ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', "location_properties" => { "city" => "Mountain View", "country_code" => "US", "latitude" => 37.419200000000004, "longitude" => -122.0574 } } ] filtered = filter(config, messages, true) assert_equal(expected, filtered) end def test_filter_when_latitude_longitude_is_nil config = %[ backend_library geoip2_c geoip_lookup_key host latitude ${location.latitude['host']} longitude ${location.longitude['host']} ] messages = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude" } ] expected = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude", "latitude" => 0.0, "longitude" => 0.0 } ] filtered = filter(config, messages) do |d| setup_geoip_mock(d) end assert_equal(expected, filtered) end end sub_test_case "geoip2_compat" do def test_filter_with_dot_key config = %[ backend_library geoip2_compat geoip_lookup_key ip.origin, ip.dest origin_country ${country_code['ip.origin']} dest_country ${country_code['ip.dest']} ] messages = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'} ] expected = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8', 'origin_country' => 'US', 'dest_country' => 'US'} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_unknown_address config = %[ backend_library geoip2_compat geoip_lookup_key host geoip_city ${city['host']} geopoint [${longitude['host']}, ${latitude['host']}] skip_adding_null_record false ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]}, {'host' => '0', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_skip_unknown_address config = %[ backend_library geoip2_compat geoip_lookup_key host geoip_city ${city['host']} geopoint [${longitude['host']}, ${latitude['host']}] skip_adding_null_record true ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot', 'geoip_city' => 'Mountain View', 'geopoint' => [-122.0574, 37.419200000000004]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_record_directive config = %[ backend_library geoip2_compat geoip_lookup_key from.ip from_city ${city['from.ip']} from_country ${country_name['from.ip']} latitude ${latitude['from.ip']} longitude ${longitude['from.ip']} float_concat ${latitude['from.ip']},${longitude['from.ip']} float_array [${longitude['from.ip']}, ${latitude['from.ip']}] float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}} string_concat ${city['from.ip']},${country_name['from.ip']} string_array [${city['from.ip']}, ${country_name['from.ip']}] string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}} unknown_city ${city['unknown_key']} undefined ${city['undefined']} broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}] broken_array2 [${longitude['undefined']}, ${latitude['undefined']}] ] messages = [ { 'from' => {'ip' => '66.102.3.80'} }, { 'message' => 'missing field' }, ] expected = [ { 'from' => {'ip' => '66.102.3.80'}, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'latitude' => 37.419200000000004, 'longitude' => -122.0574, 'float_concat' => '37.419200000000004,-122.0574', 'float_array' => [-122.0574, 37.419200000000004], 'float_nest' => { 'lat' => 37.4192000000000004, 'lon' => -122.0574 }, 'string_concat' => 'Mountain View,United States', 'string_array' => ["Mountain View", "United States"], 'string_nest' => {"city" => "Mountain View", "country_name" => "United States"}, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [-122.0574, nil], 'broken_array2' => [nil, nil] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'latitude' => nil, 'longitude' => nil, 'float_concat' => ',', 'float_array' => [nil, nil], 'float_nest' => { 'lat' => nil, 'lon' => nil }, 'string_concat' => ',', 'string_array' => [nil, nil], 'string_nest' => { "city" => nil, "country_name" => nil }, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [nil, nil], 'broken_array2' => [nil, nil] }, ] filtered = filter(config, messages) # test-unit cannot calculate diff between large Array assert_equal(expected[0], filtered[0]) assert_equal(expected[1], filtered[1]) end def test_filter_record_directive_multiple_record config = %[ backend_library geoip2_compat geoip_lookup_key from.ip, to.ip from_city ${city['from.ip']} to_city ${city['to.ip']} from_country ${country_name['from.ip']} to_country ${country_name['to.ip']} string_array [${country_name['from.ip']}, ${country_name['to.ip']}] ] messages = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}}, {'message' => 'missing field'} ] expected = [ { 'from' => { 'ip' => '66.102.3.80' }, 'to' => { 'ip' => '125.54.15.42' }, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'to_city' => 'Tokorozawa', 'to_country' => 'Japan', 'string_array' => ['United States', 'Japan'] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'to_city' => nil, 'to_country' => nil, 'string_array' => [nil, nil] } ] filtered = filter(config, messages) assert_equal(expected, filtered) end def config_quoted_record %[ backend_library geoip2_compat geoip_lookup_key host location_properties '{ "country_code" : "${country_code["host"]}", "lat": ${latitude["host"]}, "lon": ${longitude["host"]} }' location_string ${latitude['host']},${longitude['host']} location_string2 ${country_code["host"]} location_array "[${longitude['host']},${latitude['host']}]" location_array2 '[${longitude["host"]},${latitude["host"]}]' peculiar_pattern '[GEOIP] message => {"lat":${latitude["host"]}, "lon":${longitude["host"]}}' ] end def test_filter_quoted_record messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.419200000000004, 'lon' => -122.0574 }, 'location_string' => '37.419200000000004,-122.0574', 'location_string2' => 'US', 'location_array' => [-122.0574, 37.419200000000004], 'location_array2' => [-122.0574, 37.419200000000004], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}' } ] filtered = filter(config_quoted_record, messages) assert_equal(expected, filtered) end def test_filter_v1_config_compatibility messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.419200000000004, 'lon' => -122.0574 }, 'location_string' => '37.419200000000004,-122.0574', 'location_string2' => 'US', 'location_array' => [-122.0574, 37.419200000000004], 'location_array2' => [-122.0574, 37.419200000000004], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.419200000000004, "lon":-122.0574}' } ] filtered = filter(config_quoted_record, messages, true) assert_equal(expected, filtered) end def test_filter_multiline_v1_config config = %[ backend_library geoip2_compat geoip_lookup_key host location_properties { "city": "${city['host']}", "country_code": "${country_code['host']}", "latitude": "${latitude['host']}", "longitude": "${longitude['host']}" } ] messages = [ { 'host' => '66.102.3.80', 'message' => 'valid ip' } ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', "location_properties" => { "city" => "Mountain View", "country_code" => "US", "latitude" => 37.419200000000004, "longitude" => -122.0574 } } ] filtered = filter(config, messages, true) assert_equal(expected, filtered) end def test_filter_when_latitude_longitude_is_nil config = %[ backend_library geoip2_compat geoip_lookup_key host latitude ${latitude['host']} longitude ${longitude['host']} ] messages = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude" } ] expected = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude", "latitude" => 0.0, "longitude" => 0.0 } ] filtered = filter(config, messages) do |d| setup_geoip_mock(d) end assert_equal(expected, filtered) end def test_filter_with_include_tag_key config = %[ backend_library geoip2_compat geoip_lookup_key host enable_key_city geoip_city include_tag_key true ] messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'}, {'message' => 'missing field'}, ] expected = [ {'host' => '66.102.3.80', 'message' => 'valid ip', 'geoip_city' => 'Mountain View', 'tag' => 'test'}, {'message' => 'missing field', 'geoip_city' => nil, 'tag' => 'test'}, ] filtered = filter(config, messages) assert_equal(expected, filtered) end end sub_test_case "geoip legacy" do def test_filter config = %[ geoip_lookup_key host enable_key_city geoip_city ] messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'}, {'message' => 'missing field'}, ] expected = [ {'host' => '66.102.3.80', 'message' => 'valid ip', 'geoip_city' => 'Mountain View'}, {'message' => 'missing field', 'geoip_city' => nil}, ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_dot_key config = %[ geoip_lookup_key ip.origin, ip.dest origin_country ${country_code['ip.origin']} dest_country ${country_code['ip.dest']} ] messages = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8'} ] expected = [ {'ip.origin' => '66.102.3.80', 'ip.dest' => '8.8.8.8', 'origin_country' => 'US', 'dest_country' => 'US'} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_nested_attr config = %[ geoip_lookup_key host.ip enable_key_city geoip_city ] messages = [ {'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip'}, {'message' => 'missing field'} ] expected = [ {'host' => {'ip' => '66.102.3.80'}, 'message' => 'valid ip', 'geoip_city' => 'Mountain View'}, {'message' => 'missing field', 'geoip_city' => nil} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_unknown_address config = %[ geoip_lookup_key host geoip_city ${city['host']} geopoint [${longitude['host']}, ${latitude['host']}] skip_adding_null_record false ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]}, {'host' => '0', 'message' => 'invalid ip', 'geoip_city' => nil, 'geopoint' => [nil, nil]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_with_skip_unknown_address config = %[ geoip_lookup_key host geoip_city ${city['host']} geopoint [${longitude['host']}, ${latitude['host']}] skip_adding_null_record true ] # 203.0.113.1 is a test address described in RFC5737 messages = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot'} ] expected = [ {'host' => '203.0.113.1', 'message' => 'invalid ip'}, {'host' => '0', 'message' => 'invalid ip'}, {'host' => '66.102.3.80', 'message' => 'google bot', 'geoip_city' => 'Mountain View', 'geopoint' => [-122.05740356445312, 37.4192008972168]} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_multiple_key config = %[ geoip_lookup_key from.ip, to.ip enable_key_city from_city, to_city ] messages = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}}, {'message' => 'missing field'} ] expected = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}, 'from_city' => 'Mountain View', 'to_city' => 'Tokorozawa'}, {'message' => 'missing field', 'from_city' => nil, 'to_city' => nil} ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_multiple_key_multiple_record config = %[ geoip_lookup_key from.ip, to.ip enable_key_city from_city, to_city enable_key_country_name from_country, to_country ] messages = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}}, {'from' => {'ip' => '66.102.3.80'}}, {'message' => 'missing field'} ] expected = [ { 'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'to_city' => 'Tokorozawa', 'to_country' => 'Japan' }, { 'from' => {'ip' => '66.102.3.80'}, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'to_city' => nil, 'to_country' => nil }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'to_city' => nil, 'to_country' => nil } ] filtered = filter(config, messages) assert_equal(expected, filtered) end def test_filter_record_directive config = %[ geoip_lookup_key from.ip from_city ${city['from.ip']} from_country ${country_name['from.ip']} latitude ${latitude['from.ip']} longitude ${longitude['from.ip']} float_concat ${latitude['from.ip']},${longitude['from.ip']} float_array [${longitude['from.ip']}, ${latitude['from.ip']}] float_nest { "lat" : ${latitude['from.ip']}, "lon" : ${longitude['from.ip']}} string_concat ${city['from.ip']},${country_name['from.ip']} string_array [${city['from.ip']}, ${country_name['from.ip']}] string_nest { "city" : ${city['from.ip']}, "country_name" : ${country_name['from.ip']}} unknown_city ${city['unknown_key']} undefined ${city['undefined']} broken_array1 [${longitude['from.ip']}, ${latitude['undefined']}] broken_array2 [${longitude['undefined']}, ${latitude['undefined']}] ] messages = [ { 'from' => {'ip' => '66.102.3.80'} }, { 'message' => 'missing field' }, ] expected = [ { 'from' => {'ip' => '66.102.3.80'}, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'latitude' => 37.4192008972168, 'longitude' => -122.05740356445312, 'float_concat' => '37.4192008972168,-122.05740356445312', 'float_array' => [-122.05740356445312, 37.4192008972168], 'float_nest' => { 'lat' => 37.4192008972168, 'lon' => -122.05740356445312 }, 'string_concat' => 'Mountain View,United States', 'string_array' => ["Mountain View", "United States"], 'string_nest' => {"city" => "Mountain View", "country_name" => "United States"}, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [-122.05740356445312, nil], 'broken_array2' => [nil, nil] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'latitude' => nil, 'longitude' => nil, 'float_concat' => ',', 'float_array' => [nil, nil], 'float_nest' => { 'lat' => nil, 'lon' => nil }, 'string_concat' => ',', 'string_array' => [nil, nil], 'string_nest' => { "city" => nil, "country_name" => nil }, 'unknown_city' => nil, 'undefined' => nil, 'broken_array1' => [nil, nil], 'broken_array2' => [nil, nil] }, ] filtered = filter(config, messages) # test-unit cannot calculate diff between large Array assert_equal(expected[0], filtered[0]) assert_equal(expected[1], filtered[1]) end def test_filter_record_directive_multiple_record config = %[ geoip_lookup_key from.ip, to.ip from_city ${city['from.ip']} to_city ${city['to.ip']} from_country ${country_name['from.ip']} to_country ${country_name['to.ip']} string_array [${country_name['from.ip']}, ${country_name['to.ip']}] ] messages = [ {'from' => {'ip' => '66.102.3.80'}, 'to' => {'ip' => '125.54.15.42'}}, {'message' => 'missing field'} ] expected = [ { 'from' => { 'ip' => '66.102.3.80' }, 'to' => { 'ip' => '125.54.15.42' }, 'from_city' => 'Mountain View', 'from_country' => 'United States', 'to_city' => 'Tokorozawa', 'to_country' => 'Japan', 'string_array' => ['United States', 'Japan'] }, { 'message' => 'missing field', 'from_city' => nil, 'from_country' => nil, 'to_city' => nil, 'to_country' => nil, 'string_array' => [nil, nil] } ] filtered = filter(config, messages) assert_equal(expected, filtered) end def config_quoted_record %[ geoip_lookup_key host location_properties '{ "country_code" : "${country_code["host"]}", "lat": ${latitude["host"]}, "lon": ${longitude["host"]} }' location_string ${latitude['host']},${longitude['host']} location_string2 ${country_code["host"]} location_array "[${longitude['host']},${latitude['host']}]" location_array2 '[${longitude["host"]},${latitude["host"]}]' peculiar_pattern '[GEOIP] message => {"lat":${latitude["host"]}, "lon":${longitude["host"]}}' ] end def test_filter_quoted_record messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.4192008972168, 'lon' => -122.05740356445312 }, 'location_string' => '37.4192008972168,-122.05740356445312', 'location_string2' => 'US', 'location_array' => [-122.05740356445312, 37.4192008972168], 'location_array2' => [-122.05740356445312, 37.4192008972168], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.4192008972168, "lon":-122.05740356445312}' } ] filtered = filter(config_quoted_record, messages) assert_equal(expected, filtered) end def test_filter_v1_config_compatibility messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'} ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', 'location_properties' => { 'country_code' => 'US', 'lat' => 37.4192008972168, 'lon' => -122.05740356445312 }, 'location_string' => '37.4192008972168,-122.05740356445312', 'location_string2' => 'US', 'location_array' => [-122.05740356445312, 37.4192008972168], 'location_array2' => [-122.05740356445312, 37.4192008972168], 'peculiar_pattern' => '[GEOIP] message => {"lat":37.4192008972168, "lon":-122.05740356445312}' } ] filtered = filter(config_quoted_record, messages, true) assert_equal(expected, filtered) end def test_filter_multiline_v1_config config = %[ geoip_lookup_key host location_properties { "city": "${city['host']}", "country_code": "${country_code['host']}", "latitude": "${latitude['host']}", "longitude": "${longitude['host']}" } ] messages = [ { 'host' => '66.102.3.80', 'message' => 'valid ip' } ] expected = [ { 'host' => '66.102.3.80', 'message' => 'valid ip', "location_properties" => { "city" => "Mountain View", "country_code" => "US", "latitude" => 37.4192008972168, "longitude" => -122.05740356445312 } } ] filtered = filter(config, messages, true) assert_equal(expected, filtered) end def test_filter_when_latitude_longitude_is_nil config = %[ backend_library geoip geoip_lookup_key host latitude ${latitude['host']} longitude ${longitude['host']} ] messages = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude" } ] expected = [ { "host" => "180.94.85.84", "message" => "nil latitude and longitude", "latitude" => 0.0, "longitude" => 0.0 } ] filtered = filter(config, messages) do |d| setup_geoip_mock(d) end assert_equal(expected, filtered) end def test_filter_with_include_tag_key config = %[ geoip_lookup_key host enable_key_city geoip_city include_tag_key true ] messages = [ {'host' => '66.102.3.80', 'message' => 'valid ip'}, {'message' => 'missing field'}, ] expected = [ {'host' => '66.102.3.80', 'message' => 'valid ip', 'geoip_city' => 'Mountain View', 'tag' => 'test'}, {'message' => 'missing field', 'geoip_city' => nil, 'tag' => 'test'}, ] filtered = filter(config, messages) assert_equal(expected, filtered) end end end