/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.workspace.server.jpa;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.workspace.server.model.impl.ProjectConfigImpl;
import org.eclipse.che.commons.test.db.H2JpaCleaner;
import org.eclipse.che.commons.test.tck.JpaCleaner;
import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.singletonList;
import static org.eclipse.che.api.workspace.server.spi.tck.WorkspaceDaoTest.createWorkspace;
import static org.testng.Assert.assertEquals;
/**
* Tests JPA specific use-cases.
*
* @author Yevhenii Voevodin
*/
public class JpaWorkspaceDaoTest {
private EntityManager manager;
private JpaWorkspaceDao workspaceDao;
private JpaCleaner cleaner;
@BeforeMethod
private void setUpManager() {
final Injector injector = Guice.createInjector(new WorkspaceTckModule());
manager = injector.getInstance(EntityManager.class);
workspaceDao = injector.getInstance(JpaWorkspaceDao.class);
cleaner = injector.getInstance(H2JpaCleaner.class);
}
@AfterMethod
private void cleanup() {
manager.getTransaction().begin();
final List<Object> entities = new ArrayList<>();
entities.addAll(manager.createQuery("SELECT w FROM Workspace w").getResultList());
entities.addAll(manager.createQuery("SELECT a FROM Account a").getResultList());
for (Object entity : entities) {
manager.remove(entity);
}
manager.getTransaction().commit();
cleaner.clean();
}
@Test
public void shouldCascadeRemoveObjectsWhenTheyRemovedFromEntity() {
final AccountImpl account = new AccountImpl("accountId", "namespace", "test");
final WorkspaceImpl workspace = createWorkspace("id", account, "name");
// Persist the account
manager.getTransaction().begin();
manager.persist(account);
manager.getTransaction().commit();
manager.clear();
// Persist the workspace
manager.getTransaction().begin();
manager.persist(workspace);
manager.getTransaction().commit();
manager.clear();
// Cleanup one to many dependencies
manager.getTransaction().begin();
final WorkspaceConfigImpl config = workspace.getConfig();
config.getProjects().clear();
config.getCommands().clear();
config.getEnvironments().clear();
manager.merge(workspace);
manager.getTransaction().commit();
manager.clear();
// If all the One To Many dependencies are removed then all the embedded objects
// which depend on those object are also removed, which guaranteed by foreign key constraints
assertEquals(asLong("SELECT COUNT(p) FROM ProjectConfig p"), 0L, "Project configs");
assertEquals(asLong("SELECT COUNT(c) FROM Command c"), 0L, "Commands");
assertEquals(asLong("SELECT COUNT(e) FROM Environment e"), 0L, "Environments");
}
@Test(expectedExceptions = DuplicateKeyException.class)
public void shouldSynchronizeWorkspaceNameWithConfigNameWhenConfigIsUpdated() throws Exception {
final AccountImpl account = new AccountImpl("accountId", "namespace", "test");
final WorkspaceImpl workspace1 = createWorkspace("id", account, "name1");
final WorkspaceImpl workspace2 = createWorkspace("id2", account, "name2");
// persist prepared data
manager.getTransaction().begin();
manager.persist(account);
manager.persist(workspace1);
manager.persist(workspace2);
manager.getTransaction().commit();
// make conflict update
workspace2.getConfig().setName(workspace1.getConfig().getName());
manager.getTransaction().begin();
manager.merge(workspace2);
manager.getTransaction().commit();
}
@Test
public void shouldSyncDbAttributesWhileUpdatingWorkspace() throws Exception {
final AccountImpl account = new AccountImpl("accountId", "namespace", "test");
final WorkspaceImpl workspace = createWorkspace("id", account, "name");
if (workspace.getConfig() != null) {
workspace.getConfig().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
// persist the workspace
manager.getTransaction().begin();
manager.persist(account);
manager.persist(workspace);
manager.getTransaction().commit();
manager.clear();
// put a new attribute
workspace.getConfig()
.getProjects()
.get(0)
.getAttributes()
.put("new-attr", singletonList("value"));
WorkspaceImpl result = workspaceDao.update(workspace);
manager.clear();
// check it's okay
assertEquals(result.getConfig()
.getProjects()
.get(0)
.getAttributes()
.size(), 3);
}
private long asLong(String query) {
return manager.createQuery(query, Long.class).getSingleResult();
}
}