// 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.scheduler.utils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.twitter.heron.common.basics.FileUtils;
import com.twitter.heron.proto.system.Common;
import com.twitter.heron.proto.system.PackingPlans;
import com.twitter.heron.spi.common.Config;
import com.twitter.heron.spi.packing.PackingPlan;
import com.twitter.heron.spi.statemgr.SchedulerStateManagerAdaptor;
import com.twitter.heron.spi.utils.PackingTestUtils;
import com.twitter.heron.spi.utils.ShellUtils;
import static org.mockito.Mockito.eq;
@RunWith(PowerMockRunner.class)
@PrepareForTest({FileUtils.class, ShellUtils.class, SchedulerUtils.class})
public class SchedulerUtilsTest {
private static final String WORKING_DIR = "home";
private static final String CORE_RELEASE_URI = "mock://uri:121/only#swan";
private static final String CORE_RELEASE_DEST = "core";
private static final String TOPOLOGY_URI = "mock://uri:121/ruo#xi";
private static final String TOPOLOGY_DEST = "topology";
private static final String TOPOLOGY_NAME = "topology_name";
private static final boolean IS_DELETE_PACKAGE = true;
private static final boolean IS_VERBOSE = true;
@Test
public void testConstructSchedulerResponse() throws Exception {
Common.Status okStatus = Common.Status.newBuilder().
setStatus(Common.StatusCode.OK)
.build();
Assert.assertEquals(okStatus, SchedulerUtils.constructSchedulerResponse(true).getStatus());
Common.Status notOKStatus = Common.Status.newBuilder()
.setStatus(Common.StatusCode.NOTOK)
.build();
Assert.assertEquals(notOKStatus, SchedulerUtils.constructSchedulerResponse(false).getStatus());
}
/**
* Test curlAndExtractPackage()
*/
@Test
public void testCurlAndExtractPackage() throws Exception {
PowerMockito.mockStatic(ShellUtils.class);
PowerMockito.mockStatic(FileUtils.class);
// Failed to curl the package
PowerMockito.
when(ShellUtils.curlPackage(TOPOLOGY_URI, TOPOLOGY_DEST, IS_VERBOSE, false)).
thenReturn(false);
Assert.assertFalse(SchedulerUtils.curlAndExtractPackage(
WORKING_DIR, TOPOLOGY_URI, TOPOLOGY_DEST, IS_DELETE_PACKAGE, IS_VERBOSE));
// Ok to curl package
PowerMockito.
when(ShellUtils.curlPackage(TOPOLOGY_URI, TOPOLOGY_DEST, IS_VERBOSE, false)).
thenReturn(true);
// Failed to extract package
PowerMockito.
when(ShellUtils.extractPackage(TOPOLOGY_DEST, WORKING_DIR, IS_VERBOSE, false)).
thenReturn(false);
Assert.assertFalse(SchedulerUtils.curlAndExtractPackage(
WORKING_DIR, TOPOLOGY_URI, TOPOLOGY_DEST, IS_DELETE_PACKAGE, IS_VERBOSE));
// Ok to curl and extract the package (inheritIO is off)
PowerMockito.
when(ShellUtils.curlPackage(TOPOLOGY_URI, TOPOLOGY_DEST, IS_VERBOSE, false)).
thenReturn(true);
PowerMockito.
when(ShellUtils.extractPackage(TOPOLOGY_DEST, WORKING_DIR, IS_VERBOSE, false)).
thenReturn(true);
// Not required to delete the package
boolean isToDeletePackage = false;
Assert.assertTrue(SchedulerUtils.curlAndExtractPackage(
WORKING_DIR, TOPOLOGY_URI, TOPOLOGY_DEST, isToDeletePackage, IS_VERBOSE));
// deleteFile should not be invoked
PowerMockito.verifyStatic(Mockito.never());
FileUtils.deleteFile(Mockito.anyString());
// the whole process should success even if failed to delete the package
PowerMockito.when(FileUtils.deleteFile(Mockito.anyString())).thenReturn(false);
Assert.assertTrue(SchedulerUtils.curlAndExtractPackage(
WORKING_DIR, TOPOLOGY_URI, TOPOLOGY_DEST, true, IS_VERBOSE));
// deleteFile should be invoked once
PowerMockito.verifyStatic(Mockito.times(1));
FileUtils.deleteFile(Mockito.anyString());
}
/**
* Test method setupWorkingDirectory()
*/
@Test
public void testSetupWorkingDirectory() throws Exception {
boolean isVerbose = true;
PowerMockito.mockStatic(FileUtils.class);
// work directory not exist
PowerMockito.when(FileUtils.isDirectoryExists(Mockito.anyString())).thenReturn(false);
// Failed to create dir
PowerMockito.when(FileUtils.createDirectory(Mockito.anyString())).thenReturn(false);
Assert.assertFalse(SchedulerUtils.setupWorkingDirectory(
WORKING_DIR, CORE_RELEASE_URI, CORE_RELEASE_DEST,
TOPOLOGY_URI, TOPOLOGY_DEST, isVerbose));
// OK to create dir
PowerMockito.when(FileUtils.createDirectory(Mockito.anyString())).thenReturn(true);
PowerMockito.spy(SchedulerUtils.class);
// OK to curl and extract core-release-package
PowerMockito.doReturn(true).when(SchedulerUtils.class, "curlAndExtractPackage",
Mockito.eq(WORKING_DIR), Mockito.eq(CORE_RELEASE_URI),
Mockito.eq(CORE_RELEASE_DEST), Mockito.eq(true), Mockito.eq(isVerbose));
// Failed to curl and extract topology-package
PowerMockito.doReturn(false).when(SchedulerUtils.class, "curlAndExtractPackage",
Mockito.eq(WORKING_DIR), Mockito.eq(TOPOLOGY_URI),
Mockito.eq(TOPOLOGY_DEST), Mockito.anyBoolean(), Mockito.anyBoolean());
Assert.assertFalse(SchedulerUtils.setupWorkingDirectory(
WORKING_DIR, CORE_RELEASE_URI, CORE_RELEASE_DEST,
TOPOLOGY_URI, TOPOLOGY_DEST, isVerbose));
// OK to curl and extract topology-package
PowerMockito.doReturn(true).when(SchedulerUtils.class, "curlAndExtractPackage",
Mockito.eq(WORKING_DIR), Mockito.eq(TOPOLOGY_URI),
Mockito.eq(TOPOLOGY_DEST), Mockito.anyBoolean(), Mockito.anyBoolean());
Assert.assertTrue(SchedulerUtils.setupWorkingDirectory(
WORKING_DIR, CORE_RELEASE_URI, CORE_RELEASE_DEST,
TOPOLOGY_URI, TOPOLOGY_DEST, isVerbose));
}
@Test
public void testSchedulerCommandArgs() throws Exception {
List<Integer> freePorts = new ArrayList<>();
freePorts.add(1);
String[] expectedArgs =
{"--cluster", null, "--role", null,
"--environment", null, "--topology_name", null,
"--topology_bin", null, "--http_port", "1"};
Assert.assertArrayEquals(expectedArgs, SchedulerUtils.schedulerCommandArgs(
Mockito.mock(Config.class), Mockito.mock(Config.class), freePorts));
}
@Test
public void persistUpdatedPackingPlanWillUpdatesStateManager() {
SchedulerStateManagerAdaptor adaptor = Mockito.mock(SchedulerStateManagerAdaptor.class);
Mockito.when(adaptor
.updatePackingPlan(Mockito.any(PackingPlans.PackingPlan.class), eq(TOPOLOGY_NAME)))
.thenReturn(true);
Set<PackingPlan.ContainerPlan> containers = new HashSet<>();
containers.add(PackingTestUtils.testContainerPlan(1, 0, 1, 2));
PackingPlan packing = new PackingPlan("id", containers);
SchedulerUtils.persistUpdatedPackingPlan(TOPOLOGY_NAME, packing, adaptor);
Mockito.verify(adaptor)
.updatePackingPlan(Mockito.any(PackingPlans.PackingPlan.class), eq(TOPOLOGY_NAME));
}
}