/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package br.uff.ic.oceano.core.service.vcs; import br.uff.ic.oceano.CppProjectsHelper; import br.uff.ic.oceano.util.test.AbstractNGTest; import br.uff.ic.oceano.core.dao.OceanoUserDao; import br.uff.ic.oceano.core.dao.controle.JPAUtil; import br.uff.ic.oceano.core.dao.impl.OceanoUserDaoImpl; import br.uff.ic.oceano.core.exception.ObjetoNaoEncontradoException; import br.uff.ic.oceano.core.exception.ServiceException; import br.uff.ic.oceano.core.exception.VCSException; import br.uff.ic.oceano.core.factory.ObjectFactory; import br.uff.ic.oceano.core.model.*; import br.uff.ic.oceano.core.service.ProjectUserService; import br.uff.ic.oceano.core.tools.vcs.VCSUtil; import br.uff.ic.oceano.util.file.FileUtils; import br.uff.ic.oceano.util.HashUtil; import br.uff.ic.oceano.util.file.PathUtil; import br.uff.ic.oceano.util.SystemUtil; import br.uff.ic.oceano.util.test.DiffUtil; import java.io.File; import java.io.IOException; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import static org.testng.Assert.*; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * * @author dheraclio */ public class VCSServiceNGTest extends AbstractNGTest { private VCSService vcsService; private SoftwareProject project; private ProjectUser projectUser; private String tempPath; protected static final CppProjectsHelper testConstantsCpp = new CppProjectsHelper(); @BeforeClass @Override public void beforeClass() { super.beforeClass(); try { JPAUtil.startUp(); project = testConstantsCpp.getDBNeoPZProject(); assertNotNull(project); OceanoUserDao oceanoUserDao = ObjectFactory.getObjectWithDataBaseDependencies(OceanoUserDaoImpl.class); assertNotNull(oceanoUserDao); OceanoUser oceanoUser; oceanoUser = oceanoUserDao.getByLogin("dheraclio"); assertNotNull(oceanoUser); ProjectUserService projectUserService = ObjectFactory.getObjectWithDataBaseDependencies(ProjectUserService.class); assertNotNull(projectUserService); projectUser = projectUserService.getByProjectAndOceanoUser(project, oceanoUser); assertNotNull(projectUser); vcsService = ObjectFactory.getObjectWithDataBaseDependencies(VCSService.class); assertNotNull(vcsService); tempPath = SystemUtil.getTempDirectory(); assertNotNull(tempPath); } catch (Exception ex) { fail(ex.getMessage()); } } @Test public void testCheckOut_FilesDiff() { try { println("testCheckOut_FilesDiff"); Calendar date = Calendar.getInstance(); Set<String> leftFiles = getCheckoutFiles(date, "checkoutTest", "checkout1", false); Set<String> rightFiles = getCheckoutFiles(date, "checkoutTest", "checkout2", false); assertTrue(leftFiles.size() == rightFiles.size(), "Different sizes"); assertFalse(DiffUtil.hasDiff(leftFiles, rightFiles)); deleteCheckoutDirectory("checkoutTest", "checkout1"); deleteCheckoutDirectory("checkoutTest", "checkout2"); } catch (VCSException ex) { fail(ex.getMessage()); } catch (IOException ex) { fail(ex.getMessage()); } } @Test public void testCheckOut_Files() { println("testCheckOut_Files"); try { Calendar date = Calendar.getInstance(); Set<String> leftFiles = getCheckoutFiles(date, "checkoutTest", "checkout1", true); Set<String> rightFiles = getCheckoutFiles(date, "checkoutTest", "checkout2", true); assertTrue(leftFiles.size() == rightFiles.size(), "Different sizes"); assertEqualsNoOrder(leftFiles.toArray(), rightFiles.toArray(), "Not equal ignoring order"); assertTrue(leftFiles.containsAll(rightFiles), "Left doesn´t contains Right"); assertTrue(rightFiles.containsAll(leftFiles), "Right doesn´t contains Left"); } catch (VCSException ex) { fail(ex.getMessage()); } } @Test public void testDirectMD5_SameDirectory() { println("testDirectMD5_SameDirectory"); try { Calendar date = Calendar.getInstance(); deleteCheckoutDirectory("checkoutTest", "checkout1"); Collection files = getCheckoutFiles(date, "checkoutTest", "checkout1", false); String expected = HashUtil.getMD5(files); deleteCheckoutDirectory("checkoutTest", "checkout1"); deleteCheckoutDirectory("checkoutTest", "checkout1"); files = getCheckoutFiles(date, "checkoutTest", "checkout1", false); String actual = HashUtil.getMD5(files); deleteCheckoutDirectory("checkoutTest", "checkout1"); assertEquals(actual, expected); } catch (Exception ex) { fail(ex.getMessage()); } } @Test public void testDirectMD5_DifferentDirectory() { println("testDirectMD5_DifferentDirectory"); try { Calendar date = Calendar.getInstance(); deleteCheckoutDirectory("checkoutTest", "checkout1"); Set files1 = getCheckoutFiles(date, "checkoutTest", "checkout1", false); List sorted1 = new LinkedList(files1); Collections.sort(sorted1); String expected = HashUtil.getMD5(sorted1); deleteCheckoutDirectory("checkoutTest", "checkout1"); deleteCheckoutDirectory("checkoutTest", "checkout2"); Set files2 = getCheckoutFiles(date, "checkoutTest", "checkout2", false); List sorted2 = new LinkedList(files2); Collections.sort(sorted2); String actual = HashUtil.getMD5(sorted2); deleteCheckoutDirectory("checkoutTest", "checkout2"); assertEquals(actual, expected); } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test clean checkout. */ @Test public void testCheckOutMD5_SameDirectory() { println("testCheckOutMD5_SameDirectory"); try { Calendar date = Calendar.getInstance(); String firstMD5 = getCheckoutMD5(date, "checkoutTest", "checkout1"); String secondMD5 = getCheckoutMD5(date, "checkoutTest", "checkout1"); assertEquals(firstMD5, secondMD5); } catch (Exception ex) { fail(ex.getMessage()); } } @Test public void testCheckOutMD5_DifferentDirectory() { println("testCheckOutMD5_DifferentDirectory"); try { Calendar date = Calendar.getInstance(); String firstMD5 = getCheckoutMD5(date, "checkoutTest", "checkout1"); String secondMD5 = getCheckoutMD5(date, "checkoutTest", "checkout2"); assertEquals(firstMD5, secondMD5); } catch (Exception ex) { fail(ex.getMessage()); } } @Test public void testCheckoutMD5vsDirectMD5() { println("testCheckoutMD5vsDirectMD5"); try { Calendar date = Calendar.getInstance(); Collection files = getCheckoutFiles(date, "checkoutTest", "checkout1", false); List sorted = new LinkedList(files); Collections.sort(sorted); String expected = HashUtil.getMD5(sorted); deleteCheckoutDirectory("checkoutTest", "checkout1"); String actual = getCheckoutMD5(date, "checkoutTest", "checkout1"); deleteCheckoutDirectory("checkoutTest", "checkout1"); assertEquals(actual, expected); } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test checkout then update. */ @Test public void testUpdate() { println("testUpdate"); try { String expected = getCheckoutMD5(Calendar.getInstance(), "updateTest", "checkout"); //month back from today Calendar updateFromDate = Calendar.getInstance(); updateFromDate.roll(Calendar.MONTH, -1); String actual = getHeadUpdateMD5(updateFromDate, "updateTest", "update"); assertEquals(actual, expected); } catch (Exception ex) { fail(ex.getMessage()); } } /** * Test checkout head revision and compare to checkout revision 0 then * update to head revision. */ @Test public void testUpdateFirstToHead() { println("testUpdateFirstToHead"); try { String actual = getFirstRevisionUpdatedToHeadMD5("updateTest", "update"); String expected = getCheckoutMD5(Calendar.getInstance(), "updateTest", "checkout"); assertEquals(actual, expected); } catch (Exception ex) { fail(ex.getMessage()); } } /** * */ @Test public void testSequencialUpdatesAgainstCheckout() { println("testSequencialUpdatesAgainstCheckout"); try { long numHeadRevision = getNumberOfHeadRevision(); long firstRevision = numHeadRevision - 10L; if (firstRevision < 1L) { firstRevision = Math.abs(firstRevision) + 1L; } checkoutRevision(firstRevision, "updateTest", "update", false); firstRevision++; for (long revNumber = firstRevision; revNumber <= numHeadRevision; revNumber++) { String checkoutHash = checkoutRevision(revNumber, "updateTest", "checkout", true); String updateHash = updateToRevision(revNumber, "updateTest", "update", true); assertEquals(checkoutHash, updateHash, "Not same hash code"); } } catch (Exception ex) { fail(ex.getMessage()); } } @Test public void testSequencialUpdatesUntilHead() { println("testSequencialUpdatesUntilHead"); try { final String checkout = "checkout"; final String update = "update"; final String updateTest = "updateTest"; long numHeadRevision = getNumberOfHeadRevision(); long checkpoint = numHeadRevision / 100; // long revNumber = checkpoint * 80; //test last 20% revisions checkoutRevision(revNumber, updateTest, update, false); for (revNumber += 1L; revNumber < numHeadRevision; revNumber++) { if(!checkRevisionAvailable(revNumber)){ //there is a bug on recovering revision from svn //remove when bug is fixed continue; } if (revNumber % checkpoint == 0) { //check every checkpoint String updateHash = updateToRevision(revNumber, updateTest, update, true); String checkoutHash = checkoutRevision(revNumber, updateTest, checkout, true); assertEquals(checkoutHash, updateHash, "Not same hash code"); } else { updateToRevision(revNumber, updateTest, update, false); } } String updateHash = updateToRevision(numHeadRevision, updateTest, update, true); String checkoutHash = checkoutRevision(numHeadRevision, updateTest, "checkout", true); assertEquals(checkoutHash, updateHash, "Not same hash code"); } catch (Exception ex) { fail(ex.getMessage()); } } /** * Bug found in svnkit revision recovery. Several revisions are ignored. * No reason found. Try to implement method on SVN_by_CommandLine may solve it. * * @throws VCSException */ @Test public void testRevisionsAvailable() throws VCSException { long numHeadRevision = getNumberOfHeadRevision(); long notFoundRevisions = 0L; for (long revNumber = 1L; revNumber <= numHeadRevision; revNumber++) { if(checkRevisionAvailable(revNumber)){ println("Not found revision " + revNumber); notFoundRevisions++; } } println("Missed " + notFoundRevisions + " revisions"); } private boolean checkRevisionAvailable(long revNumber) throws VCSException { return vcsService.getRevision(project, projectUser, revNumber) != null; } private long getNumberOfHeadRevision() throws VCSException { return vcsService.getNumberOfHEADRevision(projectUser); } private String checkoutRevision(long revNumber, String mainDir, String subDir, boolean calchash) throws VCSException { String fixedDir = PathUtil.getWellFormedPath(tempPath, mainDir, subDir); FileUtils.deleteDirectory(new File(fixedDir)); Revision revision = vcsService.getRevision(project, projectUser, revNumber); assertNotNull(revision); revision.setLocalPath(fixedDir); vcsService.doCheckout(revision, projectUser, false); if (calchash) { return vcsService.getMD5(revision); } else { return null; } } private String updateToRevision(long revNumber, String mainDir, String subDir, boolean calchash) throws VCSException { String fixedDir = PathUtil.getWellFormedPath(tempPath, mainDir, subDir); Revision revision = vcsService.getRevision(project, projectUser, revNumber); assertNotNull(revision, "Revision " + revNumber + " not found"); revision.setLocalPath(fixedDir); vcsService.doUpdate(revision, projectUser, false); if (calchash) { return vcsService.getMD5(revision); } else { return null; } } /** * Returns MD5 of resulting project from checkout of last revision from a * deserid date. * * @param date * @param mainPath * @param subdir * @return * @throws VCSException */ private String getCheckoutMD5(Calendar date, String mainPath, String subdir) throws VCSException { String checkoutPath = PathUtil.getWellFormedPath(tempPath, mainPath, subdir); FileUtils.deleteDirectory(new File(checkoutPath)); Revision revision = vcsService.getRevision(project, projectUser, date); assertNotNull(revision); revision.setLocalPath(checkoutPath); vcsService.doCheckout(revision, projectUser, false); String md5 = vcsService.getMD5(revision); FileUtils.deleteDirectory(new File(checkoutPath)); return md5; } /** * Returns MD5 resulting project update to head on checkout of last revision * from a desired date. * * @param checkoutFromDate * @param mainPath * @param subdir * @return * @throws VCSException */ private String getHeadUpdateMD5(Calendar checkoutFromDate, String mainPath, String subdir) throws VCSException { String fixedPath = PathUtil.getWellFormedPath(tempPath, mainPath, subdir); FileUtils.deleteDirectory(new File(fixedPath)); Revision revision = vcsService.getRevision(project, projectUser, checkoutFromDate); assertNotNull(revision); revision.setLocalPath(fixedPath); vcsService.doCheckout(revision, projectUser, false); Long number = vcsService.getNumberOfHEADRevision(projectUser); revision.setNumber(number); vcsService.doUpdate(revision, projectUser, false); String oldMD5 = vcsService.getMD5(revision); FileUtils.deleteDirectory(new File(fixedPath)); return oldMD5; } /** * Returns MD5 resulting project of update to head a checkout of the first * revision. * * @param mainPath * @param subdir * @return MD5 * @throws VCSException */ private String getFirstRevisionUpdatedToHeadMD5(String mainPath, String subdir) throws VCSException { String updatedPath = PathUtil.getWellFormedPath(tempPath, mainPath, subdir); FileUtils.deleteDirectory(new File(updatedPath)); Revision revision = vcsService.getRevision(project, projectUser, 1L); assertNotNull(revision); revision.setLocalPath(updatedPath); vcsService.doCheckout(revision, projectUser, false); Long number = vcsService.getNumberOfHEADRevision(projectUser); revision.setNumber(number); vcsService.doUpdate(revision, projectUser, false); String oldMD5 = vcsService.getMD5(revision); FileUtils.deleteDirectory(new File(updatedPath)); return oldMD5; } /** * Does not delete files from checkout. * * @param date * @param mainPath * @param subdir * @param relative * @param ignoreVCSFiles * @return * @throws VCSException */ private Set<String> getCheckoutFiles(Calendar date, String mainPath, String subdir, boolean relative) throws VCSException { String updatedPath = PathUtil.getWellFormedPath(tempPath, mainPath, subdir); File updateDirectory = new File(updatedPath); FileUtils.deleteDirectory(updateDirectory); Revision revision = vcsService.getRevision(project, projectUser, date); assertNotNull(revision); revision.setLocalPath(updatedPath); vcsService.doCheckout(revision, projectUser, false); Set<String> files = FileUtils.getAllFilesInFolderAndSubFolders(updateDirectory); //FileUtils.deleteDirectory(updateDirectory); Set<String> relativeFile = new HashSet<String>(files.size()); for (String string : files) { if (VCSUtil.isVCSpath(string)) { continue; } if (relative) { relativeFile.add(string.substring(updatedPath.length())); } else { relativeFile.add(string); } } return relativeFile; } private void deleteCheckoutDirectory(String mainPath, String subdir) { String updatedPath = PathUtil.getWellFormedPath(tempPath, mainPath, subdir); File updateDirectory = new File(updatedPath); FileUtils.deleteDirectory(updateDirectory); } }