/*******************************************************************************
* Copyright (C) 2010, Dariusz Luksza <dariusz@luksza.org>
*
* 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
*******************************************************************************/
package org.eclipse.egit.core.synchronize;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.Arrays;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.egit.core.test.GitTestCase;
import org.eclipse.egit.core.test.TestRepository;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.team.core.variants.IResourceVariant;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class GitResourceVariantComparatorTest extends GitTestCase {
private Repository repo;
private IProject iProject;
private TestRepository testRepo;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
iProject = project.project;
testRepo = new TestRepository(gitDir);
testRepo.connect(iProject);
repo = RepositoryMapping.getMapping(iProject).getRepository();
// make initial commit
try (Git git = new Git(repo)) {
git.commit().setAuthor("JUnit", "junit@jgit.org")
.setMessage("Initial commit").call();
}
}
@After
public void clearGitResources() throws Exception {
testRepo.disconnect(iProject);
testRepo.dispose();
repo = null;
super.tearDown();
}
/* ============================================
* compare(IResource, IResourceVariant) tests
* ============================================ */
/**
* When remote variant wasn't found, compare method is called with null as
* second parameter. In this case compare should return false.
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenRemoteDoesNotExist() {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
IResource local = mock(IResource.class);
when(local.exists()).thenReturn(false);
// then
assertFalse(grvc.compare(local, null));
}
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenRemoteDoesNotExist2() throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
IResource local = mock(IResource.class);
when(local.exists()).thenReturn(false);
IResourceVariant remote = new GitRemoteFolder(repo, null, null, null, "./");
// then
assertFalse(grvc.compare(local, remote));
}
/**
* It is possible to have a local file that has same name as a remote
* folder. In some cases that two resources can be compared. In this case
* compare method should return false, because they aren't same resources
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenComparingFileAndContainer() {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(true);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* Comparing two folders that have different path should return false.
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenComparingContainerAndContainer()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
IPath localPath = mock(IPath.class);
IContainer local = mock(IContainer.class);
when(local.exists()).thenReturn(true);
when(local.getLocation()).thenReturn(localPath);
File file = testRepo.createFile(iProject, "test" + File.separator
+ "keep");
RevCommit commit = testRepo.addAndCommit(iProject, file,
"initial commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
commit.getTree(), path);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* When comparing two folders that have same path, compare() method should
* return true.
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnTrueWhenComparingContainerAndContainer()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file = testRepo.createFile(iProject, "test" + File.separator
+ "keep");
RevCommit commit = testRepo.addAndCommit(iProject, file,
"initial commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
IPath iPath = new Path(path);
IContainer local = mock(IContainer.class);
when(local.exists()).thenReturn(true);
when(local.getLocation()).thenReturn(iPath);
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
commit.getTree(), path);
// then
assertTrue(grvc.compare(local, remote));
}
/**
* Compare() should return false when comparing two files with different
* content length
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenContentLengthIsDifferent()
throws Exception {
// when
byte[] shortContent = "short content".getBytes("UTF-8");
byte[] longContent = "very long long content".getBytes("UTF-8");
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(longContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(shortContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* Comparing two files that have same content length but having small
* difference inside content should return false.
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenShortContentIsDifferent() throws Exception {
// when
byte[] localContent = "very long long content".getBytes("UTF-8");
// this typo should be here
byte[] remoteContent = "very long lonk content".getBytes("UTF-8");
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(localContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(remoteContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* Comparing two 'large' files that have same length and almost identical
* content should return false.
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenLongContentIsDifferent() throws Exception {
// when
byte[] localContent = new byte[8192];
Arrays.fill(localContent, (byte) 'a');
byte[] remoteContent = new byte[8192];
Arrays.fill(remoteContent, (byte) 'a');
remoteContent[8101] = 'b';
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(localContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(remoteContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* Comparing two 'large' files that have different length but same content
* should return false.
* <p>
* This and previous three test cases cover almost the same functionality
* but they are covering all return points in compare methods that can be
* used when comparing files content
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnFalseWhenLongContentLengthIsDifferent()
throws Exception {
// when
byte[] localContent = new byte[8192];
Arrays.fill(localContent, (byte) 'a');
byte[] remoteContent = new byte[8200];
Arrays.fill(remoteContent, (byte) 'a');
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(localContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(remoteContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertFalse(grvc.compare(local, remote));
}
/**
* Comparing two files that have the same content and content length should
* return true
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnTrueWhenShortContentIsDifferent() throws Exception {
// when
byte[] localContent = "very long long content".getBytes("UTF-8");
byte[] remoteContent = "very long long content".getBytes("UTF-8");
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(localContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(remoteContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertTrue(grvc.compare(local, remote));
}
/**
* Compare two 'large' files that have same content length and content
* should return true.
*
* @throws Exception
*/
@Test
@SuppressWarnings("boxing")
public void shouldReturnTrueWhenLongContentLengthIsDifferent()
throws Exception {
// when
byte[] localContent = new byte[8192];
Arrays.fill(localContent, (byte) 'a');
byte[] remoteContent = new byte[8192];
Arrays.fill(remoteContent, (byte) 'a');
GitSynchronizeData data = new GitSynchronizeData(repo, HEAD, HEAD, true);
GitSynchronizeDataSet dataSet = new GitSynchronizeDataSet(data);
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
dataSet);
// given
IFile local = mock(IFile.class);
when(local.exists()).thenReturn(true);
when(local.getProject()).thenReturn(project.getProject());
when(local.getContents()).thenReturn(
new ByteArrayInputStream(localContent));
IStorage storage = mock(IStorage.class);
when(storage.getContents()).thenReturn(
new ByteArrayInputStream(remoteContent));
IResourceVariant remote = mock(IResourceVariant.class);
when(remote.isContainer()).thenReturn(false);
when(remote.getStorage(any(IProgressMonitor.class))).thenReturn(
storage);
// then
assertTrue(grvc.compare(local, remote));
}
/* ==================================================
* compare(IResourceVariant, IResourceVariant) tests
* ================================================== */
/**
* When comparing file that don't exist in base, but exists in remote
* compare method should return false.
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenBaseDoesntExist() throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
RevCommit baseCommit = testRepo.createInitialCommit("initial commit");
testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS
+ "test");
File file = testRepo.createFile(iProject, "test-file");
RevCommit remoteCommit = testRepo.addAndCommit(iProject, file,
"second commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
baseCommit.getTree(), path);
GitRemoteFile remote = new GitRemoteFile(repo, baseCommit,
remoteCommit.getTree(), path);
// then
assertFalse(grvc.compare(base, remote));
}
/**
* Compare() should return false when remote file does not exists, but
* equivalent local file exist.
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenRemoteVariantDoesntExist()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
RevCommit remoteCommit = testRepo.createInitialCommit("initial commit");
testRepo.createAndCheckoutBranch(Constants.HEAD, Constants.R_HEADS
+ "test");
File file = testRepo.createFile(iProject, "test-file");
RevCommit baseCommit = testRepo.addAndCommit(iProject, file,
"second commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
baseCommit.getTree(), path);
GitRemoteFile remote = new GitRemoteFile(repo, remoteCommit,
remoteCommit.getTree(), path);
// then
assertFalse(grvc.compare(base, remote));
}
/**
* Return false when comparing incompatible types (file against folder) that
* also maps onto different resources
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenComparingRemoteVariantFileWithContainer()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file = testRepo.createFile(iProject, "test" + File.separator
+ "keep");
RevCommit commit = testRepo.addAndCommit(iProject, file,
"initial commit");
String filePath = Repository.stripWorkDir(repo.getWorkTree(), file);
String folderPath = Repository.stripWorkDir(repo.getWorkTree(),
new File(file.getParent()));
GitRemoteFile base = new GitRemoteFile(repo, commit, commit.getTree(),
filePath);
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
commit.getTree(), folderPath);
// then
assertFalse(grvc.compare(base, remote));
}
/**
* Return false when comparing incompatible types (folder against file) that
* also map onto different resources
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenComparingRemoteVariantContainerWithFile()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file = testRepo.createFile(iProject, "test" + File.separator
+ "keep");
RevCommit commit = testRepo.addAndCommit(iProject, file,
"initial commit");
String filePath = Repository.stripWorkDir(repo.getWorkTree(), file);
String folderPath = Repository.stripWorkDir(repo.getWorkTree(),
new File(file.getParent()));
GitRemoteFolder base = new GitRemoteFolder(repo, null, commit,
commit.getTree(), folderPath);
GitRemoteFile remote = new GitRemoteFile(repo, commit,
commit.getTree(), filePath);
// then
assertFalse(grvc.compare(base, remote));
}
/**
* When comparing two remote variants that have different path compare
* method should return false
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenComparingRemoteVariantContainerWithContainer()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file1 = testRepo.createFile(iProject, "test1" + File.separator
+ "keep1");
File file2 = testRepo.createFile(iProject, "test2" + File.separator
+ "keep2");
testRepo.track(file1);
testRepo.track(file2);
testRepo.addToIndex(testRepo.getIFile(iProject, file1));
testRepo.addToIndex(testRepo.getIFile(iProject, file2));
RevCommit commit = testRepo.commit("initial commit");
try (TreeWalk tw = new TreeWalk(repo)) {
int nth = tw.addTree(commit.getTree());
tw.next();
tw.enterSubtree(); // enter project node
tw.next();
GitRemoteFolder base = new GitRemoteFolder(repo, null, commit,
tw.getObjectId(nth), tw.getNameString());
tw.next();
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
tw.getObjectId(nth), tw.getNameString());
// then
assertFalse(grvc.compare(base, remote));
}
}
/**
* Comparing two remote folders that have same path should return true
*
* @throws Exception
*/
@Test
public void shouldReturnTrueWhenComparingRemoteVariantContainerWithContainer()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file1 = testRepo.createFile(iProject, "test1" + File.separator
+ "keep1");
testRepo.track(file1);
testRepo.addToIndex(testRepo.getIFile(iProject, file1));
RevCommit commit = testRepo.commit("initial commit");
String path1 = Repository.stripWorkDir(repo.getWorkTree(), new File(
file1.getParent()));
GitRemoteFolder base = new GitRemoteFolder(repo, null, commit,
commit.getTree(), path1);
GitRemoteFolder remote = new GitRemoteFolder(repo, null, commit,
commit.getTree(), path1);
// then
assertTrue(grvc.compare(base, remote));
}
/**
* Comparing two remote files that have different git ObjectId should return false.
*
* @throws Exception
*/
@Test
public void shouldReturnFalseWhenComparingRemoteVariantWithDifferentObjectId()
throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file = testRepo.createFile(iProject, "test-file");
RevCommit baseCommit = testRepo.appendContentAndCommit(iProject, file,
"a", "initial commit");
RevCommit remoteCommit = testRepo.appendContentAndCommit(iProject,
file, "bc", "second commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, baseCommit,
baseCommit.getTree(), path);
GitRemoteFile remote = new GitRemoteFile(repo, remoteCommit,
remoteCommit.getTree(), path);
// then
assertFalse(grvc.compare(base, remote));
}
/**
* Comparing two remote files that have the same git ObjectId should return
* true.
*
* @throws Exception
*/
@Test
public void shouldReturnTrueWhenComparingRemoteVariant() throws Exception {
// when
GitResourceVariantComparator grvc = new GitResourceVariantComparator(
null);
// given
File file = testRepo.createFile(iProject, "test-file");
RevCommit commit = testRepo.appendContentAndCommit(iProject, file,
"a", "initial commit");
String path = Repository.stripWorkDir(repo.getWorkTree(), file);
GitRemoteFile base = new GitRemoteFile(repo, commit, commit.getTree(),
path);
GitRemoteFile remote = new GitRemoteFile(repo, commit,
commit.getTree(), path);
// then
assertTrue(grvc.compare(base, remote));
}
}