// Copyright 2016 Twitter. All rights reserved.
//
// 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.twitter.heron.simulator.utils;
import java.io.Serializable;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.twitter.heron.api.Config;
import com.twitter.heron.api.bolt.BaseBasicBolt;
import com.twitter.heron.api.bolt.BasicOutputCollector;
import com.twitter.heron.api.generated.TopologyAPI;
import com.twitter.heron.api.spout.BaseRichSpout;
import com.twitter.heron.api.spout.SpoutOutputCollector;
import com.twitter.heron.api.topology.OutputFieldsDeclarer;
import com.twitter.heron.api.topology.TopologyBuilder;
import com.twitter.heron.api.topology.TopologyContext;
import com.twitter.heron.api.tuple.Fields;
import com.twitter.heron.api.tuple.Tuple;
import com.twitter.heron.common.basics.ByteAmount;
import com.twitter.heron.proto.system.PhysicalPlans;
/**
* PhysicalPlanGenerator Tester.
*/
public class PhysicalPlanUtilTest implements Serializable {
private static final long serialVersionUID = -8532695494712446731L;
public static final String TOPOLOGY_NAME = "topology-name";
public static final String TOPOLOGY_ID = "topology-id";
private static PhysicalPlans.PhysicalPlan plan;
private static TopologyAPI.Topology topology;
@BeforeClass
public static void beforeClass() throws Exception {
topology = PhysicalPlanUtilTest.getTestTopology();
plan = PhysicalPlanUtil.getPhysicalPlan(topology);
}
@AfterClass
public static void afterClass() throws Exception {
}
/**
* Construct the test topology
*/
public static TopologyAPI.Topology getTestTopology() {
TopologyBuilder topologyBuilder = new TopologyBuilder();
topologyBuilder.setSpout("word", new BaseRichSpout() {
private static final long serialVersionUID = 5406114907377311020L;
@Override
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("word"));
}
@Override
public void open(
Map<String, Object> map,
TopologyContext topologyContext,
SpoutOutputCollector spoutOutputCollector) {
}
@Override
public void nextTuple() {
}
}, 2);
topologyBuilder.setBolt("exclaim", new BaseBasicBolt() {
private static final long serialVersionUID = 4398578755681473899L;
@Override
public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) {
}
@Override
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
}
}, 2)
.shuffleGrouping("word");
Config conf = new Config();
conf.setDebug(true);
conf.setMaxSpoutPending(10);
conf.put(Config.TOPOLOGY_WORKER_CHILDOPTS, "-XX:+HeapDumpOnOutOfMemoryError");
conf.setComponentRam("word", ByteAmount.fromMegabytes(500));
conf.setComponentRam("exclaim", ByteAmount.fromGigabytes(1));
conf.setMessageTimeoutSecs(1);
return topologyBuilder.createTopology().
setName("topology-name").
setConfig(conf).
setState(TopologyAPI.TopologyState.RUNNING).
getTopology();
}
@Before
public void before() throws Exception {
}
@After
public void after() throws Exception {
}
/**
* Method: getPhysicalPlan(TopologyAPI.Topology topology)
*/
@Test
public void testGetPhysicalPlan() throws Exception {
Assert.assertEquals(topology, plan.getTopology());
Assert.assertEquals(1, plan.getStmgrsCount());
PhysicalPlans.StMgr stMgr = plan.getStmgrs(0);
Assert.assertEquals("", stMgr.getId());
Assert.assertEquals("", stMgr.getHostName());
Assert.assertEquals(-1, stMgr.getDataPort());
Assert.assertEquals("", stMgr.getLocalEndpoint());
Assert.assertEquals("", stMgr.getCwd());
Assert.assertEquals(4, plan.getInstancesCount());
ArrayList<String> componentsName = new ArrayList<>();
ArrayList<String> instancesId = new ArrayList<>();
ArrayList<Integer> componentsIndex = new ArrayList<>();
for (int i = 0; i < plan.getInstancesCount(); i++) {
PhysicalPlans.Instance instance = plan.getInstances(i);
Assert.assertEquals("", instance.getStmgrId());
Assert.assertEquals(i + 1, instance.getInfo().getTaskId());
componentsName.add(instance.getInfo().getComponentName());
instancesId.add(instance.getInstanceId());
componentsIndex.add(instance.getInfo().getComponentIndex());
}
// Sort to guarantee the order to make the unit test deterministic
Collections.sort(componentsName);
Collections.sort(instancesId);
Collections.sort(componentsIndex);
Assert.assertEquals("[exclaim, exclaim, word, word]", componentsName.toString());
Assert.assertEquals("[exclaim_1, exclaim_2, word_1, word_2]", instancesId.toString());
Assert.assertEquals("[1, 1, 2, 2]", componentsIndex.toString());
}
/**
* Method: getComponentToTaskIds(PhysicalPlans.PhysicalPlan physicalPlan)
*/
@Test
public void testGetComponentToTaskIds() throws Exception {
Map<String, List<Integer>> map = PhysicalPlanUtil.getComponentToTaskIds(plan);
Assert.assertEquals(2, map.size());
Assert.assertEquals(2, map.get("word").size());
Assert.assertEquals(2, map.get("exclaim").size());
List<Integer> taskIds = new LinkedList<>();
taskIds.addAll(map.get("word"));
taskIds.addAll(map.get("exclaim"));
Collections.sort(taskIds);
Assert.assertEquals("[1, 2, 3, 4]", taskIds.toString());
}
/**
* Method: extractTopologyTimeout(TopologyAPI.Topology topology)
*/
@Test
public void testExtractTopologyTimeout() throws Exception {
Assert.assertEquals(Duration.ofSeconds(1), PhysicalPlanUtil.extractTopologyTimeout(topology));
}
}