Package org.sonar.batch.index

Source Code of org.sonar.batch.index.DefaultResourcePersisterTest

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package org.sonar.batch.index;

import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.MetricFinder;
import org.sonar.api.resources.Directory;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.security.ResourcePermissions;
import org.sonar.batch.ProjectTree;
import org.sonar.batch.issue.DeprecatedViolations;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.ScanGraph;
import org.sonar.core.component.db.ComponentMapper;
import org.sonar.core.persistence.MyBatis;
import org.sonar.jpa.test.AbstractDbUnitTestCase;

import javax.persistence.Query;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;

import static org.fest.assertions.Assertions.assertThat;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class DefaultResourcePersisterTest extends AbstractDbUnitTestCase {

  @Rule
  public ExpectedException thrown = ExpectedException.none();

  @Rule
  public TemporaryFolder temp = new TemporaryFolder();

  Project singleProject, singleCopyProject, multiModuleProject, moduleA, moduleB, moduleB1, existingProject;
  SnapshotCache snapshotCache = mock(SnapshotCache.class);
  ResourceCache resourceCache = mock(ResourceCache.class);

  @Before
  public void before() throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
    singleProject = newProject("foo", "java");
    singleProject.setName("Foo").setDescription("some description").setAnalysisDate(format.parse("25/12/2010"));

    existingProject = newProject("my:key", "java");
    existingProject.setName("Other project").setDescription("some description").setAnalysisDate(format.parse("25/12/2010"));

    singleCopyProject = newCopyProject("foo", "java", 10);
    singleCopyProject.setName("Foo").setDescription("some description").setAnalysisDate(format.parse("25/12/2010"));

    multiModuleProject = newProject("root", "java");
    multiModuleProject.setName("Root").setAnalysisDate(format.parse("25/12/2010"));

    moduleA = newProject("a", "java");
    moduleA.setName("A").setAnalysisDate(format.parse("25/12/2010"));
    moduleA.setParent(multiModuleProject);
    moduleA.setPath("/moduleA");

    moduleB = newProject("b", "java");
    moduleB.setName("B").setAnalysisDate(format.parse("25/12/2010"));
    moduleB.setParent(multiModuleProject);
    moduleB.setPath("/moduleB");

    moduleB1 = newProject("b1", "java");
    moduleB1.setName("B1").setAnalysisDate(format.parse("25/12/2010"));
    moduleB1.setParent(moduleB);
    moduleB1.setPath("/moduleB1");
  }

  @Test
  public void shouldSaveNewProject() {
    setupData("shared");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);

    checkTables("shouldSaveNewProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"},
      "projects", "snapshots");

    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1001);
    SqlSession session = getMyBatis().openSession(false);
    try {
      ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo");
      assertThat(newProject.uuid()).isNotNull();
      assertThat(newProject.projectUuid()).isEqualTo(newProject.uuid());
      assertThat(newProject.moduleUuid()).isNull();
      assertThat(newProject.moduleUuidPath()).isNull();
      // SONAR-3636 : created_at must be fed when inserting a new entry in the 'projects' table
      assertThat(newProject.getCreatedAt()).isNotNull();
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  @Test
  public void shouldSaveCopyProject() {
    setupData("shared");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(singleCopyProject, null);

    checkTables("shouldSaveCopyProject", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"},
      "projects", "snapshots");
    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1001);
    SqlSession session = getMyBatis().openSession(false);
    try {
      ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo");
      assertThat(newProject.uuid()).isNotNull();
      assertThat(newProject.projectUuid()).isEqualTo(newProject.uuid());
      assertThat(newProject.moduleUuid()).isNull();
      assertThat(newProject.moduleUuidPath()).isNull();
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  @Test
  public void shouldSaveNewMultiModulesProject() {
    setupData("shared");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(multiModuleProject, null);
    persister.saveProject(moduleA, multiModuleProject);
    persister.saveProject(moduleB, multiModuleProject);
    persister.saveProject(moduleB1, moduleB);
    Resource file = File.create("src/main/java/org/Foo.java").setEffectiveKey("b1:src/main/java/org/Foo.java");
    file.getParent().setEffectiveKey("b1:src/main/java/org");
    persister.saveResource(moduleB1, file.getParent());
    persister.saveResource(moduleB1, file, file.getParent());

    checkTables("shouldSaveNewMultiModulesProject",
      new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots");

    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1001);
    enableSnapshot(1002);
    enableSnapshot(1003);
    enableSnapshot(1004);
    enableSnapshot(1005);
    enableSnapshot(1006);
    SqlSession session = getMyBatis().openSession(false);
    try {
      ComponentDto root = session.getMapper(ComponentMapper.class).selectByKey("root");
      assertThat(root.uuid()).isNotNull();
      assertThat(root.projectUuid()).isEqualTo(root.uuid());
      assertThat(root.moduleUuid()).isNull();
      assertThat(root.moduleUuidPath()).isNull();
      ComponentDto a = session.getMapper(ComponentMapper.class).selectByKey("a");
      assertThat(a.uuid()).isNotNull();
      assertThat(a.projectUuid()).isEqualTo(root.uuid());
      assertThat(a.moduleUuid()).isEqualTo(root.uuid());
      assertThat(a.moduleUuidPath()).isEqualTo(root.uuid());
      ComponentDto b = session.getMapper(ComponentMapper.class).selectByKey("b");
      assertThat(b.uuid()).isNotNull();
      assertThat(b.projectUuid()).isEqualTo(root.uuid());
      assertThat(b.moduleUuid()).isEqualTo(root.uuid());
      assertThat(b.moduleUuidPath()).isEqualTo(root.uuid());
      ComponentDto b1 = session.getMapper(ComponentMapper.class).selectByKey("b1");
      assertThat(b1.uuid()).isNotNull();
      assertThat(b1.projectUuid()).isEqualTo(root.uuid());
      assertThat(b1.moduleUuid()).isEqualTo(b.uuid());
      assertThat(b1.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid());
      ComponentDto dir = session.getMapper(ComponentMapper.class).selectByKey("b1:src/main/java/org");
      assertThat(dir.uuid()).isNotNull();
      assertThat(dir.projectUuid()).isEqualTo(root.uuid());
      assertThat(dir.moduleUuid()).isEqualTo(b1.uuid());
      assertThat(dir.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid() + "." + b1.uuid());
      ComponentDto fileComp = session.getMapper(ComponentMapper.class).selectByKey("b1:src/main/java/org/Foo.java");
      assertThat(fileComp.uuid()).isNotNull();
      assertThat(fileComp.projectUuid()).isEqualTo(root.uuid());
      assertThat(fileComp.moduleUuid()).isEqualTo(b1.uuid());
      assertThat(fileComp.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid() + "." + b1.uuid());
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  // FIXME this is a kind of medium test
  @Test
  public void shouldSaveNewMultiModulesProjectUsingIndex() throws IOException {
    setupData("shared");

    java.io.File baseDir = temp.newFolder();

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);

    ProjectTree projectTree = mock(ProjectTree.class);
    when(projectTree.getRootProject()).thenReturn(multiModuleProject);
    when(projectTree.getProjectDefinition(multiModuleProject)).thenReturn(ProjectDefinition.create().setBaseDir(baseDir));
    when(projectTree.getProjectDefinition(moduleA)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleA")));
    when(projectTree.getProjectDefinition(moduleB)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB")));
    when(projectTree.getProjectDefinition(moduleB1)).thenReturn(ProjectDefinition.create().setBaseDir(new java.io.File(baseDir, "moduleB/moduleB1")));

    PersistenceManager persistenceManager = new DefaultPersistenceManager(persister, null, null, null, null);
    DefaultIndex index = new DefaultIndex(persistenceManager, projectTree, mock(MetricFinder.class), mock(ScanGraph.class), mock(DeprecatedViolations.class),
      mock(ResourceKeyMigration.class),
      mock(MeasureCache.class));

    index.start();

    Resource file = File.create("src/main/java/org/Foo.java");

    index.setCurrentProject(moduleB1, null);
    index.index(file);

    // Emulate another project having library dependency on moduleA
    index.addResource(new Library(moduleA.getKey(), "1.0"));

    checkTables("shouldSaveNewMultiModulesProjectAndLibrary",
      new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"}, "projects", "snapshots");

    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1001);
    enableSnapshot(1002);
    enableSnapshot(1003);
    enableSnapshot(1004);
    enableSnapshot(1005);
    enableSnapshot(1006);
    SqlSession session = getMyBatis().openSession(false);
    try {
      ComponentDto root = session.getMapper(ComponentMapper.class).selectByKey("root");
      System.out.println("Root: " + root.uuid());
      assertThat(root.uuid()).isNotNull();
      assertThat(root.projectUuid()).isEqualTo(root.uuid());
      assertThat(root.moduleUuid()).isNull();
      assertThat(root.moduleUuidPath()).isNull();
      ComponentDto a = session.getMapper(ComponentMapper.class).selectByKey("a");
      System.out.println("A: " + a.uuid());
      assertThat(a.uuid()).isNotNull();
      assertThat(a.projectUuid()).isEqualTo(root.uuid());
      assertThat(a.moduleUuid()).isEqualTo(root.uuid());
      assertThat(a.moduleUuidPath()).isEqualTo(root.uuid());
      ComponentDto b = session.getMapper(ComponentMapper.class).selectByKey("b");
      System.out.println("B: " + b.uuid());
      assertThat(b.uuid()).isNotNull();
      assertThat(b.projectUuid()).isEqualTo(root.uuid());
      assertThat(b.moduleUuid()).isEqualTo(root.uuid());
      assertThat(b.moduleUuidPath()).isEqualTo(root.uuid());
      ComponentDto b1 = session.getMapper(ComponentMapper.class).selectByKey("b1");
      System.out.println("B1: " + b1.uuid());
      assertThat(b1.uuid()).isNotNull();
      assertThat(b1.projectUuid()).isEqualTo(root.uuid());
      assertThat(b1.moduleUuid()).isEqualTo(b.uuid());
      assertThat(b1.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid());
      ComponentDto dir = session.getMapper(ComponentMapper.class).selectByKey("b1:src/main/java/org");
      assertThat(dir.uuid()).isNotNull();
      assertThat(dir.projectUuid()).isEqualTo(root.uuid());
      assertThat(dir.moduleUuid()).isEqualTo(b1.uuid());
      assertThat(dir.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid() + "." + b1.uuid());
      ComponentDto fileComp = session.getMapper(ComponentMapper.class).selectByKey("b1:src/main/java/org/Foo.java");
      assertThat(fileComp.uuid()).isNotNull();
      assertThat(fileComp.projectUuid()).isEqualTo(root.uuid());
      assertThat(fileComp.moduleUuid()).isEqualTo(b1.uuid());
      assertThat(fileComp.moduleUuidPath()).isEqualTo(root.uuid() + "." + b.uuid() + "." + b1.uuid());
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  @Test
  public void shouldSaveNewDirectory() {
    setupData("shared");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);
    persister.saveResource(singleProject,
      Directory.create("src/main/java/org/foo", "org.foo").setEffectiveKey("foo:src/main/java/org/foo"));
    // check that the directory is attached to the project
    checkTables("shouldSaveNewDirectory", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"},
      "projects", "snapshots");

    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1001);
    enableSnapshot(1002);
    SqlSession session = getMyBatis().openSession(false);
    try {
      ComponentDto newProject = session.getMapper(ComponentMapper.class).selectByKey("foo");
      ComponentDto newDir = session.getMapper(ComponentMapper.class).selectByKey("foo:src/main/java/org/foo");
      assertThat(newDir.uuid()).isNotNull();
      assertThat(newDir.projectUuid()).isEqualTo(newProject.uuid());
      assertThat(newDir.moduleUuid()).isEqualTo(newProject.uuid());
      assertThat(newDir.moduleUuidPath()).isEqualTo(newProject.uuid());
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  private void enableSnapshot(int resourceId) {
    String hql = "UPDATE " + Snapshot.class.getSimpleName() + " SET last=true";
    hql += " WHERE project_id=:resourceId";
    Query query = getSession().createQuery(hql);
    query.setParameter("resourceId", resourceId);
    query.executeUpdate();
    getSession().commit();
  }

  @Test
  public void shouldSaveNewLibrary() {
    setupData("shared");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);
    persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"));
    persister.saveResource(singleProject, new Library("junit:junit", "4.8.2").setEffectiveKey("junit:junit"));// do nothing, already saved
    persister.saveResource(singleProject, new Library("junit:junit", "3.2").setEffectiveKey("junit:junit"));

    checkTables("shouldSaveNewLibrary", new String[] {"build_date", "created_at", "authorization_updated_at", "uuid", "project_uuid", "module_uuid", "module_uuid_path"},
      "projects", "snapshots");

    // Need to enable snapshot to make resource visible using ComponentMapper
    enableSnapshot(1002);
    SqlSession session = getMyBatis().openSession(false);
    try {
      // FIXME selectByKey returns duplicates for libraries because of the join on snapshots table
      ComponentDto newLib = session.getMapper(ComponentMapper.class).findByKeys(Arrays.asList("junit:junit")).get(0);
      assertThat(newLib.uuid()).isNotNull();
      assertThat(newLib.projectUuid()).isEqualTo(newLib.uuid());
      assertThat(newLib.moduleUuid()).isNull();
      assertThat(newLib.moduleUuidPath()).isNull();
    } finally {
      MyBatis.closeQuietly(session);
    }
  }

  @Test
  public void shouldClearResourcesExceptProjects() {
    setupData("shared");

    DefaultResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(multiModuleProject, null);
    persister.saveProject(moduleA, multiModuleProject);
    persister.saveResource(moduleA, new Directory("org/foo").setEffectiveKey("a:org/foo"));
    persister.saveResource(moduleA, new File("org/foo/MyClass.java").setEffectiveKey("a:org/foo/MyClass.java"));
    persister.clear();

    assertThat(persister.getSnapshotsByResource().size(), is(2));
    assertThat(persister.getSnapshotsByResource().get(multiModuleProject), notNullValue());
    assertThat(persister.getSnapshotsByResource().get(moduleA), notNullValue());
  }

  @Test
  public void shouldUpdateExistingResource() {
    setupData("shouldUpdateExistingResource");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    singleProject.setName("new name");
    singleProject.setDescription("new description");
    persister.saveProject(singleProject, null);

    checkTables("shouldUpdateExistingResource", new String[] {"build_date", "created_at", "authorization_updated_at"}, "projects", "snapshots");
  }

  // SONAR-1700
  @Test
  public void shouldRemoveRootIndexIfResourceIsProject() {
    setupData("shouldRemoveRootIndexIfResourceIsProject");

    ResourcePersister persister = new DefaultResourcePersister(getSession(), mock(ResourcePermissions.class), snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);

    checkTables("shouldRemoveRootIndexIfResourceIsProject", new String[] {"build_date", "created_at", "authorization_updated_at"}, "projects", "snapshots");
  }

  @Test
  public void shouldGrantDefaultPermissionsIfNewProject() {
    setupData("shared");

    ResourcePermissions permissions = mock(ResourcePermissions.class);
    when(permissions.hasRoles(singleProject)).thenReturn(false);

    ResourcePersister persister = new DefaultResourcePersister(getSession(), permissions, snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);

    verify(permissions).grantDefaultRoles(singleProject);
  }

  @Test
  public void shouldNotGrantDefaultPermissionsIfExistingProject() {
    setupData("shared");

    ResourcePermissions permissions = mock(ResourcePermissions.class);
    when(permissions.hasRoles(singleProject)).thenReturn(true);

    ResourcePersister persister = new DefaultResourcePersister(getSession(), permissions, snapshotCache, resourceCache);
    persister.saveProject(singleProject, null);

    verify(permissions, never()).grantDefaultRoles(singleProject);
  }

  private static Project newProject(String key, String language) {
    Settings settings = new Settings();
    settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, language);
    return new Project(key).setSettings(settings).setAnalysisType(Project.AnalysisType.DYNAMIC);
  }

  private static Project newCopyProject(String key, String language, int copyResourceId) {
    Settings settings = new Settings();
    settings.setProperty(CoreProperties.PROJECT_LANGUAGE_PROPERTY, language);
    return new CopyProject(key, copyResourceId).setSettings(settings).setAnalysisType(Project.AnalysisType.DYNAMIC);
  }

  private static class CopyProject extends Project implements ResourceCopy {

    private int copyResourceId;

    public CopyProject(String key, int copyResourceId) {
      super(key);
      this.copyResourceId = copyResourceId;
    }

    public int getCopyResourceId() {
      return copyResourceId;
    }

  }

}
TOP

Related Classes of org.sonar.batch.index.DefaultResourcePersisterTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.