blob: dc50126f0661895c2a1b4c7310dc36f40e8d11cf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.druid.query.lookup.namespace;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Module;
import org.apache.druid.common.config.NullHandling;
import org.apache.druid.guice.GuiceAnnotationIntrospector;
import org.apache.druid.guice.GuiceInjectableValues;
import org.apache.druid.guice.annotations.Json;
import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.util.Map;
/**
*
*/
public class UriExtractionNamespaceTest
{
static {
NullHandling.initializeForTests();
}
public static ObjectMapper registerTypes(
final ObjectMapper mapper
)
{
mapper.setInjectableValues(
new GuiceInjectableValues(
Guice.createInjector(
ImmutableList.of(
new Module()
{
@Override
public void configure(Binder binder)
{
binder.bind(ObjectMapper.class).annotatedWith(Json.class).toInstance(mapper);
binder.bind(ObjectMapper.class).toInstance(mapper);
}
}
)
)
)
).registerSubtypes(UriExtractionNamespace.class, UriExtractionNamespace.FlatDataParser.class);
final GuiceAnnotationIntrospector guiceIntrospector = new GuiceAnnotationIntrospector();
mapper.setAnnotationIntrospectors(
new AnnotationIntrospectorPair(
guiceIntrospector,
mapper.getSerializationConfig().getAnnotationIntrospector()
),
new AnnotationIntrospectorPair(
guiceIntrospector,
mapper.getDeserializationConfig().getAnnotationIntrospector()
)
);
return mapper;
}
@Test
public void testCSV()
{
UriExtractionNamespace.CSVFlatDataParser parser = new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of(
"col1",
"col2",
"col3"
), "col2", "col3"
);
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A,B,C"));
}
@Test
public void testCSVWithHeader()
{
UriExtractionNamespace.CSVFlatDataParser parser = new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3"),
"col2",
"col3",
true,
1
);
// parser return empyt list as the 1 row header need to be skipped.
Assert.assertEquals(ImmutableMap.of(), parser.getParser().parseToMap("row to skip "));
//Header also need to be skipped.
Assert.assertEquals(ImmutableMap.of(), parser.getParser().parseToMap("col1,col2,col3"));
// test the header is parsed
Assert.assertEquals(ImmutableList.of("col1", "col2", "col3"), parser.getParser().getFieldNames());
// The third row will parse to data
Assert.assertEquals(ImmutableMap.of("val2", "val3"), parser.getParser().parseToMap("val1,val2,val3"));
}
@Test(expected = IllegalArgumentException.class)
public void testBadCSV()
{
UriExtractionNamespace.CSVFlatDataParser parser = new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of(
"col1",
"col2",
"col3"
), "col2", "col3ADFSDF"
);
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A,B,C"));
}
@Test(expected = NullPointerException.class)
public void testBadCSV2()
{
UriExtractionNamespace.CSVFlatDataParser parser = new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of(
"col1",
"col2",
"col3"
), "col2", "col3"
);
Map<String, String> map = parser.getParser().parseToMap("A");
}
@Test
public void testTSV()
{
UriExtractionNamespace.TSVFlatDataParser parser = new UriExtractionNamespace.TSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3"),
"|",
null, "col2",
"col3"
);
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A|B|C"));
}
@Test
public void testWithListDelimiterTSV()
{
UriExtractionNamespace.TSVFlatDataParser parser = new UriExtractionNamespace.TSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3"),
"\\u0001",
"\\u0002", "col2",
"col3"
);
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A\\u0001B\\u0001C"));
}
@Test
public void testWithHeaderAndListDelimiterTSV()
{
UriExtractionNamespace.TSVFlatDataParser parser = new UriExtractionNamespace.TSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3"),
"\\u0001",
"\\u0002", "col2",
"col3",
true,
1
);
// skipping one row
Assert.assertEquals(ImmutableMap.of(), parser.getParser().parseToMap("Skipping some rows"));
// skip the header as well
Assert.assertEquals(ImmutableMap.of(), parser.getParser().parseToMap("col1\\u0001col2\\u0001col3"));
// test if the headers are parsed well.
Assert.assertEquals(ImmutableList.of("col1", "col2", "col3"), parser.getParser().getFieldNames());
// test if the data row is parsed correctly
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A\\u0001B\\u0001C"));
}
@Test(expected = IllegalArgumentException.class)
public void testBadTSV()
{
UriExtractionNamespace.TSVFlatDataParser parser = new UriExtractionNamespace.TSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3fdsfds"),
",",
null, "col2",
"col3"
);
Map<String, String> map = parser.getParser().parseToMap("A,B,C");
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A,B,C"));
}
@Test(expected = NullPointerException.class)
public void testBadTSV2()
{
UriExtractionNamespace.TSVFlatDataParser parser = new UriExtractionNamespace.TSVFlatDataParser(
ImmutableList.of("col1", "col2", "col3"),
",",
null, "col2",
"col3"
);
Map<String, String> map = parser.getParser().parseToMap("A");
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("A,B,C"));
}
@Test
public void testJSONFlatDataParser()
{
final String keyField = "keyField";
final String valueField = "valueField";
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
new ObjectMapper(),
keyField,
valueField
);
Assert.assertEquals(
ImmutableMap.of("B", "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%s\":\"B\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
valueField
)
)
);
}
@Test(expected = NullPointerException.class)
public void testJSONFlatDataParserBad()
{
final String keyField = "keyField";
final String valueField = "valueField";
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
new ObjectMapper(),
keyField,
valueField
);
Assert.assertEquals(
ImmutableMap.of("B", "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%sDFSDFDS\":\"B\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
valueField
)
)
);
}
@Test(expected = IllegalArgumentException.class)
public void testJSONFlatDataParserBad2()
{
final String keyField = "keyField";
final String valueField = "valueField";
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
registerTypes(new ObjectMapper()),
null,
valueField
);
Assert.assertEquals(
ImmutableMap.of("B", "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%sDFSDFDS\":\"B\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
valueField
)
)
);
}
@Test(expected = IllegalArgumentException.class)
public void testJSONFlatDataParserBad3()
{
final String keyField = "keyField";
final String valueField = "valueField";
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
registerTypes(new ObjectMapper()),
keyField,
null
);
Assert.assertEquals(
ImmutableMap.of("B", "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%sDFSDFDS\":\"B\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
valueField
)
)
);
}
@Test(expected = IllegalArgumentException.class)
public void testJSONFlatDataParserBad4()
{
final String keyField = "keyField";
final String valueField = "valueField";
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
registerTypes(new ObjectMapper()),
"",
""
);
Assert.assertEquals(
ImmutableMap.of("B", "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%sDFSDFDS\":\"B\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
valueField
)
)
);
}
@Test
public void testObjectMapperFlatDataParser()
{
UriExtractionNamespace.ObjectMapperFlatDataParser parser = new UriExtractionNamespace.ObjectMapperFlatDataParser(
registerTypes(new ObjectMapper())
);
Assert.assertEquals(ImmutableMap.of("B", "C"), parser.getParser().parseToMap("{\"B\":\"C\"}"));
}
@Test
public void testSimpleJSONSerDe() throws IOException
{
final ObjectMapper mapper = registerTypes(new DefaultObjectMapper());
for (UriExtractionNamespace.FlatDataParser parser : ImmutableList.of(
new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of(
"col1",
"col2",
"col3"
), "col2", "col3"
),
new UriExtractionNamespace.ObjectMapperFlatDataParser(mapper),
new UriExtractionNamespace.JSONFlatDataParser(mapper, "keyField", "valueField"),
new UriExtractionNamespace.TSVFlatDataParser(ImmutableList.of("A", "B"), ",", null, "A", "B")
)) {
final String str = mapper.writeValueAsString(parser);
final UriExtractionNamespace.FlatDataParser parser2 = mapper.readValue(
str,
UriExtractionNamespace.FlatDataParser.class
);
Assert.assertEquals(str, mapper.writeValueAsString(parser2));
}
}
@Test
public void testSimpleToString()
{
final ObjectMapper mapper = registerTypes(new DefaultObjectMapper());
for (UriExtractionNamespace.FlatDataParser parser : ImmutableList.of(
new UriExtractionNamespace.CSVFlatDataParser(
ImmutableList.of(
"col1",
"col2",
"col3"
), "col2", "col3"
),
new UriExtractionNamespace.ObjectMapperFlatDataParser(mapper),
new UriExtractionNamespace.JSONFlatDataParser(mapper, "keyField", "valueField"),
new UriExtractionNamespace.TSVFlatDataParser(ImmutableList.of("A", "B"), ",", null, "A", "B")
)) {
Assert.assertFalse(parser.toString().contains("@"));
}
}
@Test
public void testMatchedJson() throws IOException
{
final ObjectMapper mapper = registerTypes(new DefaultObjectMapper());
UriExtractionNamespace namespace = mapper.readValue(
"{\"type\":\"uri\", \"uriPrefix\":\"file:/foo\", \"namespaceParseSpec\":{\"format\":\"simpleJson\"}, \"pollPeriod\":\"PT5M\", \"versionRegex\":\"a.b.c\", \"namespace\":\"testNamespace\"}",
UriExtractionNamespace.class
);
Assert.assertEquals(
UriExtractionNamespace.ObjectMapperFlatDataParser.class.getName(),
namespace.getNamespaceParseSpec().getClass().getName()
);
Assert.assertEquals("file:/foo", namespace.getUriPrefix().toString());
Assert.assertEquals("a.b.c", namespace.getFileRegex());
Assert.assertEquals(5L * 60_000L, namespace.getPollMs());
}
@Test
public void testExplicitJson() throws IOException
{
final ObjectMapper mapper = registerTypes(new DefaultObjectMapper());
UriExtractionNamespace namespace = mapper.readValue(
"{\"type\":\"uri\", \"uri\":\"file:/foo\", \"namespaceParseSpec\":{\"format\":\"simpleJson\"}, \"pollPeriod\":\"PT5M\"}",
UriExtractionNamespace.class
);
Assert.assertEquals(
UriExtractionNamespace.ObjectMapperFlatDataParser.class.getName(),
namespace.getNamespaceParseSpec().getClass().getName()
);
Assert.assertEquals("file:/foo", namespace.getUri().toString());
Assert.assertEquals(5L * 60_000L, namespace.getPollMs());
}
@Test(expected = JsonMappingException.class)
public void testExplicitJsonException() throws IOException
{
final ObjectMapper mapper = registerTypes(new DefaultObjectMapper());
mapper.readValue(
"{\"type\":\"uri\", \"uri\":\"file:/foo\", \"namespaceParseSpec\":{\"format\":\"simpleJson\"}, \"pollPeriod\":\"PT5M\", \"versionRegex\":\"a.b.c\", \"namespace\":\"testNamespace\"}",
UriExtractionNamespace.class
);
}
@Test
public void testFlatDataNumeric()
{
final String keyField = "keyField";
final String valueField = "valueField";
final int n = 341879;
final String nString = StringUtils.format("%d", n);
UriExtractionNamespace.JSONFlatDataParser parser = new UriExtractionNamespace.JSONFlatDataParser(
new ObjectMapper(),
keyField,
valueField
);
Assert.assertEquals(
"num string value",
ImmutableMap.of("B", nString),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%s\":\"B\", \"%s\":\"%d\", \"FOO\":\"BAR\"}",
keyField,
valueField,
n
)
)
);
Assert.assertEquals(
"num string key",
ImmutableMap.of(nString, "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%s\":\"%d\", \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
n,
valueField
)
)
);
Assert.assertEquals(
"num value",
ImmutableMap.of("B", nString),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%s\":\"B\", \"%s\":%d, \"FOO\":\"BAR\"}",
keyField,
valueField,
n
)
)
);
Assert.assertEquals(
"num key",
ImmutableMap.of(nString, "C"),
parser.getParser()
.parseToMap(
StringUtils.format(
"{\"%s\":%d, \"%s\":\"C\", \"FOO\":\"BAR\"}",
keyField,
n,
valueField
)
)
);
}
@Test
public void testSimpleJsonNumeric()
{
final UriExtractionNamespace.ObjectMapperFlatDataParser parser = new UriExtractionNamespace.ObjectMapperFlatDataParser(
registerTypes(new DefaultObjectMapper())
);
final int n = 341879;
final String nString = StringUtils.format("%d", n);
Assert.assertEquals(
ImmutableMap.of("key", nString),
parser.getParser().parseToMap(StringUtils.format("{\"key\":%d}", n))
);
}
}