/** * Copyright 2013-2014 Recruit Technologies Co., Ltd. and contributors * (see CONTRIBUTORS.md) * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. A copy of the * License is distributed with this work in the LICENSE.md file. You may * also obtain a copy of the License from * * 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.gennai.gungnir.topology.operator.tuplejoin; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import java.util.List; import mockit.Mock; import mockit.MockUp; import mockit.integration.junit4.JMockit; import org.gennai.gungnir.GungnirConfig; import org.gennai.gungnir.topology.GungnirContext; import org.gennai.gungnir.topology.operator.tuplejoin.JoinTupleCollection.DispatchHandler; import org.gennai.gungnir.topology.processor.InMemoryTtlCacheProcessor; import org.gennai.gungnir.tuple.FieldAccessor; import org.gennai.gungnir.tuple.GungnirTuple; import org.gennai.gungnir.tuple.TupleAccessor; import org.gennai.gungnir.tuple.schema.TupleSchema; import org.gennai.gungnir.utils.GungnirUtils; import org.junit.Test; import org.junit.runner.RunWith; import com.google.common.collect.Lists; @RunWith(JMockit.class) public class TestJoinTupleCollection { // CHECKSTYLE IGNORE MethodLength FOR NEXT 1 LINES @Test public void testJoin() throws Exception { TupleAccessor t1 = new TupleAccessor("t1"); TupleAccessor t2 = new TupleAccessor("t2"); SimpleJoinContext simpleContext1 = new SimpleJoinContext(t1, Lists.<FieldAccessor>newArrayList(t1.field("f1"), t1.field("f3"))); simpleContext1.setJoinKey(new SimpleJoinKey(t1.field("f0"))); SimpleJoinContext simpleContext2 = new SimpleJoinContext(t2, Lists.<FieldAccessor>newArrayList(t2.field("f3"), t2.field("f1"))); simpleContext2.setJoinKey(new SimpleJoinKey(t2.field("f1"))); ComplexJoinContext complexContext1 = new ComplexJoinContext(); complexContext1.addContext(simpleContext1); complexContext1.addContext(simpleContext2); final List<List<Object>> valuesList = Lists.newArrayList(); GungnirConfig config = GungnirConfig.readGugnirConfig(); GungnirContext context = new GungnirContext(); JoinTupleCollection collection = new JoinTupleCollection(complexContext1, new InMemoryTtlCacheProcessor(), 10, null, 8); collection.prepare(config, context, null); collection.setDispatchHandler(new DispatchHandler() { @Override public void dispatch(List<Object> values) { valuesList.add(values); } }); GungnirTuple tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t1f1").put("f2", "t1f2").put("f3", "t1f3").build(); collection.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t1f1-2").put("f2", "t1f2-2").put("f3", "t1f3-2").build(); collection.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t1f1-3").put("f2", "t1f2-3").put("f3", "t1f3-3").build(); collection.put(tuple1); GungnirTuple tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "t2f0").put("f1", "key1").put("f2", "t2f2").put("f3", "t2f3").build(); collection.put(tuple2); assertThat(valuesList.size(), is(3)); assertThat(valuesList.get(0), is((List<Object>) Lists.<Object>newArrayList("t1f1", "t1f3", "t2f3", "key1"))); assertThat(valuesList.get(1), is((List<Object>) Lists.<Object>newArrayList("t1f1-2", "t1f3-2", "t2f3", "key1"))); assertThat(valuesList.get(2), is((List<Object>) Lists.<Object>newArrayList("t1f1-3", "t1f3-3", "t2f3", "key1"))); collection.cleanup(); valuesList.clear(); SimpleJoinContext simpleContext3 = new SimpleJoinContext(t1, Lists.<FieldAccessor>newArrayList(t1.field("f1"), t1.field("f3"))); ComplexJoinKey joinKey = new ComplexJoinKey(); joinKey.add(new SimpleJoinKey(t1.field("f0"))); joinKey.add(new SimpleJoinKey(t1.field("f1"))); simpleContext3.setJoinKey(joinKey); SimpleJoinContext simpleContext4 = new SimpleJoinContext(t2, Lists.<FieldAccessor>newArrayList(t2.field("f1"), t2.field("f3"))); joinKey = new ComplexJoinKey(); joinKey.add(new SimpleJoinKey(t2.field("f0"))); joinKey.add(new SimpleJoinKey(t2.field("f1"))); simpleContext4.setJoinKey(joinKey); ComplexJoinContext complexContext2 = new ComplexJoinContext(); complexContext2.addContext(simpleContext3); complexContext2.addContext(simpleContext4); JoinTupleCollection collection2 = new JoinTupleCollection(complexContext2, new InMemoryTtlCacheProcessor(), 10, null, 8); collection2.prepare(config, context, null); collection2.setDispatchHandler(new DispatchHandler() { @Override public void dispatch(List<Object> values) { valuesList.add(values); } }); tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "key2").put("f2", "t2f2").put("f3", "t2f3").build(); collection2.put(tuple2); tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "key2").put("f2", "t2f2-2").put("f3", "t2f3-2").build(); collection2.put(tuple2); tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "key2").put("f2", "t2f2-3").put("f3", "t2f3-3").build(); collection2.put(tuple2); tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key3").put("f1", "key2").put("f2", "t2f2-4").put("f3", "t2f3-4").build(); collection2.put(tuple2); tuple2 = GungnirTuple.builder( new TupleSchema("t2").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key3").put("f1", "key4").put("f2", "t2f2-5").put("f3", "t2f3-5").build(); collection2.put(tuple2); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "key2").put("f2", "t1f2").put("f3", "t1f3").build(); collection2.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key3").put("f1", "key4").put("f2", "t1f2-2").put("f3", "t1f3-2").build(); collection2.put(tuple1); assertThat(valuesList.size(), is(4)); assertThat(valuesList.get(0), is((List<Object>) Lists.<Object>newArrayList("key2", "t1f3", "key2", "t2f3"))); assertThat(valuesList.get(1), is((List<Object>) Lists.<Object>newArrayList("key2", "t1f3", "key2", "t2f3-2"))); assertThat(valuesList.get(2), is((List<Object>) Lists.<Object>newArrayList("key2", "t1f3", "key2", "t2f3-3"))); assertThat(valuesList.get(3), is((List<Object>) Lists.<Object>newArrayList("key4", "t1f3-2", "key4", "t2f3-5"))); collection2.cleanup(); } // CHECKSTYLE IGNORE MethodLength FOR NEXT 1 LINES @Test public void testJoin2() throws Exception { TupleAccessor t1 = new TupleAccessor("t1"); TupleAccessor t2 = new TupleAccessor("t2"); TupleAccessor t3 = new TupleAccessor("t3"); TupleAccessor t4 = new TupleAccessor("t4"); SimpleJoinContext simpleContext1 = new SimpleJoinContext(t1, Lists.<FieldAccessor>newArrayList(t1.field("f1"), t1.field("f3"))); simpleContext1.setJoinKey(new SimpleJoinKey(t1.field("f0"))); SimpleJoinContext simpleContext2 = new SimpleJoinContext(t2, Lists.<FieldAccessor>newArrayList(t2.field("f3"), t2.field("f1"))); simpleContext2.setJoinKey(new SimpleJoinKey(t2.field("f1"))); SimpleJoinContext simpleContext3 = new SimpleJoinContext(t3, Lists.<FieldAccessor>newArrayList(t3.field("f2"), t3.field("f1"))); simpleContext3.setJoinKey(new SimpleJoinKey(t3.field("f2"))); ComplexJoinContext complexContext1 = new ComplexJoinContext(); complexContext1.addContext(simpleContext1); complexContext1.addContext(simpleContext2); complexContext1.addContext(simpleContext3); complexContext1.setJoinKey(new SimpleJoinKey(t3.field("f2"))); SimpleJoinContext simpleContext4 = new SimpleJoinContext(t4, Lists.<FieldAccessor>newArrayList(t4.field("f2"), t4.field("f1"))); simpleContext4.setJoinKey(new SimpleJoinKey(t4.field("f0"))); ComplexJoinContext complexContext2 = new ComplexJoinContext(); complexContext2.addContext(complexContext1); complexContext2.addContext(simpleContext4); final List<List<Object>> valuesList = Lists.newArrayList(); GungnirConfig config = GungnirConfig.readGugnirConfig(); GungnirContext context = new GungnirContext(); JoinTupleCollection collection = new JoinTupleCollection(complexContext2, new InMemoryTtlCacheProcessor(), 10, Lists.<FieldAccessor>newArrayList(t4.field("f1"), t4.field("f2"), t3.field("f1"), t1.field("f3"), t1.field("f1"), t2.field("f3").as("f4")), 8); collection.prepare(config, context, null); collection.setDispatchHandler(new DispatchHandler() { @Override public void dispatch(List<Object> values) { valuesList.add(values); } }); GungnirTuple tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1").put("+t1:f3", "t1f3").put("+t2:f3", "t2f3").put("+t2:f1", "t2f1") .put("+t3:f2", "key1").put("+t3:f1", "t3f1").build(); collection.put(tuple1); GungnirTuple tuple4 = GungnirTuple.builder( new TupleSchema("t4").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t4f1").put("f2", "t4f2").put("f3", "t4f3").build(); collection.put(tuple4); tuple4 = GungnirTuple.builder( new TupleSchema("t4").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t4f1-2").put("f2", "t4f2-2").put("f3", "t4f3-2").build(); collection.put(tuple4); tuple4 = GungnirTuple.builder( new TupleSchema("t4").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key1").put("f1", "t4f1-3").put("f2", "t4f2-3").put("f3", "t4f3-3").build(); collection.put(tuple4); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-2").put("+t1:f3", "t1f3-2").put("+t2:f3", "t2f3-2") .put("+t2:f1", "t2f1-2").put("+t3:f2", "key1").put("+t3:f1", "t3f1-2").build(); collection.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-3").put("+t1:f3", "t1f3-3").put("+t2:f3", "t2f3-3") .put("+t2:f1", "t2f1-3").put("+t3:f2", "key1").put("+t3:f1", "t3f1-3").build(); collection.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-4").put("+t1:f3", "t1f3-4").put("+t2:f3", "t2f3-4") .put("+t2:f1", "t2f1-4").put("+t3:f2", "key2").put("+t3:f1", "t3f1-4").build(); collection.put(tuple1); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-5").put("+t1:f3", "t1f3-5").put("+t2:f3", "t2f3-5") .put("+t2:f1", "t2f1-5").put("+t3:f2", "key2").put("+t3:f1", "t3f1-5").build(); collection.put(tuple1); tuple4 = GungnirTuple.builder( new TupleSchema("t4").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key2").put("f1", "t4f1-4").put("f2", "t4f2-4").put("f3", "t4f3-4").build(); collection.put(tuple4); tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-6").put("+t1:f3", "t1f3-6").put("+t2:f3", "t2f3-6") .put("+t2:f1", "t2f1-6").put("+t3:f2", "key3").put("+t3:f1", "t3f1-6").build(); collection.put(tuple1); final int now = GungnirUtils.currentTimeSecs(); new MockUp<GungnirUtils>() { @Mock public int currentTimeSecs() { return now + 20; } }; tuple1 = GungnirTuple.builder( new TupleSchema("t1").field("+t1:f1").field("+t1:f3").field("+t2:f3").field("+t2:f1") .field("+t3:f2").field("+t3:f1")) .put("+t1:f1", "t1f1-7").put("+t1:f3", "t1f3-7").put("+t2:f3", "t2f3-7") .put("+t2:f1", "t2f1-7").put("+t3:f2", "key3").put("+t3:f1", "t3f1-7").build(); collection.put(tuple1); tuple4 = GungnirTuple.builder( new TupleSchema("t4").field("f0").field("f1").field("f2").field("f3")) .put("f0", "key3").put("f1", "t4f1-5").put("f2", "t4f2-5").put("f3", "t4f3-5").build(); collection.put(tuple4); assertThat(valuesList.size(), is(6)); assertThat(valuesList.get(0), is((List<Object>) Lists.<Object>newArrayList("t4f1", "t4f2", "t3f1", "t1f3", "t1f1", "t2f3"))); assertThat(valuesList.get(1), is((List<Object>) Lists.<Object>newArrayList("t4f1-2", "t4f2-2", "t3f1-2", "t1f3-2", "t1f1-2", "t2f3-2"))); assertThat(valuesList.get(2), is((List<Object>) Lists.<Object>newArrayList("t4f1-3", "t4f2-3", "t3f1-2", "t1f3-2", "t1f1-2", "t2f3-2"))); assertThat(valuesList.get(3), is((List<Object>) Lists.<Object>newArrayList("t4f1-4", "t4f2-4", "t3f1-4", "t1f3-4", "t1f1-4", "t2f3-4"))); assertThat(valuesList.get(4), is((List<Object>) Lists.<Object>newArrayList("t4f1-4", "t4f2-4", "t3f1-5", "t1f3-5", "t1f1-5", "t2f3-5"))); assertThat(valuesList.get(5), is((List<Object>) Lists.<Object>newArrayList("t4f1-5", "t4f2-5", "t3f1-7", "t1f3-7", "t1f1-7", "t2f3-7"))); collection.cleanup(); } }