/*******************************************************************************
* Copyright (c) 2012 GigaSpaces Technologies Ltd. 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 org.cloudifysource.dsl;
import static org.junit.Assert.fail;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Assert;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.cloudifysource.domain.Service;
import org.cloudifysource.domain.Unit;
import org.cloudifysource.domain.UserInterface;
import org.cloudifysource.dsl.internal.DSLException;
import org.cloudifysource.dsl.internal.DSLValidationContext;
import org.cloudifysource.dsl.internal.DSLValidationException;
import org.cloudifysource.dsl.internal.ServiceReader;
import org.cloudifysource.dsl.internal.packaging.PackagingException;
import org.cloudifysource.dsl.internal.validators.ServiceValidator;
import org.junit.Test;
/**
* Test Service DSL Validations.
* @author noak, adaml
*
*/
public class ServiceValidationTest {
private static final String SERVICE_WITHOUT_ICON_PATH = "testResources/simple/simple-service.groovy";
private static final String SERVICE_WITH_ICON_PATH =
"testResources/applications/simple/service1/service1-service.groovy";
private static final String APPLICATION_MISSING_SERVICE_ICON_PATH =
"testResources/applications/ApplicationValidationTest/appMissingServiceIconTest";
private static final String MULTI_TENANT_WITH_STATIC_STORAGE =
"testResources/applications/ServiceValidationTest/multitenantWithStaticStorage";
private static final String ICON_FILE = "icon.png";
private static final String SERVICE_WITHOUT_NAME_GROOVY
= "testResources/applications/ServiceValidationTest/serviceWithoutNameTest";
private static final String SERVICE_WITH_EMPTY_NAME_GROOVY
= "testResources/applications/ServiceValidationTest/serviceWithEmptyNameTest";
private static final String SERVICE_WITH_INVALID_NAME_GROOVY
= "testResources/applications/ServiceValidationTest/serviceWithInvalidNameTest";
private static final String SERVICE_WITH_VALID_USER_INTERFACE =
"src/test/resources/ExternalDSLFiles/userInterfaceConversionTestFiles/"
+ "service_with_metrics_and_widgets.groovy";
private static final String SERVICE_WITH_INVALID_USER_INTERFACE =
"src/test/resources/groovyFileValidation/badUserInterface.groovy";
private static final String INVALID_SERVICE_NAME = "my[1]service";
@Test
public void testStaticStorageMTWithNumInstances() {
try {
ServiceReader.readService(new File(MULTI_TENANT_WITH_STATIC_STORAGE));
Assert.fail("Multi-tenant with numInstances > 1 and static storage is illegal, DSLValidationException expected.");
} catch (DSLValidationException e) {
return;
//OK - the invalid service name caused the exception
} catch (Exception e) {
Assert.fail("Multi-tenant with numInstances > 1 and static storage is defined but no DSLValidationException was thrown : " + e.getMessage());
}
Assert.fail("Multi-tenant with numInstances > 1 and static storage is defined but no DSLValidationException was thrown.");
}
/**
* Triple-test for the instances number (invalid configuration, default configuration and a valid configuration).
*/
@Test
public void testIllegalNumberOfInstances() {
//illegal number of instances:
try {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setNumInstances(2);
service.setMaxAllowedInstances(1);
serviceValidator.validateDefaultValues(new DSLValidationContext());
fail("an invalid service was successfully validated");
} catch (DSLValidationException e) {
//OK - the invalid number of instances caused the exception
}
//no num instances defined. using default values:
try {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setType("WEB_SERVER");
serviceValidator.validateDefaultValues(new DSLValidationContext());
} catch (DSLValidationException e) {
fail("Validation of service failed");
}
//test legal state:
try {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setNumInstances(1);
service.setMaxAllowedInstances(1);
service.setType("WEB_SERVER");
serviceValidator.validateDefaultValues(new DSLValidationContext());
} catch (DSLValidationException e) {
fail("Validation of service failed");
}
}
/**
* Double-test for the service type.
*/
@Test
public void testIllegalServiceType() {
//invalid service type
try {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setType("NonExistionType");
serviceValidator.validateDefaultValues(new DSLValidationContext());
fail("an invalid service was successfully validated");
} catch (DSLValidationException e) {
//OK - the invalid service type caused the exception
}
//valid service type
try {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setType("WEB_SERVER");
serviceValidator.validateDefaultValues(new DSLValidationContext());
} catch (DSLValidationException e) {
fail("Validation of service failed");
}
}
/*******
* Tests the validation of an illegal service's name
* (service without a name or with an empty name).
* <p>Should throw <code>DSLValidationException</code>.
*/
@Test
public void testIllegalServiceName() {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
try {
serviceValidator.validateName(new DSLValidationContext());
fail("A service without a name was successfully validated");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
}
try {
service.setName(StringUtils.EMPTY);
serviceValidator.validateName(new DSLValidationContext());
fail("A service with an empty name was successfully validated");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
}
try {
service.setName(INVALID_SERVICE_NAME);
serviceValidator.validateName(new DSLValidationContext());
fail("A service with an invalid name was successfully validated");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
}
}
/*******
* Tests the validation of a service without a name using DSL parsing of a groovy file.
* <p>Should throw <code>DSLValidationException</code>.
*/
@Test
public void testServiceWithoutNameGroovy() {
try {
ServiceReader.readService(new File(SERVICE_WITHOUT_NAME_GROOVY));
Assert.fail("Service name is missing, DSLValidationException expected.");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
} catch (Exception e) {
Assert.fail("Service name is missing, DSLValidationException expected, instead "
+ e.getClass() + " was thrown.");
}
}
/*******
* Tests the validation of a service without a name using DSL parsing of a groovy file.
* <p>Should throw <code>DSLValidationException</code>
*/
@Test
public void testServiceWithEmptyNameGroovy() {
try {
ServiceReader.readService(new File(SERVICE_WITH_EMPTY_NAME_GROOVY));
Assert.fail("Service name is empty, DSLValidationException expected.");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
} catch (Exception e) {
Assert.fail("Service name is empty, DSLValidationException expected, instead "
+ e.getClass() + " was thrown.");
}
}
/*******
* Tests the validation of a service with an invalid name using DSL parsing of a groovy file.
* <p>Should throw <code>DSLValidationException</code>
*/
@Test
public void testServiceWithInvalidNameGroovy() {
try {
ServiceReader.readService(new File(SERVICE_WITH_INVALID_NAME_GROOVY));
Assert.fail("Service name is invalid: " + INVALID_SERVICE_NAME + ". DSLValidationException expected.");
} catch (DSLValidationException e) {
//OK - the invalid service name caused the exception
} catch (Exception e) {
Assert.fail("Service name is invalid: " + INVALID_SERVICE_NAME + ". DSLValidationException expected, "
+ "but " + e.getClass() + " was thrown instead.");
}
}
@Test
public void testApplicationMissingServiceIcon() {
final File applicationFile = new File(APPLICATION_MISSING_SERVICE_ICON_PATH);
try {
ServiceReader.getApplicationFromFile(applicationFile).getApplication();
Assert.fail("Application has a service without an icon, IllegalArgumentException expected.");
} catch (final IllegalArgumentException e) {
// OK - the invalid application name caused the exception
} catch (final Exception e) {
Assert.fail("Application has a service without an icon, IllegalArgumentException expected, instead "
+ e.getClass() + " was thrown.");
}
}
@Test
public void testServiceWithoutIconGroovy() {
try {
ServiceReader.readService(new File(SERVICE_WITHOUT_ICON_PATH));
Assert.fail("Service name is empty, DSLValidationException expected.");
} catch (PackagingException e) {
//OK - the invalid service name caused the exception
} catch (Exception e) {
Assert.fail("Service name is empty, DSLValidationException expected, instead "
+ e.getClass() + " was thrown.");
}
}
/**
* Double-test for the service icon.
*/
@Test
public void testMissingServiceIcon() {
Service service = new Service();
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
service.setIcon(ICON_FILE);
DSLValidationContext validationContext = new DSLValidationContext();
//missing icon file:
try {
validationContext.setFilePath(SERVICE_WITHOUT_ICON_PATH);
serviceValidator.validateIcon(validationContext);
fail("an invalid icon path was successfully validated: " + SERVICE_WITHOUT_ICON_PATH);
} catch (DSLValidationException e) {
//OK - the invalid icon path caused the exception
}
//valid icon file:
try {
validationContext.setFilePath(SERVICE_WITH_ICON_PATH);
serviceValidator.validateIcon(validationContext);
} catch (DSLValidationException e) {
fail("Validation of service failed on a valid icon path: "
+ SERVICE_WITH_ICON_PATH + ": " + e.getMessage());
}
}
private UserInterface createOpenspacesUIObject(
org.cloudifysource.domain.UserInterface userInterface)
throws IllegalAccessException, InvocationTargetException {
UserInterface ui = new UserInterface();
BeanUtils.copyProperties(ui, userInterface);
return ui;
}
@Test
public void testBadUserInterfaceDef()
throws PackagingException, DSLException, IllegalAccessException, InvocationTargetException {
Service service = ServiceReader.readService(new File(SERVICE_WITH_VALID_USER_INTERFACE));
ServiceValidator serviceValidator = new ServiceValidator();
serviceValidator.setDSLEntity(service);
DSLValidationContext validationContext = new DSLValidationContext();
validationContext.setFilePath(SERVICE_WITH_VALID_USER_INTERFACE);
try {
serviceValidator.validateUserInterfaceObjectIsWellDefined(validationContext);
} catch (DSLValidationException e) {
fail("Validation of a valid User Interface object failed");
}
validationContext.setFilePath(SERVICE_WITH_INVALID_USER_INTERFACE);
UserInterface userInterface = createOpenspacesUIObject(service.getUserInterface());
//we change the UserInterface object a few times and run a validation test on it.
//invalid because expecting string not object
List<Object> firstInvalidMetricList = new ArrayList<Object>();
firstInvalidMetricList.add(new Object());
userInterface.getMetricGroups().get(0).setMetrics(firstInvalidMetricList);
try {
serviceValidator.validateUserInterfaceObjectIsWellDefined(validationContext);
fail("Validation of User Interface object is expected to fail");
} catch (DSLValidationException e) {
//expected
}
//invalid because expecting Unit not String
List<Object> secondInvalidMetricList = new ArrayList<Object>();
List<Object> invalidMetricListForm = new ArrayList<Object>();
invalidMetricListForm.add("metricName");
invalidMetricListForm.add("nonUnit instance type object");
secondInvalidMetricList.add(invalidMetricListForm);
userInterface.getMetricGroups().get(0).setMetrics(secondInvalidMetricList);
try {
serviceValidator.validateUserInterfaceObjectIsWellDefined(validationContext);
fail("Validation of User Interface object is expected to fail");
} catch (DSLValidationException e) {
//expected
}
//invalid because expecting string not object
List<Object> thirdInvalidMetricList = new ArrayList<Object>();
invalidMetricListForm = new ArrayList<Object>();
invalidMetricListForm.add(new Object());
invalidMetricListForm.add(Unit.PERCENTAGE);
thirdInvalidMetricList.add(invalidMetricListForm);
userInterface.getMetricGroups().get(0).setMetrics(thirdInvalidMetricList);
try {
serviceValidator.validateUserInterfaceObjectIsWellDefined(validationContext);
fail("Validation of User Interface object is expected to fail");
} catch (DSLValidationException e) {
//expected
}
//invalid because expecting metric to be either string or a list
//of size 2
List<Object> fourthInvalidMetricList = new ArrayList<Object>();
invalidMetricListForm = new ArrayList<Object>();
invalidMetricListForm.add("metricName");
invalidMetricListForm.add(Unit.PERCENTAGE);
invalidMetricListForm.add("some unrelatedString");
fourthInvalidMetricList.add(invalidMetricListForm);
userInterface.getMetricGroups().get(0).setMetrics(fourthInvalidMetricList);
try {
serviceValidator.validateUserInterfaceObjectIsWellDefined(validationContext);
fail("Validation of User Interface object is expected to fail");
} catch (DSLValidationException e) {
//expected
}
}
}