/******************************************************************************* * 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.factory.server.impl; import com.google.common.collect.ImmutableMap; import org.eclipse.che.api.core.ApiException; import org.eclipse.che.api.core.BadRequestException; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.factory.server.FactoryConstants; import org.eclipse.che.api.factory.server.builder.FactoryBuilder; import org.eclipse.che.api.factory.shared.dto.IdeActionDto; import org.eclipse.che.api.factory.shared.dto.AuthorDto; import org.eclipse.che.api.factory.shared.dto.FactoryDto; import org.eclipse.che.api.factory.shared.dto.IdeDto; import org.eclipse.che.api.factory.shared.dto.OnAppClosedDto; import org.eclipse.che.api.factory.shared.dto.OnAppLoadedDto; import org.eclipse.che.api.factory.shared.dto.OnProjectsLoadedDto; import org.eclipse.che.api.factory.shared.dto.PoliciesDto; import org.eclipse.che.api.user.server.model.impl.UserImpl; import org.eclipse.che.api.user.server.spi.PreferenceDao; import org.eclipse.che.api.user.server.spi.UserDao; import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto; import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto; import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto; import org.eclipse.che.dto.server.DtoFactory; import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Listeners; import org.testng.annotations.Test; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.text.ParseException; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import static java.util.Collections.singletonList; import static java.util.Objects.*; import static org.eclipse.che.dto.server.DtoFactory.*; import static org.eclipse.che.dto.server.DtoFactory.newDto; import static org.mockito.Mockito.when; @Listeners(value = {MockitoTestNGListener.class}) public class FactoryBaseValidatorTest { private static final String VALID_REPOSITORY_URL = "https://github.com/codenvy/cloudide"; private static final String VALID_PROJECT_PATH = "/cloudide"; private static final String ID = "id"; @Mock private UserDao userDao; @Mock private PreferenceDao preferenceDao; @Mock private FactoryBuilder builder; @Mock private HttpServletRequest request; private TesterFactoryBaseValidator validator; private FactoryDto factory; @BeforeMethod public void setUp() throws ParseException, NotFoundException, ServerException { factory = newDto(FactoryDto.class).withV("4.0") .withCreator(newDto(AuthorDto.class).withUserId("userid")); final UserImpl user = new UserImpl("userid", "email", "name"); when(userDao.getById("userid")).thenReturn(user); validator = new TesterFactoryBaseValidator(); } @Test public void shouldBeAbleToValidateFactoryUrlObject() throws ApiException { factory = prepareFactoryWithGivenStorage("git", VALID_REPOSITORY_URL, VALID_PROJECT_PATH); validator.validateProjects(factory); validator.validateProjects(factory); } @Test public void shouldBeAbleToValidateFactoryUrlObjectIfStorageIsESBWSO2() throws ApiException { factory = prepareFactoryWithGivenStorage("esbwso2", VALID_REPOSITORY_URL, VALID_PROJECT_PATH); validator.validateProjects(factory); validator.validateProjects(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "The parameter project.source.location has a value submitted http://codenvy.com/git/04%2 with a value that is " + "unexpected. " + "For more information, please visit http://docs.codenvy.com/user/project-lifecycle/#configuration-reference") public void shouldNotValidateIfStorageLocationContainIncorrectEncodedSymbol() throws ApiException { // given factory = prepareFactoryWithGivenStorage("git", "http://codenvy.com/git/04%2", VALID_PROJECT_PATH); // when, then validator.validateProjects(factory); } @Test public void shouldValidateIfStorageLocationIsCorrectSsh() throws ApiException { // given factory = prepareFactoryWithGivenStorage("git", "ssh://codenvy@review.gerrithub.io:29418/codenvy/exampleProject", "example-project"); // when, then validator.validateProjects(factory); } @Test public void shouldValidateIfStorageLocationIsCorrectHttps() throws ApiException { // given factory = prepareFactoryWithGivenStorage("git", "https://github.com/codenvy/example.git", "/example"); // when, then validator.validateProjects(factory); } @Test public void shouldValidateSubProjectWithNoLocation() throws ApiException { // given factory = prepareFactoryWithGivenStorage("git", "null", "/cloudide/core"); // when, then validator.validateProjects(factory); } @Test(dataProvider = "badAdvancedFactoryUrlProvider", expectedExceptions = ApiException.class) public void shouldNotValidateIfStorageOrStorageLocationIsInvalid(FactoryDto factory) throws ApiException { validator.validateProjects(factory); } @DataProvider(name = "badAdvancedFactoryUrlProvider") public Object[][] invalidParametersFactoryUrlProvider() throws UnsupportedEncodingException { FactoryDto adv1 = prepareFactoryWithGivenStorage("notagit", VALID_REPOSITORY_URL, VALID_PROJECT_PATH); FactoryDto adv2 = prepareFactoryWithGivenStorage("git", null, VALID_PROJECT_PATH); FactoryDto adv3 = prepareFactoryWithGivenStorage("git", "", VALID_PROJECT_PATH); return new Object[][]{ {adv1},// invalid vcs {adv2},// invalid vcsurl {adv3}// invalid vcsurl }; } @Test(dataProvider = "invalidProjectNamesProvider", expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "Project name must contain only Latin letters, " + "digits or these following special characters -._.") public void shouldThrowFactoryUrlExceptionIfProjectNameInvalid(String projectName) throws Exception { // given factory.withWorkspace(newDto(WorkspaceConfigDto.class).withProjects(singletonList(newDto(ProjectConfigDto.class) .withType("type") .withName(projectName)))); // when, then validator.validateProjects(factory); } @Test(dataProvider = "validProjectNamesProvider") public void shouldBeAbleToValidateValidProjectName(String projectName) throws Exception { // given prepareFactoryWithGivenStorage("git", VALID_REPOSITORY_URL, VALID_PROJECT_PATH); factory.withWorkspace(newDto(WorkspaceConfigDto.class).withProjects( singletonList(newDto(ProjectConfigDto.class).withType("type") .withName(projectName) .withSource(newDto(SourceStorageDto.class) .withType("git") .withLocation(VALID_REPOSITORY_URL)) .withPath(VALID_PROJECT_PATH)))); // when, then validator.validateProjects(factory); } @DataProvider(name = "validProjectNamesProvider") public Object[][] validProjectNames() { return new Object[][]{ {"untitled"}, {"Untitled"}, {"untitled.project"}, {"untitled-project"}, {"untitled_project"}, {"untitled01"}, {"000011111"}, {"0untitled"}, {"UU"}, {"untitled-proj12"}, {"untitled.pro....111"}, {"SampleStruts"} }; } @DataProvider(name = "invalidProjectNamesProvider") public Object[][] invalidProjectNames() { return new Object[][]{ {"-untitled"}, {"untitled->3"}, {"untitled__2%"}, {"untitled_!@#$%^&*()_+?><"} }; } @Test public void shouldValidateIfCurrentTimeBeforeSinceUntil() throws Exception { Long currentTime = new Date().getTime(); factory.withPolicies(newDto(PoliciesDto.class) .withSince(currentTime + 10000L) .withUntil(currentTime + 20000L)); validator.validateCurrentTimeAfterSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_SINCE_MESSAGE) public void shouldNotValidateIfSinceBeforeCurrent() throws ApiException { factory.withPolicies(newDto(PoliciesDto.class) .withSince(1L)); validator.validateCurrentTimeAfterSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_UNTIL_MESSAGE) public void shouldNotValidateIfUntilBeforeCurrent() throws ApiException { factory.withPolicies(newDto(PoliciesDto.class) .withUntil(1L)); validator.validateCurrentTimeAfterSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_SINCEUNTIL_MESSAGE) public void shouldNotValidateIfUntilBeforeSince() throws ApiException { factory.withPolicies(newDto(PoliciesDto.class) .withSince(2L) .withUntil(1L)); validator.validateCurrentTimeAfterSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.ILLEGAL_FACTORY_BY_UNTIL_MESSAGE) public void shouldNotValidateIfUntilBeforeCurrentTime() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(newDto(PoliciesDto.class) .withUntil(currentTime - 10000L)); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test public void shouldValidateIfCurrentTimeBetweenUntilSince() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(newDto(PoliciesDto.class) .withSince(currentTime - 10000L) .withUntil(currentTime + 10000L)); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.ILLEGAL_FACTORY_BY_SINCE_MESSAGE) public void shouldNotValidateIfUntilSinceAfterCurrentTime() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(newDto(PoliciesDto.class) .withSince(currentTime + 10000L)); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test public void shouldValidateTrackedParamsIfOrgIdIsMissingButOnPremisesTrue() throws Exception { final DtoFactory dtoFactory = getInstance(); FactoryDto factory = dtoFactory.createDto(FactoryDto.class); factory.withV("4.0") .withPolicies(dtoFactory.createDto(PoliciesDto.class) .withSince(System.currentTimeMillis() + 1_000_000) .withUntil(System.currentTimeMillis() + 10_000_000) .withReferer("codenvy.com")); validator = new TesterFactoryBaseValidator(); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateOpenfileActionIfInWrongSectionOnAppClosed() throws Exception { //given validator = new TesterFactoryBaseValidator(); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("openFile")); IdeDto ide = newDto(IdeDto.class) .withOnAppClosed(newDto(OnAppClosedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateFindReplaceActionIfInWrongSectionOnAppLoaded() throws Exception { //given validator = new TesterFactoryBaseValidator(); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("findReplace")); IdeDto ide = newDto(IdeDto.class) .withOnAppLoaded(newDto(OnAppLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateIfOpenfileActionInsufficientParams() throws Exception { //given validator = new TesterFactoryBaseValidator(); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("openFile")); IdeDto ide = newDto(IdeDto.class) .withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateIfrunCommandActionInsufficientParams() throws Exception { //given validator = new TesterFactoryBaseValidator(); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("openFile")); IdeDto ide = newDto(IdeDto.class) .withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateIfOpenWelcomePageActionInsufficientParams() throws Exception { //given validator = new TesterFactoryBaseValidator(); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("openWelcomePage")); IdeDto ide = newDto(IdeDto.class) .withOnAppLoaded((newDto(OnAppLoadedDto.class) .withActions(actions))); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = BadRequestException.class) public void shouldNotValidateIfFindReplaceActionInsufficientParams() throws Exception { //given validator = new TesterFactoryBaseValidator(); Map<String, String> params = new HashMap<>(); params.put("in", "pom.xml"); // find is missing! params.put("replace", "123"); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("findReplace") .withProperties(params)); IdeDto ide = newDto(IdeDto.class) .withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test public void shouldValidateFindReplaceAction() throws Exception { //given validator = new TesterFactoryBaseValidator(); Map<String, String> params = new HashMap<>(); params.put("in", "pom.xml"); params.put("find", "123"); params.put("replace", "456"); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("findReplace") .withProperties(params)); IdeDto ide = newDto(IdeDto.class) .withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test public void shouldValidateOpenfileAction() throws Exception { //given validator = new TesterFactoryBaseValidator(); Map<String, String> params = new HashMap<>(); params.put("file", "pom.xml"); List<IdeActionDto> actions = singletonList(newDto(IdeActionDto.class) .withId("openFile") .withProperties(params)); IdeDto ide = newDto(IdeDto.class) .withOnProjectsLoaded(newDto(OnProjectsLoadedDto.class) .withActions(actions)); FactoryDto factoryWithAccountId = requireNonNull(getInstance().clone(factory)).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @DataProvider(name = "trackedFactoryParameterWithoutValidAccountId") public Object[][] trackedFactoryParameterWithoutValidAccountId() throws URISyntaxException, IOException, NoSuchMethodException { return new Object[][]{ { newDto(FactoryDto.class) .withV("4.0") .withIde(newDto(IdeDto.class) .withOnAppLoaded(newDto(OnAppLoadedDto.class) .withActions(singletonList(newDto(IdeActionDto.class) .withId("openWelcomePage") .withProperties( ImmutableMap .<String, String>builder() .put("authenticatedTitle", "title") .put("authenticatedIconUrl", "url") .put("authenticatedContentUrl", "url") .put("nonAuthenticatedTitle", "title") .put("nonAuthenticatedIconUrl", "url") .put("nonAuthenticatedContentUrl", "url") .build())) )))}, {newDto(FactoryDto.class) .withV("4.0") .withPolicies(newDto(PoliciesDto.class) .withSince(10000L))}, {newDto(FactoryDto.class) .withV("4.0") .withPolicies(newDto(PoliciesDto.class) .withUntil(10000L))}, {newDto(FactoryDto.class) .withV("4.0") .withPolicies(newDto(PoliciesDto.class) .withReferer("host"))} }; } private FactoryDto prepareFactoryWithGivenStorage(String type, String location, String path) { return factory.withWorkspace(newDto(WorkspaceConfigDto.class) .withProjects(singletonList(newDto(ProjectConfigDto.class) .withSource(newDto(SourceStorageDto.class) .withType(type) .withLocation( location)) .withPath(path)))); } }