/******************************************************************************* * Copyright (c) 2012-2015 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; import com.google.common.collect.ImmutableMap; import org.eclipse.che.api.account.server.dao.AccountDao; import org.eclipse.che.api.account.server.dao.Member; import org.eclipse.che.api.account.server.dao.Subscription; import org.eclipse.che.api.core.ApiException; import org.eclipse.che.api.core.ConflictException; import org.eclipse.che.api.core.NotFoundException; import org.eclipse.che.api.core.ServerException; import org.eclipse.che.api.factory.dto.Action; import org.eclipse.che.api.factory.dto.Actions; import org.eclipse.che.api.factory.dto.Author; import org.eclipse.che.api.factory.dto.Factory; import org.eclipse.che.api.factory.dto.Ide; import org.eclipse.che.api.factory.dto.OnAppClosed; import org.eclipse.che.api.factory.dto.OnAppLoaded; import org.eclipse.che.api.factory.dto.OnProjectOpened; import org.eclipse.che.api.factory.dto.Policies; import org.eclipse.che.api.factory.dto.WelcomePage; import org.eclipse.che.api.factory.dto.Workspace; import org.eclipse.che.api.project.shared.dto.ImportSourceDescriptor; import org.eclipse.che.api.project.shared.dto.NewProject; import org.eclipse.che.api.project.shared.dto.Source; import org.eclipse.che.api.user.server.dao.PreferenceDao; import org.eclipse.che.api.user.server.dao.User; import org.eclipse.che.api.user.server.dao.UserDao; 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 static java.util.Collections.singletonList; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.when; @Listeners(value = {MockitoTestNGListener.class}) public class FactoryBaseValidatorTest { private static final String VALID_REPOSITORY_URL = "http://github.com/codenvy/cloudide"; private static final String ID = "id"; @Mock private AccountDao accountDao; @Mock private UserDao userDao; @Mock private PreferenceDao preferenceDao; @Mock private FactoryBuilder builder; @Mock private HttpServletRequest request; private TestFactoryBaseValidator validator; private Member member; private Factory factory; private DtoFactory dto = DtoFactory.getInstance(); @BeforeMethod public void setUp() throws ParseException, NotFoundException, ServerException { factory = dto.createDto(Factory.class) .withV("2.1") .withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git") .withLocation(VALID_REPOSITORY_URL))) .withCreator(dto.createDto(Author.class) .withAccountId(ID) .withUserId("userid")); User user = new User().withId("userid"); Subscription subscription = new Subscription() .withServiceId("Factory") .withProperties(Collections.singletonMap("Package", "Tracked")); member = new Member().withUserId("userid").withRoles(Arrays.asList("account/owner")); when(accountDao.getActiveSubscription(ID, "Factory")).thenReturn(subscription); when(accountDao.getMembers(anyString())).thenReturn(Arrays.asList(member)); when(userDao.getById("userid")).thenReturn(user); validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); } @Test public void shouldBeAbleToValidateFactoryUrlObject() throws ApiException { validator.validateSource(factory); validator.validateProjectName(factory); validator.validateAccountId(factory); } @Test public void shouldBeAbleToValidateFactoryUrlObjectIfVcsIsESBWSO2() throws ApiException { factory = factory.withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("esbwso2") .withLocation(VALID_REPOSITORY_URL))); validator.validateSource(factory); validator.validateProjectName(factory); validator.validateAccountId(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "The parameter source.project.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 shouldNotValidateIfVcsurlContainIncorrectEncodedSymbol() throws ApiException { // given factory = factory.withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git") .withLocation("http://codenvy.com/git/04%2"))); // when, then validator.validateSource(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "workspace.type have only two possible values - named or temp") public void shouldNotValidateIfWorkspaceTypeIsInvalid() throws ApiException { factory = factory.withWorkspace(dto.createDto(Workspace.class) .withType("wrongg")); validator.validateWorkspace(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "workspace.location have only two possible values - owner or acceptor") public void shouldNotValidateIfWorkspaceLocationIsInvalid() throws ApiException { factory = factory.withWorkspace(dto.createDto(Workspace.class) .withLocation("wrongg")); validator.validateWorkspace(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "current workspace location requires factory creator accountId to be set") public void shouldNotValidateIfWorkspaceLocationOwnerButNotAuthor() throws ApiException { factory = factory.withWorkspace(dto.createDto(Workspace.class).withLocation("owner")).withCreator(null); validator.validateCreator(factory); } @Test public void shouldValidateIfVcsurlIsCorrectSsh() throws ApiException { // given factory = factory.withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git") .withLocation("ssh://codenvy@review.gerrithub.io:29418/codenvy/exampleProject"))); // when, then validator.validateSource(factory); } @Test public void shouldValidateIfVcsurlIsCorrectHttps() throws ApiException { // given factory = factory.withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git") .withLocation("https://github.com/codenvy/example.git"))); // when, then validator.validateSource(factory); } @Test(dataProvider = "badAdvancedFactoryUrlProvider", expectedExceptions = ApiException.class) public void shouldNotValidateIfVcsOrVcsUrlIsInvalid(Factory factory) throws ApiException { validator.validateSource(factory); } @DataProvider(name = "badAdvancedFactoryUrlProvider") public Object[][] invalidParametersFactoryUrlProvider() throws UnsupportedEncodingException { Factory adv1 = DtoFactory.getInstance().createDto(Factory.class) .withV("2.1") .withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("notagit") .withLocation(VALID_REPOSITORY_URL))); Factory adv2 = DtoFactory.getInstance().createDto(Factory.class).withV("2.1") .withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git"))); Factory adv3 = DtoFactory.getInstance().createDto(Factory.class).withV("2.1") .withSource(dto.createDto(Source.class) .withProject(dto.createDto(ImportSourceDescriptor.class) .withType("git").withLocation(""))); 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.withProject(dto.createDto(NewProject.class) .withType("type") .withName(projectName)); // when, then validator.validateProjectName(factory); } @Test(dataProvider = "validProjectNamesProvider") public void shouldBeAbleToValidateValidProjectName(String projectName) throws Exception { // given factory.withProject(dto.createDto(NewProject.class) .withType("type") .withName(projectName)); // when, then validator.validateProjectName(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 shouldBeAbleToValidateIfOrgIdIsValid() throws ApiException, ParseException { validator.validateAccountId(factory); } @Test public void shouldBeAbleToValidateIfOrgIdAndOwnerAreValid() throws ApiException, ParseException { // when, then validator.validateAccountId(factory); } @Test(expectedExceptions = ApiException.class) public void shouldNotValidateIfAccountDoesNotExist() throws ApiException { when(accountDao.getMembers(anyString())).thenReturn(Collections.<Member>emptyList()); validator.validateAccountId(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = "You are not authorized to use this accountId.") public void shouldNotValidateIfFactoryOwnerIsNotOrgidOwner() throws ApiException, ParseException { Member wrongMember = member; wrongMember.setUserId("anotheruserid"); when(accountDao.getMembers(anyString())).thenReturn(Arrays.asList(wrongMember)); // when, then validator.validateAccountId(factory); } @Test public void shouldValidateIfCurrentTimeBeforeSinceUntil() throws ConflictException { Long currentTime = new Date().getTime(); factory.withPolicies(dto.createDto(Policies.class) .withValidSince(currentTime + 10000l) .withValidUntil(currentTime + 20000l) ); validator.validateCurrentTimeBeforeSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_VALIDSINCE_MESSAGE) public void shouldNotValidateIfValidSinceBeforeCurrent() throws ApiException { factory.withPolicies(dto.createDto(Policies.class) .withValidSince(1l) ); validator.validateCurrentTimeBeforeSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_VALIDUNTIL_MESSAGE) public void shouldNotValidateIfValidUntilBeforeCurrent() throws ApiException { factory.withPolicies(dto.createDto(Policies.class) .withValidUntil(1l) ); validator.validateCurrentTimeBeforeSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.INVALID_VALIDSINCEUNTIL_MESSAGE) public void shouldNotValidateIfValidUntilBeforeValidSince() throws ApiException { factory.withPolicies(dto.createDto(Policies.class) .withValidSince(2l) .withValidUntil(1l) ); validator.validateCurrentTimeBeforeSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.ILLEGAL_FACTORY_BY_VALIDUNTIL_MESSAGE) public void shouldNotValidateIfValidUntilBeforeCurrentTime() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(dto.createDto(Policies.class) .withValidUntil(currentTime - 10000l) ); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test public void shouldValidateIfCurrentTimeBetweenValidUntilSince() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(dto.createDto(Policies.class) .withValidSince(currentTime - 10000l) .withValidUntil(currentTime + 10000l) ); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test(expectedExceptions = ApiException.class, expectedExceptionsMessageRegExp = FactoryConstants.ILLEGAL_FACTORY_BY_VALIDSINCE_MESSAGE) public void shouldNotValidateIfValidUntilSinceAfterCurrentTime() throws ApiException { Long currentTime = new Date().getTime(); factory.withPolicies(dto.createDto(Policies.class) .withValidSince(currentTime + 10000l) ); validator.validateCurrentTimeBetweenSinceUntil(factory); } @Test public void shouldValidateTrackedParamsIfOrgIdIsMissingButOnPremisesTrue() throws Exception { final DtoFactory dtoFactory = DtoFactory.getInstance(); Factory factory = dtoFactory.createDto(Factory.class); factory.withV("2.1") .withPolicies(dtoFactory.createDto(Policies.class) .withValidSince(System.currentTimeMillis() + 1_000_000) .withValidUntil(System.currentTimeMillis() + 10_000_000) .withRefererHostname("codenvy.com")) .withActions(dtoFactory.createDto(Actions.class) .withWelcome(dtoFactory.createDto(WelcomePage.class))); validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); validator.validateAccountId(factory); } @Test(expectedExceptions = ConflictException.class) public void shouldNotValidateOpenfileActionIfInWrongSectionOnAppClosed() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("openFile")); Ide ide = dto.createDto(Ide.class).withOnAppClosed(dto.createDto(OnAppClosed.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = ConflictException.class) public void shouldNotValidateFindReplaceActionIfInWrongSectionOnAppLoaded() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("findReplace")); Ide ide = dto.createDto(Ide.class).withOnAppLoaded(dto.createDto(OnAppLoaded.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = ConflictException.class) public void shouldNotValidateIfOpenfileActionInsufficientParams() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("openFile")); Ide ide = dto.createDto(Ide.class).withOnProjectOpened(dto.createDto(OnProjectOpened.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = ConflictException.class) public void shouldNotValidateIfOpenWelcomePageActionInsufficientParams() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("openWelcomePage")); Ide ide = dto.createDto(Ide.class).withOnAppLoaded((dto.createDto(OnAppLoaded.class).withActions(actions))); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test(expectedExceptions = ConflictException.class) public void shouldNotValidateIfFindReplaceActionInsufficientParams() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); Map<String, String> params = new HashMap<>(); params.put("in", "pom.xml"); // find is missing! params.put("replace", "123"); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("findReplace").withProperties(params)); Ide ide = dto.createDto(Ide.class).withOnProjectOpened( dto.createDto(OnProjectOpened.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test public void shouldValidateFindReplaceAction() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); Map<String, String> params = new HashMap<>(); params.put("in", "pom.xml"); params.put("find", "123"); params.put("replace", "456"); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("findReplace").withProperties(params)); Ide ide = dto.createDto(Ide.class).withOnProjectOpened( dto.createDto(OnProjectOpened.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @Test public void shouldValidateOpenfileAction() throws Exception { //given validator = new TestFactoryBaseValidator(accountDao, userDao, preferenceDao); Map<String, String> params = new HashMap<>(); params.put("file", "pom.xml"); List<Action> actions = Arrays.asList(dto.createDto(Action.class).withId("openFile").withProperties(params)); Ide ide = dto.createDto(Ide.class).withOnProjectOpened( dto.createDto(OnProjectOpened.class).withActions(actions)); Factory factoryWithAccountId = dto.clone(factory).withIde(ide); //when validator.validateProjectActions(factoryWithAccountId); } @DataProvider(name = "trackedFactoryParameterWithoutValidAccountId") public Object[][] trackedFactoryParameterWithoutValidAccountId() throws URISyntaxException, IOException, NoSuchMethodException { return new Object[][]{ { dto.createDto(Factory.class) .withV("2.1") .withIde(dto.createDto(Ide.class) .withOnAppLoaded(dto.createDto(OnAppLoaded.class) .withActions(singletonList(dto.createDto(Action.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())) )))}, {dto.createDto(Factory.class).withV("2.1").withPolicies(dto.createDto(Policies.class).withValidSince(10000l))}, {dto.createDto(Factory.class).withV("2.1").withPolicies(dto.createDto(Policies.class).withValidUntil(10000l))}, {dto.createDto(Factory.class).withV("2.0") .withActions(dto.createDto(Actions.class).withWelcome(dto.createDto(WelcomePage.class)))}, {dto.createDto(Factory.class).withV("2.1").withPolicies(dto.createDto(Policies.class).withRefererHostname("host"))} }; } }