org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheTest.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheTest.java

Source

/*******************************************************************************
 * Copyright (C) 2011, 2012 Jens Baumgart <jens.baumgart@sap.com> and others.
 *
 * 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.internal.indexdiff;

import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.FileOutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.eclipse.core.resources.IFile;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCache;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffChangedListener;
import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
import org.eclipse.egit.core.op.ConnectProviderOperation;
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.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class IndexDiffCacheTest extends GitTestCase {

    TestRepository testRepository;

    Repository repository;

    private AtomicBoolean listenerCalled;

    private AtomicReference<IndexDiffData> indexDiffDataResult;

    private IndexDiffChangedListener indexDiffListener;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        testRepository = new TestRepository(gitDir);
        repository = testRepository.getRepository();
        listenerCalled = new AtomicBoolean(false);
        indexDiffDataResult = new AtomicReference<>(null);
        indexDiffListener = new IndexDiffChangedListener() {
            @Override
            public void indexDiffChanged(Repository repo, IndexDiffData indexDiffData) {
                listenerCalled.set(true);
                indexDiffDataResult.set(indexDiffData);
            }
        };
    }

    @Override
    @After
    public void tearDown() throws Exception {
        IndexDiffCache indexDiffCache = Activator.getDefault().getIndexDiffCache();
        indexDiffCache.removeIndexDiffChangedListener(indexDiffListener);
        testRepository.dispose();
        repository = null;
        super.tearDown();
    }

    @Test
    public void testAddingAFile() throws Exception {
        new ConnectProviderOperation(project.project, repository.getDirectory()).execute(null);
        // create first commit containing a dummy file
        testRepository.createInitialCommit("testBranchOperation\n\nfirst commit\n");
        prepareCacheEntry();
        waitForListenerCalled();
        final String fileName = "aFile";
        // This call should trigger an indexDiffChanged event (triggered via
        // resource changed event)
        project.createFile(fileName, "content".getBytes("UTF-8"));
        IndexDiffData indexDiffData = waitForListenerCalled();
        String path = project.project.getFile(fileName).getFullPath().toString().substring(1);
        if (!indexDiffData.getUntracked().contains(path))
            fail("IndexDiffData did not contain aFile as untracked");
        // This call should trigger an indexDiffChanged event
        new Git(repository).add().addFilepattern(path).call();
        IndexDiffData indexDiffData2 = waitForListenerCalled();
        if (indexDiffData2.getUntracked().contains(path))
            fail("IndexDiffData contains aFile as untracked");
        if (!indexDiffData2.getAdded().contains(path))
            fail("IndexDiffData does not contain aFile as added");
    }

    @Test
    public void testAddFileFromUntrackedFolder() throws Exception {
        testRepository.connect(project.project);
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testAddFileFromUntrackedFolder\n\nfirst commit\n");
        prepareCacheEntry();

        project.createFolder("folder");
        project.createFolder("folder/a");
        project.createFolder("folder/b");
        IFile fileA = project.createFile("folder/a/file", new byte[] {});
        project.createFile("folder/b/file", new byte[] {});

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getUntrackedFolders(), hasItem("Project-1/folder/"));

        testRepository.track(fileA.getLocation().toFile());

        IndexDiffData data2 = waitForListenerCalled();
        assertThat(data2.getAdded(), hasItem("Project-1/folder/a/file"));
        assertThat(data2.getUntrackedFolders(), not(hasItem("Project-1/folder/")));
        assertThat(data2.getUntrackedFolders(), not(hasItem("Project-1/folder/a")));
        assertThat(data2.getUntrackedFolders(), hasItem("Project-1/folder/b/"));
    }

    @Test
    public void testAddIgnoredFolder() throws Exception {
        testRepository.connect(project.project);
        project.createFile(".gitignore", "ignore\n".getBytes("UTF-8"));
        project.createFolder("ignore");
        project.createFile("ignore/file.txt", new byte[] {});
        project.createFolder("sub");
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testAddFileInIgnoredFolder\n\nfirst commit\n");
        prepareCacheEntry();

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getIgnoredNotInIndex(), hasItem("Project-1/ignore"));

        project.createFolder("sub/ignore");

        IndexDiffData data2 = waitForListenerCalled();
        assertThat(data2.getIgnoredNotInIndex(), hasItem("Project-1/ignore"));
        assertThat(data2.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));

        // Must not change anything (ignored path starts with this string, but
        // it's not a prefix path of it)
        project.createFile("sub/ignorenot", new byte[] {});

        IndexDiffData data3 = waitForListenerCalled();
        assertThat(data3.getUntracked(), hasItem("Project-1/sub/ignorenot"));
        assertThat(data3.getIgnoredNotInIndex(), hasItem("Project-1/ignore"));
        assertThat(data3.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));
    }

    @Test
    public void testRemoveIgnoredFile() throws Exception {
        testRepository.connect(project.project);
        project.createFile(".gitignore", "ignore\n".getBytes("UTF-8"));
        project.createFolder("sub");
        IFile file = project.createFile("sub/ignore", new byte[] {});
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testRemoveIgnoredFile\n\nfirst commit\n");
        IndexDiffCacheEntry entry = prepareCacheEntry();

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));

        // Must not change anything (ignored path starts with this string, but
        // it's not a prefix path of it)
        project.createFile("sub/ignorenot", new byte[] {});

        IndexDiffData data2 = waitForListenerCalled();
        assertThat(data2.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));

        file.delete(false, null);

        waitForListenerNotCalled();
        entry.refresh(); // need explicit as ignored file shall not trigger.
        IndexDiffData data3 = waitForListenerCalled();
        assertThat(data3.getIgnoredNotInIndex(), not(hasItem("Project-1/sub/ignore")));
    }

    @Test
    public void testAddAndRemoveGitIgnoreFileToIgnoredDir() throws Exception {
        testRepository.connect(project.project);
        project.createFile(".gitignore", "ignore\n".getBytes("UTF-8"));
        project.createFolder("sub");
        project.createFile("sub/ignore", new byte[] {});
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testRemoveIgnoredFile\n\nfirst commit\n");
        prepareCacheEntry();

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));

        project.createFile("sub/ignored", "Ignored".getBytes("UTF-8"));

        // adding this file will trigger a refresh, so no manual refresh must be
        // required.
        project.createFile("sub/.gitignore", "ignored\n".getBytes("UTF-8"));

        IndexDiffData data2 = waitForListenerCalled();
        assertThat(data2.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignored"));

        // removing must also trigger the listener
        project.getProject().getFile("sub/.gitignore").delete(true, null);

        IndexDiffData data3 = waitForListenerCalled();
        assertThat(data3.getUntracked(), hasItem("Project-1/sub/ignored"));
    }

    @Test
    public void testAddAndRemoveFileToIgnoredDir() throws Exception {
        testRepository.connect(project.project);
        project.createFile(".gitignore", "sub\n".getBytes("UTF-8"));
        project.createFolder("sub");
        project.createFile("sub/ignore", new byte[] {});
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testRemoveIgnoredFile\n\nfirst commit\n");
        prepareCacheEntry();

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getIgnoredNotInIndex(), hasItem("Project-1/sub"));

        // creating a file in an ignored directory will not trigger the listener
        project.createFile("sub/ignored", "Ignored".getBytes("UTF-8"));
        waitForListenerNotCalled();

        // removing must also not trigger the listener
        project.getProject().getFile("sub/ignored").delete(true, null);
        waitForListenerNotCalled();
    }

    @Test
    public void testModifyFileInIgnoredDir() throws Exception {
        testRepository.connect(project.project);
        project.createFile(".gitignore", "ignore\n".getBytes("UTF-8"));
        project.createFolder("sub");
        project.createFile("sub/ignore", new byte[] {});
        testRepository.addToIndex(project.project);
        testRepository.createInitialCommit("testRemoveIgnoredFile\n\nfirst commit\n");
        prepareCacheEntry();

        IndexDiffData data1 = waitForListenerCalled();
        assertThat(data1.getIgnoredNotInIndex(), hasItem("Project-1/sub/ignore"));

        IFile file = project.getProject().getFile("sub/ignore");
        FileOutputStream str = new FileOutputStream(file.getLocation().toFile());
        try {
            str.write("other contents".getBytes("UTF-8"));
        } finally {
            str.close();
        }

        // no job should be triggered for that change.
        waitForListenerNotCalled();
    }

    private IndexDiffCacheEntry prepareCacheEntry() {
        listenerCalled.set(false);
        indexDiffDataResult.set(null);

        IndexDiffCache indexDiffCache = Activator.getDefault().getIndexDiffCache();
        indexDiffCache.addIndexDiffChangedListener(indexDiffListener);
        // This call should trigger an indexDiffChanged event
        IndexDiffCacheEntry cacheEntry = indexDiffCache.getIndexDiffCacheEntry(repository);
        return cacheEntry;
    }

    private IndexDiffData waitForListenerCalled() throws InterruptedException {
        long time = 0;
        while (!listenerCalled.get() && time < 60000) {
            Thread.sleep(100);
            time += 100;
        }
        assertTrue("indexDiffChanged was not called after " + time + " ms", listenerCalled.get());
        listenerCalled.set(false);
        return indexDiffDataResult.get();
    }

    private void waitForListenerNotCalled() throws InterruptedException {
        long time = 0;
        while (!listenerCalled.get() && time < 1000) {
            Thread.sleep(100);
            time += 100;
        }
        assertTrue("indexDiffChanged was called where it shouldn't have been", !listenerCalled.get());
    }

}