Package com.google.devtools.moe.client.codebase

Source Code of com.google.devtools.moe.client.codebase.CodebaseMergerTest

// Copyright 2011 The MOE Authors All Rights Reserved.

package com.google.devtools.moe.client.codebase;

import static org.easymock.EasyMock.expect;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.moe.client.AppContext;
import com.google.devtools.moe.client.CommandRunner;
import com.google.devtools.moe.client.FileSystem;
import com.google.devtools.moe.client.Ui;
import com.google.devtools.moe.client.testing.AppContextForTesting;

import junit.framework.TestCase;

import org.easymock.EasyMock;
import org.easymock.IMocksControl;

import java.io.File;
import java.util.List;

/**
* Unit tests for the CodebaseMerger class.
*
* Here is a diagram illustrating a merge situation. The test cases below will refer to this
* diagram when explaining what type of case they are testing.
*
*                                                   _____
*                                                  |     |
*                                                  |  7  | (mod)
*                                                  |_____|
*                                                     |
*                                                     |
*                                                     |
*                                                     |
*                        ____                       __|__
*                       |    |                     |     |
*                (dest) |1006|=====================|  6  | (orig)
*                       |____|                     |_____|
*
*                    internalrepo                 publicrepo
*
*
*/
public class CodebaseMergerTest extends TestCase {

  private IMocksControl control;
  private FileSystem fileSystem;
  private CommandRunner cmd;
  private Codebase orig, dest, mod;

  @Override
  public void setUp() {
    AppContextForTesting.initForTest();
    control = EasyMock.createControl();
    fileSystem = control.createMock(FileSystem.class);
    cmd = control.createMock(CommandRunner.class);
    AppContext.RUN.cmd = cmd;
    AppContext.RUN.fileSystem = fileSystem;

    orig = control.createMock(Codebase.class);
    dest = control.createMock(Codebase.class);
    mod = control.createMock(Codebase.class);
  }

