com.tasktop.c2c.server.profile.tests.service.BaseProfileServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for com.tasktop.c2c.server.profile.tests.service.BaseProfileServiceTest.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2012 Tasktop Technologies
 * Copyright (c) 2010, 2011 SpringSource, a division of VMware
 * 
 * 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:
 *     Tasktop Technologies - initial API and implementation
 ******************************************************************************/
package com.tasktop.c2c.server.profile.tests.service;

import static com.tasktop.c2c.server.common.tests.util.ValidationAssert.assertHaveValidationError;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import junit.framework.Assert;

import org.apache.commons.lang.RandomStringUtils;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.github.api.GitHub;
import org.springframework.tenancy.context.TenancyContextHolder;
import org.springframework.transaction.annotation.Transactional;

import com.tasktop.c2c.server.auth.service.AuthUtils;
import com.tasktop.c2c.server.cloud.domain.ServiceType;
import com.tasktop.c2c.server.common.service.AuthenticationException;
import com.tasktop.c2c.server.common.service.EntityNotFoundException;
import com.tasktop.c2c.server.common.service.MockJobService;
import com.tasktop.c2c.server.common.service.ReplicationScope;
import com.tasktop.c2c.server.common.service.Security;
import com.tasktop.c2c.server.common.service.ValidationException;
import com.tasktop.c2c.server.common.service.domain.QueryRequest;
import com.tasktop.c2c.server.common.service.domain.QueryResult;
import com.tasktop.c2c.server.common.service.domain.Region;
import com.tasktop.c2c.server.common.service.domain.Role;
import com.tasktop.c2c.server.common.service.job.Job;
import com.tasktop.c2c.server.common.service.web.TenancyUtil;
import com.tasktop.c2c.server.internal.deployment.domain.DeploymentConfiguration;
import com.tasktop.c2c.server.internal.profile.service.EmailJob;
import com.tasktop.c2c.server.internal.profile.service.InternalProfileService;
import com.tasktop.c2c.server.internal.profile.service.ReplicateProjectProfileJob;
import com.tasktop.c2c.server.profile.domain.Email;
import com.tasktop.c2c.server.profile.domain.internal.Agreement;
import com.tasktop.c2c.server.profile.domain.internal.ConfigurationProperty;
import com.tasktop.c2c.server.profile.domain.internal.InvitationToken;
import com.tasktop.c2c.server.profile.domain.internal.Organization;
import com.tasktop.c2c.server.profile.domain.internal.OrganizationProfile;
import com.tasktop.c2c.server.profile.domain.internal.PasswordResetToken;
import com.tasktop.c2c.server.profile.domain.internal.Profile;
import com.tasktop.c2c.server.profile.domain.internal.Project;
import com.tasktop.c2c.server.profile.domain.internal.ProjectProfile;
import com.tasktop.c2c.server.profile.domain.internal.ProjectService;
import com.tasktop.c2c.server.profile.domain.internal.ProjectServiceProfile;
import com.tasktop.c2c.server.profile.domain.internal.QuotaSetting;
import com.tasktop.c2c.server.profile.domain.internal.ServiceHost;
import com.tasktop.c2c.server.profile.domain.internal.SignUpToken;
import com.tasktop.c2c.server.profile.domain.internal.SshPublicKey;
import com.tasktop.c2c.server.profile.domain.project.ProjectAccessibility;
import com.tasktop.c2c.server.profile.domain.project.ProjectRelationship;
import com.tasktop.c2c.server.profile.domain.project.ProjectsQuery;
import com.tasktop.c2c.server.profile.domain.project.SignUpTokens;
import com.tasktop.c2c.server.profile.domain.project.SshPublicKeySpec;
import com.tasktop.c2c.server.profile.domain.project.WikiMarkupLanguage;
import com.tasktop.c2c.server.profile.service.ProfileService;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockAgreementFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockOrganizationFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockProfileFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockProjectFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockProjectInvitationTokenFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockProjectProfileFactory;
import com.tasktop.c2c.server.profile.tests.domain.mock.MockSshPublicKeyFactory;
import com.tasktop.c2c.server.profile.tests.mock.MockTaskServiceProvider;
import com.tasktop.c2c.server.profile.tests.mock.MockWikiServiceProvider;
import com.tasktop.c2c.server.tasks.domain.TaskUserProfile;
import com.tasktop.c2c.server.tasks.service.TaskService;
import com.tasktop.c2c.server.wiki.domain.Person;
import com.tasktop.c2c.server.wiki.service.WikiService;

@Transactional
public abstract class BaseProfileServiceTest {

    public static final String NOTFOUND_SUFFIX = "notfound";

    @Value("${profile.defaultLanguage}")
    protected String defaultLanguage;

    @Autowired
    protected ProfileService profileService;

    @Autowired
    protected InternalProfileService internalProfileService;

    @PersistenceContext
    protected EntityManager entityManager;

    @Autowired
    private MockJobService jobService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    private Mockery context = new JUnit4Mockery();

    @Before
    public void clearJobService() {
        jobService.getScheduledJobs().clear();
    }

    @Before
    public void swapInMockGithubConnector() {

        context = new JUnit4Mockery();

        final UsersConnectionRepository userConnRepo = context.mock(UsersConnectionRepository.class);
        final ConnectionRepository mockConnRepo = context.mock(ConnectionRepository.class);

        context.checking(new Expectations() {
            {
                allowing(userConnRepo).createConnectionRepository(with(any(String.class)));
                will(returnValue(mockConnRepo));
                allowing(mockConnRepo).findPrimaryConnection(with(GitHub.class));
                will(returnValue(null));
            }
        });

        // applicationContext.getBean(AuthenticationServiceInternal.class).setUsersConnectionRepository(userConnRepo);
    }

    @After
    public void after() {
        jobService.getScheduledJobs().clear();
        clearCredentials();
        TenancyContextHolder.clearContext();
    }

