/*
* Licensed 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 com.addthis.hydra.task.map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.any;
import java.io.IOException;
import java.util.List;
import com.addthis.bundle.core.Bundle;
import com.addthis.bundle.core.list.ListBundle;
import com.addthis.bundle.value.ValueFactory;
import com.addthis.bundle.value.ValueMap;
import com.addthis.bundle.value.ValueObject;
import com.addthis.codec.config.Configs;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
public class StreamMapSplitBuilderTest {
StreamEmitter emitter;
Bundle bundle;
ValueMap map;
StreamMapSplitBuilder builder;
@Before
public void setup() throws IOException {
emitter = mock(StreamEmitter.class);
bundle = new ListBundle();
map = ValueFactory.createMap();
builder = Configs.decodeObject(StreamMapSplitBuilder.class, "field: foo, keyField: key, valueField: value");
}
@Test
public void basicFunctionality() {
map.put("hello", ValueFactory.create("boo"));
map.put("hi", ValueFactory.create("hoo"));
ValueMap map2 = ValueFactory.createMap();
map2.put("deep", ValueFactory.create("deeper"));
map.put("nest", map2);
bundle.setValue(bundle.getFormat().getField("foo"), map);
bundle.setValue(bundle.getFormat().getField("bar"), ValueFactory.create("biz"));
builder.process(bundle, emitter);
ArgumentCaptor<Bundle> bundleCapture = ArgumentCaptor.forClass(Bundle.class);
verify(emitter, times(3)).emit(bundleCapture.capture());
List<Bundle> newBundles = bundleCapture.getAllValues();
for (Bundle newBundle : newBundles) {
assertEquals("biz", newBundle.getValue(newBundle.getFormat().getField("bar")).asString().asNative());
String key = newBundle.getValue(newBundle.getFormat().getField("key")).asString().asNative();
assertTrue(key.equals("hello") || key.equals("hi") || key.equals("nest"));
if (key.equals("hello")) {
assertEquals("boo", newBundle.getValue(newBundle.getFormat().getField("value")).asString().asNative());
} else if (key.equals("hi")) {
assertEquals("hoo", newBundle.getValue(newBundle.getFormat().getField("value")).asString().asNative());
} else if (key.equals("nest")) {
assertEquals(ValueObject.TYPE.MAP, newBundle.getValue(newBundle.getFormat().getField("value")).getObjectType());
} else {
fail("An unexpected bundle was emitted");
}
}
}
@Test
public void noErrorsShouldBeThrown() {
// there is no map
builder.process(bundle, emitter);
// map not a map
bundle.setValue(bundle.getFormat().getField("foo"), ValueFactory.create("notamap"));
builder.process(bundle, emitter);
verify(emitter, never()).emit(any());
}
@Test
public void emitOriginal() throws IOException {
map.put("hello", ValueFactory.create("boo"));
map.put("hi", ValueFactory.create("hoo"));
bundle.setValue(bundle.getFormat().getField("foo"), map);
bundle.setValue(bundle.getFormat().getField("bar"), ValueFactory.create("biz"));
builder = Configs.decodeObject(StreamMapSplitBuilder.class, "field: foo, keyField: key, valueField: value, emitOriginal: true");
builder.process(bundle, emitter);
ArgumentCaptor<Bundle> bundleCapture = ArgumentCaptor.forClass(Bundle.class);
verify(emitter, times(3)).emit(bundleCapture.capture());
List<Bundle> newBundles = bundleCapture.getAllValues();
int originalSeen = 0;
for (Bundle b : newBundles) {
if (b.getValue(b.getFormat().getField("key")) == null) {
originalSeen++;
assertEquals("biz", b.getValue(b.getFormat().getField("bar")).asString().asNative());
assertNull(b.getValue(b.getFormat().getField("foo")));
}
}
assertEquals(1, originalSeen);
}
@Test
public void emitOriginalNoMapField() throws IOException {
bundle.setValue(bundle.getFormat().getField("bar"), ValueFactory.create("biz"));
builder = Configs.decodeObject(StreamMapSplitBuilder.class, "field: foo, keyField: key, valueField: value, emitOriginal: false");
builder.process(bundle, emitter);
verify(emitter, never()).emit(any());;
}
@Test
public void emitFilter() throws IOException {
map.put("hello", ValueFactory.create("is it me you're looking for?"));
map.put("you say", ValueFactory.create("good-bye"));
map.put("I say", ValueFactory.create("hello"));
bundle.setValue(bundle.getFormat().getField("foo"), map);
bundle.setValue(bundle.getFormat().getField("bar"), ValueFactory.create("lyrics"));
builder = Configs.decodeObject(StreamMapSplitBuilder.class, "field: foo, keyField: key, valueField: value, emitFilter: {from: value, to: baz}");
builder.process(bundle, emitter);
ArgumentCaptor<Bundle> bundleCapture = ArgumentCaptor.forClass(Bundle.class);
verify(emitter, times(3)).emit(bundleCapture.capture());
List<Bundle> newBundles = bundleCapture.getAllValues();
for (Bundle newBundle: newBundles) {
assertEquals("lyrics", newBundle.getValue(newBundle.getFormat().getField("bar")).asString().asNative());
String baz = newBundle.getValue(newBundle.getFormat().getField("baz")).asString().asNative();
String key = newBundle.getValue(newBundle.getFormat().getField("key")).asString().asNative();
String value = newBundle.getValue(newBundle.getFormat().getField("value")).asString().asNative();
assertEquals("Filter to copy field didn't work", value, baz);
assertTrue(key.equals("hello") || key.equals("you say") || key.equals("I say"));
switch (key) {
case "hello":
assertEquals("is it me you're looking for?", value);
break;
case "you say":
assertEquals("good-bye", value);
break;
case "I say":
assertEquals("hello", value);
break;
default:
fail("An unexpected bundle was emitted");
break;
}
}
}
@Test
public void emitFilterEmitOriginal() throws IOException {
map.put("hello", ValueFactory.create("is it me you're looking for?"));
map.put("you say", ValueFactory.create("good-bye"));
map.put("I say", ValueFactory.create("hello"));
bundle.setValue(bundle.getFormat().getField("foo"), map);
bundle.setValue(bundle.getFormat().getField("bar"), ValueFactory.create("lyrics"));
builder = Configs.decodeObject(StreamMapSplitBuilder.class, "field: foo, keyField: key, valueField: value, emitOriginal: true, emitFilter: {from.const: 42, to: baz}");
builder.process(bundle, emitter);
ArgumentCaptor<Bundle> bundleCapture = ArgumentCaptor.forClass(Bundle.class);
verify(emitter, times(4)).emit(bundleCapture.capture());
List<Bundle> newBundles = bundleCapture.getAllValues();
int nullPreKey = 0;
for (Bundle newBundle: newBundles) {
assertEquals("lyrics", newBundle.getValue(newBundle.getFormat().getField("bar")).asString().asNative());
long baz = newBundle.getValue(newBundle.getFormat().getField("baz")).asLong().asNative();
final ValueObject preKey = newBundle.getValue(newBundle.getFormat().getField("key"));
if (preKey == null) {
nullPreKey++;
continue;
}
String key = preKey.asString().asNative();
String value = newBundle.getValue(newBundle.getFormat().getField("value")).asString().asNative();
assertEquals("Constant filter value set didn't work", 42L, baz);
assertTrue(key.equals("hello") || key.equals("you say") || key.equals("I say"));
switch (key) {
case "hello":
assertEquals("is it me you're looking for?", value);
break;
case "you say":
assertEquals("good-bye", value);
break;
case "I say":
assertEquals("hello", value);
break;
default:
fail("An unexpected bundle was emitted");
break;
}
}
assertEquals(1, nullPreKey);
}
}