/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.environment.server.compose;
import org.eclipse.che.api.environment.server.DefaultServicesStartStrategy;
import org.eclipse.che.api.environment.server.model.CheServiceImpl;
import org.eclipse.che.api.environment.server.model.CheServicesEnvironmentImpl;
import org.testng.annotations.Test;
import java.util.List;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertEqualsNoOrder;
import static org.testng.Assert.assertTrue;
/**
* @author Alexander Garagatyi
* @author Alexander Andrienko
*/
public class DefaultServicesStartStrategyTest {
DefaultServicesStartStrategy strategy = new DefaultServicesStartStrategy();
@Test
public void shouldOrderServicesWithDependenciesWhereOrderIsStrict() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withDependsOn(singletonList("first")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withDependsOn(asList("first", "second")));
composeEnvironment.getServices().put("first", new CheServiceImpl().withDependsOn(emptyList()));
composeEnvironment.getServices().put("forth", new CheServiceImpl().withDependsOn(singletonList("third")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withDependsOn(asList("forth", "first")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void shouldOrderServicesWithDependenciesWhereOrderIsStrict2() {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("web", new CheServiceImpl().withDependsOn(asList("db", "redis")));
composeEnvironment.getServices().put("redis", new CheServiceImpl().withDependsOn(singletonList("dev-machine")));
composeEnvironment.getServices().put("db", new CheServiceImpl().withDependsOn(singletonList("redis")));
composeEnvironment.getServices().put("dev-machine", new CheServiceImpl().withDependsOn(emptyList()));
List<String> expected = asList("dev-machine", "redis", "db", "web");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void testOrderingOfServicesWithoutDependencies() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl());
composeEnvironment.getServices().put("third", new CheServiceImpl());
composeEnvironment.getServices().put("first", new CheServiceImpl());
String[] expected = new String[] {"first", "second", "third"};
// when
String[] actual = strategy.order(composeEnvironment)
.toArray(new String[composeEnvironment.getServices().size()]);
// then
assertEqualsNoOrder(actual, expected);
}
@Test
public void shouldOrderServicesWithDependenciesWhereOrderIsNotStrict() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withDependsOn(singletonList("first")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withDependsOn(singletonList("second")));
composeEnvironment.getServices().put("first", new CheServiceImpl().withDependsOn(emptyList()));
composeEnvironment.getServices().put("forth", new CheServiceImpl().withDependsOn(singletonList("second")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withDependsOn(singletonList("second")));
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual.get(0), "first");
assertEquals(actual.get(1), "second");
assertTrue(actual.contains("third"));
assertTrue(actual.contains("forth"));
assertTrue(actual.contains("fifth"));
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Launch order of machines '.*, .*' can't be evaluated. Circular dependency.")
public void shouldFailIfCircularDependencyFound() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withDependsOn(singletonList("third")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withDependsOn(singletonList("second")));
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "A machine can not link to itself: .*")
public void shouldFailIfMachineLinksByItSelf() {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("first", new CheServiceImpl().withLinks(singletonList("first")));
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "A machine can not depend on itself: .*")
public void shouldFailIfMachineDependsOnByItSelf() {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("first", new CheServiceImpl().withDependsOn(singletonList("first")));
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "A machine can not contain 'volumes_from' to itself:.*")
public void shouldFailIfMachineContainsVolumesFromByItSelf() {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("first", new CheServiceImpl().withVolumesFrom(singletonList("first")));
// when
strategy.order(composeEnvironment);
}
@Test
public void shouldOrderServicesWithLinks() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withLinks(singletonList("first:alias")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withLinks(asList("first", "second")));
composeEnvironment.getServices().put("first", new CheServiceImpl().withLinks(emptyList()));
composeEnvironment.getServices().put("forth", new CheServiceImpl().withLinks(singletonList("third")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withLinks(asList("forth:alias", "first:alias")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void shouldOrderServicesWithVolumesFrom() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withVolumesFrom(singletonList("first")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withVolumesFrom(asList("first", "second")));
composeEnvironment.getServices().put("first", new CheServiceImpl().withVolumesFrom(emptyList()));
composeEnvironment.getServices().put("forth", new CheServiceImpl().withVolumesFrom(singletonList("third")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withVolumesFrom(asList("forth", "first")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void shouldOrderServicesWithMixedDependenciesInDependsOnVolumesFromAndLinks() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withDependsOn(singletonList("first")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withVolumesFrom(asList("first", "second")));
composeEnvironment.getServices().put("first", new CheServiceImpl().withLinks(emptyList()));
composeEnvironment.getServices().put("forth", new CheServiceImpl().withLinks(singletonList("third")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withDependsOn(asList("forth", "first")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void shouldOrderServicesWithTheSameDependenciesInDependsOnVolumesFromAndLinks() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withVolumesFrom(singletonList("first"))
.withDependsOn(singletonList("first"))
.withLinks(singletonList("first:alias")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withVolumesFrom(asList("first", "second"))
.withDependsOn(asList("first", "second"))
.withLinks(asList("first", "second")));
composeEnvironment.getServices().put("first", new CheServiceImpl());
composeEnvironment.getServices().put("forth", new CheServiceImpl().withVolumesFrom(singletonList("third"))
.withDependsOn(singletonList("third"))
.withLinks(singletonList("third")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withVolumesFrom(asList("forth", "first"))
.withDependsOn(asList("forth", "first"))
.withLinks(asList("forth:alias", "first")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test
public void shouldOrderServicesWithComplementaryDependenciesInDependsOnLinksAndVolumesFrom() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withVolumesFrom(singletonList("first")));
composeEnvironment.getServices().put("third", new CheServiceImpl().withVolumesFrom(singletonList("second"))
.withDependsOn(singletonList("first")));
composeEnvironment.getServices().put("first", new CheServiceImpl());
composeEnvironment.getServices().put("forth", new CheServiceImpl().withVolumesFrom(singletonList("third"))
.withDependsOn(singletonList("second"))
.withLinks(singletonList("first:alias")));
composeEnvironment.getServices().put("fifth", new CheServiceImpl().withVolumesFrom(singletonList("first"))
.withLinks(singletonList("forth"))
.withDependsOn(singletonList("second")));
List<String> expected = asList("first", "second", "third", "forth", "fifth");
// when
List<String> actual = strategy.order(composeEnvironment);
// then
assertEquals(actual, expected);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Dependency 'fifth' in machine 'second' points to unknown machine.")
public void shouldFailIfDependsOnFieldContainsNonExistingService() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withDependsOn(singletonList("fifth")));
composeEnvironment.getServices().put("third", new CheServiceImpl());
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Dependency 'fifth' in machine 'third' points to unknown machine.")
public void shouldFailIfVolumesFromFieldContainsNonExistingService() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl());
composeEnvironment.getServices().put("third", new CheServiceImpl().withVolumesFrom(singletonList("fifth")));
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Service volumes_from '.*' is invalid")
public void shouldFailIfVolumesFromFieldHasIllegalFormat() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices()
.put("second",
new CheServiceImpl().withVolumesFrom(singletonList("first:broken:dependency")));
composeEnvironment.getServices().put("third", new CheServiceImpl());
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Dependency 'fifth' in machine 'second' points to unknown machine.")
public void shouldFailIfLinksFieldContainsNonExistingService() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices().put("second", new CheServiceImpl().withLinks(singletonList("fifth")));
composeEnvironment.getServices().put("third", new CheServiceImpl());
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
@Test(expectedExceptions = IllegalArgumentException.class,
expectedExceptionsMessageRegExp = "Service link '.*' is invalid")
public void shouldFailIfLinksFieldHasIllegalFormat() throws Exception {
// given
CheServicesEnvironmentImpl composeEnvironment = new CheServicesEnvironmentImpl();
composeEnvironment.getServices()
.put("second",
new CheServiceImpl().withLinks(singletonList("first:broken:dependency")));
composeEnvironment.getServices().put("third", new CheServiceImpl());
composeEnvironment.getServices().put("first", new CheServiceImpl());
// when
strategy.order(composeEnvironment);
}
}