    private void clearCredentials() {
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    private void logon(Profile profile) {
        // NOTE: the token type and password are propagated so that they can be reused
        // elsewhere (see rest client)
        // add the default role
        Authentication authentication = new UsernamePasswordAuthenticationToken(profile.getUsername(),
                profile.getPassword(), AuthUtils.toGrantedAuthorities(Collections.singletonList(Role.User)));
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private void logonWithOrganization(Profile profile, String orgIdentifier)
            throws EntityNotFoundException, ValidationException {
        setupOrganization();
        Authentication authentication = new UsernamePasswordAuthenticationToken(profile.getUsername(),
                profile.getPassword(), AuthUtils.toGrantedAuthorities(
                        Collections.singletonList(AuthUtils.toCompoundOrganizationRole(Role.User, orgIdentifier))));
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private boolean hasRole(Authentication auth, String role) {
        return new SecurityExpressionRoot(auth) {
        }.hasRole(role);
    }

    protected Profile createMockProfile(EntityManager entityManager) {
        return MockProfileFactory.create(entityManager);
    }

    protected Project createMockProject(EntityManager entityManager) {
        return MockProjectFactory.create(entityManager);
    }

    @Test
    public void testAuthenticate() throws AuthenticationException {
        Profile profile = createMockProfile(entityManager);

        String originalPassword = profile.getPassword();
        profile.setPassword(passwordEncoder.encodePassword(originalPassword, null));

        Project project = createMockProject(entityManager);
        ProjectProfile projectProfile = new ProjectProfile();
        projectProfile.setProject(project);
        project.getProjectProfiles().add(projectProfile);
        projectProfile.setProfile(profile);
        projectProfile.setUser(true);
        profile.getProjectProfiles().add(projectProfile);

        profileService.authenticate(profile.getUsername(), originalPassword);

        assertEquals(profile.getUsername(), Security.getCurrentUser());

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        assertNotNull(authentication);

        assertTrue(hasRole(authentication, Role.User));
        assertTrue(hasRole(authentication, Role.User + "/" + project.getIdentifier()));
        assertFalse(hasRole(authentication, Role.Admin + "/" + project.getIdentifier()));

        projectProfile.setOwner(true);

        profileService.authenticate(profile.getUsername(), originalPassword);

        authentication = SecurityContextHolder.getContext().getAuthentication();

        assertNotNull(authentication);

        assertTrue(hasRole(authentication, Role.User));
        assertTrue(hasRole(authentication, Role.User + "/" + project.getIdentifier()));
        assertTrue(hasRole(authentication, Role.Admin + "/" + project.getIdentifier()));

        try {
            profileService.authenticate(profile.getUsername(), originalPassword + "BAD PASSWORD");
            Assert.fail("expect exception");
        } catch (AuthenticationException e) {
            // Expected
        } finally {
            // There should be an exception, and our existing credentials should be wiped out
            assertNull(SecurityContextHolder.getContext().getAuthentication());
        }
    }

    @Test(expected = IllegalArgumentException.class)
    public void testCreateProfile() throws ValidationException {
        Profile arg = createMockProfile(null);
        Long id = profileService.createProfile(arg);

        assertNotNull(id);
        Profile profile = entityManager.find(Profile.class, id);
        assertEquals(id, profile.getId());
        assertNotNull(profile.getVersion());
        assertEquals(arg.getFirstName(), profile.getFirstName());
        assertEquals(arg.getLastName(), profile.getLastName());
        assertEquals(arg.getUsername(), profile.getUsername());

        profileService.createProfile(arg);
    }

    @Test(expected = ValidationException.class)
    public void testCreateProfileUsernameNonunique() throws ValidationException {
        Profile profileExists = createMockProfile(entityManager);
        Profile arg = createMockProfile(null);
        arg.setUsername(profileExists.getUsername());
        try {
            profileService.createProfile(arg);
        } catch (ValidationException e) {
            assertHaveValidationError(e, "Username is in use. Please try a different username.");
            throw e;
        }
    }

    @Test(expected = ValidationException.class)
    public void testCreateProfileEmailNonunique() throws ValidationException {
        Profile profileExists = createMockProfile(entityManager);
        Profile arg = createMockProfile(null);
        arg.setEmail(profileExists.getEmail());
        try {
            profileService.createProfile(arg);
        } catch (ValidationException e) {
            assertHaveValidationError(e,
                    "Email is already registered. Please login or use a different email address.");
            throw e;
        }
    }

    @Test(expected = ValidationException.class)
    public void testCreateProfileNonAsciiUsername() throws ValidationException {
        String[] testEscapeSequences = new String[] { "\\u2297", //
                "\u00E5", // 
                "\u00E4", // 
                "\u00F6", // 
                "\u00FC", // 

        };
        for (String escapeSequence : testEscapeSequences) {
            Profile arg = createMockProfile(null);
            String username = "abc123" + escapeSequence;
            arg.setUsername(username);
            try {
                profileService.createProfile(arg);
            } catch (ValidationException e) {
                assertHaveValidationError(e,
                        "Username must not use special characters. Please try a different username.");
                throw e;
            }
        }
    }

    @Test
    public void testCreateProfileNullLanguage() throws ValidationException {
        Profile arg = createMockProfile(null);
        arg.setLanguage(null);
        Long id = profileService.createProfile(arg);

        Profile profile = entityManager.find(Profile.class, id);
        assertEquals(defaultLanguage, profile.getLanguage());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetProfileNotFound() throws Exception {
        profileService.getProfile(0L);
    }

    @Test
    public void testGetProfile() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);

        entityManager.flush();
        entityManager.clear();

        Long id = profile.getId();

        Profile profile2 = profileService.getProfile(id);
        assertNotNull(profile2);
        assertEquals(id, profile2.getId());
        assertEquals(profile.getUsername(), profile2.getUsername());
    }

    @Test
    public void testGetProfileByEmail() {
        Profile profile = createMockProfile(entityManager);

        entityManager.flush();
        entityManager.clear();

        Profile profile2 = profileService.getProfileByEmail(profile.getEmail());
        assertNull(profileService.getProfileByEmail(profile.getEmail() + NOTFOUND_SUFFIX));
        assertEquals(profile.getId(), profile2.getId());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetProfileByUsername() throws Exception {
        Profile profile = createMockProfile(entityManager);

        entityManager.flush();
        entityManager.clear();

        Profile profile2 = profileService.getProfileByUsername(profile.getUsername());
        assertNotNull(profile2);
        assertEquals(profile.getId(), profile2.getId());

        profileService.getProfileByUsername(profile.getUsername() + NOTFOUND_SUFFIX);
    }

    @Test
    public void testGetProject() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);
        entityManager.persist(project.addProfile(profile));

        Long id = project.getId();

        entityManager.flush();
        entityManager.clear();

        Project project2 = profileService.getProject(id);
        assertNotNull(project2);
        assertEquals(id, project2.getId());
        assertEquals(project.getName(), project2.getName());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetProjectNotFound() throws Exception {
        profileService.getProject(0L);
    }

    @Test
    public void testGetProjectByIdentity() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);
        entityManager.persist(project.addProfile(profile));

        entityManager.flush();
        entityManager.clear();

        Long id = project.getId();

        Project project2 = profileService.getProjectByIdentifier(project.getIdentifier());
        assertNotNull(project2);
        assertNotSame(project, project2);
        assertEquals(id, project2.getId());
        assertEquals(project.getName(), project2.getName());
        assertEquals(project.getIdentifier(), project2.getIdentifier());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetProjectByIdentityNotFound() throws Exception {
        profileService.getProjectByIdentifier("123");
    }

    @Test
    public void testCreateProject() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);

        Project project = createMockProject(null);

        Long id = profileService.createProject(profile.getId(), project).getId();

        assertNotNull(id);
        Project project2 = entityManager.find(Project.class, id);
        assertNotNull(project2);
        assertEquals(id, project2.getId());
        assertEquals(project.getName(), project2.getName());

