Change-Id: I2c24d1201d4c36963a708b178e780c1828707269tags/v1.4.0
@@ -1,7 +1,10 @@ | |||
[bugtraq "issues"] | |||
url = http://code.google.com/p/gitblit/issues/detail?id=%BUGID% | |||
logRegex = "[Ii]ssue[-#:\\s]{1}\\d+" | |||
logRegex1 = "\\d+" | |||
[bugtraq "[pullrequests"] | |||
loglinkregex = "[Ii]ssue[-#:\\s]{1}\\d+" | |||
logregex = "\\d+" | |||
loglinktext = issue-%BUGID% | |||
[bugtraq "pullrequests"] | |||
url = "https://github.com/gitblit/gitblit/pull/%BUGID%" | |||
logRegex = "(?:pull request|pull|pr)\\s*[-#]?([0-9]+)" | |||
loglinkregex = "(?:pull request|pull|pr)\\s*[-#]?[0-9]+" | |||
logregex = "\\d+" | |||
loglinktext = "pull request #%BUGID%" |
@@ -29,80 +29,104 @@ | |||
*/ | |||
package com.syntevo.bugtraq; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Set; | |||
import org.eclipse.jgit.errors.ConfigInvalidException; | |||
import org.eclipse.jgit.lib.Config; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.FileMode; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.ObjectLoader; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.revwalk.RevCommit; | |||
import org.eclipse.jgit.revwalk.RevTree; | |||
import org.eclipse.jgit.revwalk.RevWalk; | |||
import org.eclipse.jgit.storage.file.FileBasedConfig; | |||
import org.eclipse.jgit.treewalk.TreeWalk; | |||
import org.eclipse.jgit.treewalk.filter.PathFilterGroup; | |||
import org.jetbrains.annotations.NotNull; | |||
import org.jetbrains.annotations.Nullable; | |||
import java.io.*; | |||
import java.util.*; | |||
import org.eclipse.jgit.errors.*; | |||
import org.eclipse.jgit.lib.*; | |||
import org.eclipse.jgit.revwalk.*; | |||
import org.eclipse.jgit.storage.file.*; | |||
import org.eclipse.jgit.treewalk.*; | |||
import org.eclipse.jgit.treewalk.filter.*; | |||
import org.jetbrains.annotations.*; | |||
public final class BugtraqConfig { | |||
// Constants ============================================================== | |||
private static final String DOT_GIT_BUGTRAQ = ".gitbugtraq"; | |||
private static final String DOT_TGITCONFIG = ".tgitconfig"; | |||
private static final String BUGTRAQ = "bugtraq"; | |||
private static final String URL = "url"; | |||
private static final String ENABLED = "enabled"; | |||
private static final String LOG_REGEX = "logRegex"; | |||
private static final String LOG_REGEX = "logregex"; | |||
private static final String LOG_FILTERREGEX = "logfilterregex"; | |||
private static final String LOG_LINKREGEX = "loglinkregex"; | |||
private static final String LOG_LINKTEXT = "loglinktext"; | |||
// Static ================================================================= | |||
@Nullable | |||
public static BugtraqConfig read(@NotNull Repository repository) throws IOException, ConfigInvalidException { | |||
final Config baseConfig = getBaseConfig(repository); | |||
Config baseConfig = getBaseConfig(repository, DOT_GIT_BUGTRAQ); | |||
if (baseConfig == null) { | |||
baseConfig = getBaseConfig(repository, DOT_TGITCONFIG); | |||
} | |||
final Set<String> allNames = new HashSet<String>(); | |||
final Config config = repository.getConfig(); | |||
allNames.addAll(config.getSubsections(BUGTRAQ)); | |||
if (baseConfig != null) { | |||
allNames.addAll(baseConfig.getSubsections(BUGTRAQ)); | |||
if (getString(null, URL, config, baseConfig) != null) { | |||
allNames.add(null); | |||
} | |||
else { | |||
allNames.addAll(config.getSubsections(BUGTRAQ)); | |||
if (baseConfig != null) { | |||
allNames.addAll(baseConfig.getSubsections(BUGTRAQ)); | |||
} | |||
} | |||
final List<BugtraqEntry> entries = new ArrayList<BugtraqEntry>(); | |||
for (String name : allNames) { | |||
final String url = getString(name, URL, config, baseConfig); | |||
if (url == null) { | |||
continue; | |||
} | |||
final String enabled = getString(name, ENABLED, config, baseConfig); | |||
if (enabled != null && !"true".equals(enabled)) { | |||
continue; | |||
} | |||
final String logIdRegex = getString(name, LOG_REGEX, config, baseConfig); | |||
if (url == null || logIdRegex == null) { | |||
String idRegex = getString(name, LOG_REGEX, config, baseConfig); | |||
if (idRegex == null) { | |||
return null; | |||
} | |||
final List<String> logIdRegexs = new ArrayList<String>(); | |||
logIdRegexs.add(logIdRegex); | |||
for (int index = 1; index < Integer.MAX_VALUE; index++) { | |||
final String logIdRegexN = getString(name, LOG_REGEX + index, config, baseConfig); | |||
if (logIdRegexN == null) { | |||
break; | |||
String filterRegex = getString(name, LOG_FILTERREGEX, config, baseConfig); | |||
final String linkRegex = getString(name, LOG_LINKREGEX, config, baseConfig); | |||
if (filterRegex == null && linkRegex == null) { | |||
final String[] split = idRegex.split("\n", Integer.MAX_VALUE); | |||
if (split.length == 2) { | |||
// Compatibility with TortoiseGit | |||
filterRegex = split[0]; | |||
idRegex = split[1]; | |||
} | |||
else { | |||
// Backwards compatibility with specification version < 0.3 | |||
final List<String> logIdRegexs = new ArrayList<String>(); | |||
for (int index = 1; index < Integer.MAX_VALUE; index++) { | |||
final String logIdRegexN = getString(name, LOG_REGEX + index, config, baseConfig); | |||
if (logIdRegexN == null) { | |||
break; | |||
} | |||
logIdRegexs.add(logIdRegexN); | |||
} | |||
logIdRegexs.add(logIdRegexN); | |||
if (logIdRegexs.size() > 1) { | |||
throw new ConfigInvalidException("More than three " + LOG_REGEX + " entries found. This is not supported anymore since bugtraq version 0.3, use " + LOG_FILTERREGEX + " and " + LOG_LINKREGEX + " instead."); | |||
} | |||
else if (logIdRegexs.size() == 1) { | |||
filterRegex = idRegex; | |||
idRegex = logIdRegexs.get(0); | |||
} | |||
} | |||
} | |||
entries.add(new BugtraqEntry(url, logIdRegexs)); | |||
final String linkText = getString(name, LOG_LINKTEXT, config, baseConfig); | |||
entries.add(new BugtraqEntry(url, idRegex, linkRegex, filterRegex, linkText)); | |||
} | |||
if (entries.isEmpty()) { | |||
@@ -133,14 +157,14 @@ public final class BugtraqConfig { | |||
// Utils ================================================================== | |||
@Nullable | |||
private static Config getBaseConfig(Repository repository) throws IOException, ConfigInvalidException { | |||
private static Config getBaseConfig(@NotNull Repository repository, @NotNull String configFileName) throws IOException, ConfigInvalidException { | |||
final Config baseConfig; | |||
if (repository.isBare()) { | |||
// read bugtraq config directly from the repository | |||
String content = null; | |||
RevWalk rw = new RevWalk(repository); | |||
TreeWalk tw = new TreeWalk(repository); | |||
tw.setFilter(PathFilterGroup.createFromStrings(DOT_GIT_BUGTRAQ)); | |||
tw.setFilter(PathFilterGroup.createFromStrings(configFileName)); | |||
try { | |||
ObjectId headId = repository.getRef(Constants.HEAD).getTarget().getObjectId(); | |||
RevCommit commit = rw.parseCommit(headId); | |||
@@ -155,7 +179,8 @@ public final class BugtraqConfig { | |||
break; | |||
} | |||
} | |||
} finally { | |||
} | |||
finally { | |||
rw.dispose(); | |||
tw.release(); | |||
} | |||
@@ -173,7 +198,7 @@ public final class BugtraqConfig { | |||
} | |||
else { | |||
// read bugtraq config from work tree | |||
final File baseFile = new File(repository.getWorkTree(), DOT_GIT_BUGTRAQ); | |||
final File baseFile = new File(repository.getWorkTree(), configFileName); | |||
if (baseFile.isFile()) { | |||
FileBasedConfig fileConfig = new FileBasedConfig(baseFile, repository.getFS()); | |||
fileConfig.load(); | |||
@@ -187,7 +212,7 @@ public final class BugtraqConfig { | |||
} | |||
@Nullable | |||
private static String getString(@NotNull String subsection, @NotNull String key, @NotNull Config config, @Nullable Config baseConfig) { | |||
private static String getString(@Nullable String subsection, @NotNull String key, @NotNull Config config, @Nullable Config baseConfig) { | |||
final String value = config.getString(BUGTRAQ, subsection, key); | |||
if (value != null) { | |||
return trimMaybeNull(value); | |||
@@ -197,8 +222,8 @@ public final class BugtraqConfig { | |||
return trimMaybeNull(baseConfig.getString(BUGTRAQ, subsection, key)); | |||
} | |||
return value; | |||
} | |||
return value; | |||
} | |||
@Nullable | |||
private static String trimMaybeNull(@Nullable String string) { |
@@ -29,8 +29,6 @@ | |||
*/ | |||
package com.syntevo.bugtraq; | |||
import java.util.*; | |||
import org.jetbrains.annotations.*; | |||
final class BugtraqEntry { | |||
@@ -38,13 +36,15 @@ final class BugtraqEntry { | |||
// Fields ================================================================= | |||
private final String url; | |||
private final String logLinkText; | |||
private final BugtraqParser parser; | |||
// Setup ================================================================== | |||
public BugtraqEntry(@NotNull String url, @NotNull List<String> logIdRegexs) throws BugtraqException { | |||
public BugtraqEntry(@NotNull String url, @NotNull String logIdRegex, @Nullable String logLinkRegex, @Nullable String logFilterRegex, @Nullable String logLinkText) throws BugtraqException { | |||
this.url = url; | |||
this.parser = BugtraqParser.createInstance(logIdRegexs); | |||
this.logLinkText = logLinkText; | |||
this.parser = BugtraqParser.createInstance(logIdRegex, logLinkRegex, logFilterRegex); | |||
} | |||
// Accessing ============================================================== | |||
@@ -54,6 +54,11 @@ final class BugtraqEntry { | |||
return url; | |||
} | |||
@Nullable | |||
public String getLogLinkText() { | |||
return logLinkText; | |||
} | |||
@NotNull | |||
public BugtraqParser getParser() { | |||
return parser; |
@@ -59,10 +59,6 @@ public final class BugtraqFormatter { | |||
for (BugtraqEntry entry : config.getEntries()) { | |||
final List<BugtraqParserIssueId> ids = entry.getParser().parse(message); | |||
if (ids == null) { | |||
continue; | |||
} | |||
for (BugtraqParserIssueId id : ids) { | |||
allIds.add(new IssueId(entry, id)); | |||
} | |||
@@ -76,8 +72,15 @@ public final class BugtraqFormatter { | |||
} | |||
appendText(message.substring(lastIdEnd + 1, id.getFrom()), outputHandler); | |||
final String logLinkText = issueId.entry.getLogLinkText(); | |||
final String linkText; | |||
if (logLinkText != null) { | |||
linkText = logLinkText.replace("%BUGID%", id.getId()); | |||
} | |||
else { | |||
linkText = message.substring(id.getFrom(), id.getTo() + 1); | |||
} | |||
final String linkText = message.substring(id.getFrom(), id.getTo() + 1); | |||
final String target = issueId.entry.getUrl().replace("%BUGID%", id.getId()); | |||
outputHandler.appendLink(linkText, target); | |||
lastIdEnd = id.getTo(); |
@@ -39,9 +39,9 @@ final class BugtraqParser { | |||
// Static ================================================================= | |||
@NotNull | |||
public static BugtraqParser createInstance(@NotNull List<String> regexs) throws BugtraqException { | |||
public static BugtraqParser createInstance(@NotNull String idRegex, @Nullable String linkRegex, @Nullable String filterRegex) throws BugtraqException { | |||
try { | |||
return new BugtraqParser(regexs); | |||
return new BugtraqParser(idRegex, linkRegex, filterRegex); | |||
} | |||
catch (PatternSyntaxException ex) { | |||
throw new BugtraqException(ex); | |||
@@ -50,16 +50,16 @@ final class BugtraqParser { | |||
// Fields ================================================================= | |||
private final List<Pattern> patterns; | |||
private final Pattern idPattern; | |||
private final Pattern linkPattern; | |||
private final Pattern filterPattern; | |||
// Setup ================================================================== | |||
private BugtraqParser(List<String> regexs) { | |||
this.patterns = new ArrayList<Pattern>(); | |||
for (String regex : regexs) { | |||
patterns.add(compilePatternSafe(regex)); | |||
} | |||
private BugtraqParser(@NotNull String idRegex, @Nullable String linkRegex, @Nullable String filterRegex) { | |||
idPattern = compilePatternSafe(idRegex); | |||
linkPattern = linkRegex != null ? compilePatternSafe(linkRegex) : null; | |||
filterPattern = filterRegex != null ? compilePatternSafe(filterRegex) : null; | |||
} | |||
// Accessing ============================================================== | |||
@@ -69,49 +69,45 @@ final class BugtraqParser { | |||
List<Part> parts = new ArrayList<Part>(); | |||
parts.add(new Part(message, 0, message.length() - 1)); | |||
boolean firstMatch = false; | |||
for (Pattern pattern : patterns) { | |||
final List<Part> newParts = new ArrayList<Part>(); | |||
for (Part part : parts) { | |||
final Matcher matcher = pattern.matcher(part.text); | |||
while (matcher.find()) { | |||
firstMatch = true; | |||
if (matcher.groupCount() == 0) { | |||
addNewPart(part, matcher, 0, newParts); | |||
} | |||
else { | |||
addNewPart(part, matcher, 1, newParts); | |||
} | |||
} | |||
} | |||
parts = newParts; | |||
if (parts.isEmpty()) { | |||
parts = null; | |||
break; | |||
} | |||
if (filterPattern != null) { | |||
parts = collectParts(parts, filterPattern); | |||
} | |||
if (!firstMatch) { | |||
return null; | |||
} | |||
if (parts == null) { | |||
parts = new ArrayList<Part>(); | |||
if (linkPattern != null) { | |||
parts = collectParts(parts, linkPattern); | |||
} | |||
final List<BugtraqParserIssueId> ids = new ArrayList<BugtraqParserIssueId>(); | |||
for (Part part : parts) { | |||
final BugtraqParserIssueId id = new BugtraqParserIssueId(part.from, part.to, part.text); | |||
if (ids.size() > 0) { | |||
final BugtraqParserIssueId lastId = ids.get(ids.size() - 1); | |||
if (id.getFrom() <= lastId.getTo()) { | |||
for (final Part part : parts) { | |||
final Matcher matcher = idPattern.matcher(part.text); | |||
while (matcher.find()) { | |||
final Part subPart = createSubPart(part, matcher, matcher.groupCount() == 0 ? 0 : 1); | |||
if (subPart == null) { | |||
continue; | |||
} | |||
} | |||
final BugtraqParserIssueId id; | |||
if (linkPattern == null) { | |||
id = new BugtraqParserIssueId(subPart.from, subPart.to, subPart.text); | |||
} | |||
else { | |||
if (matcher.find()) { | |||
// If we are using links, the last pattern (link) must produce exactly one id. | |||
continue; | |||
} | |||
id = new BugtraqParserIssueId(part.from, part.to, subPart.text); | |||
} | |||
ids.add(id); | |||
if (ids.size() > 0) { | |||
final BugtraqParserIssueId lastId = ids.get(ids.size() - 1); | |||
if (id.getFrom() <= lastId.getTo()) { | |||
continue; | |||
} | |||
} | |||
ids.add(id); | |||
} | |||
} | |||
return ids; | |||
@@ -119,15 +115,30 @@ final class BugtraqParser { | |||
// Utils ================================================================== | |||
private static void addNewPart(Part part, Matcher matcher, int group, List<Part> newParts) { | |||
private static List<Part> collectParts(@NotNull List<Part> mainParts, @NotNull Pattern pattern) { | |||
final List<Part> subParts = new ArrayList<Part>(); | |||
for (final Part part : mainParts) { | |||
final Matcher matcher = pattern.matcher(part.text); | |||
while (matcher.find()) { | |||
final Part newPart = createSubPart(part, matcher, matcher.groupCount() == 0 ? 0 : 1); | |||
if (newPart != null) { | |||
subParts.add(newPart); | |||
} | |||
} | |||
} | |||
return subParts; | |||
} | |||
@Nullable | |||
private static Part createSubPart(Part part, Matcher matcher, int group) { | |||
final int textStart = matcher.start(group) + part.from; | |||
final int textEnd = matcher.end(group) - 1 + part.from; | |||
if (textEnd < 0) { | |||
return; | |||
return null; | |||
} | |||
final Part newPart = new Part(matcher.group(group), textStart, textEnd); | |||
newParts.add(newPart); | |||
return new Part(matcher.group(group), textStart, textEnd); | |||
} | |||
private static Pattern compilePatternSafe(String pattern) throws PatternSyntaxException { |
@@ -29,34 +29,42 @@ | |||
*/ | |||
package com.syntevo.bugtraq; | |||
import junit.framework.*; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.*; | |||
import junit.framework.TestCase; | |||
import org.jetbrains.annotations.*; | |||
import org.jetbrains.annotations.NotNull; | |||
import org.jetbrains.annotations.Nullable; | |||
public class BugtraqFormatterTest extends TestCase { | |||
// Accessing ============================================================== | |||
public void testSimple() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%BUGID%", "JRA-\\d+")); | |||
public void testSimpleWithExtendedLink() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", null)); | |||
doTest(formatter, "JRA-7399: Email subject formatting", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(": Email subject formatting")); | |||
doTest(formatter, " JRA-7399, JRA-7398: Email subject formatting", t(" "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", "), l("JRA-7398", "https://jira.atlassian.com/browse/JRA-7398"), t(": Email subject formatting")); | |||
doTest(formatter, "Fixed JRA-7399", t("Fixed "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399")); | |||
} | |||
public void testLinkText() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/JRA-%BUGID%", null, "JRA-\\d+", "\\d+", "JIRA-%BUGID%")); | |||
doTest(formatter, " JRA-7399, JRA is text, JRA-7398: Email subject formatting", t(" "), l("JIRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", JRA is text, "), l("JIRA-7398", "https://jira.atlassian.com/browse/JRA-7398"), t(": Email subject formatting")); | |||
} | |||
public void testTwoNonIntersectingConfigurations() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%BUGID%", "JRA-\\d+"), | |||
createEntry("https://issues.apache.org/jira/browse/%BUGID%", "VELOCITY-\\d+")); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://jira.atlassian.com/browse/%BUGID%", null, null, "JRA-\\d+", null), | |||
createEntry("https://issues.apache.org/jira/browse/%BUGID%", null, null, "VELOCITY-\\d+", null)); | |||
doTest(formatter, "JRA-7399, VELOCITY-847: fix", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(", "), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847"), t(": fix")); | |||
doTest(formatter, " JRA-7399: fix/VELOCITY-847", t(" "), l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), t(": fix/"), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847")); | |||
doTest(formatter, "JRA-7399VELOCITY-847", l("JRA-7399", "https://jira.atlassian.com/browse/JRA-7399"), l("VELOCITY-847", "https://issues.apache.org/jira/browse/VELOCITY-847")); | |||
} | |||
public void testTwoIntersectingConfigurations() throws BugtraqException { | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://host1/%BUGID%", "A[AB]"), | |||
createEntry("https://host2/%BUGID%", "BA[A]?")); | |||
final BugtraqFormatter formatter = createFormatter(createEntry("https://host1/%BUGID%", null, null, "A[AB]", null), | |||
createEntry("https://host2/%BUGID%", null, null, "BA[A]?", null)); | |||
doTest(formatter, "AA: fix", l("AA", "https://host1/AA"), t(": fix")); | |||
doTest(formatter, "AB: fix", l("AB", "https://host1/AB"), t(": fix")); | |||
doTest(formatter, "BA: fix", l("BA", "https://host2/BA"), t(": fix")); | |||
@@ -76,33 +84,36 @@ public class BugtraqFormatterTest extends TestCase { | |||
private BugtraqFormatter createFormatter(BugtraqEntry ... entries) { | |||
return new BugtraqFormatter(new BugtraqConfig(Arrays.asList(entries))); | |||
} | |||
private BugtraqEntry createEntry(String url, String ... logRegexs) throws BugtraqException { | |||
return new BugtraqEntry(url, Arrays.asList(logRegexs)); | |||
private BugtraqEntry createEntry(String url, @Nullable String filterRegex, @Nullable String linkRegex, @NotNull String idRegex, @Nullable String linkText) throws BugtraqException { | |||
return new BugtraqEntry(url, idRegex, linkRegex, filterRegex, linkText); | |||
} | |||
private Text t(String text) { | |||
return new Text(text); | |||
} | |||
private Link l(String text, String url) { | |||
return new Link(text, url); | |||
} | |||
private void doTest(BugtraqFormatter formatter, String message, Atom ... expectedAtoms) { | |||
final List<Atom> actualAtoms = new ArrayList<Atom>(); | |||
final StringBuilder sb = new StringBuilder(); | |||
formatter.formatLogMessage(message, new BugtraqFormatter.OutputHandler() { | |||
@Override | |||
public void appendText(@NotNull String text) { | |||
actualAtoms.add(t(text)); | |||
sb.append(text); | |||
} | |||
@Override | |||
public void appendLink(@NotNull String name, @NotNull String target) { | |||
actualAtoms.add(l(name, target)); | |||
sb.append(name); | |||
} | |||
}); | |||
assertEquals(Arrays.asList(expectedAtoms), actualAtoms); | |||
} | |||
@@ -110,7 +121,7 @@ public class BugtraqFormatterTest extends TestCase { | |||
private static interface Atom { | |||
} | |||
private static class Text implements Atom { | |||
private final String text; | |||
@@ -133,11 +144,11 @@ public class BugtraqFormatterTest extends TestCase { | |||
if (obj == null || obj.getClass() != getClass()) { | |||
return false; | |||
} | |||
return text.equals(((Text)obj).text); | |||
} | |||
} | |||
private static class Link implements Atom { | |||
private final String text; | |||
private final String url; | |||
@@ -162,7 +173,7 @@ public class BugtraqFormatterTest extends TestCase { | |||
if (obj == null || obj.getClass() != getClass()) { | |||
return false; | |||
} | |||
return text.equals(((Link)obj).text) | |||
&& url.equals(((Link)obj).url); | |||
} |
@@ -33,79 +33,84 @@ import junit.framework.*; | |||
import java.util.*; | |||
import org.jetbrains.annotations.*; | |||
public class BugtraqParserTest extends TestCase { | |||
// Accessing ============================================================== | |||
public void testSimple1() throws BugtraqException { | |||
final BugtraqParser parser = createParser("\\d"); | |||
assertNull(parser.parse("")); | |||
final BugtraqParser parser = createParser(null, null, "\\d+"); | |||
doTest("", parser); | |||
doTest("1", parser, id(0, 0, "1")); | |||
doTest("1 2 3", parser, id(0, 0, "1"), id(2, 2, "2"), id(4, 4, "3")); | |||
} | |||
public void testSimple2() throws BugtraqException { | |||
final BugtraqParser parser = createParser("(\\d)"); | |||
assertNull(parser.parse("")); | |||
final BugtraqParser parser = createParser(null, null, "(\\d+)"); | |||
doTest("1", parser, id(0, 0, "1")); | |||
doTest("1 2 3", parser, id(0, 0, "1"), id(2, 2, "2"), id(4, 4, "3")); | |||
} | |||
public void testSimple3() throws BugtraqException { | |||
final BugtraqParser parser = createParser("(SG-\\d)"); | |||
assertNull(parser.parse("")); | |||
final BugtraqParser parser = createParser(null, null, "(SG-\\d+)"); | |||
doTest("SG-1", parser, id(0, 3, "SG-1")); | |||
doTest("SG-1 SG-2 SG-3", parser, id(0, 3, "SG-1"), id(5, 8, "SG-2"), id(10, 13, "SG-3")); | |||
} | |||
public void testSimple4() throws BugtraqException { | |||
final BugtraqParser parser = createParser("SG-(\\d)"); | |||
assertNull(parser.parse("")); | |||
final BugtraqParser parser = createParser(null, null, "SG-(\\d+)"); | |||
doTest("SG-1", parser, id(3, 3, "1")); | |||
doTest("SG-1 SG-2 SG-3", parser, id(3, 3, "1"), id(8, 8, "2"), id(13, 13, "3")); | |||
} | |||
public void testTwoLevel1() throws BugtraqException { | |||
final BugtraqParser parser = createParser("(SG-\\d)", "\\d"); | |||
public void testFilter1() throws BugtraqException { | |||
final BugtraqParser parser = createParser("(SG-\\d+)", null, "\\d+"); | |||
doTest("SG-1", parser, id(3, 3, "1")); | |||
doTest("SG-1 SG-2 SG-3", parser, id(3, 3, "1"), id(8, 8, "2"), id(13, 13, "3")); | |||
} | |||
public void testTwoLevel2() throws BugtraqException { | |||
final BugtraqParser parser = createParser("xSG-\\dx", "\\d"); | |||
public void testFilter2() throws BugtraqException { | |||
final BugtraqParser parser = createParser("xSG-\\d+x", null, "\\d+"); | |||
doTest("SG-1 xSG-2x SG-3", parser, id(9, 9, "2")); | |||
} | |||
public void testTwoLevel3() throws BugtraqException { | |||
final BugtraqParser parser = createParser("[Ii]ssues?:?((\\s*(,|and)?\\s*#\\d+)+)", "\\d"); | |||
public void testFilter3() throws BugtraqException { | |||
final BugtraqParser parser = createParser("[Ii]ssues?:?((\\s*(,|and)?\\s*#\\d+)+)", null, "\\d+"); | |||
doTest("Issues #3, #4 and #5: Git Bugtraq Configuration options (see #12)", parser, id(8, 8, "3"), id(12, 12, "4"), id(19, 19, "5")); | |||
} | |||
public void testThreeLevel() throws BugtraqException { | |||
public void testLink() throws BugtraqException { | |||
final BugtraqParser parser = createParser(null, "(SG-\\d+)", "\\d+"); | |||
doTest("SG-1", parser, id(0, 3, "1")); | |||
doTest("SG-1 SG-2 SG-3", parser, id(0, 3, "1"), id(5, 8, "2"), id(10, 13, "3")); | |||
} | |||
public void testLinkAndFilter() throws BugtraqException { | |||
final BugtraqParser parser = createParser("[ab]\\d[cd]", "a\\dc|b\\dd", "\\d"); | |||
doTest("a1c a2d b3c b4d", parser, id(1, 1, "1"), id(13, 13, "4")); | |||
doTest("a1c a2d b3c b4d", parser, id(0, 2, "1"), id(12, 14, "4")); | |||
} | |||
public void testFogBugz() throws BugtraqException { | |||
final BugtraqParser parser = createParser("(?:Bug[zs]?\\s*IDs?\\s*|Cases?)[#:; ]+((\\d+[ ,:;#]*)+)", "\\d"); | |||
doTest("Bug IDs: 3, 4, 5", parser, id(9, 9, "3"), id(12, 12, "4"), id(15, 15, "5")); | |||
final BugtraqParser parser = createParser("(?:Bug[zs]?\\s*IDs?\\s*|Cases?)[#:; ]+((\\d+[ ,:;#]*)+)", "[#]?\\d+", "\\d+"); | |||
doTest("Bug IDs: 3, #4, 5", parser, id(9, 9, "3"), id(12, 13, "4"), id(16, 16, "5")); | |||
} | |||
public void testFogBugzInvalid() throws BugtraqException { | |||
final BugtraqParser parser = createParser("Bug[zs]?\\s*IDs?\\s*|Cases?[#:; ]+((\\d+[ ,:;#]*)+)", "\\d"); | |||
final BugtraqParser parser = createParser("Bug[zs]?\\s*IDs?\\s*|Cases?[#:; ]+((\\d+[ ,:;#]*)+)", null, "\\d+"); | |||
doTest("Bug IDs: 3, 4, 5", parser); | |||
} | |||
// Utils ================================================================== | |||
private BugtraqParser createParser(String ... regexs) throws BugtraqException { | |||
return BugtraqParser.createInstance(Arrays.asList(regexs)); | |||
private BugtraqParser createParser(@Nullable String filterRegex, @Nullable String linkRegex, @NotNull String idRegex) throws BugtraqException { | |||
return BugtraqParser.createInstance(idRegex, linkRegex, filterRegex); | |||
} | |||
private BugtraqParserIssueId id(int from, int to, String id) { | |||
return new BugtraqParserIssueId(from, to, id); | |||
} | |||
private void doTest(String message, BugtraqParser parser, BugtraqParserIssueId... expectedIds) { | |||
final List<BugtraqParserIssueId> actualIds = parser.parse(message); | |||
assertEquals(expectedIds.length, actualIds.size()); |