/*******************************************************************************
* Copyright (c) 2010 Red Hat Inc. 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.linuxtools.changelog.core.formatters.tests;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Calendar;
import java.util.GregorianCalendar;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Path;
import org.eclipse.linuxtools.changelog.tests.fixtures.ChangeLogTestProject;
import org.eclipse.linuxtools.changelog.tests.helpers.EditorHelper;
import org.eclipse.linuxtools.internal.changelog.core.formatters.GNUFormat;
import static org.eclipse.linuxtools.changelog.tests.helpers.EditorHelper.closeEditor;
import static org.eclipse.linuxtools.changelog.tests.helpers.EditorHelper.openEditor;
import static org.eclipse.linuxtools.changelog.tests.helpers.EditorHelper.getContent;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.eclipse.jface.text.IDocument;
public class GNUFormatTest {
// The instance under test
private GNUFormat gnuFormatter;
// A faked project
private ChangeLogTestProject project;
// The IEditorPart corresponding to the ChangeLog file
private IEditorPart changelogEditorPart = null;
// Tokens for the GNU format
private static final String TWO_SPACES = " ";
private static final String SPACE = " ";
private static final String TAB = "\t";
private static final String LEFT_EMAIL_BRACKET = "<";
private static final String RIGHT_EMAIL_BRACKET = ">";
private static final String FILE_ENTRY_START_MARKER = "* ";
private static final String FILE_ENTRY_END_MARKER = ": ";
private static final String FUNCTION_START_MARKER = "(";
private static final String FUNCTION_END_MARKER = ")";
private static final String NEW_LINE = "\n";
@Before
public void setUp() throws Exception {
gnuFormatter = new GNUFormat();
project = new ChangeLogTestProject("GNUFormatterTest");
}
@After
public void tearDown() throws Exception {
// Most tests in this class use changelogEditorPart. In order to avoid
// spill-over from previous runs, truncate content (i.e. manually set
// content to the empty string).
if (changelogEditorPart != null) { // testFormatDateLine does not use it
AbstractTextEditor castEditor = (AbstractTextEditor) changelogEditorPart;
IDocumentProvider iDocProvider = castEditor.getDocumentProvider();
IDocument changelogContentDoc = iDocProvider.getDocument(castEditor.getEditorInput());
changelogContentDoc.set(""); // empty content
changelogEditorPart.doSave(null);
// Also close open editor in order for default content to work.
// I.e. avoid spill over from previous test runs
closeEditor(changelogEditorPart);
}
project.getTestProject().delete(true, true, null); // dispose
}
/**
* GNU ChangeLog style date lines are of the following format
*
* YYYY-MM-DD Author Name <author.email@domain.com>
*/
@Test
public void testFormatDateLine() {
// Today's date in ISO format
Calendar c = new GregorianCalendar();
String isoDate = String.format("%1$tY-%1$tm-%1$td", c);
String authorName = "William Shakespeare";
String authorEmail = "william.shakespeare@medieval.com";
final String expectedDateFormatting = isoDate +
TWO_SPACES +
authorName +
TWO_SPACES +
LEFT_EMAIL_BRACKET +
authorEmail +
RIGHT_EMAIL_BRACKET +
"\n\n";
assertEquals(expectedDateFormatting,
gnuFormatter.formatDateLine(authorName, authorEmail));
}
/**
* Assume the following initial content of ChangeLog:
*
* <code>
* 2010-11-26 Severin Gehwolf <sgehwolf@redhat.com>
*
* * src/org/eclipse/linuxtools/changelog/parsers/java/HelloWorld.java (test): New Method\n\t\n
* </code>
*
* Note the trailing new-line, tab, new-line combination. If another change in the same file but
* in a different method (or function) is merged, the empty line containing a tab only should be
* removed.
*
*/
@Test
public void twoChangesInSameFileAreProperlyMergedWhenThereIsATrailingTabNewLine() throws Exception {
// set date/author line
String authorName = "Test Foo";
String email = "test@example.com";
final String dateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file (relative to project root)
String changelogPath = "/" + project.getTestProject().getName() + "/path/to";
final String changelogFilePath = changelogPath + "/ChangeLog";
// entry file path (need overlap with changelogPath)
String fileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
final String entryFilePath = changelogPath + "/" + fileEntryRelPath;
final String firstMethodName = "main";
final String firstChangeComment = "Fix args parsing.";
// Setup proper pre-existing content
String content = dateLine + NEW_LINE + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
firstMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
firstChangeComment + NEW_LINE +
TAB + NEW_LINE; // produces an empty line which should be removed
assertNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// add a ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(
content.getBytes());
IFile changelogFile = project.addFileToProject( "/path/to", "ChangeLog",
newFileInputStream);
assertNotNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// Open a document and get the IEditorPart
changelogEditorPart = EditorHelper.openEditor(changelogFile);
// make sure changelog editor content is right before merging
assertEquals(content, getContent(changelogEditorPart));
final String secondMethodName = "toString";
// Do the merge with the existing content
gnuFormatter.mergeChangelog(dateLine, secondMethodName,
"" /* no default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
final String actualMergeResult = getContent(changelogEditorPart);
// Expect trailing tab+newline combination to not show up in merge
final String expectedResult = dateLine + NEW_LINE + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
firstMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
firstChangeComment + NEW_LINE + TAB + FUNCTION_START_MARKER +
secondMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
NEW_LINE + NEW_LINE;
assertEquals(expectedResult, actualMergeResult);
}
/**
* Test merge of two separate changes to an existing file within the same changelog entry.
* I.e. test for
*
* * path/to/file (method1): First change.
* (method2): Another change in same file but different function/method.
*/
@Test
public void twoChangesInSameFileAreProperlyMerged() throws Exception {
// set date/author line
String authorName = "Test Author";
String email = "test@example.com";
final String dateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file (relative to project root)
String changelogPath = "/" + project.getTestProject().getName() + "/path/to";
final String changelogFilePath = changelogPath + "/ChangeLog";
// entry file path (need overlap with changelogPath)
String fileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
final String entryFilePath = changelogPath + "/" + fileEntryRelPath;
final String firstMethodName = "main";
final String firstChangeComment = "Fix args parsing.";
// Setup proper pre-existing content
String content = dateLine + NEW_LINE + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
firstMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
firstChangeComment + NEW_LINE;
assertNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// add a ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(
content.getBytes());
IFile changelogFile = project.addFileToProject( "/path/to", "ChangeLog",
newFileInputStream);
assertNotNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// Open a document and get the IEditorPart
changelogEditorPart = openEditor(changelogFile);
// make sure changelog editor content is right before merging
assertEquals(content, getContent(changelogEditorPart));
final String secondMethodName = "toString";
// Do the merge with the existing content
gnuFormatter.mergeChangelog(dateLine, secondMethodName,
"" /* no default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
final String actualMergeResult = getContent(changelogEditorPart);
final String expectedResult = dateLine + NEW_LINE + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
firstMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
firstChangeComment + NEW_LINE + TAB + FUNCTION_START_MARKER +
secondMethodName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
NEW_LINE;
assertEquals(expectedResult, actualMergeResult);
}
/**
* If two different authors make modifications on the same day, both modifications must
* show up as separate changelog entries for that day.
*/
@Test
public void newChangeLogEntryForNewAuthorOnSameDay() throws Exception {
// first author
String authorName = "Test Author";
String email = "test@example.com";
final String firstDateLine = gnuFormatter.formatDateLine(authorName, email);
// second author
authorName = "William Shakespeare";
email = "will@pear.com";
final String secondDateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file
String changelogPath = "/" + project.getTestProject().getName() + "/path/to";
final String changelogFilePath = changelogPath + "/ChangeLog";
// No existing content in ChangeLog file
String content = "";
assertNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// add a ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(
content.getBytes());
IFile changelogFile = project.addFileToProject( changelogPath, "ChangeLog",
newFileInputStream);
// Open a document and get the IEditorPart
changelogEditorPart = openEditor(changelogFile);
// entry file path (needs overlap with changelogPath)
String fileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
final String entryFilePath = changelogPath + "/" + fileEntryRelPath;
final String guessedFunctionName = "bazinga";
// merge first changelog entry with empty content
gnuFormatter.mergeChangelog(firstDateLine, guessedFunctionName,
"" /* empty default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
String actualMergeResult = getContent(changelogEditorPart);
String expectedResult = firstDateLine + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
guessedFunctionName + FUNCTION_END_MARKER +
FILE_ENTRY_END_MARKER;
assertEquals(expectedResult, actualMergeResult);
// add second changelog entry on same date but by different author
gnuFormatter.mergeChangelog(secondDateLine, guessedFunctionName,
"" /* empty default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
actualMergeResult = getContent(changelogEditorPart);
expectedResult = secondDateLine + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
guessedFunctionName + FUNCTION_END_MARKER +
FILE_ENTRY_END_MARKER + NEW_LINE + NEW_LINE +
expectedResult;
assertEquals(expectedResult, actualMergeResult);
}
/**
* Basic format check.
*/
@Test
public void mergeChangeLogHasProperFormat() throws Exception {
// set date/author line
String authorName = "Test Author";
String email = "test@example.com";
final String dateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file (relative to project root)
String changelogPath = "/" + project.getTestProject().getName() + "/path/to";
final String changelogFilePath = changelogPath + "/ChangeLog";
// Content to merge into
String content = "";
assertNull(project.getTestProject().findMember(new Path("/path/to/ChangeLog")));
// add a ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(
content.getBytes());
IFile changelogFile = project.addFileToProject( "/path/to", "ChangeLog",
newFileInputStream);
// Open a document and get the IEditorPart
changelogEditorPart = openEditor(changelogFile);
// make sure changelog editor content is empty
assertEquals(content, getContent(changelogEditorPart));
// entry file path (need overlap with changelogPath)
String fileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
final String entryFilePath = changelogPath + "/" + fileEntryRelPath;
// Will show up surrounded by "(" and ")" in ChangeLog
final String guessedFunctionName = "bazinga";
// This always returns an empty String (should probably be changed...)
// merge result will be written to editorContent
gnuFormatter.mergeChangelog(dateLine, guessedFunctionName,
"" /* empty default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
final String actualMergeResult = getContent(changelogEditorPart);
final String expectedResult = dateLine + TAB + FILE_ENTRY_START_MARKER +
fileEntryRelPath + SPACE + FUNCTION_START_MARKER +
guessedFunctionName + FUNCTION_END_MARKER +
FILE_ENTRY_END_MARKER;
assertEquals(expectedResult, actualMergeResult);
}
/**
* Here's the scenario for this test. It may be that there are only files removed and
* new files added for a commit. This should yield to changelog entries for the following
* form:
*
*<code>
* 2010-11-26 Some Author <some.author@example.com>
*
* * path/to/deleted/file.c: Removed.
* * path/to/new/file.c: New file.
*</code>
*
* Prior to the fix for Eclipse Bz #331244 the result was:
*
*<code>
* 2010-11-26 Some Author <some.author@example.com>
*
* * path/to/deleted/file.c: Removed.
* * path/to/new/file.c:
*</code>
*
* This regression test should catch this.
*/
@Test
public void canHaveEntriesWithDefaultTextOnly() throws Exception {
// set date/author line
String authorName = "Test Author";
String email = "test@example.com";
final String dateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file (relative to project root)
String changelogPath = "/" + project.getTestProject().getName() + "/path/example";
final String changelogFilePath = changelogPath + "/ChangeLog";
// Content to merge into
String content = "";
// add a ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(
content.getBytes());
IFile changelogFile = project.addFileToProject( "/path/example", "ChangeLog",
newFileInputStream);
// Open a document and get the IEditorPart
changelogEditorPart = openEditor(changelogFile);
// make sure changelog editor content is empty
assertEquals(content, getContent(changelogEditorPart));
// entry file path (need overlap with changelogPath)
final String firstFileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
String entryFilePath = changelogPath + "/" + firstFileEntryRelPath;
final String firstDefaultContent = "New file.";
// Note: This always returns an empty String (should probably be changed...)
// merge result will be written to editorContent.
//
// Create a line with default text "New file"
gnuFormatter.mergeChangelog(dateLine, "" /* no guessed function name */,
firstDefaultContent, changelogEditorPart,
changelogFilePath, entryFilePath);
final String secondFileEntryRelPath = "eclipse/example/test/OldCoffeeMaker.java";
entryFilePath = changelogPath + "/" + secondFileEntryRelPath;
final String secondDefaultContent = "Removed.";
// Add entry for removed file
gnuFormatter.mergeChangelog(dateLine, "" /* no guessed function name */,
secondDefaultContent, changelogEditorPart,
changelogFilePath, entryFilePath);
final String actualMergeResult = getContent(changelogEditorPart);
// Note: Removed files occur in the list first, new file items come after that.
final String expectedResult = dateLine + TAB + FILE_ENTRY_START_MARKER +
secondFileEntryRelPath+ FILE_ENTRY_END_MARKER +
secondDefaultContent + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
firstFileEntryRelPath + FILE_ENTRY_END_MARKER +
firstDefaultContent;
assertEquals(expectedResult, actualMergeResult);
}
/**
* Test for a changelog entry with items for removed files, new files and modified
* existing files. This test differs from the previous in that the ChangeLog is
* empty to start with. This verifies Bz #366854 fix.
*
* @throws Exception
*/
@Test
public void canHaveEntriesWithDefaultTextAndSomeModificationToAnExistingFile2() throws Exception {
// set date/author line
String authorName = "Test Author";
String email = "test@example.com";
final String dateLine = gnuFormatter.formatDateLine(authorName, email);
// full absolute path to ChangeLog file (relative to project root)
String changelogPath = "/" + project.getTestProject().getName() + "/test/example";
final String changelogFilePath = changelogPath + "/ChangeLog";
// add a new empty ChangeLog file to our test project
InputStream newFileInputStream = new ByteArrayInputStream(new byte[0]);
IFile changelogFile = project.addFileToProject( "/test/example", "ChangeLog",
newFileInputStream);
// Open a document and get the IEditorPart
changelogEditorPart = openEditor(changelogFile);
// entry file path (need overlap with changelogPath)
final String firstFileEntryRelPath = "eclipse/example/test/NewCoffeeMaker.java";
String entryFilePath = changelogPath + "/" + firstFileEntryRelPath;
final String firstDefaultContent = "New file.";
// Note: This always returns an empty String (should probably be changed...)
// merge result will be written to editorContent.
//
// Create an item with default text "New file"
gnuFormatter.mergeChangelog(dateLine, "" /* no guessed function name */,
firstDefaultContent, changelogEditorPart,
changelogFilePath, entryFilePath);
final String secondFileEntryRelPath = "eclipse/example/test/OldCoffeeMaker.java";
entryFilePath = changelogPath + "/" + secondFileEntryRelPath;
final String secondDefaultContent = "Removed.";
// Add entry for removed file
gnuFormatter.mergeChangelog(dateLine, "" /* no guessed function name */,
secondDefaultContent, changelogEditorPart,
changelogFilePath, entryFilePath);
final String thirdFileEntryRelPath = "eclipse/example/test/ModifiedFile.java";
entryFilePath = changelogPath + "/" + thirdFileEntryRelPath;
final String guessedFunctionName = "main";
// Create a bullet point describing a change in some existing file
gnuFormatter.mergeChangelog(dateLine, guessedFunctionName,
"" /* no default content */, changelogEditorPart,
changelogFilePath, entryFilePath);
final String actualMergeResult = getContent(changelogEditorPart);
// Note that changes to existing files appear first in the changelog entries.
// Second are removed files and new files are last.
final String expectedResult = dateLine + TAB + FILE_ENTRY_START_MARKER +
thirdFileEntryRelPath + SPACE + FUNCTION_START_MARKER +
guessedFunctionName + FUNCTION_END_MARKER + FILE_ENTRY_END_MARKER +
NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
secondFileEntryRelPath+ FILE_ENTRY_END_MARKER +
secondDefaultContent + NEW_LINE + TAB + FILE_ENTRY_START_MARKER +
firstFileEntryRelPath + FILE_ENTRY_END_MARKER +
firstDefaultContent;
assertEquals(expectedResult, actualMergeResult);
}
}