  /**
   * Test generateMergedFile(...) in the case where the file exists in orig and mod but not dest.
   * In this case, the file is unchanged in orig and mod, so the file is not placed in the
   * merged codebase.
   */
  public void testGenerateMergedFileDestDelete() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true).times(2);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(false);
    destFile = new File("/dev/null");

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true).times(2);

    expect(fileSystem.isExecutable(origFile)).andReturn(false);
    expect(fileSystem.isExecutable(modFile)).andReturn(false);

    expect(cmd.runCommand("diff", ImmutableList.of("-N", origFile.getAbsolutePath(),
      modFile.getAbsolutePath()), "")).andReturn(null);

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();
  }

  /**
   * Test generateMergedFile(...) in the case where the file exists in orig and dest but not mod.
   * The orig version and the dest version of the file differ. This should be treated as a conflict
   * for the user to resolve.
   */
  public void testGenerateMergedFileModDeleteConflict() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(false);

    // Expect no copy operations or anything. Deletion of the original file (i.e. non-existence of
    // modFile) should result in not copying destFile to the merged codebase, i.e. deleting it.

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertTrue(merger.getFailedToMergeFiles().isEmpty());
    assertTrue(merger.getMergedFiles().isEmpty());
  }

  /**
   * Test generateMergedFile(...) in the case when the file exists only in mod.
   * In this case, the file should simply be copied to the merged codebase.
   */
  public void testGenerateMergedFileAddFile() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(false);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(false);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(modFile, mergedFile);

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertTrue(merger.getMergedFiles().isEmpty());
    assertTrue(merger.getFailedToMergeFiles().isEmpty());
  }

  /**
   * Test generateMergedFile(...) in the most ideal case where the file exists in all three
   * codebases and there is no conflict.
   */
  public void testGenerateMergedFileClean() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    List<String> mergeArgs = ImmutableList.of(mergedFile.getAbsolutePath(),
        origFile.getAbsolutePath(), modFile.getAbsolutePath());

    expect(cmd.runCommand("merge", mergeArgs,
        mergedCodebaseLocation.getAbsolutePath())).andReturn("");

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertEquals(0, merger.getFailedToMergeFiles().size());
    assertTrue(merger.getMergedFiles().contains(mergedFile.getAbsolutePath().toString()));
  }

  /**
   * Test generateMergedFile(...) in the case where the file exists in all three codebases but
   * there is a conflict when merging.
   */
  public void testGenerateMergedFileConflict() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    List<String> mergeArgs = ImmutableList.of(mergedFile.getAbsolutePath(),
        origFile.getAbsolutePath(), modFile.getAbsolutePath());

    expect(cmd.runCommand("merge", mergeArgs,
        mergedCodebaseLocation.getAbsolutePath())).andThrow(
        new CommandRunner.CommandException("merge", mergeArgs, "", "", 1));

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertEquals(0, merger.getMergedFiles().size());
    assert(merger.getFailedToMergeFiles().contains(mergedFile.getAbsolutePath().toString()));
  }

  /**
   * Test generateMergedFile(...) in the case where the file only exists in dest. The file should
   * appear in the merged codebase unchanged.
   */
  public void testGenerateMergedFileDestOnly() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(false);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(false);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertTrue(merger.getFailedToMergeFiles().isEmpty());
    assertTrue(merger.getMergedFiles().isEmpty());
  }

  /**
   * Test generateMergedFile(...) in the case where the file exists in mod and dest but not orig.
   * In this case, the mod version and dest version are the same so there should be no conflict.
   * The file should remain unchanged in the merged codebase.
   */
  public void testGenerateMergedFileNoOrig() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(false);
    origFile = new File("/dev/null");

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    List<String> mergeArgs = ImmutableList.of(mergedFile.getAbsolutePath(),
        origFile.getAbsolutePath(), modFile.getAbsolutePath());

    expect(cmd.runCommand("merge", mergeArgs,
        mergedCodebaseLocation.getAbsolutePath())).andReturn("");

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertEquals(0, merger.getFailedToMergeFiles().size());
    assertTrue(merger.getMergedFiles().contains(mergedFile.getAbsolutePath().toString()));
  }

  /**
   * Test generateMergedFile(...) in the case where the file exists in mod and dest but not orig.
   * In this case, the mod version and dest version are different so a conflict should occur when
   * merging so that the user can resolved the discrepancy.
   */
  public void testGenerateMergedFileNoOrigConflict() throws Exception {
    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(false);
    origFile = new File("/dev/null");

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    List<String> mergeArgs = ImmutableList.of(mergedFile.getAbsolutePath(),
        origFile.getAbsolutePath(), modFile.getAbsolutePath());

    expect(cmd.runCommand("merge", mergeArgs,
        mergedCodebaseLocation.getAbsolutePath())).andThrow(
        new CommandRunner.CommandException("merge", mergeArgs, "", "", 1));

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.generateMergedFile("foo");

    control.verify();

    assertEquals(0, merger.getMergedFiles().size());
    assertTrue(merger.getFailedToMergeFiles().contains(mergedFile.getAbsolutePath().toString()));
  }

  /**
   * Test for merge()
   */
  public void testMerge() throws Exception {
    Ui ui = control.createMock(Ui.class);
    AppContext.RUN.ui = ui;

    File mergedCodebaseLocation = new File("merged_codebase_7");
    expect(fileSystem.getTemporaryDirectory("merged_codebase_")).andReturn(mergedCodebaseLocation);

    expect(dest.getRelativeFilenames()).andReturn(ImmutableSet.of("foo"));
    expect(mod.getRelativeFilenames()).andReturn(ImmutableSet.of("foo", "bar"));

    // generateMergedFile(...) on foo
    File origFile = new File("orig/foo");
    expect(orig.getFile("foo")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true);

    File destFile = new File("dest/foo");
    expect(dest.getFile("foo")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    File modFile = new File("mod/foo");
    expect(mod.getFile("foo")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(true);

    File mergedFile = new File("merged_codebase_7/foo");
    fileSystem.makeDirsForFile(mergedFile);
    fileSystem.copyFile(destFile, mergedFile);

    List<String> mergeArgs = ImmutableList.of(mergedFile.getAbsolutePath(),
        origFile.getAbsolutePath(), modFile.getAbsolutePath());

    expect(cmd.runCommand("merge", mergeArgs,
        mergedCodebaseLocation.getAbsolutePath())).andReturn("");


    // generateMergedFile(...) on bar
    origFile = new File("orig/bar");
    expect(orig.getFile("bar")).andReturn(origFile);
    expect(fileSystem.exists(origFile)).andReturn(true);

    destFile = new File("dest/bar");
    expect(dest.getFile("bar")).andReturn(destFile);
    expect(fileSystem.exists(destFile)).andReturn(true);

    modFile = new File("mod/bar");
    expect(mod.getFile("bar")).andReturn(modFile);
    expect(fileSystem.exists(modFile)).andReturn(false);

    // No merging of bar, just follow deletion of origFile by not copying destFile to merged
    // codebase.


    // Expect in call to report()
    ui.info("Merged codebase generated at: " + mergedCodebaseLocation.getAbsolutePath());
    ui.info(String.format(
        "%d files merged successfully%n" +
        "%d files have merge conflicts. Edit the following files to resolve conflicts:%n%s",
        1, 0, ImmutableSet.of()));

    control.replay();

    CodebaseMerger merger = new CodebaseMerger(orig, mod, dest);
    merger.merge();

    control.verify();

    assertTrue(merger.getMergedFiles().contains(mergedFile.getAbsolutePath().toString()));
    assertTrue(merger.getFailedToMergeFiles().isEmpty());
  }
}
TOP

Related Classes of com.google.devtools.moe.client.codebase.CodebaseMergerTest

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.