        assertEquals(1, project.getProjectProfiles().size());
        assertEquals(profile, project.getProjectProfiles().get(0).getProfile());
        assertEquals(true, project.getProjectProfiles().get(0).getOwner());
    }

    @Test(expected = ValidationException.class)
    public void testCreateProjectNameNonunique() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project projectExists = createMockProject(entityManager);
        Project project = createMockProject(null);
        project.setName(projectExists.getName());

        try {
            profileService.createProject(profile.getId(), project);
        } catch (ValidationException e) {
            // expected
            assertHaveValidationError(e, "Project name is in use. Please try a different project name.");
            throw e;
        }
    }

    @Test
    public void testCreateProjectNonAsciiCharacters() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);

        Project project = createMockProject(null);
        project.setName("Project Name With Non-Ascii\u00E4");
        project.setDescription("a description with non-ascii\u00E4");

        Long id;
        try {
            id = profileService.createProject(profile.getId(), project).getId();
            fail("expected validation exception");
        } catch (ValidationException e) {
            // expected
        }

        project.setName("Normal Project Name");
        id = profileService.createProject(profile.getId(), project).getId();

        entityManager.flush();
        entityManager.clear();

        assertNotNull(id);
        Project project2 = entityManager.find(Project.class, id);
        assertNotNull(project2);
        assertEquals(id, project2.getId());
        assertEquals(project.getName(), project2.getName());
        assertEquals(project.getDescription(), project2.getDescription());
    }

    @Test(expected = ValidationException.class)
    public void testCreateProjectDescriptionTooLong() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(null);

        String string256 = RandomStringUtils.randomAlphanumeric(256);
        project.setDescription(string256);
        try {
            profileService.createProject(profile.getId(), project);
        } catch (ValidationException e) {
            // expected
            assertHaveValidationError(e, "Description is too long (Maximum of 255 characters)");
            throw e;
        }
    }

    @Test(expected = EntityNotFoundException.class)
    public void testCreateProjectNotFound() throws ValidationException, EntityNotFoundException {
        Project project = createMockProject(null);

        // should throw EntityNotFoundException
        profileService.createProject(0L, project);
    }

    @Test
    public void testCreateProjectWithTenantOrg() throws Exception {
        // create an organization and set it as the current tenant
        String orgId = "qa-dev";
        Organization org = new Organization();
        org.setIdentifier(orgId);
        org.setName("test organization");
        entityManager.persist(org);
        TenancyUtil.setOrganizationTenancyContext(orgId);

        Profile profile = setupProfile(false);

        Project project = createMockProject(null);
        project.setIdentifier(null); // org specific identifier will be generated on project creation
        Long id = profileService.createProject(profile.getId(), project).getId();
        assertNotNull(id);
        Project project2 = entityManager.find(Project.class, id);
        assertNotNull(project2);
        assertTrue(project2.getIdentifier().startsWith(orgId));

        // reset our tenant org so that other tests aren't affected
        TenancyUtil.clearContext();
    }

    private <T> int getEntityCount(Class<T> entityClass) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Long> query = criteriaBuilder.createQuery(Long.class);
        Root<T> root = query.from(entityClass);
        query.select(criteriaBuilder.count(root));
        return entityManager.createQuery(query).getSingleResult().intValue();
    }

    @SuppressWarnings("unchecked")
    @Test(expected = ValidationException.class)
    public void testCreateProjectMaxProjectsReached() throws ValidationException, EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(null);

        for (ConfigurationProperty existingProperty : (List<ConfigurationProperty>) entityManager
                .createQuery("SELECT c FROM " + ConfigurationProperty.class.getSimpleName() + " c")
                .getResultList()) {
            entityManager.remove(existingProperty);
        }
        entityManager.flush();

        // Set our global number of projects to be the same as our current number so we trigger an exception
        int numProjects = getEntityCount(Project.class);
        ConfigurationProperty configProp = new ConfigurationProperty();
        configProp.setName(ConfigurationProperty.MAXNUM_PROJECTS_NAME);
        configProp.setValue(String.valueOf(numProjects));
        entityManager.persist(configProp);

        try {
            profileService.createProject(profile.getId(), project);
        } catch (ValidationException e) {
            // expected
            assertHaveValidationError(e,
                    "Unable to create project - the maximum number of projects in the system has been reached");
            throw e;
        }
    }

    @Test
    public void testUpdateProject() throws ValidationException, EntityNotFoundException {

        Profile profile = setupProfile(false);

        Project project = createMockProject(null);

        project = profileService.createProject(profile.getId(), project);
        entityManager.clear();

        String originalIdentity = project.getIdentifier();

        project.setName(project.getName() + "2");
        project.setDescription(project.getDescription() + "2");
        project.setIdentifier(project.getIdentifier() + "2");
        project.setAccessibility(ProjectAccessibility.PUBLIC);

        Project updatedProject = profileService.updateProject(project);

        assertEquals(project.getName(), updatedProject.getName());
        assertEquals(project.getDescription(), updatedProject.getDescription());
        assertEquals(project.getAccessibility(), updatedProject.getAccessibility());

        // identifier should never change
        assertEquals(originalIdentity, updatedProject.getIdentifier());
    }

    @Test
    public void testUpdateProjectWikiLanguage() throws ValidationException, EntityNotFoundException {

        Profile profile = setupProfile(false);
        Project project = createMockProject(null);

        project = profileService.createProject(profile.getId(), project);
        entityManager.clear();

        assertEquals(WikiMarkupLanguage.TEXTILE, project.getProjectPreferences().getWikiLanguage());
        project.getProjectPreferences().setWikiLanguage(WikiMarkupLanguage.CONFLUENCE);
        int size = jobService.getScheduledJobs().size();

        Project updatedProject = profileService.updateProject(project);

        assertEquals(size + 2, jobService.getScheduledJobs().size());
        assertEquals(WikiMarkupLanguage.CONFLUENCE, updatedProject.getProjectPreferences().getWikiLanguage());
    }

    // task 1824
    @Test(expected = ValidationException.class)
    public void testUpdateProject_DescriptionTooLong() throws EntityNotFoundException, ValidationException {
        Profile profile = setupProfile(true);
        Project project = createMockProject(null);

        project = profileService.createProject(profile.getId(), project);

        entityManager.flush();
        entityManager.clear();

        project.setDescription(RandomStringUtils.random(256));
        profileService.updateProject(project);
    }

    @Test(expected = EntityNotFoundException.class)
    public void testUpdateProject_ProjectNotFound() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);

        project = profileService.createProject(profile.getId(), project);

        entityManager.flush();
        entityManager.clear();

        project.setId(project.getId() + 2);

        profileService.updateProject(project);
    }

    @Test
    public void testGetProfileProjects() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        List<Project> projects = MockProjectFactory.create(entityManager, 5);
        for (Project project : projects) {
            entityManager.persist(project.addProfile(profile));
        }

        List<Project> foundProjects = profileService.getProfileProjects(profile.getId());
        assertNotNull(foundProjects);
        assertTrue(projects.containsAll(foundProjects));
        assertTrue(foundProjects.containsAll(projects));
        for (Project project : foundProjects) {
            assertNotNull(project.getId());
        }
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetProfileProjectsNotFound() throws EntityNotFoundException {
        // should throw EntityNotFoundException
        profileService.getProfileProjects(0L);
    }

    @Test(expected = EntityNotFoundException.class)
    public void testUpdateProfileNotFound() throws Exception {
        Profile profile = createMockProfile(null);
        profile.setId(123L);

        // should throw EntityNotFoundException
        profileService.updateProfile(profile);
    }

    @Test
    public void testUpdateProfile() throws ValidationException, EntityNotFoundException {

        Profile profile = createMockProfile(entityManager);
        entityManager.flush();
        entityManager.clear();

        Organization org = setupOrganization();
        logonWithOrganization(profile, org.getIdentifier());

        profile.setFirstName(profile.getFirstName() + "_updated");
        profile.setLastName(profile.getLastName() + "_updated");
        profile.setEmail("updated_" + profile.getEmail());

        profileService.updateProfile(profile);

        Profile profile2 = entityManager.find(Profile.class, profile.getId());
        assertNotNull(profile2);
        assertNotSame(profile, profile2);

        assertEquals(profile.getFirstName(), profile2.getFirstName());
        assertEquals(profile.getEmail(), profile2.getEmail());
    }

    @Test
    public void testCreatePasswordResetToken() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        Profile profile2 = entityManager.find(Profile.class, profile.getId());
        assertEquals(1, profile2.getPasswordResetTokens().size());
    }

    @Test
    public void testPasswordReset() throws EntityNotFoundException, ValidationException {
        List<Job> scheduledJobs = jobService.getScheduledJobs();
        assertEquals(0, scheduledJobs.size());

        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        PasswordResetToken token = profile.getPasswordResetTokens().get(0);
        profileService.resetPassword(token.getToken(), "abc123ABC)$(^");

        Profile profile2 = entityManager.find(Profile.class, profile.getId());

        assertEquals(1, profile2.getPasswordResetTokens().size());
        assertNotNull(profile2.getPasswordResetTokens().get(0).getDateUsed());

        scheduledJobs = jobService.getScheduledJobs();
        assertEquals(1, scheduledJobs.size());

        Job job = scheduledJobs.get(0);
        assertTrue(job instanceof EmailJob);
        EmailJob emailJob = (EmailJob) job;
        assertEquals(profile2.getEmail(), emailJob.getEmail().getTo());
    }

    @Test(expected = ValidationException.class)
    public void testPasswordResetWithUnsafePassword() throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        PasswordResetToken token = profile.getPasswordResetTokens().get(0);

        // username is not a safe password, this should blow up.
        profileService.resetPassword(token.getToken(), profile.getUsername());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testPasswordResetTokenNotFound() throws Exception {
        // This should blow up.
        profileService.resetPassword("invalid-token", "abc123");
    }

    @Test(expected = EntityNotFoundException.class)
    public void testPasswordResetTokenAlreadyUsed() throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        PasswordResetToken token = profile.getPasswordResetTokens().get(0);
        profileService.resetPassword(token.getToken(), "abc123ABC)$(^");

        // This should blow up.
        profileService.resetPassword(token.getToken(), "def123ABC)$(^");
    }

    @Test
    public void testIsTokenAvailableTokenIsValid() throws Exception {
        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        PasswordResetToken token = profile.getPasswordResetTokens().get(0);

        assertTrue(profileService.getPasswordResetToken(token.getToken()) != null);
    }

    @Test(expected = EntityNotFoundException.class)
    public void testIsTokenAvailableTokenIsUsed() throws Exception {
        Profile profile = createMockProfile(entityManager);
        profileService.requestPasswordReset(profile.getEmail());
        PasswordResetToken token = profile.getPasswordResetTokens().get(0);
        profileService.resetPassword(token.getToken(), "abc123ABC)$(^");

        profileService.getPasswordResetToken(token.getToken());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testIsTokenAvailableTokenDoesNotExist() throws Exception {
        profileService.getPasswordResetToken("invalid-token");
    }

    @Test
    public void testFindProfiles() {
        int count = 20;
        int max = count * 3;
        List<Profile> profiles = MockProfileFactory.create(null, max);
        int x = -1;
        for (Profile profile : profiles) {
            ++x;
            // 20 profiles with some variant of test123 is username, firstname, or lastname
            if (x < count) {
                if (x % 3 == 0) {
                    profile.setUsername("tEst123" + x);
                } else if (x % 3 == 1) {
                    profile.setFirstName("TEST123" + x + profile.getFirstName());
                } else {
                    profile.setLastName("teSt123" + x + profile.getLastName());
                }
            }
            // 40 more profiles with test123 set only in the email field
            else {
                profile.setUsername("abc" + x);
                profile.setEmail("Test123_" + x + profile.getEmail());
                profile.setFirstName("abc" + x + profile.getFirstName());
                profile.setLastName("abc" + x + profile.getLastName());
            }
            entityManager.persist(profile);
        }
        entityManager.flush();
        entityManager.clear();

        Region region = new Region(0, count / 2);
        QueryResult<Profile> result = profileService.findProfiles("Test123", region, null);
        assertNotNull(result);
        assertEquals(count, result.getTotalResultSize().intValue());
        assertEquals(region.getSize().intValue(), result.getResultPage().size());
    }

    protected ProjectProfile getProjectProfile(Project project, Profile profile) {
        try {
            return (ProjectProfile) entityManager
                    .createQuery("select e from " + ProjectProfile.class.getSimpleName()
                            + " e where e.project = :a and e.profile = :p")
                    .setParameter("a", project).setParameter("p", profile).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Test
    public void testRemoveProjectProfile() throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        Profile profile2 = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);

        ProjectProfile projectProfile = addProject(profile, project);
        projectProfile.setOwner(true);
        addProject(profile2, project);

        try {
            profileService.removeProjectProfile(project.getId(), profile.getId());
            fail("Expected exception");
        } catch (ValidationException e) {
            // expected
        }
        profileService.removeProjectProfile(project.getId(), profile2.getId());

        assertEquals(1, project.getProjectProfiles().size());
        assertEquals(1, profile.getProjectProfiles().size());

        projectProfile = getProjectProfile(project, profile2);
        assertNull(projectProfile);
    }

    protected ProjectProfile addProject(Profile profile, Project project) throws EntityNotFoundException {
        return MockProjectProfileFactory.create(project, profile, entityManager);
    }

    @Test
    public void testGetProjectProfile() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);

        ProjectProfile projectProfile = addProject(profile, project);
        projectProfile.setOwner(true);

        ProjectProfile projectProfile2 = profileService.getProjectProfile(project.getId(), profile.getId());

        assertSame(projectProfile, projectProfile2);
    }

    @Test
    public void testUpdateProjectProfile() throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        Profile profile2 = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);

        ProjectProfile projectProfile = addProject(profile, project);
        projectProfile.setOwner(true);
        ProjectProfile projectProfile2 = addProject(profile2, project);
        entityManager.flush();
        entityManager.clear();

        projectProfile2.setOwner(true);
        profileService.updateProjectProfile(projectProfile2); // This blows up

        ProjectProfile projectProfile3 = entityManager.find(ProjectProfile.class, projectProfile2.getId());

        assertNotSame(projectProfile2, projectProfile3);
        assertEquals(projectProfile2, projectProfile3);
        assertEquals(projectProfile2.getOwner(), projectProfile3.getOwner());
    }

    @Test(expected = ValidationException.class)
    public void testUpdateProjectProfileOwnerCannotDisownProject()
            throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        logon(profile);
        Project project = createMockProject(entityManager);

        ProjectProfile projectProfile = addProject(profile, project);
        projectProfile.setOwner(true);
        entityManager.flush();
        entityManager.clear();

        projectProfile.setOwner(false);
        try {
            profileService.updateProjectProfile(projectProfile);
        } catch (ValidationException e) {
            assertHaveValidationError(e,
                    "You cannot remove yourself as an owner. To give up ownership of a project, have another project owner remove your role.");
            throw e;
        }
    }

    @Test
    public void testGetPendingAgreements() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        logon(profile);
        MockAgreementFactory.create(entityManager);

        Agreement agreement = MockAgreementFactory.create(entityManager);
        agreement.setActive(false);
        entityManager.flush();

        List<Agreement> agreements = profileService.getPendingAgreements();
        assertEquals(1, agreements.size());
    }

    @Test
    public void testApproveAgreement() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        logon(profile);
        Agreement agreement = MockAgreementFactory.create(entityManager);

        List<Agreement> agreements = null;
        agreements = profileService.getPendingAgreements();
        assertEquals(1, agreements.size());
        assertEquals(agreement, agreements.get(0));

        profileService.approveAgreement(agreement.getId());

        agreements = profileService.getPendingAgreements();
        assertEquals(0, agreements.size());
    }

    @Test
    public void testGetApprovedAgreements() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        logon(profile);
        Agreement a = MockAgreementFactory.create(entityManager);

        List<Agreement> agreements = profileService.getPendingAgreements();
        assertEquals(1, agreements.size());

        profileService.approveAgreement(a.getId());

        List<Agreement> agreementsAfter = profileService.getPendingAgreements();
        assertEquals(0, agreementsAfter.size());
    }

    @Test
    public void testProjectInvitationForEmail() throws Exception {
        List<Job> scheduledJobs = jobService.getScheduledJobs();
        assertEquals(0, scheduledJobs.size());

        // Create an project which we can invite someone to.
        Project mockProject = createMockProject(entityManager);

        // Create a user, who will be an administrator on this project
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);
        ProjectProfile adminLink = new ProjectProfile();
        adminLink.setProject(mockProject);
        adminLink.setProfile(mockProfile);
        adminLink.setOwner(true);
        entityManager.persist(adminLink);

        // Now, invite some user to our project
        String testEmail = "test@email.com";
        profileService.inviteUserForProject(testEmail, mockProject.getIdentifier());

        // Confirm that our email was sent, and that it contained the info we expected.
        scheduledJobs = jobService.getScheduledJobs();
        assertEquals(1, scheduledJobs.size());

        Job job = scheduledJobs.get(0);
        assertTrue(job instanceof EmailJob);
        EmailJob emailJob = (EmailJob) job;
        Email sentEmail = emailJob.getEmail();

        assertEquals(testEmail, sentEmail.getTo());
        assertTrue(sentEmail.getBody().contains(mockProfile.getFirstName()));
        assertTrue(sentEmail.getBody().contains(mockProfile.getLastName()));
        assertTrue(sentEmail.getBody().contains(mockProfile.getUsername()));
        assertTrue(sentEmail.getBody().contains(mockProject.getName()));
        assertTrue(sentEmail.getBody().contains(mockProject.getDescription()));
    }

    @Test
    public void testAcceptInvitation() throws Exception {
        // Create an project which we can invite someone to.
        Project mockProject = createMockProject(entityManager);

        // Create a user, who will be an administrator on this project
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);
        ProjectProfile adminLink = new ProjectProfile();
        adminLink.setProject(mockProject);
        adminLink.setProfile(mockProfile);
        adminLink.setOwner(true);
        entityManager.persist(adminLink);

        // Now, invite some user to our project
        String testEmail = "test@email.com";
        profileService.inviteUserForProject(testEmail, mockProject.getIdentifier());

        // Create a second user, who will accept this invitation
        Profile invitedProfile = createMockProfile(entityManager);
        logon(invitedProfile);

        for (ProjectProfile projectProfile : mockProject.getProjectProfiles()) {
            assertFalse(invitedProfile.equals(projectProfile.getProfile()));
        }

        // Find our one and only invitation token, and make sure it's the one we expect.
        Query query = entityManager.createQuery("select i from " + InvitationToken.class.getSimpleName() + " i");
        @SuppressWarnings("unchecked")
        List<InvitationToken> tokenList = query.getResultList();
        assertEquals(1, tokenList.size());
        InvitationToken token = tokenList.get(0);
        assertEquals(mockProject, token.getProject());
        assertEquals(mockProfile, token.getIssuingProfile());

        // Make sure that our used date is blank before we accept the invitaiton.
        assertNull(token.getDateUsed());

        // Do the actual acceptance now.
        profileService.acceptInvitation(token.getToken());

        boolean userPresent = false;
        boolean permissionsCorrect = false;

        // Confirm that our user now has the expected roles.
        for (ProjectProfile projectProfile : mockProject.getProjectProfiles()) {
            if (invitedProfile.equals(projectProfile.getProfile())) {
                userPresent = true;
                // If the owner is false, then the permissions are correct.
                permissionsCorrect = !projectProfile.getOwner();
            }
        }

        assertTrue(userPresent);
        assertTrue(permissionsCorrect);

        // Make sure that our used date was updated
        assertNotNull(token.getDateUsed());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testAcceptInvitation_NotFound() throws Exception {
        // Create an project which we can invite someone to.
        Project mockProject = createMockProject(entityManager);

        // Create a user, who will be an administrator on this project
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);
        ProjectProfile adminProjectProfile = new ProjectProfile();
        adminProjectProfile.setProject(mockProject);
        adminProjectProfile.setProfile(mockProfile);
        adminProjectProfile.setOwner(true);
        entityManager.persist(adminProjectProfile);

        // Invite some user to our project
        String testEmail = "test@example.com";
        profileService.inviteUserForProject(testEmail, mockProject.getIdentifier());

        // Create a second user, who will accept this invitation
        Profile invitedProfile = createMockProfile(entityManager);
        logon(invitedProfile);

        for (ProjectProfile projectProfile : mockProject.getProjectProfiles()) {
            assertFalse(invitedProfile.equals(projectProfile.getProfile()));
        }

        // Accept the invite
        profileService.acceptInvitation(UUID.randomUUID().toString());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testAcceptInvitation_AlreadyUsed() throws Exception {
        // Create an project which we can invite someone to.
        Project mockProject = createMockProject(entityManager);

        // Create a user, who will be an administrator on this project
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);
        ProjectProfile adminProjectProfile = new ProjectProfile();
        adminProjectProfile.setProject(mockProject);
        adminProjectProfile.setProfile(mockProfile);
        adminProjectProfile.setOwner(true);
        entityManager.persist(adminProjectProfile);

        // Now, invite some user to our project
        String testEmail = "test@email.com";
        profileService.inviteUserForProject(testEmail, mockProject.getIdentifier());

        // Create a second user, who will accept this invitation
        Profile invitedProfile = createMockProfile(entityManager);
        logon(invitedProfile);

        for (ProjectProfile projectProfile : mockProject.getProjectProfiles()) {
            assertFalse(invitedProfile.equals(projectProfile.getProfile()));
        }

        // Find our one and only invitation token, and make sure it's the one we expect.
        Query query = entityManager.createQuery("select i from " + InvitationToken.class.getSimpleName() + " i");
        @SuppressWarnings("unchecked")
        List<InvitationToken> tokenList = query.getResultList();
        assertEquals(1, tokenList.size());
        InvitationToken token = tokenList.get(0);
        assertEquals(mockProject, token.getProject());
        assertEquals(mockProfile, token.getIssuingProfile());

        // Do the correct acceptance now.
        profileService.acceptInvitation(token.getToken());

        // Do the acceptance a second time, will throw exception.
        profileService.acceptInvitation(token.getToken());
    }

    @Test
    public void testFindPublicProjects() {
        int count = 20;
        setupProjects(count, ProjectAccessibility.PUBLIC, null);

        Region region = new Region(0, count / 2);
        QueryResult<Project> result = profileService
                .findProjects(new ProjectsQuery("tesT123", new QueryRequest(region, null)));
        assertNotNull(result);
        assertEquals(count, result.getTotalResultSize().intValue());
        assertEquals(region.getSize().intValue(), result.getResultPage().size());

        region = new Region(count / 2, count / 2);
        result = profileService.findProjects(new ProjectsQuery("tesT123", new QueryRequest(region, null)));
        assertNotNull(result);
        assertEquals(count, result.getTotalResultSize().intValue());
        assertEquals(region.getSize().intValue(), result.getResultPage().size());
    }

    @Test
    public void testFindPrivateProjects() {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);

        int count = 20;
        setupProjects(count, ProjectAccessibility.PRIVATE, mockProfile);

        Region region = new Region(0, count / 2);
        QueryResult<Project> result = profileService
                .findProjects(new ProjectsQuery("tesT123", new QueryRequest(region, null)));
        assertNotNull(result);
        assertEquals(count, result.getTotalResultSize().intValue());
        assertEquals(region.getSize().intValue(), result.getResultPage().size());
    }

    @Test
    public void testFindOrgPrivateProjectsForOrgUserNotBelongingToProjectWithOrgId() throws Exception {
        Organization org = setupOrganization();
        Profile projectOwner = setupProfile(false);
        OrganizationProfile orgToOwner = new OrganizationProfile();
        orgToOwner.setOrganization(org);
        orgToOwner.setProfile(projectOwner);
        org.getOrganizationProfiles().add(orgToOwner);
        projectOwner.getOrganizationProfiles().add(orgToOwner);
        entityManager.persist(orgToOwner);

        Profile anotherGuyInSameOrg = createMockProfile(entityManager);
        OrganizationProfile orgToAnotherGuy = new OrganizationProfile();
        orgToAnotherGuy.setOrganization(org);
        orgToAnotherGuy.setProfile(anotherGuyInSameOrg);
        org.getOrganizationProfiles().add(orgToAnotherGuy);
        anotherGuyInSameOrg.getOrganizationProfiles().add(orgToAnotherGuy);
        entityManager.persist(orgToAnotherGuy);
        entityManager.flush();

        Project project = createMockProject(null);
        project.setAccessibility(ProjectAccessibility.ORGANIZATION_PRIVATE);
        project.setOrganization(org);
        profileService.createProject(projectOwner.getId(), project);

        logon(anotherGuyInSameOrg);

        ProjectsQuery query = new ProjectsQuery(ProjectRelationship.ALL, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        QueryResult<Project> result = profileService.findProjects(query);
        assertNotNull(result);
        assertEquals(1, result.getTotalResultSize().intValue());
    }

    @Test
    public void testFindAllProjectsForOrgUser() throws Exception {
        Organization org = setupOrganization();
        Profile projectOwner = setupProfile(false);
        OrganizationProfile orgToOwner = new OrganizationProfile();
        orgToOwner.setOrganization(org);
        orgToOwner.setProfile(projectOwner);
        org.getOrganizationProfiles().add(orgToOwner);
        projectOwner.getOrganizationProfiles().add(orgToOwner);
        entityManager.persist(orgToOwner);

        Profile anotherGuyInSameOrg = createMockProfile(entityManager);
        entityManager.flush();

        // create a org-private project ...
        Project orgPrivateProject = createMockProject(null);
        orgPrivateProject.setAccessibility(ProjectAccessibility.ORGANIZATION_PRIVATE);
        orgPrivateProject.setOrganization(org);
        profileService.createProject(projectOwner.getId(), orgPrivateProject);

        // create an org-private project in a different org
        Organization org2 = setupOrganization();
        Project orgPrivateProject2 = createMockProject(null);
        orgPrivateProject2.setAccessibility(ProjectAccessibility.ORGANIZATION_PRIVATE);
        orgPrivateProject2.setOrganization(org2);
        profileService.createProject(projectOwner.getId(), orgPrivateProject2);

        // ... and a private project (that should be excluded from results)
        Project privateProject = createMockProject(null);
        privateProject.setAccessibility(ProjectAccessibility.PRIVATE);
        privateProject.setOrganization(org);
        profileService.createProject(projectOwner.getId(), privateProject);

        // create a public project without an orgId which should also appear in the results
        Project publicProject = createMockProject(null);
        publicProject.setAccessibility(ProjectAccessibility.PUBLIC);
        profileService.createProject(projectOwner.getId(), publicProject);

        // login the user with an authority associating the user to the organization
        String authRole = AuthUtils.toCompoundOrganizationRole(Role.User, org.getIdentifier());
        Authentication authentication = new UsernamePasswordAuthenticationToken(anotherGuyInSameOrg.getUsername(),
                anotherGuyInSameOrg.getPassword(),
                AuthUtils.toGrantedAuthorities(Collections.singletonList(authRole)));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        ProjectsQuery query = new ProjectsQuery(ProjectRelationship.ALL, null);
        QueryResult<Project> result = profileService.findProjects(query);
        assertNotNull(result);
        assertEquals(2, result.getTotalResultSize().intValue());
    }

    private void setupProjects(int count, ProjectAccessibility projectAccessibility, Profile profile) {
        int max = count * 3;
        List<Project> projects = MockProjectFactory.create(entityManager, max);
        int x = -1;
        for (Project project : projects) {
            project.setAccessibility(projectAccessibility);
            ++x;
            if (x < count) {
                if (x % 3 == 0) {
                    project.setName("Test123" + x + project.getName());
                } else if (x % 3 == 1) {
                    project.setDescription("tEst123" + x + project.getDescription());
                } else {
                    project.setIdentifier("teSt123" + x + project.getIdentifier());
                }
                if (profile != null) {
                    ProjectProfile mock = new ProjectProfile();
                    mock.setProfile(profile);
                    mock.setProject(project);
                    entityManager.persist(mock);
                }

            } else {
                project.setName("abc" + x + project.getName());
                project.setDescription("abc" + x + project.getDescription());
                project.setIdentifier("abc" + x + project.getIdentifier());
            }

        }
        entityManager.flush();
        entityManager.clear();
    }

    @Test
    public void testWatchProject() throws Exception {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);

        Project project = createMockProject(entityManager);
        project.setAccessibility(ProjectAccessibility.PUBLIC);
        entityManager.persist(project);

        assertEquals(0, profileService.getProfileProjects(mockProfile.getId()).size());
        profileService.watchProject(project.getIdentifier());
        assertEquals(1, profileService.getProfileProjects(mockProfile.getId()).size());
    }

    @Test
    public void testUnwatchProject() throws Exception {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);

        Project project = createMockProject(entityManager);
        project.setAccessibility(ProjectAccessibility.PUBLIC);
        entityManager.persist(project);

        assertEquals(0, profileService.getProfileProjects(mockProfile.getId()).size());
        profileService.watchProject(project.getIdentifier());
        assertEquals(1, profileService.getProfileProjects(mockProfile.getId()).size());
        profileService.unwatchProject(project.getIdentifier());
        assertEquals(0, profileService.getProfileProjects(mockProfile.getId()).size());
    }

    @Test
    public void testIsWatchingProject() throws Exception {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);

        Project project = createMockProject(entityManager);
        project.setAccessibility(ProjectAccessibility.PUBLIC);
        entityManager.persist(project);

        assertEquals(0, profileService.getProfileProjects(mockProfile.getId()).size());
        assertEquals(false, profileService.isWatchingProject(project.getIdentifier()));

        profileService.watchProject(project.getIdentifier());
        entityManager.flush();

        assertEquals(1, profileService.getProfileProjects(mockProfile.getId()).size());
        assertEquals(true, profileService.isWatchingProject(project.getIdentifier()));
    }

    @Test
    public void createSignUpToken() throws ValidationException {
        String fname = "first";
        String lname = "last";
        String email = "email@exmaple.com";
        SignUpToken signUpToken = profileService.createSignUpToken(fname, lname, email);

        assertNotNull(signUpToken.getId());
        assertEquals(signUpToken.getFirstname(), fname);
        assertEquals(signUpToken.getLastname(), lname);
        assertEquals(signUpToken.getEmail(), email);
        assertEquals(signUpToken.getDateUsed(), null);
        assertNotNull(signUpToken.getToken());
    }

    @Test(expected = EntityNotFoundException.class)
    public void markSignUpTokenUsed() throws EntityNotFoundException, ValidationException {
        String fname = "first";
        String lname = "last";
        String email = "email@exmaple.com";
        SignUpToken internalToken = profileService.createSignUpToken(fname, lname, email);

        SignUpToken tokenBefore = profileService.getSignUpToken(internalToken.getToken());
        assertNull(tokenBefore.getDateUsed());

        profileService.markSignUpTokenUsed(internalToken.getToken());

        // will throw EntityNotFoundException
        profileService.getSignUpToken(internalToken.getToken());
    }

    @Test
    // FIXME
    @Ignore("It seems that sending out an invitation more than once (re-sending) is actually a desired behaviour")
    public void sendSignUpInvitation() throws EntityNotFoundException, ValidationException {
        List<Job> scheduledJobs = jobService.getScheduledJobs();
        assertEquals(0, scheduledJobs.size());

        String fname = "first";
        String lname = "last";
        String email = "email@exmaple.com";
        SignUpToken internalToken = profileService.createSignUpToken(fname, lname, email);

        // try to send it once
        profileService.sendSignUpInvitation(internalToken.getEmail());

        scheduledJobs = jobService.getScheduledJobs();
        assertEquals(1, scheduledJobs.size());
        Job job = scheduledJobs.get(0);
        assertTrue(job instanceof EmailJob);
        EmailJob emailJob = (EmailJob) job;
        assertEquals(internalToken.getEmail(), emailJob.getEmail().getTo());

        // try to send it again
        try {
            profileService.sendSignUpInvitation(internalToken.getEmail());
        } catch (EntityNotFoundException e) {
            // expected
        }
        // no more jobs were added
        assertEquals(1, scheduledJobs.size());
    }

    @Test(expected = EntityNotFoundException.class)
    public void sendSignUpInvitation_ProfileAlreadyExistsWithEmail()
            throws EntityNotFoundException, ValidationException {
        List<Job> scheduledJobs = jobService.getScheduledJobs();
        assertEquals(0, scheduledJobs.size());

        Profile profile = createMockProfile(entityManager);
        SignUpToken internalToken = profileService.createSignUpToken(profile.getFirstName(), profile.getLastName(),
                profile.getEmail());

        // try to send it - should throw EntityNotFoundException
        try {
            profileService.sendSignUpInvitation(internalToken.getEmail());
        } catch (EntityNotFoundException e) {
            // expected
            assertEquals(0, scheduledJobs.size());
            throw e;
        }
    }

    @Test
    public void testCreateInvitations() throws ValidationException, MalformedURLException {
        setupProfile(true);
        jobService.getScheduledJobs().clear();
        SignUpTokens invitationTokens = new SignUpTokens();
        for (int x = 0; x < 10; ++x) {
            com.tasktop.c2c.server.profile.domain.project.SignUpToken token = new com.tasktop.c2c.server.profile.domain.project.SignUpToken();
            token.setFirstname("First" + x);
            token.setLastname("Last" + x);
            token.setEmail(token.getFirstname().toLowerCase() + x + "." + token.getLastname().toLowerCase()
                    + "@example.com");
            invitationTokens.add(token);
        }
        SignUpTokens invitations = profileService.createInvitations(invitationTokens, true);

        // Expect there to be twice as many jobs as invitations in the queue, since two emails are now sent out for
        // every system invite (one to the invitee, one to info@code.cloudfoundry.com).
        assertEquals(invitationTokens.getTokens().size() * 2, jobService.getScheduledJobs().size());

        assertEquals(invitationTokens.getTokens().size(), invitations.getTokens().size());
        for (int x = 0; x < invitationTokens.getTokens().size(); ++x) {
            com.tasktop.c2c.server.profile.domain.project.SignUpToken original = invitationTokens.getTokens()
                    .get(x);
            com.tasktop.c2c.server.profile.domain.project.SignUpToken created = invitations.getTokens().get(x);
            assertEquals(original.getFirstname(), created.getFirstname());
            assertEquals(original.getLastname(), created.getLastname());
            assertEquals(original.getEmail(), created.getEmail());
            assertNotNull(created.getToken());
            assertNotNull(created.getUrl());
            assertTrue(created.getUrl().contains("/#signup"));
            assertTrue(created.getUrl().contains(created.getToken()));
            new URL(created.getUrl());
        }
    }

    @Test
    public void testReplicateProfile() throws EntityNotFoundException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);
        project.addProfile(profile);

        ServiceHost serviceHost = new ServiceHost();
        serviceHost.setAvailable(true);
        entityManager.persist(serviceHost);

        ProjectServiceProfile psp = new ProjectServiceProfile();
        psp.setProject(project);
        project.setProjectServiceProfile(psp);

        entityManager.persist(psp);

        ProjectService projectService = new ProjectService();
        projectService.setType(ServiceType.TASKS);
        projectService.setServiceHost(serviceHost);
        projectService.setUriPattern("/tasks/(.*)");
        serviceHost.add(projectService);

        psp.add(projectService);

        entityManager.persist(projectService);

        entityManager.flush();

        JUnit4Mockery mockery = new JUnit4Mockery();
        final TaskService taskService = mockery.mock(TaskService.class);
        final WikiService wikiService = mockery.mock(WikiService.class);

        MockTaskServiceProvider.setTaskService(taskService);
        MockWikiServiceProvider.setWikiService(wikiService);

        mockery.checking(new Expectations() {
            {
                allowing(taskService).replicateProfile(with(any(TaskUserProfile.class)),
                        with(any(ReplicationScope.class)));
                allowing(wikiService).replicateProfile(with(any(Person.class)), with(any(ReplicationScope.class)));
            }
        });

        profileService.replicateProjectProfile(profile.getId(), project.getId(), ReplicationScope.CREATE_OR_UPDATE);

        mockery.assertIsSatisfied();
    }

    @Test
    public void testReplicateProfileGetsScheduledOnTeamModification()
            throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);
        entityManager.flush();

        profileService.createProjectProfile(project.getIdentifier(), profile.getUsername());
        assertReplicateJobScheduled(project);
    }

    protected void assertReplicateJobScheduled(Project project) {
        boolean found = false;
        for (Job job : jobService.getScheduledJobs()) {
            if (job instanceof ReplicateProjectProfileJob) {
                ReplicateProjectProfileJob replicateProjectTeamJob = (ReplicateProjectProfileJob) job;
                if (replicateProjectTeamJob.getProjectId().equals(project.getId())) {
                    found = true;
                }
            }
        }
        assertTrue(found);
    }

    @Test
    public void testReplicateTeamGetsScheduledOnNameChange() throws EntityNotFoundException, ValidationException {
        Profile profile = createMockProfile(entityManager);
        Project project = createMockProject(entityManager);
        project.addProfile(profile);

        entityManager.flush();

        Organization org = setupOrganization();
        logonWithOrganization(profile, org.getIdentifier());
        entityManager.detach(profile);

        profile.setFirstName(profile.getFirstName() + "changed");
        profileService.updateProfile(profile);

        assertReplicateJobScheduled(project);
    }

    @Test
    public void testFindAccessibleProjectsForProfile() throws Exception {
        Profile profile = createMockProfile(entityManager);

        // add an Organization and log on using it
        Organization org = setupOrganization();
        logonWithOrganization(profile, org.getIdentifier());

        // create a private Project and add the Profile to it; this should be excluded in results
        Project privateProject = createMockProject(entityManager);
        privateProject.setAccessibility(ProjectAccessibility.PRIVATE);
        privateProject.addProfile(profile);

        // create a public Project, which should be included in results
        Project publicProject = createMockProject(entityManager);
        publicProject.setAccessibility(ProjectAccessibility.PUBLIC);
        entityManager.flush();

        List<ProjectProfile> pps = internalProfileService.findAccessibleProjectsForProfile(profile);
        assertEquals(1, pps.size());
        assertEquals(publicProject.getId().longValue(), pps.get(0).getProject().getId().longValue());

        // create an org-private Project for the Organization we created earlier; this should also be included in
        // results
        Project orgPrivateProject = createMockProject(entityManager);
        orgPrivateProject.setAccessibility(ProjectAccessibility.ORGANIZATION_PRIVATE);
        orgPrivateProject.setOrganization(org);
        orgPrivateProject.addProfile(profile);
        entityManager.flush();

        pps = internalProfileService.findAccessibleProjectsForProfile(profile);
        assertEquals(2, pps.size());
    }

    @Test
    public void testCreateSshPublicKey() throws ValidationException {
        Profile profile = createMockProfile(entityManager);
        entityManager.flush();
        logon(profile);

        SshPublicKey publicKey = MockSshPublicKeyFactory.create(null, null);

        SshPublicKey sshPublicKey = profileService.createSshPublicKey(publicKey);

        assertNotNull(sshPublicKey);
        assertEquals(profile, sshPublicKey.getProfile());
        assertTrue(profile.getSshPublicKeys().contains(sshPublicKey));
        assertNotNull(sshPublicKey.getId());
        assertEquals(publicKey.getAlgorithm(), sshPublicKey.getAlgorithm());
        assertArrayEquals(publicKey.getKeyData(), sshPublicKey.getKeyData());
    }

    @Test
    public void createSshPublicKeySpec_BlankKeyText() { // task 2359
        Profile profile = createMockProfile(entityManager);
        entityManager.flush();
        logon(profile);

        SshPublicKeySpec publicKeySpec = new SshPublicKeySpec("abc", null);
        try {
            profileService.createSshPublicKey(publicKeySpec);
        } catch (ValidationException e) {
            assertHaveValidationError(e, "Please provide an RSA key.");
        }
        publicKeySpec.setKeyData("XXXX");
        try {
            profileService.createSshPublicKey(publicKeySpec);
        } catch (ValidationException e) {
            assertHaveValidationError(e, "Unrecognized key format. Please provide an RSA key.");
        }
    }

    @Test
    public void testListSshPublicKeys() throws ValidationException {
        Profile profile = createMockProfile(entityManager);
        SshPublicKey publicKey = MockSshPublicKeyFactory.create(entityManager, profile);
        entityManager.flush();

        logon(profile);

        List<SshPublicKey> sshPublicKeys = profileService.listSshPublicKeys();

        assertEquals(1, sshPublicKeys.size());
        assertTrue(sshPublicKeys.contains(publicKey));
        assertNotSame(profile.getSshPublicKeys(), sshPublicKeys);
    }

    protected Profile setupProfile() throws ValidationException {
        return setupProfile(false);
    }

    private int nextProfileNum = 0;

    protected Profile setupProfile(Boolean isAdmin) throws ValidationException {
        Profile internalProfile = createMockProfile(null);
        internalProfile.setEmail("email@profile" + nextProfileNum++ + ".clm");
        internalProfile.setFirstName("First");
        internalProfile.setLastName("Last" + nextProfileNum);
        internalProfile.setAdmin(isAdmin);
        profileService.createProfile(internalProfile);

        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
                internalProfile.getUsername(), internalProfile.getPassword()));

        return internalProfile;
    }

    private Organization setupOrganization() throws ValidationException, EntityNotFoundException {
        Organization org = MockOrganizationFactory.create(null);
        org = profileService.createOrganization(org);
        assertEquals(0, org.getProjects().size());
        assertNotNull(org.getIdentifier());
        org = profileService.getOrganizationByIdentfier(org.getIdentifier());
        assertNotNull(org);
        return org;
    }

    @Test
    public void testfindProjectsByRelationship() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);

        Long id = profileService.createProject(profile.getId(), project).getId();

        assertNotNull(id);
        Project project2 = entityManager.find(Project.class, id);
        assertNotNull(project2);
        assertEquals(id, project2.getId());
        assertEquals(project.getName(), project2.getName());

        assertEquals(1, project.getProjectProfiles().size());
        assertEquals(profile, project.getProjectProfiles().get(0).getProfile());
        assertEquals(true, project.getProjectProfiles().get(0).getOwner());

        QueryResult<Project> projects = profileService
                .findProjects(new ProjectsQuery(ProjectRelationship.ALL, null));
        Assert.assertEquals((Integer) 1, projects.getTotalResultSize());

        // TODO more testing
    }

    @Test
    public void testCreateOrganizationWithProjects() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile();

        Organization org = setupOrganization();

        ProjectsQuery query = new ProjectsQuery(ProjectRelationship.ALL, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        QueryResult<Project> queryResult = profileService.findProjects(query);

        assertEquals(0, (int) queryResult.getTotalResultSize());

        Project project = createMockProject(null);
        project.setOrganization(org);
        project = profileService.createProject(profile.getId(), project);

        org = profileService.getOrganizationByIdentfier(org.getIdentifier());
        assertEquals(1, org.getProjects().size());

        query = new ProjectsQuery(ProjectRelationship.ALL, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        queryResult = profileService.findProjects(query);

        assertEquals(1, (int) queryResult.getTotalResultSize());

        query = new ProjectsQuery(ProjectRelationship.PUBLIC, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        queryResult = profileService.findProjects(query);

        assertEquals(0, (int) queryResult.getTotalResultSize());

        query = new ProjectsQuery(ProjectRelationship.MEMBER, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        queryResult = profileService.findProjects(query);

        assertEquals(1, (int) queryResult.getTotalResultSize());

        query = new ProjectsQuery(ProjectRelationship.ORGANIZATION_PRIVATE, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        queryResult = profileService.findProjects(query);

        assertEquals(0, (int) queryResult.getTotalResultSize());

        query = new ProjectsQuery(project.getIdentifier(), null);
        query.setOrganizationIdentifier(org.getIdentifier());
        queryResult = profileService.findProjects(query);

        assertEquals(1, (int) queryResult.getTotalResultSize());
    }

    @Test
    public void testDeleteOrganization() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile();
        Organization org = setupOrganization();

        Project project = createMockProject(null);
        project.setOrganization(org);
        project = profileService.createProject(profile.getId(), project);

        int preDeleteJobCount = jobService.getScheduledJobs().size();
        profileService.deleteOrganization(org.getIdentifier());
        assertTrue("We should have more jobs after deleting the org",
                jobService.getScheduledJobs().size() > preDeleteJobCount);
    }

    @Test
    public void testDoDeleteOrganization() throws ValidationException, EntityNotFoundException {
        Organization org = setupOrganization();

        // Add a related entity
        QuotaSetting qs = new QuotaSetting();
        qs.setName("name");
        qs.setValue("value");
        qs.setOrganization(org);
        entityManager.persist(qs);
        assertEquals(org.getId(), qs.getOrganization().getId());

        internalProfileService.doDeleteOrganization(org.getIdentifier());

        // Organization should be gone
        try {
            profileService.getOrganizationByIdentfier(org.getIdentifier());
            Assert.fail();
        } catch (EntityNotFoundException e) {
            // expected
        }

        // QuotaSetting should be gone
        QuotaSetting foundQs = entityManager.find(QuotaSetting.class, qs.getId());
        assertNull(foundQs);
    }

    @Test
    public void testFindOrganizationPrivateProjects() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile();

        Profile profile2 = setupProfile();

        Organization org = setupOrganization();
        Organization org2 = setupOrganization();

        Project project = createMockProject(null);
        project.setOrganization(org2);
        project = profileService.createProject(profile.getId(), project);

        Project project2 = createMockProject(null);
        project2.setOrganization(org);
        project2 = profileService.createProject(profile2.getId(), project2);

        createOrgPrivateProject(org, profile);
        createOrgPrivateProject(org2, profile);
        createOrgPrivateProject(org, profile2);
        createOrgPrivateProject(org2, profile2);

        org = profileService.getOrganizationByIdentfier(org.getIdentifier());
        assertEquals(3, org.getProjects().size());

        ProjectsQuery query = new ProjectsQuery(ProjectRelationship.ORGANIZATION_PRIVATE, null);
        query.setOrganizationIdentifier(org.getIdentifier());
        QueryResult<Project> queryResult = profileService.findProjects(query);

        assertEquals(2, (int) queryResult.getTotalResultSize());

    }

    private Project createOrgPrivateProject(Organization org, Profile profile)
            throws EntityNotFoundException, ValidationException {
        Project orgPrivateProject = createMockProject(null);
        orgPrivateProject.setOrganization(org);
        orgPrivateProject.setAccessibility(ProjectAccessibility.ORGANIZATION_PRIVATE);
        orgPrivateProject = profileService.createProject(profile.getId(), orgPrivateProject);

        OrganizationProfile op = new OrganizationProfile();
        op.setOrganization(org);
        op.setProfile(profile);
        org.getOrganizationProfiles().add(op);
        entityManager.persist(op);

        return orgPrivateProject;
    }

    @Test
    public void testProjectIdentifierUniqueness() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile();

        Organization org = MockOrganizationFactory.create(null);
        org = profileService.createOrganization(org);
        assertEquals(0, org.getProjects().size());
        assertNotNull(org.getIdentifier());
        org = profileService.getOrganizationByIdentfier(org.getIdentifier());
        assertNotNull(org);

        String projectName = "projectNameABC";

        Project project = createMockProject(null);
        project.setName(projectName);
        project = profileService.createProject(profile.getId(), project);

        project = createMockProject(null);
        project.setName(projectName);
        try {
            project = profileService.createProject(profile.getId(), project);
            Assert.fail();
        } catch (ValidationException e) {
            // expected
        }

        project = createMockProject(null);
        project.setOrganization(org);
        project.setName(projectName);
        project = profileService.createProject(profile.getId(), project);

        project = createMockProject(null);
        project.setOrganization(org);
        project.setName(projectName);
        try {
            project = profileService.createProject(profile.getId(), project);
            Assert.fail();
        } catch (ValidationException e) {
            // expected
        }

    }

    @Test
    public void testDoDeleteProject() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);

        Long id = profileService.createProject(profile.getId(), project).getId();
        Project created = entityManager.find(Project.class, id);
        profileService.getProjectByIdentifier(created.getIdentifier());

        // Add some referencing objects
        DeploymentConfiguration dep = new DeploymentConfiguration();
        dep.setProject(created);
        entityManager.persist(dep);

        InvitationToken token = MockProjectInvitationTokenFactory.create(null);
        token.setProject(created);
        token.setIssuingProfile(profile);
        entityManager.persist(token);

        QuotaSetting qs = new QuotaSetting();
        qs.setProject(created);
        qs.setName("name");
        qs.setValue("value");
        entityManager.persist(qs);

        internalProfileService.doDeleteProject(created.getIdentifier());
        entityManager.flush();
        try {
            profileService.getProjectByIdentifier(created.getIdentifier());
            Assert.fail();
        } catch (EntityNotFoundException e) {
            // expected
        }
    }

    @Test
    public void testGetOwnedOrganizations() {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);

        List<Organization> organizations = profileService.getOwnedOrganizations();
        assertEquals(organizations.size(), 0);

        Organization mockOrg = MockOrganizationFactory.create(entityManager);

        OrganizationProfile orgProf = new OrganizationProfile();
        orgProf.setProfile(mockProfile);
        orgProf.setOwner(true);
        orgProf.setUser(true);
        orgProf.setOrganization(mockOrg);
        entityManager.persist(orgProf);

        entityManager.flush();

        List<Organization> organizations2 = profileService.getOwnedOrganizations();
        assertEquals(organizations2.size(), 1);
    }

    @Test
    public void testUpdateOrganization() throws EntityNotFoundException, ValidationException {
        Organization mockOrg = MockOrganizationFactory.create(entityManager);

        profileService.createOrganization(mockOrg);

        com.tasktop.c2c.server.profile.domain.internal.ProjectPreferences preferences = new com.tasktop.c2c.server.profile.domain.internal.ProjectPreferences();
        preferences.setWikiLanguage(WikiMarkupLanguage.CONFLUENCE);

        String originalIdentifier = mockOrg.getIdentifier();

        mockOrg.setName(mockOrg.getName() + "2");
        mockOrg.setDescription(mockOrg.getDescription() + "2");
        mockOrg.setIdentifier(mockOrg.getIdentifier() + "2");
        mockOrg.setProjectPreferences(preferences);

        Organization newOrg = profileService.updateOrganization(mockOrg);

        assertEquals(newOrg.getName(), mockOrg.getName());
        assertEquals(newOrg.getDescription(), mockOrg.getDescription());
        assertEquals(newOrg.getProjectPreferences(), mockOrg.getProjectPreferences());
        assertEquals(originalIdentifier, mockOrg.getIdentifier());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testUpdatePartiallyDeletedProject() throws EntityNotFoundException, ValidationException {
        Project project = changeDeletedProject();
        profileService.updateProject(project);
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetPartiallyDeletedProjectByIdentifier() throws EntityNotFoundException, ValidationException {
        Project project = changeDeletedProject();
        profileService.getProjectByIdentifier(project.getIdentifier());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetPartiallyDeletedProject() throws EntityNotFoundException, ValidationException {
        Project project = changeDeletedProject();
        profileService.getProject(project.getId());
    }

    private Project changeDeletedProject() throws EntityNotFoundException, ValidationException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);

        project = profileService.createProject(profile.getId(), project);

        project.setIsDeleted(true);
        entityManager.persist(project);

        project.setName(project.getName() + "2");
        return project;
    }

    @Test()
    public void testGetDeletedProfileProjects() throws EntityNotFoundException {

        Profile profile = createMockProfile(entityManager);

        Project project = createMockProject(entityManager);
        entityManager.persist(project.addProfile(profile));

        profileService.getProjectByIdentifier(project.getIdentifier());
        int numProjects = profileService.getProfileProjects(profile.getId()).size();

        Assert.assertEquals(1, numProjects);

        project.setIsDeleted(true);

        try {
            profileService.getProjectByIdentifier(project.getIdentifier());
            Assert.fail();
        } catch (EntityNotFoundException e) {
            // expected
        }
        numProjects = profileService.getProfileProjects(profile.getId()).size();
        Assert.assertEquals(0, numProjects); // Should still work task 4429
    }

    @Test
    public void testFindPublicDeletedProjects() throws EntityNotFoundException {
        setupDeletedAndNonDeletedProject(true, null);

        Region region = new Region(0, 2);
        QueryResult<Project> result = profileService
                .findProjects(new ProjectsQuery("Test123", new QueryRequest(region, null)));
        assertEquals(1, result.getTotalResultSize().intValue());
    }

    @Test
    public void testFindPrivateDeletedProjects() throws EntityNotFoundException {
        Profile mockProfile = createMockProfile(entityManager);
        logon(mockProfile);
        setupDeletedAndNonDeletedProject(false, mockProfile);

        Region region = new Region(0, 2);
        QueryResult<Project> result = profileService
                .findProjects(new ProjectsQuery("Test123", new QueryRequest(region, null)));
        assertEquals(1, result.getTotalResultSize().intValue());
    }

    private void setupDeletedAndNonDeletedProject(boolean isPublic, Profile profile) {
        List<Project> projects = MockProjectFactory.create(entityManager, 2);
        int x = 1;
        for (Project project : projects) {
            if (x == 1) {
                project.setIsDeleted(true);
            }
            project.setName("Test123" + x);
            project.setIdentifier("Test123" + x);
            project.setAccessibility(isPublic ? ProjectAccessibility.PUBLIC : ProjectAccessibility.PRIVATE);
            if (profile != null) {
                ProjectProfile mock = new ProjectProfile();
                mock.setProfile(profile);
                mock.setProject(project);
                entityManager.persist(mock);
            }
            x++;
        }

        entityManager.flush();
        entityManager.clear();
    }

    @Test
    public void testFindDeletedProjectsByRelationship() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);
        Long id = profileService.createProject(profile.getId(), project).getId();

        Project project2 = entityManager.find(Project.class, id);
        project2.setIsDeleted(true);

        QueryResult<Project> projects = profileService
                .findProjects(new ProjectsQuery(ProjectRelationship.ALL, null));
        Assert.assertEquals((Integer) 0, projects.getTotalResultSize());
    }

    @Test(expected = EntityNotFoundException.class)
    public void testGetDeletedProjectForInvitationToken() throws ValidationException, EntityNotFoundException {
        Profile profile = setupProfile(false);
        Project project = createMockProject(null);
        Long id = profileService.createProject(profile.getId(), project).getId();
        Project created = entityManager.find(Project.class, id);
        created.setIsDeleted(true);

        InvitationToken token = MockProjectInvitationTokenFactory.create(null);
        token.setProject(created);
        token.setIssuingProfile(profile);
        entityManager.persist(token);

        profileService.getProjectForInvitationToken(token.getToken());

    }

}