| /* |
| * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com> |
| * and other copyright owners as documented in the project's IP log. |
| * |
| * This program and the accompanying materials are made available |
| * under the terms of the Eclipse Distribution License v1.0 which |
| * accompanies this distribution, is reproduced below, and is |
| * available at http://www.eclipse.org/org/documents/edl-v10.php |
| * |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or |
| * without modification, are permitted provided that the following |
| * conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * - Neither the name of the Eclipse Foundation, Inc. nor the |
| * names of its contributors may be used to endorse or promote |
| * products derived from this software without specific prior |
| * written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
| * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
| * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| package org.eclipse.jgit.api; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.util.concurrent.Callable; |
| |
| import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode; |
| import org.eclipse.jgit.api.MergeResult.MergeStatus; |
| import org.eclipse.jgit.api.errors.NoHeadException; |
| import org.eclipse.jgit.junit.JGitTestUtil; |
| import org.eclipse.jgit.junit.RepositoryTestCase; |
| import org.eclipse.jgit.lib.Constants; |
| import org.eclipse.jgit.lib.ObjectId; |
| import org.eclipse.jgit.lib.RefUpdate; |
| import org.eclipse.jgit.lib.Repository; |
| import org.eclipse.jgit.lib.RepositoryState; |
| import org.eclipse.jgit.lib.StoredConfig; |
| import org.eclipse.jgit.revwalk.RevCommit; |
| import org.eclipse.jgit.revwalk.RevSort; |
| import org.eclipse.jgit.revwalk.RevWalk; |
| import org.eclipse.jgit.transport.RefSpec; |
| import org.eclipse.jgit.transport.RemoteConfig; |
| import org.eclipse.jgit.transport.URIish; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class PullCommandTest extends RepositoryTestCase { |
| /** Second Test repository */ |
| protected Repository dbTarget; |
| |
| private Git source; |
| |
| private Git target; |
| |
| private File sourceFile; |
| |
| private File targetFile; |
| |
| @Test |
| public void testPullFastForward() throws Exception { |
| PullResult res = target.pull().call(); |
| // nothing to update since we don't have different data yet |
| assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty()); |
| assertTrue(res.getMergeResult().getMergeStatus().equals( |
| MergeStatus.ALREADY_UP_TO_DATE)); |
| |
| assertFileContentsEqual(targetFile, "Hello world"); |
| |
| // change the source file |
| writeToFile(sourceFile, "Another change"); |
| source.add().addFilepattern("SomeFile.txt").call(); |
| source.commit().setMessage("Some change in remote").call(); |
| |
| res = target.pull().call(); |
| |
| assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty()); |
| assertEquals(res.getMergeResult().getMergeStatus(), |
| MergeStatus.FAST_FORWARD); |
| assertFileContentsEqual(targetFile, "Another change"); |
| assertEquals(RepositoryState.SAFE, target.getRepository() |
| .getRepositoryState()); |
| |
| res = target.pull().call(); |
| assertEquals(res.getMergeResult().getMergeStatus(), |
| MergeStatus.ALREADY_UP_TO_DATE); |
| } |
| |
| @Test |
| public void testPullMerge() throws Exception { |
| PullResult res = target.pull().call(); |
| // nothing to update since we don't have different data yet |
| assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty()); |
| assertTrue(res.getMergeResult().getMergeStatus() |
| .equals(MergeStatus.ALREADY_UP_TO_DATE)); |
| |
| writeToFile(sourceFile, "Source change"); |
| source.add().addFilepattern("SomeFile.txt"); |
| RevCommit sourceCommit = source.commit() |
| .setMessage("Source change in remote").call(); |
| |
| File targetFile2 = new File(dbTarget.getWorkTree(), "OtherFile.txt"); |
| writeToFile(targetFile2, "Unconflicting change"); |
| target.add().addFilepattern("OtherFile.txt").call(); |
| RevCommit targetCommit = target.commit() |
| .setMessage("Unconflicting change in local").call(); |
| |
| res = target.pull().call(); |
| |
| MergeResult mergeResult = res.getMergeResult(); |
| ObjectId[] mergedCommits = mergeResult.getMergedCommits(); |
| assertEquals(targetCommit.getId(), mergedCommits[0]); |
| assertEquals(sourceCommit.getId(), mergedCommits[1]); |
| try (RevWalk rw = new RevWalk(dbTarget)) { |
| RevCommit mergeCommit = rw.parseCommit(mergeResult.getNewHead()); |
| String message = "Merge branch 'master' of " |
| + db.getWorkTree().getAbsolutePath(); |
| assertEquals(message, mergeCommit.getShortMessage()); |
| } |
| } |
| |
| @Test |
| public void testPullConflict() throws Exception { |
| PullResult res = target.pull().call(); |
| // nothing to update since we don't have different data yet |
| assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty()); |
| assertTrue(res.getMergeResult().getMergeStatus().equals( |
| MergeStatus.ALREADY_UP_TO_DATE)); |
| |
| assertFileContentsEqual(targetFile, "Hello world"); |
| |
| // change the source file |
| writeToFile(sourceFile, "Source change"); |
| source.add().addFilepattern("SomeFile.txt").call(); |
| source.commit().setMessage("Source change in remote").call(); |
| |
| // change the target file |
| writeToFile(targetFile, "Target change"); |
| target.add().addFilepattern("SomeFile.txt").call(); |
| target.commit().setMessage("Target change in local").call(); |
| |
| res = target.pull().call(); |
| |
| String sourceChangeString = "Source change\n>>>>>>> branch 'master' of " |
| + target.getRepository().getConfig().getString("remote", |
| "origin", "url"); |
| |
| assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty()); |
| assertEquals(res.getMergeResult().getMergeStatus(), |
| MergeStatus.CONFLICTING); |
| String result = "<<<<<<< HEAD\nTarget change\n=======\n" |
| + sourceChangeString + "\n"; |
| assertFileContentsEqual(targetFile, result); |
| assertEquals(RepositoryState.MERGING, target.getRepository() |
| .getRepositoryState()); |
| } |
| |
| @Test |
| public void testPullWithUntrackedStash() throws Exception { |
| target.pull().call(); |
| |
| // change the source file |
| writeToFile(sourceFile, "Source change"); |
| source.add().addFilepattern("SomeFile.txt").call(); |
| source.commit().setMessage("Source change in remote").call(); |
| |
| // write untracked file |
| writeToFile(new File(dbTarget.getWorkTree(), "untracked.txt"), |
| "untracked"); |
| RevCommit stash = target.stashCreate().setIndexMessage("message here") |
| .setIncludeUntracked(true).call(); |
| assertNotNull(stash); |
| assertTrue(target.status().call().isClean()); |
| |
| // pull from source |
| assertTrue(target.pull().call().isSuccessful()); |
| assertEquals("[SomeFile.txt, mode:100644, content:Source change]", |
| indexState(dbTarget, CONTENT)); |
| assertFalse(JGitTestUtil.check(dbTarget, "untracked.txt")); |
| assertEquals("Source change", |
| JGitTestUtil.read(dbTarget, "SomeFile.txt")); |
| |
| // apply the stash |
| target.stashApply().setStashRef(stash.getName()).call(); |
| assertEquals("[SomeFile.txt, mode:100644, content:Source change]", |
| indexState(dbTarget, CONTENT)); |
| assertEquals("untracked", JGitTestUtil.read(dbTarget, "untracked.txt")); |
| assertEquals("Source change", |
| JGitTestUtil.read(dbTarget, "SomeFile.txt")); |
| } |
| |
| @Test |
| public void testPullLocalConflict() throws Exception { |
| target.branchCreate().setName("basedOnMaster").setStartPoint( |
| "refs/heads/master").setUpstreamMode(SetupUpstreamMode.TRACK) |
| .call(); |
| target.getRepository().updateRef(Constants.HEAD).link( |
| "refs/heads/basedOnMaster"); |
| PullResult res = target.pull().call(); |
| // nothing to update since we don't have different data yet |
| assertNull(res.getFetchResult()); |
| assertTrue(res.getMergeResult().getMergeStatus().equals( |
| MergeStatus.ALREADY_UP_TO_DATE)); |
| |
| assertFileContentsEqual(targetFile, "Hello world"); |
| |
| // change the file in master |
| target.getRepository().updateRef(Constants.HEAD).link( |
| "refs/heads/master"); |
| writeToFile(targetFile, "Master change"); |
| target.add().addFilepattern("SomeFile.txt").call(); |
| target.commit().setMessage("Source change in master").call(); |
| |
| // change the file in slave |
| target.getRepository().updateRef(Constants.HEAD).link( |
| "refs/heads/basedOnMaster"); |
| writeToFile(targetFile, "Slave change"); |
| target.add().addFilepattern("SomeFile.txt").call(); |
| target.commit().setMessage("Source change in based on master").call(); |
| |
| res = target.pull().call(); |
| |
| String sourceChangeString = "Master change\n>>>>>>> branch 'master' of local repository"; |
| |
| assertNull(res.getFetchResult()); |
| assertEquals(res.getMergeResult().getMergeStatus(), |
| MergeStatus.CONFLICTING); |
| String result = "<<<<<<< HEAD\nSlave change\n=======\n" |
| + sourceChangeString + "\n"; |
| assertFileContentsEqual(targetFile, result); |
| assertEquals(RepositoryState.MERGING, target.getRepository() |
| .getRepositoryState()); |
| } |
| |
| @Test(expected = NoHeadException.class) |
| public void testPullEmptyRepository() throws Exception { |
| Repository empty = createWorkRepository(); |
| RefUpdate delete = empty.updateRef(Constants.HEAD, true); |
| delete.setForceUpdate(true); |
| delete.delete(); |
| Git.wrap(empty).pull().call(); |
| } |
| |
| @Test |
| public void testPullMergeProgrammaticConfiguration() throws Exception { |
| // create another commit on another branch in source |
| source.checkout().setCreateBranch(true).setName("other").call(); |
| sourceFile = new File(db.getWorkTree(), "file2.txt"); |
| writeToFile(sourceFile, "content"); |
| source.add().addFilepattern("file2.txt").call(); |
| RevCommit sourceCommit = source.commit() |
| .setMessage("source commit on branch other").call(); |
| |
| File targetFile2 = new File(dbTarget.getWorkTree(), "OtherFile.txt"); |
| writeToFile(targetFile2, "Unconflicting change"); |
| target.add().addFilepattern("OtherFile.txt").call(); |
| RevCommit targetCommit = target.commit() |
| .setMessage("Unconflicting change in local").call(); |
| |
| PullResult res = target.pull().setRemote("origin") |
| .setRemoteBranchName("other") |
| .setRebase(false).call(); |
| |
| MergeResult mergeResult = res.getMergeResult(); |
| ObjectId[] mergedCommits = mergeResult.getMergedCommits(); |
| assertEquals(targetCommit.getId(), mergedCommits[0]); |
| assertEquals(sourceCommit.getId(), mergedCommits[1]); |
| try (RevWalk rw = new RevWalk(dbTarget)) { |
| RevCommit mergeCommit = rw.parseCommit(mergeResult.getNewHead()); |
| String message = "Merge branch 'other' of " |
| + db.getWorkTree().getAbsolutePath(); |
| assertEquals(message, mergeCommit.getShortMessage()); |
| } |
| } |
| |
| @Test |
| public void testPullMergeProgrammaticConfigurationImpliedTargetBranch() |
| throws Exception { |
| // create another commit on another branch in source |
| source.checkout().setCreateBranch(true).setName("other").call(); |
| sourceFile = new File(db.getWorkTree(), "file2.txt"); |
| writeToFile(sourceFile, "content"); |
| source.add().addFilepattern("file2.txt").call(); |
| RevCommit sourceCommit = source.commit() |
| .setMessage("source commit on branch other").call(); |
| |
| target.checkout().setCreateBranch(true).setName("other").call(); |
| File targetFile2 = new File(dbTarget.getWorkTree(), "OtherFile.txt"); |
| writeToFile(targetFile2, "Unconflicting change"); |
| target.add().addFilepattern("OtherFile.txt").call(); |
| RevCommit targetCommit = target.commit() |
| .setMessage("Unconflicting change in local").call(); |
| |
| // the source branch "other" matching the target branch should be |
| // implied |
| PullResult res = target.pull().setRemote("origin").setRebase(false) |
| .call(); |
| |
| MergeResult mergeResult = res.getMergeResult(); |
| ObjectId[] mergedCommits = mergeResult.getMergedCommits(); |
| assertEquals(targetCommit.getId(), mergedCommits[0]); |
| assertEquals(sourceCommit.getId(), mergedCommits[1]); |
| try (RevWalk rw = new RevWalk(dbTarget)) { |
| RevCommit mergeCommit = rw.parseCommit(mergeResult.getNewHead()); |
| String message = "Merge branch 'other' of " |
| + db.getWorkTree().getAbsolutePath() + " into other"; |
| assertEquals(message, mergeCommit.getShortMessage()); |
| } |
| } |
| |
| private enum TestPullMode { |
| MERGE, REBASE, REBASE_PREASERVE |
| } |
| |
| @Test |
| /** global rebase config should be respected */ |
| public void testPullWithRebasePreserve1Config() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "preserve"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); |
| } |
| |
| @Test |
| /** the branch-local config should win over the global config */ |
| public void testPullWithRebasePreserveConfig2() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "false"); |
| config.setString("branch", "master", "rebase", "preserve"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); |
| } |
| |
| @Test |
| /** the branch-local config should be respected */ |
| public void testPullWithRebasePreserveConfig3() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("branch", "master", "rebase", "preserve"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE_PREASERVE); |
| } |
| |
| @Test |
| /** global rebase config should be respected */ |
| public void testPullWithRebaseConfig1() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "true"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE); |
| } |
| |
| @Test |
| /** the branch-local config should win over the global config */ |
| public void testPullWithRebaseConfig2() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "preserve"); |
| config.setString("branch", "master", "rebase", "true"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE); |
| } |
| |
| @Test |
| /** the branch-local config should be respected */ |
| public void testPullWithRebaseConfig3() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("branch", "master", "rebase", "true"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.REBASE); |
| } |
| |
| @Test |
| /** without config it should merge */ |
| public void testPullWithoutConfig() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.MERGE); |
| } |
| |
| @Test |
| /** the branch local config should win over the global config */ |
| public void testPullWithMergeConfig() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "true"); |
| config.setString("branch", "master", "rebase", "false"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.MERGE); |
| } |
| |
| @Test |
| /** the branch local config should win over the global config */ |
| public void testPullWithMergeConfig2() throws Exception { |
| Callable<PullResult> setup = new Callable<PullResult>() { |
| public PullResult call() throws Exception { |
| StoredConfig config = dbTarget.getConfig(); |
| config.setString("pull", null, "rebase", "false"); |
| config.save(); |
| return target.pull().call(); |
| } |
| }; |
| doTestPullWithRebase(setup, TestPullMode.MERGE); |
| } |
| |
| private void doTestPullWithRebase(Callable<PullResult> pullSetup, |
| TestPullMode expectedPullMode) throws Exception { |
| // simple upstream change |
| writeToFile(sourceFile, "content"); |
| source.add().addFilepattern(sourceFile.getName()).call(); |
| RevCommit sourceCommit = source.commit().setMessage("source commit") |
| .call(); |
| |
| // create a merge commit in target |
| File loxalFile = new File(dbTarget.getWorkTree(), "local.txt"); |
| writeToFile(loxalFile, "initial\n"); |
| target.add().addFilepattern("local.txt").call(); |
| RevCommit t1 = target.commit().setMessage("target commit 1").call(); |
| |
| target.checkout().setCreateBranch(true).setName("side").call(); |
| |
| String newContent = "initial\n" + "and more\n"; |
| writeToFile(loxalFile, newContent); |
| target.add().addFilepattern("local.txt").call(); |
| RevCommit t2 = target.commit().setMessage("target commit 2").call(); |
| |
| target.checkout().setName("master").call(); |
| |
| MergeResult mergeResult = target.merge() |
| .setFastForward(MergeCommand.FastForwardMode.NO_FF).include(t2) |
| .call(); |
| assertEquals(MergeStatus.MERGED, mergeResult.getMergeStatus()); |
| assertFileContentsEqual(loxalFile, newContent); |
| ObjectId merge = mergeResult.getNewHead(); |
| |
| // pull |
| PullResult res = pullSetup.call(); |
| assertNotNull(res.getFetchResult()); |
| |
| if (expectedPullMode == TestPullMode.MERGE) { |
| assertEquals(MergeStatus.MERGED, res.getMergeResult() |
| .getMergeStatus()); |
| assertNull(res.getRebaseResult()); |
| } else { |
| assertNull(res.getMergeResult()); |
| assertEquals(RebaseResult.OK_RESULT, res.getRebaseResult()); |
| } |
| assertFileContentsEqual(sourceFile, "content"); |
| |
| try (RevWalk rw = new RevWalk(dbTarget)) { |
| rw.sort(RevSort.TOPO); |
| rw.markStart(rw.parseCommit(dbTarget.resolve("refs/heads/master"))); |
| |
| RevCommit next; |
| if (expectedPullMode == TestPullMode.MERGE) { |
| next = rw.next(); |
| assertEquals(2, next.getParentCount()); |
| assertEquals(merge, next.getParent(0)); |
| assertEquals(sourceCommit, next.getParent(1)); |
| // since both parents are known do no further checks here |
| } else { |
| if (expectedPullMode == TestPullMode.REBASE_PREASERVE) { |
| next = rw.next(); |
| assertEquals(2, next.getParentCount()); |
| } |
| next = rw.next(); |
| assertEquals(t2.getShortMessage(), next.getShortMessage()); |
| next = rw.next(); |
| assertEquals(t1.getShortMessage(), next.getShortMessage()); |
| next = rw.next(); |
| assertEquals(sourceCommit, next); |
| next = rw.next(); |
| assertEquals("Initial commit for source", |
| next.getShortMessage()); |
| next = rw.next(); |
| assertNull(next); |
| } |
| } |
| } |
| |
| @Override |
| @Before |
| public void setUp() throws Exception { |
| super.setUp(); |
| dbTarget = createWorkRepository(); |
| source = new Git(db); |
| target = new Git(dbTarget); |
| |
| // put some file in the source repo |
| sourceFile = new File(db.getWorkTree(), "SomeFile.txt"); |
| writeToFile(sourceFile, "Hello world"); |
| // and commit it |
| source.add().addFilepattern("SomeFile.txt").call(); |
| source.commit().setMessage("Initial commit for source").call(); |
| |
| // configure the target repo to connect to the source via "origin" |
| StoredConfig targetConfig = dbTarget.getConfig(); |
| targetConfig.setString("branch", "master", "remote", "origin"); |
| targetConfig |
| .setString("branch", "master", "merge", "refs/heads/master"); |
| RemoteConfig config = new RemoteConfig(targetConfig, "origin"); |
| |
| config |
| .addURI(new URIish(source.getRepository().getWorkTree() |
| .getAbsolutePath())); |
| config.addFetchRefSpec(new RefSpec( |
| "+refs/heads/*:refs/remotes/origin/*")); |
| config.update(targetConfig); |
| targetConfig.save(); |
| |
| targetFile = new File(dbTarget.getWorkTree(), "SomeFile.txt"); |
| // make sure we have the same content |
| target.pull().call(); |
| assertFileContentsEqual(targetFile, "Hello world"); |
| } |
| |
| private static void writeToFile(File actFile, String string) |
| throws IOException { |
| FileOutputStream fos = null; |
| try { |
| fos = new FileOutputStream(actFile); |
| fos.write(string.getBytes("UTF-8")); |
| fos.close(); |
| } finally { |
| if (fos != null) |
| fos.close(); |
| } |
| } |
| |
| private static void assertFileContentsEqual(File actFile, String string) |
| throws IOException { |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| FileInputStream fis = null; |
| byte[] buffer = new byte[100]; |
| try { |
| fis = new FileInputStream(actFile); |
| int read = fis.read(buffer); |
| while (read > 0) { |
| bos.write(buffer, 0, read); |
| read = fis.read(buffer); |
| } |
| String content = new String(bos.toByteArray(), "UTF-8"); |
| assertEquals(string, content); |
| } finally { |
| if (fis != null) |
| fis.close(); |
| } |
| } |
| } |