From 91645349b069ce811bf0a609f2230ee0d2e1da3e Mon Sep 17 00:00:00 2001 From: GaOrtiga <49285692+GaOrtiga@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:43:45 -0300 Subject: [PATCH] Allow privateips on console proxy (#6808) Co-authored-by: Rodrigo D. Lopez <19981369+RodrigoDLopez@users.noreply.github.com> Co-authored-by: Stephan Krug Co-authored-by: Gabriel Ortiga Fernandes --- .../java/com/cloud/configuration/Config.java | 10 +- .../ConfigurationManagerImpl.java | 201 +++++++++++------- .../com/cloud/configuration/ConfigTest.java | 42 ++++ .../ConfigurationManagerImplTest.java | 194 +++++++++++++++++ 4 files changed, 366 insertions(+), 81 deletions(-) mode change 100755 => 100644 server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java create mode 100644 server/src/test/java/com/cloud/configuration/ConfigTest.java create mode 100644 server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java diff --git a/server/src/main/java/com/cloud/configuration/Config.java b/server/src/main/java/com/cloud/configuration/Config.java index 1dafb2855a9..c07115d87c2 100644 --- a/server/src/main/java/com/cloud/configuration/Config.java +++ b/server/src/main/java/com/cloud/configuration/Config.java @@ -244,7 +244,7 @@ public enum Config { String.class, "network.loadbalancer.haproxy.stats.auth", "admin1:AdMiN123", - "Load Balancer(haproxy) authetication string in the format username:password", + "Load Balancer(haproxy) authentication string in the format username:password", null), NetworkLBHaproxyStatsPort( "Network", @@ -426,7 +426,7 @@ public enum Config { "Console proxy command port that is used to communicate with management server", null), ConsoleProxyRestart("Console Proxy", AgentManager.class, Boolean.class, "consoleproxy.restart", "true", "Console proxy restart flag, defaulted to true", null), - ConsoleProxyUrlDomain("Console Proxy", AgentManager.class, String.class, "consoleproxy.url.domain", "", "Console proxy url domain", "domainName"), + ConsoleProxyUrlDomain("Console Proxy", AgentManager.class, String.class, "consoleproxy.url.domain", "", "Console proxy url domain", "domainName", "privateip"), ConsoleProxySessionMax( "Console Proxy", AgentManager.class, @@ -1783,7 +1783,7 @@ public enum Config { private final String _name; private final String _defaultValue; private final String _description; - private final String _range; + private final String[] _range; private final String _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global private static final HashMap> s_scopeLevelConfigsMap = new HashMap>(); @@ -1833,7 +1833,7 @@ public enum Config { } } - private Config(String category, Class componentClass, Class type, String name, String defaultValue, String description, String range) { + private Config(String category, Class componentClass, Class type, String name, String defaultValue, String description, String... range) { _category = category; _componentClass = componentClass; _type = type; @@ -1896,7 +1896,7 @@ public enum Config { } } - public String getRange() { + public String[] getRange() { return _range; } diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java old mode 100755 new mode 100644 index b7ed11a61ab..7fa764d2f25 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -1103,8 +1103,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } Class type = null; - final Config c = Config.getConfig(name); - if (c == null) { + final Config configuration = Config.getConfig(name); + if (configuration == null) { s_logger.warn("Did not find configuration " + name + " in Config.java. Perhaps moved to ConfigDepot"); final ConfigKey configKey = _configDepot.get(name); if(configKey == null) { @@ -1113,7 +1113,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } type = configKey.type(); } else { - type = c.getType(); + type = configuration.getType(); } //no need to validate further if a //config can have null value. @@ -1222,96 +1222,145 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - if(c == null ) { + if (configuration == null ) { //range validation has to be done per case basis, for now //return in case of Configkey parameters return null; } - final String range = c.getRange(); + final String[] range = configuration.getRange(); if (range == null) { return null; } if (type.equals(String.class)) { - if (range.equals("privateip")) { - try { - if (!NetUtils.isSiteLocalAddress(value)) { - s_logger.error("privateip range " + value + " is not a site local address for configuration variable " + name); - return "Please enter a site local IP address."; - } - } catch (final NullPointerException e) { - s_logger.error("Error parsing ip address for " + name); - throw new InvalidParameterValueException("Error parsing ip address"); - } - } else if (range.equals("netmask")) { - if (!NetUtils.isValidIp4Netmask(value)) { - s_logger.error("netmask " + value + " is not a valid net mask for configuration variable " + name); - return "Please enter a valid netmask."; - } - } else if (range.equals("hypervisorList")) { - final String[] hypervisors = value.split(","); - if (hypervisors == null) { - return "Please enter hypervisor list, separated by comma"; - } - for (final String hypervisor : hypervisors) { - if (HypervisorType.getType(hypervisor) == HypervisorType.Any || HypervisorType.getType(hypervisor) == HypervisorType.None) { - return "Please enter a valid hypervisor type"; - } - } - } else if (range.equalsIgnoreCase("instanceName")) { - if (!NetUtils.verifyInstanceName(value)) { - return "Instance name can not contain hyphen, space or plus sign"; - } - } else if (range.equalsIgnoreCase("domainName")) { - String domainName = value; - if (value.startsWith("*")) { - domainName = value.substring(2); //skip the "*." - } - //max length for FQDN is 253 + 2, code adds xxx-xxx-xxx-xxx to domain name when creating URL - if (domainName.length() >= 238 || !domainName.matches(DOMAIN_NAME_PATTERN)) { - return "Please enter a valid string for domain name, prefixed with '*.' if applicable"; - } - } else if (range.equals("routes")) { - final String[] routes = value.split(","); - for (final String route : routes) { - if (route != null) { - final String routeToVerify = route.trim(); - if (!NetUtils.isValidIp4Cidr(routeToVerify)) { - throw new InvalidParameterValueException("Invalid value for route: " + route + " in deny list. Valid format is list" - + " of cidrs separated by coma. Example: 10.1.1.0/24,192.168.0.0/24"); - } - } - } - } else { - final String[] options = range.split(","); - for (final String option : options) { - if (option.trim().equalsIgnoreCase(value)) { - return null; - } - } - s_logger.error("configuration value for " + name + " is invalid"); - return "Please enter : " + range; - - } + return validateIfStringValueIsInRange(name, value, range); } else if (type.equals(Integer.class)) { - final String[] options = range.split("-"); - if (options.length != 2) { - final String msg = "configuration range " + range + " for " + name + " is invalid"; - s_logger.error(msg); - return msg; + return validateIfIntValueIsInRange(name, value, range[0]); + } + return String.format("Invalid value for configuration [%s].", name); + } + + /** + * A valid value should be an integer between min and max (the values from the range). + */ + protected String validateIfIntValueIsInRange(String name, String value, String range) { + final String[] options = range.split("-"); + final int min = Integer.parseInt(options[0]); + final int max = Integer.parseInt(options[1]); + final int val = Integer.parseInt(value); + if (val < min || val > max) { + s_logger.error(String.format("Invalid value for configuration [%s]. Please enter a value in the range [%s].", name, range)); + return String.format("The provided value is not valid for this configuration. Please enter an integer in the range: [%s]", range); + } + return null; + } + + /** + * Checks if the value for the configuration is valid for any of the ranges selected. + */ + protected String validateIfStringValueIsInRange(String name, String value, String... range) { + List message = new ArrayList(); + String errMessage = ""; + for (String rangeOption : range) { + switch (rangeOption) { + case "privateip": + errMessage = validateRangePrivateIp(name, value); + break; + case "hypervisorList": + errMessage = validateRangeHypervisorList(value); + break; + case "instanceName": + errMessage = validateRangeInstanceName(value); + break; + case "domainName": + errMessage = validateRangeDomainName(value); + break; + default: + errMessage = validateRangeOther(name, value, rangeOption); } - final int min = Integer.parseInt(options[0]); - final int max = Integer.parseInt(options[1]); - final int val = Integer.parseInt(value); - if (val < min || val > max) { - s_logger.error("configuration value for " + name + " is invalid"); - return "Please enter : " + range; + if (StringUtils.isEmpty(errMessage)) { + return null; + } + message.add(errMessage); + } + if (message.size() == 1) { + return String.format("The provided value is not %s.", message.get(0)); + } + return String.format("The provided value is neither %s.", String.join(" NOR ", message)); + } + + /** + * Checks if the value is a private IP according to {@link NetUtils#isSiteLocalAddress(String)}. + */ + protected String validateRangePrivateIp(String name, String value) { + try { + if (NetUtils.isSiteLocalAddress(value)) { + return null; + } + s_logger.error(String.format("Value [%s] is not a valid private IP range for configuration [%s].", value, name)); + } catch (final NullPointerException e) { + s_logger.error(String.format("Error while parsing IP address for [%s].", name)); + } + return "a valid site local IP address"; + } + + /** + * Valid values are XenServer, KVM, VMware, Hyperv, VirtualBox, Parralels, BareMetal, Simulator, Ovm, Ovm3, LXC. + * Inputting "Any" will return the hypervisor type Any, other inputs will result in the hypervisor type none. + * Both of these are invalid values and will return an error message. + */ + protected String validateRangeHypervisorList(String value) { + final String[] hypervisors = value.split(","); + for (final String hypervisor : hypervisors) { + if (HypervisorType.getType(hypervisor) == HypervisorType.Any || HypervisorType.getType(hypervisor) == HypervisorType.None) { + return "a valid hypervisor type"; } } return null; } + /** + * Valid values are instance names, the only restriction is that they may not have hyphens, spaces or plus signs. + */ + protected String validateRangeInstanceName(String value) { + if (NetUtils.verifyInstanceName(value)) { + return null; + } + return "a valid instance name (instance names cannot contain hyphens, spaces or plus signs)"; + } + + /** + * Verifies if the value is a valid domain name. If it starts with "*.", these two symbols are ignored and do not count towards the character limit. + * Max length for FQDN is 253 + 2, code adds xxx-xxx-xxx-xxx to domain name when creating URL. + */ + protected String validateRangeDomainName(String value) { + String domainName = value; + if (value.startsWith("*")) { + domainName = value.substring(2); + } + if (domainName.length() >= 238 || !domainName.matches(DOMAIN_NAME_PATTERN)) { + return "a valid domain name"; + } + return null; + } + + /** + * In configurations where this type of range is used, a list of possible values is passed as argument in the creation of the configuration, + * a valid value is any option within this list. + */ + protected String validateRangeOther(String name, String value, String rangeOption) { + final String[] options = rangeOption.split(","); + for (final String option : options) { + if (option.trim().equalsIgnoreCase(value)) { + return null; + } + } + s_logger.error(String.format("Invalid value for configuration [%s].", name)); + return String.format("a valid value for this configuration (Options are: [%s])", rangeOption); + } + + private boolean podHasAllocatedPrivateIPs(final long podId) { final HostPodVO pod = _podDao.findById(podId); final int count = _privateIpAddressDao.countIPs(podId, pod.getDataCenterId(), true); diff --git a/server/src/test/java/com/cloud/configuration/ConfigTest.java b/server/src/test/java/com/cloud/configuration/ConfigTest.java new file mode 100644 index 00000000000..1c9b2e71972 --- /dev/null +++ b/server/src/test/java/com/cloud/configuration/ConfigTest.java @@ -0,0 +1,42 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloud.configuration; + +import org.junit.Test; + +public class ConfigTest { + @Test + public void configTestIntegerRange() { + for (Config configuration : Config.values()) { + if (configuration.getType().equals(Integer.class) && configuration.getRange() != null) { + try { + final String[] options = configuration.getRange()[0].split("-"); + final int min = Integer.parseInt(options[0]); + final int max = Integer.parseInt(options[1]); + if (options.length != 2) { + throw new AssertionError(String.format("Invalid range for configuration [%s], a valid value for the range should be two integers separated by [-].", configuration.toString())); + } + if (min > max) { + throw new AssertionError(String.format("Invalid range for configuration [%s], the second value should be greater than the first.", configuration.toString())); + } + } catch (java.lang.NumberFormatException e) { + throw new AssertionError(String.format("Invalid range for configuration [%s], a valid value for the range should be two integers separated by [-].", configuration.toString())); + } + } + } + } +} diff --git a/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java new file mode 100644 index 00000000000..324ce7f9cbc --- /dev/null +++ b/server/src/test/java/com/cloud/configuration/ConfigurationManagerImplTest.java @@ -0,0 +1,194 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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.cloud.configuration; + +import com.cloud.utils.net.NetUtils; +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 java.util.List; + + +@RunWith(PowerMockRunner.class) +@PrepareForTest(NetUtils.class) +public class ConfigurationManagerImplTest { + ConfigurationManagerImpl configurationManagerImplSpy = Mockito.spy(new ConfigurationManagerImpl()); + @Test + public void validateIfIntValueIsInRangeTestValidValueReturnNull() { + String testVariable = configurationManagerImplSpy.validateIfIntValueIsInRange("String name", "3", "1-5"); + Assert.assertNull(testVariable); + } + + @Test + public void validateIfIntValueIsInRangeTestInvalidValueReturnString() { + String testVariable = configurationManagerImplSpy.validateIfIntValueIsInRange("String name", "9", "1-5"); + Assert.assertNotNull(testVariable); + } + + @Test + public void validateIfStringValueIsInRangeTestValidValuesReturnNull() { + String testVariable = ""; + List methods = List.of("privateip", "hypervisorList", "instanceName", "domainName", "default"); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangePrivateIp(Mockito.anyString(), Mockito.anyString()); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangeHypervisorList(Mockito.anyString()); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangeInstanceName(Mockito.anyString()); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangeDomainName(Mockito.anyString()); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangeOther(Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + for (String method : methods) { + testVariable = configurationManagerImplSpy.validateIfStringValueIsInRange("name", "value", method); + Assert.assertNull(testVariable); + } + } + + @Test + public void validateIfStringValueIsInRangeTestInvalidValuesReturnString() { + String testVariable = ""; + List methods = List.of("privateip", "hypervisorList", "instanceName", "domainName", "default"); + Mockito.doReturn("returnMsg").when(configurationManagerImplSpy).validateRangePrivateIp(Mockito.anyString(), Mockito.anyString()); + Mockito.doReturn("returnMsg").when(configurationManagerImplSpy).validateRangeHypervisorList(Mockito.anyString()); + Mockito.doReturn("returnMsg").when(configurationManagerImplSpy).validateRangeInstanceName(Mockito.anyString()); + Mockito.doReturn("returnMsg").when(configurationManagerImplSpy).validateRangeDomainName(Mockito.anyString()); + Mockito.doReturn("returnMsg").when(configurationManagerImplSpy).validateRangeOther(Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + for (String method : methods) { + testVariable = configurationManagerImplSpy.validateIfStringValueIsInRange("name", "value", method); + Assert.assertEquals("The provided value is not returnMsg.", testVariable); + } + } + + + @Test + public void validateIfStringValueIsInRangeTestMultipleRangesValidValueReturnNull() { + Mockito.doReturn("returnMsg1").when(configurationManagerImplSpy).validateRangePrivateIp(Mockito.anyString(), Mockito.anyString()); + Mockito.doReturn(null).when(configurationManagerImplSpy).validateRangeInstanceName(Mockito.anyString()); + Mockito.doReturn("returnMsg2").when(configurationManagerImplSpy).validateRangeOther(Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + String testVariable = configurationManagerImplSpy.validateIfStringValueIsInRange("name", "value", "privateip", "instanceName", "default"); + Assert.assertNull(testVariable); + } + + @Test + public void validateIfStringValueIsInRangeTestMultipleRangesInvalidValueReturnMessages() { + Mockito.doReturn("returnMsg1").when(configurationManagerImplSpy).validateRangePrivateIp(Mockito.anyString(), Mockito.anyString()); + Mockito.doReturn("returnMsg2").when(configurationManagerImplSpy).validateRangeInstanceName(Mockito.anyString()); + Mockito.doReturn("returnMsg3").when(configurationManagerImplSpy).validateRangeOther(Mockito.anyString(), Mockito.anyString(), Mockito.anyString()); + String testVariable = configurationManagerImplSpy.validateIfStringValueIsInRange("name", "value", "privateip", "instanceName", "default"); + Assert.assertEquals("The provided value is neither returnMsg1 NOR returnMsg2 NOR returnMsg3.", testVariable); + } + + + @Test + public void validateRangePrivateIpTestValidValueReturnNull() { + PowerMockito.mockStatic(NetUtils.class); + PowerMockito.when(NetUtils.isSiteLocalAddress(Mockito.anyString())).thenReturn(true); + String testVariable = configurationManagerImplSpy.validateRangePrivateIp("name", "value"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangePrivateIpTestInvalidValueReturnString() { + PowerMockito.mockStatic(NetUtils.class); + PowerMockito.when(NetUtils.isSiteLocalAddress(Mockito.anyString())).thenReturn(false); + String testVariable = configurationManagerImplSpy.validateRangePrivateIp("name", "value"); + Assert.assertEquals("a valid site local IP address", testVariable); + } + + @Test + public void validateRangeHypervisorListTestValidValueReturnNull() { + String testVariable = configurationManagerImplSpy.validateRangeHypervisorList("Ovm3,VirtualBox,KVM,VMware"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangeHypervisorListTestInvalidValueReturnString() { + String testVariable = configurationManagerImplSpy.validateRangeHypervisorList("Ovm3,VirtualBox,KVM,VMware,Any,InvalidHypervisorName"); + Assert.assertEquals("a valid hypervisor type", testVariable); + } + + @Test + public void validateRangeInstanceNameTestValidValueReturnNull() { + PowerMockito.mockStatic(NetUtils.class); + PowerMockito.when(NetUtils.verifyInstanceName(Mockito.anyString())).thenReturn(true); + String testVariable = configurationManagerImplSpy.validateRangeInstanceName("ThisStringShouldBeValid"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangeInstanceNameTestInvalidValueReturnString() { + PowerMockito.mockStatic(NetUtils.class); + PowerMockito.when(NetUtils.verifyInstanceName(Mockito.anyString())).thenReturn(false); + String testVariable = configurationManagerImplSpy.validateRangeInstanceName("This string should not be valid."); + Assert.assertEquals("a valid instance name (instance names cannot contain hyphen, space or plus sign)", testVariable); + } + + @Test + public void validateRangeDomainNameTestValueDoesNotStartWithStarAndIsAValidValueReturnNull() { + String testVariable = configurationManagerImplSpy.validateRangeDomainName("ThisStringShould.Work"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangeDomainNameTestValueDoesNotStartWithStarAndIsAValidValueButIsOver238charactersLongReturnString() { + String testVariable = configurationManagerImplSpy.validateRangeDomainName("ThisStringDoesNotStartWithStarAndIsOverTwoHundredAndForty.CharactersLongWithAtLeast" + + "OnePeriodEverySixtyFourLetters.ThisShouldCauseAnErrorBecauseItIsTooLong.TheRestOfThisAreRandomlyGeneratedCharacters.gNXhNOBNTNAoMCQqJMzcvFSBwHUhmWHftjfTNUaHR"); + Assert.assertEquals("a valid domain name", testVariable); + } + + @Test + public void validateRangeDomainNameTestValueDoesNotStartWithStarAndIsNotAValidValueReturnString() { + String testVariable = configurationManagerImplSpy.validateRangeDomainName("ThisStringDoesNotMatchThePatternFor.DomainNamesSinceItHas1NumberInTheLastPartOfTheString"); + Assert.assertEquals("a valid domain name", testVariable); + } + + @Test + public void validateRangeDomainNameTestValueStartsWithStarAndIsAValidValueReturnNull() { + + String testVariable = configurationManagerImplSpy.validateRangeDomainName("*.ThisStringStartsWithAStarAndAPeriod.ThisShouldWorkEvenThoughItIsOverTwoHundredAnd" + + "ThirtyEight.CharactersLong.BecauseTheFirstTwoCharactersAreIgnored.TheRestOfThisStringWasRandomlyGenerated.MgTUerXPlLyMaUpKTjAhxasFYRCfNCXmtWDwqSDOcTjASWlAXS"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangeDomainNameTestValueStartsWithStarAndIsAValidValueButIsOver238charactersLongReturnString() { + + String testVariable = configurationManagerImplSpy.validateRangeDomainName("*.ThisStringStartsWithStarAndIsOverTwoHundredAndForty.CharactersLongWithAtLeastOnePeriod" + + "EverySixtyFourLetters.ThisShouldCauseAnErrorBecauseItIsTooLong.TheRestOfThisAreRandomlyGeneratedCharacters.gNXNOBNTNAoMChQqJMzcvFSBwHUhmWHftjfTNUaHRKVyXm"); + Assert.assertEquals("a valid domain name", testVariable); + } + + @Test + public void validateRangeDomainNameTestValueStartsWithStarAndIsNotAValidValueReturnString() { + + String testVariable = configurationManagerImplSpy.validateRangeDomainName("*.ThisStringDoesNotMatchThePatternFor.DomainNamesSinceItHas1NumberInTheLastPartOfTheString"); + Assert.assertEquals("a valid domain name", testVariable); + } + + @Test + public void validateRangeOtherTestValidValueReturnNull() { + String testVariable = configurationManagerImplSpy.validateRangeOther("NameTest1", "SoShouldThis", "ThisShouldWork,ThisShouldAlsoWork,SoShouldThis"); + Assert.assertNull(testVariable); + } + + @Test + public void validateRangeOtherTestInvalidValueReturnString() { + String testVariable = configurationManagerImplSpy.validateRangeOther("NameTest1", "ThisShouldNotWork", "ThisShouldWork,ThisShouldAlsoWork,SoShouldThis"); + Assert.assertNotNull(testVariable); + } +}