package org.rakam.collection.mapper.geoip.maxmind;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import io.netty.handler.codec.http.cookie.Cookie;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericData.Record;
import org.rakam.collection.Event;
import org.rakam.collection.FieldDependencyBuilder;
import org.rakam.collection.SchemaField;
import org.rakam.plugin.EventMapper;
import org.rakam.util.AvroUtil;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.apache.avro.Schema.Type.NULL;
import static org.apache.avro.Schema.Type.STRING;
import static org.testng.Assert.*;
public class TestGeoIPEventMapper
{
@DataProvider(name = "google-ips")
public static Object[][] hashEnabledValuesProvider()
throws UnknownHostException
{
return new Object[][] {
// even if these are Google's ip Maxmind demo database may not identify so don't rely on their popularity.
{ImmutableMap.of("_ip", "8.8.8.8"), InetAddress.getLocalHost()},
{ImmutableMap.of("_ip", true), InetAddress.getByName("8.8.8.8")},
{ImmutableMap.of("_ip", "8.8.8.8"), InetAddress.getByName("8.8.8.8")}
};
}
@Test(dataProvider = "google-ips")
public void testIspEventMapper(Map<String, Object> props, InetAddress address)
throws Exception
{
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(new MaxmindGeoIPModuleConfig()
.setAttributes("")
.setIspDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-ISP-Test.mmdb")));
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
Record properties = new Record(Schema.createRecord(ImmutableList.of(
new Schema.Field("_ip", Schema.create(NULL), null, null),
new Schema.Field("__ip", Schema.create(STRING), null, null),
new Schema.Field("_isp", Schema.create(STRING), null, null))));
props.forEach(properties::put);
Event event = new Event("testproject", "testcollection", null, null, properties);
List<Cookie> resp = mapper.map(event, EventMapper.RequestParams.EMPTY_PARAMS, address, null);
assertTrue(resp == null);
assertEquals(event.getAttribute("_isp"), "Level 3 Communications");
GenericData.get().validate(properties.getSchema(), properties);
}
@Test(dataProvider = "google-ips")
public void testConnectionTypeEventMapper(Map<String, Object> props, InetAddress address)
throws Exception
{
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(new MaxmindGeoIPModuleConfig()
.setAttributes("")
.setConnectionTypeDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-Connection-Type-Test.mmdb")));
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
Record properties = new Record(Schema.createRecord(ImmutableList.of(
new Schema.Field("_ip", Schema.create(NULL), null, null),
new Schema.Field("__ip", Schema.create(STRING), null, null),
new Schema.Field("_connection_type", Schema.create(STRING), null, null))));
props.forEach(properties::put);
Event event = new Event("testproject", "testcollection", null, null, properties);
List<Cookie> resp = mapper.map(event, EventMapper.RequestParams.EMPTY_PARAMS, address, null);
assertTrue(resp == null);
// TODO: find a reliable ip that can be mapped.
assertNull(event.getAttribute("connection_type"));
GenericData.get().validate(properties.getSchema(), properties);
}
@Test(dataProvider = "google-ips")
public void testEventMapper(Map<String, Object> props, InetAddress address)
throws Exception
{
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(new MaxmindGeoIPModuleConfig());
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
ImmutableList<Schema.Field> build = ImmutableList.<Schema.Field>builder()
.addAll(builder.build().dependentFields.get("_ip").stream()
.map(AvroUtil::generateAvroField).collect(Collectors.toList()))
.add(new Schema.Field("_ip", Schema.create(NULL), null, null))
.build();
Record properties = new Record(Schema.createRecord(build));
props.forEach(properties::put);
Event event = new Event("testproject", "testcollection", null, null, properties);
List<Cookie> resp = mapper.map(event, EventMapper.RequestParams.EMPTY_PARAMS, address, null);
assertTrue(resp == null);
assertTrue(event.properties().getSchema().getField("_country_code") != null);
assertTrue(event.properties().getSchema().getField("_city") != null);
assertTrue(event.properties().getSchema().getField("_timezone") != null);
assertTrue(event.getAttribute("_latitude") instanceof Double);
assertTrue(event.properties().getSchema().getField("_region") != null);
assertTrue(event.getAttribute("_longitude") instanceof Double);
GenericData.get().validate(properties.getSchema(), properties);
}
@Test
public void testNotFoundIpEventMapper()
throws Exception
{
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(new MaxmindGeoIPModuleConfig()
.setConnectionTypeDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-Connection-Type-Test.mmdb"))
.setIspDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-ISP-Test.mmdb")));
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
List<SchemaField> ip = builder.build().dependentFields.get("_ip");
ImmutableList<Schema.Field> build = ImmutableList.<Schema.Field>builder()
.addAll(ip.stream().map(AvroUtil::generateAvroField).collect(Collectors.toList()))
.add(new Schema.Field("_ip", Schema.create(NULL), null, null))
.build();
Record properties = new Record(Schema.createRecord(build));
properties.put("_ip", "127.0.0.1");
Event event = new Event("testproject", "testcollection", null, null, properties);
List<Cookie> resp = mapper.map(event, EventMapper.RequestParams.EMPTY_PARAMS, InetAddress.getLocalHost(), null);
assertTrue(resp == null);
for (SchemaField schemaField : ip) {
if (!schemaField.getName().equals("__ip")) {
assertNull(event.getAttribute(schemaField.getName()));
}
}
}
@Test
public void testNotTrackFlagIpEventMapper()
throws Exception
{
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(new MaxmindGeoIPModuleConfig()
.setConnectionTypeDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-Connection-Type-Test.mmdb"))
.setIspDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-ISP-Test.mmdb")));
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
List<SchemaField> ip = builder.build().dependentFields.get("_ip");
ImmutableList<Schema.Field> build = ImmutableList.<Schema.Field>builder()
.addAll(ip.stream().map(AvroUtil::generateAvroField).collect(Collectors.toList()))
.add(new Schema.Field("_ip", Schema.create(NULL), null, null))
.build();
Record properties = new Record(Schema.createRecord(build));
properties.put("_ip", false);
Event event = new Event("testproject", "testcollection", null, null, properties);
List<Cookie> resp = mapper.map(event, EventMapper.RequestParams.EMPTY_PARAMS, InetAddress.getByName("8.8.8.8"), null);
assertTrue(resp == null);
for (SchemaField schemaField : ip) {
assertNull(event.getAttribute(schemaField.getName()));
}
}
@Test
public void testFieldDependency()
throws Exception
{
MaxmindGeoIPModuleConfig config = new MaxmindGeoIPModuleConfig().setAttributes(list.stream().collect(Collectors.joining(",")));
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(config);
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
FieldDependencyBuilder.FieldDependency build = builder.build();
assertEquals(0, build.constantFields.size());
assertEquals(1, build.dependentFields.size());
assertEquals(list.stream().map(a -> "_" + a).collect(Collectors.toSet()),
build.dependentFields.get("_ip").stream().map(SchemaField::getName)
.collect(Collectors.toSet()));
}
private static Set<String> list = ImmutableSet.of(
"city", "region", "_ip",
"country_code", "latitude",
"longitude", "timezone");
@Test
public void testFieldDependencyWithAll()
throws Exception
{
MaxmindGeoIPModuleConfig config = new MaxmindGeoIPModuleConfig()
.setAttributes(list.stream().collect(Collectors.joining(",")))
.setConnectionTypeDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-Connection-Type-Test.mmdb"))
.setIspDatabaseUrl(new URL("https://github.com/maxmind/MaxMind-DB/raw/master/test-data/GeoIP2-ISP-Test.mmdb"));
MaxmindGeoIPEventMapper mapper = new MaxmindGeoIPEventMapper(config);
FieldDependencyBuilder builder = new FieldDependencyBuilder();
mapper.addFieldDependency(builder);
FieldDependencyBuilder.FieldDependency build = builder.build();
assertEquals(0, build.constantFields.size());
assertEquals(1, build.dependentFields.size());
assertEquals(ImmutableSet.builder().addAll(list.stream().map(e -> "_" + e).collect(Collectors.toList())).add("_isp", "_connection_type").build(),
build.dependentFields.get("_ip").stream().map(SchemaField::getName).collect(Collectors.toSet()));
}
}