summaryrefslogtreecommitdiffstats
path: root/utils/src/test/java
diff options
context:
space:
mode:
Diffstat (limited to 'utils/src/test/java')
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java86
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java1268
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java16
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerExceptionTest.java63
-rw-r--r--utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java249
5 files changed, 400 insertions, 1282 deletions
diff --git a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
index 6dd09d6e..c29da2c7 100644
--- a/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
+++ b/utils/src/test/java/org/onap/policy/common/utils/network/NetworkUtilTest.java
@@ -1,15 +1,15 @@
-/*-
+/*
* ============LICENSE_START=======================================================
* policy-utils
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. 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.
@@ -20,21 +20,95 @@
package org.onap.policy.common.utils.network;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
-
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class NetworkUtilTest {
+ protected static Logger logger = LoggerFactory.getLogger(NetworkUtilTest.class);
+
+ private static final String LOCALHOST = "localhost";
@Test
public void test() throws InterruptedException, IOException {
assertNotNull(NetworkUtil.IPv4_WILDCARD_ADDRESS);
- assertFalse(NetworkUtil.isTcpPortOpen("localhost", 8180, 1, 5));
+ assertFalse(NetworkUtil.isTcpPortOpen(LOCALHOST, NetworkUtil.allocPort(), 1, 5));
assertNotNull(NetworkUtil.getHostname());
assertNotNull(NetworkUtil.getHostIp());
}
+ @Test
+ public void testAlwaysTrustManager() throws Exception {
+ TrustManager[] mgrarr = NetworkUtil.getAlwaysTrustingManager();
+ assertEquals(1, mgrarr.length);
+ assertTrue(mgrarr[0] instanceof X509TrustManager);
+
+ X509TrustManager mgr = (X509TrustManager) mgrarr[0];
+ assertNotNull(mgr.getAcceptedIssuers());
+ assertEquals(0, mgr.getAcceptedIssuers().length);
+
+ // these should not throw exceptions
+ mgr.checkClientTrusted(null, null);
+ mgr.checkServerTrusted(null, null);
+ }
+
+ @Test
+ public void testAllocPort_testAllocPortString__testAllocPortInetSocketAddress() throws Exception {
+ // allocate wild-card port
+ int wildCardPort = NetworkUtil.allocPort();
+ assertTrue(wildCardPort != 0);
+
+ // verify that we can listen on the port
+ try (ServerSocket wildSocket = new ServerSocket(wildCardPort)) {
+ new Accepter(wildSocket).start();
+ assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, wildCardPort, 5, 1000L));
+ }
+
+
+ // allocate port using host name
+ int localPort = NetworkUtil.allocPort(LOCALHOST);
+ assertTrue(localPort != 0);
+
+ // the OS should have allocated a new port, even though the first has been closed
+ assertTrue(localPort != wildCardPort);
+
+ try (ServerSocket localSocket = new ServerSocket()) {
+ localSocket.bind(new InetSocketAddress(LOCALHOST, localPort));
+ new Accepter(localSocket).start();
+ assertTrue(NetworkUtil.isTcpPortOpen(LOCALHOST, localPort, 5, 1000L));
+ }
+ }
+
+ /**
+ * Thread that accepts a connection on a socket.
+ */
+ private static class Accepter extends Thread {
+ private ServerSocket socket;
+
+ public Accepter(ServerSocket socket) {
+ this.socket = socket;
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ try (Socket server = socket.accept()) {
+ // do nothing
+
+ } catch (IOException e) {
+ logger.error("socket not accepted", e);
+ }
+ }
+ }
}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java b/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
deleted file mode 100644
index dbe04aee..00000000
--- a/utils/src/test/java/org/onap/policy/common/utils/properties/PropertyConfigurationTest.java
+++ /dev/null
@@ -1,1268 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP Policy Engine - Common Modules
- * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.common.utils.properties;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import java.lang.reflect.Field;
-import java.util.Properties;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.utils.properties.exception.PropertyAccessException;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-import org.onap.policy.common.utils.properties.exception.PropertyInvalidException;
-import org.onap.policy.common.utils.properties.exception.PropertyMissingException;
-
-/**
- * Test class for PropertyConfiguration.
- */
-public class PropertyConfigurationTest {
-
- /**
- * Property used for most of the simple configuration subclasses.
- */
- private static final String THE_VALUE = "the.value";
-
- /**
- * String property value.
- */
- private static final String STRING_VALUE = "a string";
-
- /**
- * Default value for string property.
- */
- private static final String STRING_VALUE_DEFAULT = "another string";
-
- /**
- * Value that cannot be coerced into any other type.
- */
- private static final String INVALID_VALUE = "invalid";
-
- /**
- * Properties used when invoking constructors.
- */
- private Properties props;
-
- @Before
- public void setUp() {
- props = new Properties();
- }
-
- @Test
- public void testPropertyConfiguration() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
-
- PlainStringConfig cfg = new PlainStringConfig();
- assertEquals(null, cfg.value);
-
- cfg.setAllFields(props);
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testPropertyConfigurationProperties() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- PlainStringConfig cfg = new PlainStringConfig(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testSetAllFields() throws Exception {
-
- /*
- * Implements an extra interface, just to see that it doesn't cause issues.
- */
- class GrandParentConfig extends PropertyConfiguration implements DoesNothing {
-
- @Property(name = "grandparent.value")
- protected boolean grandparentValue;
-
- @SuppressWarnings("unused")
- public void setGrandparentValue(boolean grandparentValue) {
- this.grandparentValue = grandparentValue;
- }
- }
-
- /*
- * Implements the extra interface, too.
- */
- class ParentConfig extends GrandParentConfig implements DoesNothing {
-
- @Property(name = "parent.value")
- protected long parentValue;
-
- @SuppressWarnings("unused")
- public void setParentValue(long parentValue) {
- this.parentValue = parentValue;
- }
- }
-
- class Config extends ParentConfig {
-
- @Property(name = THE_VALUE)
- private String value;
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
-
- final Config cfg = new Config();
-
- // try one set of values
- props.setProperty(THE_VALUE, STRING_VALUE);
- props.setProperty("parent.value", "50000");
- props.setProperty("grandparent.value", "true");
- cfg.setAllFields(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- assertEquals(50000L, cfg.parentValue);
- assertEquals(true, cfg.grandparentValue);
-
- // now a different set of values
- props.setProperty(THE_VALUE, STRING_VALUE + "x");
- props.setProperty("parent.value", "50001");
- props.setProperty("grandparent.value", "false");
- cfg.setAllFields(props);
-
- assertEquals(STRING_VALUE + "x", cfg.value);
- assertEquals(50001L, cfg.parentValue);
- assertEquals(false, cfg.grandparentValue);
- }
-
- @Test
- public void testSetAllFields_NoProperties() throws Exception {
-
- class Config extends PropertyConfiguration {
-
- private String value;
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
-
- Config cfg = new Config();
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- cfg.setAllFields(props);
-
- assertEquals(null, cfg.value);
- }
-
- @Test
- public void testSetValueFieldProperties_FieldSet() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- PlainStringConfig cfg = new PlainStringConfig(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testSetValueFieldProperties_NoAnnotation() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
-
- assertNull(cfg.value);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testSetValueFieldProperties_WrongFieldType() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- // Cannot set a property into an "Exception" field
- @Property(name = THE_VALUE)
- private Exception value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Exception value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- new Config(props);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testGetSetter_NoSetter() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- new Config(props);
- }
-
- @Test(expected = PropertyMissingException.class)
- public void testSetValueMethodFieldPropertiesProperty_NoProperty_NoDefault() throws PropertyException {
- new PlainStringConfig(props);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testSetValueMethodFieldPropertiesProperty_InvalidValue() throws PropertyException {
- class Config extends PlainPrimIntConfig {
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- /**
- * This returns a boolean, but the field is an "int", so it should throw an
- * exception when it tries to stuff the value into the field.
- */
- @Override
- protected Object getValue(Field field, Properties props, Property prop) throws PropertyException {
- return Boolean.TRUE;
- }
- }
-
- new Config(props);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testSetValueMethodFieldPropertiesProperty_MethodEx() throws PropertyException {
- class Config extends PlainStringConfig {
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @Override
- public void setValue(String value) {
- throw new IllegalArgumentException("expected exception");
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- new Config(props);
- }
-
- @Test
- public void testGetValue() throws PropertyException {
- // this class contains all of the supported field types
- class Config extends PropertyConfiguration {
-
- @Property(name = "string")
- private String stringValue;
-
- @Property(name = "boolean.true")
- private Boolean boolTrueValue;
-
- @Property(name = "boolean.false")
- private Boolean boolFalseValue;
-
- @Property(name = "primitive.boolean.true")
- private boolean primBoolTrueValue;
-
- @Property(name = "primitive.boolean.false")
- private boolean primBoolFalseValue;
-
- @Property(name = "integer")
- private Integer intValue;
-
- @Property(name = "primitive.integer")
- private int primIntValue;
-
- @Property(name = "long")
- private Long longValue;
-
- @Property(name = "primitive.long")
- private long primLongValue;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public String getStringValue() {
- return stringValue;
- }
-
- @SuppressWarnings("unused")
- public void setStringValue(String stringValue) {
- this.stringValue = stringValue;
- }
-
- @SuppressWarnings("unused")
- public Boolean getBoolTrueValue() {
- return boolTrueValue;
- }
-
- @SuppressWarnings("unused")
- public void setBoolTrueValue(Boolean boolTrueValue) {
- this.boolTrueValue = boolTrueValue;
- }
-
- @SuppressWarnings("unused")
- public Boolean getBoolFalseValue() {
- return boolFalseValue;
- }
-
- @SuppressWarnings("unused")
- public void setBoolFalseValue(Boolean boolFalseValue) {
- this.boolFalseValue = boolFalseValue;
- }
-
- @SuppressWarnings("unused")
- public boolean isPrimBoolTrueValue() {
- return primBoolTrueValue;
- }
-
- @SuppressWarnings("unused")
- public void setPrimBoolTrueValue(boolean primBoolTrueValue) {
- this.primBoolTrueValue = primBoolTrueValue;
- }
-
- @SuppressWarnings("unused")
- public boolean isPrimBoolFalseValue() {
- return primBoolFalseValue;
- }
-
- @SuppressWarnings("unused")
- public void setPrimBoolFalseValue(boolean primBoolFalseValue) {
- this.primBoolFalseValue = primBoolFalseValue;
- }
-
- @SuppressWarnings("unused")
- public Integer getIntValue() {
- return intValue;
- }
-
- @SuppressWarnings("unused")
- public void setIntValue(Integer intValue) {
- this.intValue = intValue;
- }
-
- @SuppressWarnings("unused")
- public int getPrimIntValue() {
- return primIntValue;
- }
-
- @SuppressWarnings("unused")
- public void setPrimIntValue(int primIntValue) {
- this.primIntValue = primIntValue;
- }
-
- @SuppressWarnings("unused")
- public Long getLongValue() {
- return longValue;
- }
-
- @SuppressWarnings("unused")
- public void setLongValue(Long longValue) {
- this.longValue = longValue;
- }
-
- @SuppressWarnings("unused")
- public long getPrimLongValue() {
- return primLongValue;
- }
-
- @SuppressWarnings("unused")
- public void setPrimLongValue(long primLongValue) {
- this.primLongValue = primLongValue;
- }
- }
-
- props.setProperty("string", "a string");
- props.setProperty("boolean.true", "true");
- props.setProperty("boolean.false", "false");
- props.setProperty("primitive.boolean.true", "true");
- props.setProperty("primitive.boolean.false", "false");
- props.setProperty("integer", "100");
- props.setProperty("primitive.integer", "101");
- props.setProperty("long", "10000");
- props.setProperty("primitive.long", "10001");
-
- Config cfg = new Config(props);
-
- assertEquals("a string", cfg.stringValue);
- assertEquals(true, cfg.boolTrueValue);
- assertEquals(false, cfg.boolFalseValue);
- assertEquals(true, cfg.primBoolTrueValue);
- assertEquals(false, cfg.primBoolFalseValue);
- assertEquals(100, cfg.intValue.intValue());
- assertEquals(101, cfg.primIntValue);
- assertEquals(10000, cfg.longValue.longValue());
- assertEquals(10001, cfg.primLongValue);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testGetValue_UnsupportedType() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- // Cannot set a property into an "Exception" field
- @Property(name = THE_VALUE)
- private Exception value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Exception value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- new Config(props);
- }
-
- @Test
- public void testCheckModifiable_OtherModifiers() throws PropertyException {
- // this class contains all of the supported field types
- class Config extends PropertyConfiguration {
-
- @Property(name = "public")
- public String publicString;
-
- @Property(name = "private")
- private String privateString;
-
- @Property(name = "protected")
- protected String protectedString;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setPublicString(String publicString) {
- this.publicString = publicString;
- }
-
- @SuppressWarnings("unused")
- public void setPrivateString(String privateString) {
- this.privateString = privateString;
- }
-
- @SuppressWarnings("unused")
- public void setProtectedString(String protectedString) {
- this.protectedString = protectedString;
- }
- }
-
- props.setProperty("public", "a public string");
- props.setProperty("private", "a private string");
- props.setProperty("protected", "a protected string");
-
- Config cfg = new Config(props);
-
- assertEquals("a public string", cfg.publicString);
- assertEquals("a private string", cfg.privateString);
- assertEquals("a protected string", cfg.protectedString);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testCheckModifiable_Static() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- new StaticPropConfig(props);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testCheckModifiable_Final() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- // Cannot set a property into an "final" field
- @Property(name = THE_VALUE)
- private final String value = "";
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- new Config(props);
- }
-
- @Test(expected = PropertyAccessException.class)
- public void testCheckSetter_Static() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- new StaticMethodConfig(props);
- }
-
- @Test
- public void testGetStringValue() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- PlainStringConfig cfg = new PlainStringConfig(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testGetBooleanValue_NoDefault() throws PropertyException {
- props.setProperty(THE_VALUE, "true");
- PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
- assertEquals(true, cfg.value);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testGetBooleanValue_InvalidDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Boolean value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "true");
- new Config(props);
- }
-
- @Test
- public void testGetBooleanValue_ValidDefault_True() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "true")
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Boolean value) {
- this.value = value;
- }
- }
-
- // property not defined
- Config cfg = new Config(props);
- assertEquals(true, cfg.value);
-
- // try again, with the property defined as true
- props.setProperty(THE_VALUE, "true");
- cfg = new Config(props);
- assertEquals(true, cfg.value);
-
- // try again, with the property defined as false
- props.setProperty(THE_VALUE, "false");
- cfg = new Config(props);
- assertEquals(false, cfg.value);
- }
-
- @Test
- public void testGetBooleanValue_ValidDefault_False() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "false")
- private Boolean value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Boolean value) {
- this.value = value;
- }
- }
-
- // property not defined
- Config cfg = new Config(props);
- assertEquals(false, cfg.value);
-
- // try again, with the property defined as true
- props.setProperty(THE_VALUE, "true");
- cfg = new Config(props);
- assertEquals(true, cfg.value);
-
- // try again, with the property defined as false
- props.setProperty(THE_VALUE, "false");
- cfg = new Config(props);
- assertEquals(false, cfg.value);
- }
-
- @Test
- public void testGetIntegerValue_NoDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Integer value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Integer value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "200");
- Config cfg = new Config(props);
-
- assertEquals(200, cfg.value.intValue());
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testGetIntegerValue_InvalidDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
- private Integer value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Integer value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "200");
- new Config(props);
- }
-
- @Test
- public void testGetIntegerValue_ValidDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "201")
- private Integer value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Integer value) {
- this.value = value;
- }
- }
-
- // property not defined
- Config cfg = new Config(props);
- assertEquals(201, cfg.value.intValue());
-
- // try again, with the property defined
- props.setProperty(THE_VALUE, "200");
- cfg = new Config(props);
- assertEquals(200, cfg.value.intValue());
- }
-
- @Test
- public void testGetLongValue_NoDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Long value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "20000");
- Config cfg = new Config(props);
-
- assertEquals(20000L, cfg.value.longValue());
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testGetLongValue_InvalidDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
- private Long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Long value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "20000");
- new Config(props);
- }
-
- @Test
- public void testGetLongValue_ValidDefault() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "20001")
- private Long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(Long value) {
- this.value = value;
- }
- }
-
- // property not defined
- Config cfg = new Config(props);
- assertEquals(20001L, cfg.value.longValue());
-
- // try again, with the property defined
- props.setProperty(THE_VALUE, "20000");
- cfg = new Config(props);
- assertEquals(20000L, cfg.value.longValue());
- }
-
- @Test
- public void testGetPropValue_Prop_NoDefault() throws PropertyException {
- props.setProperty(THE_VALUE, STRING_VALUE);
- PlainStringConfig cfg = new PlainStringConfig(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testGetPropValue_Prop_Default() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = STRING_VALUE_DEFAULT)
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, STRING_VALUE);
- Config cfg = new Config(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testGetPropValue_EmptyProp_EmptyOk() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, accept = "empty")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- props.setProperty(THE_VALUE, "");
- Config cfg = new Config(props);
-
- assertEquals("", cfg.value);
- }
-
- @Test
- public void testGetPropValue_EmptyDefault_EmptyOk() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals("", cfg.value);
- }
-
- @Test
- public void testGetPropValue_Default_EmptyOk() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = STRING_VALUE, accept = "empty")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test(expected = PropertyMissingException.class)
- public void testGetPropValue_EmptyDefault_EmptyNotOk() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- new Config(props);
- }
-
- @Test
- public void testGetPropValue_Default_EmptyNotOk() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = STRING_VALUE, accept = "")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test
- public void testGetRawPropertyValue() throws PropertyException {
- class Config extends PlainStringConfig {
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @Override
- protected String getRawPropertyValue(Properties props, String propnm) {
- return STRING_VALUE;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals(STRING_VALUE, cfg.getValue());
-
- }
-
- @Test
- public void testMakeBoolean_True() throws PropertyException {
- props.setProperty(THE_VALUE, "true");
- PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
- assertEquals(true, cfg.value);
- }
-
- @Test
- public void testMakeBoolean_False() throws PropertyException {
- props.setProperty(THE_VALUE, "false");
- PlainBooleanConfig cfg = new PlainBooleanConfig(props);
-
- assertEquals(false, cfg.value);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testMakeBoolean_Invalid() throws PropertyException {
- props.setProperty(THE_VALUE, INVALID_VALUE);
- new PlainBooleanConfig(props);
- }
-
- @Test
- public void testMakeInteger_Valid() throws PropertyException {
- props.setProperty(THE_VALUE, "300");
- PlainPrimIntConfig cfg = new PlainPrimIntConfig(props);
-
- assertEquals(300, cfg.value);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testMakeInteger_Invalid() throws PropertyException {
- props.setProperty(THE_VALUE, INVALID_VALUE);
- new PlainPrimIntConfig(props);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testMakeInteger_TooBig() throws PropertyException {
- props.setProperty(THE_VALUE, String.valueOf(Integer.MAX_VALUE + 10L));
- new PlainPrimIntConfig(props);
- }
-
- @Test
- public void testMakeLong_Valid() throws PropertyException {
- props.setProperty(THE_VALUE, "30000");
- PlainPrimLongConfig cfg = new PlainPrimLongConfig(props);
-
- assertEquals(30000L, cfg.value);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testMakeLong_Invalid() throws PropertyException {
- props.setProperty(THE_VALUE, INVALID_VALUE);
- new PlainPrimLongConfig(props);
- }
-
- @Test
- public void testCheckDefaultValue_NotEmpty_Valid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "700")
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals(700L, cfg.value);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testCheckDefaultValue_NotEmpty_Invalid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = INVALID_VALUE)
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- new Config(props);
- }
-
- @Test(expected = PropertyInvalidException.class)
- public void testCheckDefaultValue_Empty_EmptyOk_Invalid() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- new Config(props);
- }
-
- @Test
- public void testIsEmptyOkPropertyString_True() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- // missing property - should default to ""
- Config cfg = new Config(props);
- assertEquals("", cfg.value);
-
- // add an empty property - should take the property's value
- props.setProperty(THE_VALUE, "");
- cfg.setAllFields(props);
- assertEquals("", cfg.value);
-
- // add the property - should take the property's value
- props.setProperty(THE_VALUE, STRING_VALUE);
- cfg.setAllFields(props);
- assertEquals(STRING_VALUE, cfg.value);
- }
-
- @Test(expected = PropertyMissingException.class)
- public void testIsEmptyOkPropertyString_False() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "")
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- new Config(props);
- }
-
- @Test
- public void testIsEmptyOkProperty_True() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "empty")
- private String value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- Config cfg = new Config(props);
-
- assertEquals("", cfg.value);
- }
-
- @Test(expected = PropertyMissingException.class)
- public void testIsEmptyOkProperty_False() throws PropertyException {
- class Config extends PropertyConfiguration {
-
- @Property(name = THE_VALUE, defaultValue = "", accept = "")
- private long value;
-
- public Config(Properties props) throws PropertyException {
- super(props);
- }
-
- @SuppressWarnings("unused")
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- new Config(props);
- }
-
- /**
- * Config with a String value having no qualifiers.
- */
- public class PlainStringConfig extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private String value;
-
- public PlainStringConfig() {
-
- }
-
- public PlainStringConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
- }
-
- /**
- * Config with a Boolean value having no qualifiers.
- */
- public class PlainBooleanConfig extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private Boolean value;
-
- public PlainBooleanConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public void setValue(Boolean value) {
- this.value = value;
- }
- }
-
- /**
- * Config with an int value having no qualifiers.
- */
- public class PlainPrimIntConfig extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private int value;
-
- public PlainPrimIntConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public void setValue(int value) {
- this.value = value;
- }
- }
-
- /**
- * Config with a long value having no qualifiers.
- */
- public class PlainPrimLongConfig extends PropertyConfiguration {
-
- @Property(name = THE_VALUE)
- private long value;
-
- public PlainPrimLongConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public void setValue(long value) {
- this.value = value;
- }
- }
-
- /**
- * A config whose field is "static".
- */
- public static class StaticPropConfig extends PropertyConfiguration {
-
- // "static" field cannot be set
- @Property(name = THE_VALUE)
- private static String value;
-
- public StaticPropConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public static void setValue(String value) {
- StaticPropConfig.value = value;
- }
- }
-
- /**
- * A config whose method is "static".
- */
- public static class StaticMethodConfig extends PropertyConfiguration {
-
- // "static" field cannot be set
- @Property(name = THE_VALUE)
- private String value;
-
- public StaticMethodConfig(Properties props) throws PropertyException {
- super(props);
- }
-
- public static void setValue(String value) {
-
- }
- }
-
- /**
- * This is just used as a mix-in to ensure that the configuration ignores interfaces.
- */
- public static interface DoesNothing {
-
- }
-}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java b/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
index d1aa59d5..eb918d35 100644
--- a/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
+++ b/utils/src/test/java/org/onap/policy/common/utils/resources/ResourceUtilsTest.java
@@ -5,15 +5,15 @@
* 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.
- *
+ *
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
@@ -158,10 +158,10 @@ public class ResourceUtilsTest {
theUrl = ResourceUtils.getLocalFile("file:///");
assertNotNull(theUrl);
-
+
theUrl = ResourceUtils.getLocalFile("file:///testdir/testfile.xml");
assertNull(theUrl);
-
+
theUrl = ResourceUtils.getLocalFile(null);
assertNull(theUrl);
}
@@ -185,7 +185,7 @@ public class ResourceUtilsTest {
theStream = ResourceUtils.getResourceAsStream(jarFileResource);
assertNotNull(theStream);
-
+
theStream = ResourceUtils.getResourceAsStream(pathDirResource);
assertNotNull(theStream);
@@ -250,7 +250,7 @@ public class ResourceUtilsTest {
assertNull(theString);
theString = ResourceUtils.getResourceAsString("");
- assertEquals("org\ntestdir\n", theString);
+ assertEquals("logback-test.xml\norg\ntestdir\n", theString);
}
@Test
@@ -295,7 +295,7 @@ public class ResourceUtilsTest {
assertEquals("/something/else", ResourceUtils.getFilePath4Resource("/something/else"));
assertTrue(ResourceUtils.getFilePath4Resource("xml/example.xml").endsWith("xml/example.xml"));
}
-
+
/**
* Cleandown resource utils test.
*/
diff --git a/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerExceptionTest.java b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerExceptionTest.java
new file mode 100644
index 00000000..5fe321e8
--- /dev/null
+++ b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerExceptionTest.java
@@ -0,0 +1,63 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.services;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.junit.Test;
+
+public class ServiceManagerExceptionTest {
+ private ServiceManagerException sme;
+
+ @Test
+ public void testServiceManagerException() {
+ sme = new ServiceManagerException();
+ assertNull(sme.getMessage());
+ assertNull(sme.getCause());
+ }
+
+ @Test
+ public void testServiceManagerExceptionString() {
+ sme = new ServiceManagerException("hello");
+ assertEquals("hello", sme.getMessage());
+ assertNull(sme.getCause());
+ }
+
+ @Test
+ public void testServiceManagerExceptionThrowable() {
+ Throwable thrown = new Throwable("expected exception");
+ sme = new ServiceManagerException(thrown);
+ assertNotNull(sme.getMessage());
+ assertSame(thrown, sme.getCause());
+ }
+
+ @Test
+ public void testServiceManagerExceptionStringThrowable() {
+ Throwable thrown = new Throwable("another expected exception");
+ sme = new ServiceManagerException("world", thrown);
+ assertEquals("world", sme.getMessage());
+ assertSame(thrown, sme.getCause());
+ }
+
+}
diff --git a/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java
new file mode 100644
index 00000000..49c0599b
--- /dev/null
+++ b/utils/src/test/java/org/onap/policy/common/utils/services/ServiceManagerTest.java
@@ -0,0 +1,249 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.utils.services;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.capabilities.Startable;
+import org.onap.policy.common.utils.services.ServiceManager.RunnableWithEx;
+
+public class ServiceManagerTest {
+ private static final String ALREADY_RUNNING = "services are already running";
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+
+ private ServiceManager svcmgr;
+
+ /**
+ * Initializes {@link #svcmgr}.
+ */
+ @Before
+ public void setUp() {
+ svcmgr = new ServiceManager();
+ }
+
+ @Test
+ public void testAddAction() throws Exception {
+ RunnableWithEx start1 = mock(RunnableWithEx.class);
+ RunnableWithEx stop1 = mock(RunnableWithEx.class);
+ svcmgr.addAction("first action", start1, stop1);
+
+ RunnableWithEx start2 = mock(RunnableWithEx.class);
+ RunnableWithEx stop2 = mock(RunnableWithEx.class);
+ svcmgr.addAction("second action", start2, stop2);
+
+ svcmgr.start();
+ verify(start1).run();
+ verify(start2).run();
+ verify(stop1, never()).run();
+ verify(stop2, never()).run();
+
+ // cannot add while running
+ assertThatIllegalStateException().isThrownBy(() -> svcmgr.addAction("fail action", start1, stop1))
+ .withMessage(ALREADY_RUNNING + "; cannot add fail action");
+
+ svcmgr.stop();
+ verify(start1).run();
+ verify(start2).run();
+ verify(stop1).run();
+ verify(stop2).run();
+ }
+
+ @Test
+ public void testAddStartable() throws Exception {
+ Startable start1 = mock(Startable.class);
+ svcmgr.addService("first startable", start1);
+
+ Startable start2 = mock(Startable.class);
+ svcmgr.addService("second startable", start2);
+
+ svcmgr.start();
+ verify(start1).start();
+ verify(start1, never()).stop();
+ verify(start2).start();
+ verify(start2, never()).stop();
+
+ // cannot add while running
+ assertThatIllegalStateException().isThrownBy(() -> svcmgr.addService("fail startable", start1))
+ .withMessage(ALREADY_RUNNING + "; cannot add fail startable");
+
+ svcmgr.stop();
+ verify(start1).start();
+ verify(start1).stop();
+ verify(start2).start();
+ verify(start2).stop();
+ }
+
+ @Test
+ public void testStart() throws Exception {
+ Startable start1 = mock(Startable.class);
+ svcmgr.addService("test start", start1);
+
+ svcmgr.start();
+ verify(start1).start();
+ verify(start1, never()).stop();
+
+ // cannot re-start
+ assertThatIllegalStateException().isThrownBy(() -> svcmgr.start())
+ .withMessage(ALREADY_RUNNING);
+
+ // verify that it didn't try to start the service again
+ verify(start1).start();
+ }
+
+ @Test
+ public void testStart_Ex() {
+ Startable start1 = mock(Startable.class);
+ svcmgr.addService("test start ex", start1);
+
+ Startable start2 = mock(Startable.class);
+ svcmgr.addService("second test start ex", start2);
+
+ // this one will throw an exception
+ Startable start3 = mock(Startable.class);
+ RuntimeException exception = new RuntimeException(EXPECTED_EXCEPTION);
+ when(start3.start()).thenThrow(exception);
+ svcmgr.addService("third test start ex", start3);
+
+ Startable start4 = mock(Startable.class);
+ svcmgr.addService("fourth test start ex", start4);
+
+ Startable start5 = mock(Startable.class);
+ svcmgr.addService("fifth test start ex", start5);
+
+ assertThatThrownBy(() -> svcmgr.start()).isInstanceOf(ServiceManagerException.class).hasCause(exception);
+
+ verify(start1).start();
+ verify(start2).start();
+ verify(start3).start();
+ verify(start4, never()).start();
+ verify(start5, never()).start();
+
+ verify(start1).stop();
+ verify(start2).stop();
+ verify(start3, never()).stop();
+ verify(start4, never()).stop();
+ verify(start5, never()).stop();
+ }
+
+ @Test
+ public void testStart_RewindEx() {
+ Startable start1 = mock(Startable.class);
+ svcmgr.addService("test start rewind", start1);
+
+ // this one will throw an exception during rewind
+ Startable start2 = mock(Startable.class);
+ RuntimeException exception2 = new RuntimeException(EXPECTED_EXCEPTION);
+ when(start2.stop()).thenThrow(exception2);
+ svcmgr.addService("second test start rewind", start2);
+
+ // this one will throw an exception
+ Startable start3 = mock(Startable.class);
+ RuntimeException exception = new RuntimeException(EXPECTED_EXCEPTION);
+ when(start3.start()).thenThrow(exception);
+ svcmgr.addService("third test start rewind", start3);
+
+ Startable start4 = mock(Startable.class);
+ svcmgr.addService("fourth test start rewind", start4);
+
+ Startable start5 = mock(Startable.class);
+ svcmgr.addService("fifth test start rewind", start5);
+
+ assertThatThrownBy(() -> svcmgr.start()).isInstanceOf(ServiceManagerException.class).hasCause(exception);
+ }
+
+ @Test
+ public void testStop() throws Exception {
+ Startable start1 = mock(Startable.class);
+ svcmgr.addService("first stop", start1);
+
+ // cannot stop until started
+ assertThatIllegalStateException().isThrownBy(() -> svcmgr.stop())
+ .withMessage("services are not running");
+
+ // verify that it didn't try to stop the service
+ verify(start1, never()).stop();
+
+ // start it
+ svcmgr.start();
+
+ svcmgr.stop();
+ verify(start1).stop();
+ }
+
+ @Test
+ public void testStop_Ex() throws Exception {
+ RunnableWithEx start1 = mock(RunnableWithEx.class);
+ RunnableWithEx stop1 = mock(RunnableWithEx.class);
+ svcmgr.addAction("first stop ex", start1, stop1);
+
+ Startable start2 = mock(Startable.class);
+ svcmgr.addService("second stop ex", start2);
+
+ svcmgr.start();
+ verify(start1).run();
+ verify(stop1, never()).run();
+ verify(start2).start();
+ verify(start2, never()).stop();
+
+ svcmgr.stop();
+ verify(start1).run();
+ verify(stop1).run();
+ verify(start2).start();
+ verify(start2).stop();
+ }
+
+ @Test
+ public void testRewind() throws Exception {
+ RunnableWithEx starter = mock(RunnableWithEx.class);
+ LinkedList<String> lst = new LinkedList<>();
+
+ svcmgr.addAction("first rewind", starter, () -> lst.add("rewind1"));
+ svcmgr.addAction("second rewind", starter, () -> lst.add("rewind2"));
+
+ // this one will throw an exception during rewind
+ RuntimeException exception = new RuntimeException(EXPECTED_EXCEPTION);
+ svcmgr.addAction("third rewind", starter, () -> {
+ lst.add("rewind3");
+ throw exception;
+ });
+
+ svcmgr.addAction("fourth rewind", starter, () -> lst.add("rewind4"));
+ svcmgr.addAction("fifth rewind", starter, () -> lst.add("rewind5"));
+
+ svcmgr.start();
+
+ assertThatThrownBy(() -> svcmgr.stop()).isInstanceOf(ServiceManagerException.class).hasCause(exception);
+
+ // all of them should have been stopped, in reverse order
+ assertEquals(Arrays.asList("rewind5", "rewind4", "rewind3", "rewind2", "rewind1").toString(), lst.toString());
+ }
+
+}