--- /dev/null
+// © 2021 and later: Unicode, Inc. and others.
+// License & terms of use: https://www.unicode.org/copyright.html
+
+package com.ibm.icu.dev.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link UnicodeKnownIssues}
+ */
+@RunWith(JUnit4.class)
+public class TestUnicodeKnownIssues {
+ @Test
+ public void TestBasic() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "ICU-21756", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Three", 3, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/ICU-21756"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ }
+
+ @Test
+ public void TestNotCurtailed() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "ICU-21756", "Something is working!");
+ uki.logKnownIssue("d/e/f", "ICU-21756", "Something is working!");
+ uki.logKnownIssue("g/h/i", "ICU-21756", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of 5", 5, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/ICU-21756"));
+ // Not curtailed: test shows up in a/b/c, d/e/f, and g/h/i
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ assertTrue(l.get(3) + "#3 says d/e/f", l.get(3).contains("d/e/f"));
+ assertTrue(l.get(4) + "#4 says g/h/i", l.get(4).contains("g/h/i"));
+ }
+
+ @Test
+ public void TestCurtailed() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(false);
+ uki.logKnownIssue("a/b/c", "ICU-21756", "Something is working!");
+ uki.logKnownIssue("d/e/f", "ICU-21756", "Something is working!");
+ uki.logKnownIssue("g/h/i", "ICU-21756", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count", 4, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/ICU-21756"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ // Curtailed: the next line has "... and 2 more"
+ assertTrue(l.get(3) + "#3 has 'and 2 more'", l.get(3).contains("and 2 more"));
+ }
+
+ @Test
+ public void TestBare() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "21756", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Three", 3, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/ICU-21756"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ }
+
+ @Test
+ public void TestUnknown() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "zzz", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Three", 3, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has unknown ticket", l.get(1).contains("Unknown Ticket"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ }
+
+ @Test
+ public void TestCldrLink() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "CLDR-9787", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Three", 3, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/CLDR-9787"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ }
+
+ @Test
+ public void TestCldrBug() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ uki.logKnownIssue("a/b/c", "cldrbug:9787", "Something is working!");
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Three", 3, l.size());
+ assertTrue(l.get(0) + "#0 says Known Issues", l.get(0).contains("Known Issues"));
+ assertTrue(l.get(1) + "#1 has atlassian URL", l.get(1).contains("browse/CLDR-9787"));
+ assertTrue(l.get(2) + "#2 says a/b/c", l.get(2).contains("a/b/c"));
+ }
+
+
+ @Test
+ public void TestNoProblem() {
+ UnicodeKnownIssues uki = new UnicodeKnownIssues(true);
+ List<String> l = printToList(uki);
+ assertNotNull("no list", l);
+ assertEquals("message count Of Zero", 0, l.size());
+ }
+
+ List<String> printToList(UnicodeKnownIssues uki) {
+ // TODO: for JDK 1.8
+ // final List<String> l = new LinkedList<>();
+ // uki.printKnownIssues(s -> l.add(s));
+
+ // TODO: Pre JDK 1.8 below
+ MyConsumer m = new MyConsumer();
+ uki.printKnownIssues(m);
+ return m.l;
+ }
+
+ // TODO: remove for JDK 1.8
+ static final class MyConsumer implements UnicodeKnownIssues.Consumer<String> {
+ final List<String> l = new LinkedList<>();
+ @Override
+ public void accept(String t) {
+ l.add(t);
+ }
+ }
+}
import java.util.TreeMap;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
}
}
+ @AfterClass
+ public final static void testClassTeardown() {
+ getParams().knownIssues.printKnownIssues(new UnicodeKnownIssues.Consumer<String>() {
+ // TODO: make this a Lambda once JDK 1.8 ships
+ public void accept(String t) {
+ System.out.println(t);
+ }
+ });
+ getParams().knownIssues.reset();
+ }
+
private static TestParams getParams() {
//return paramsReference.get();
return testParams;
}
- static final String ICU_TRAC_URL = "http://bugs.icu-project.org/trac/ticket/";
- static final String CLDR_TRAC_URL = "http://unicode.org/cldr/trac/ticket/";
- static final String CLDR_TICKET_PREFIX = "cldrbug:";
-
/**
* Log the known issue.
* This method returns true unless -prop:logKnownIssue=no is specified
if (!getBooleanProperty("logKnownIssue", true)) {
return false;
}
-
// TODO: This method currently does not do very much.
// See http://bugs.icu-project.org/trac/ticket/12589
-
- StringBuffer descBuf = new StringBuffer();
// TODO(junit) : what to do about this?
+ final String path = "";
//getParams().stack.appendPath(descBuf);
- if (comment != null && comment.length() > 0) {
- descBuf.append(" (" + comment + ")");
- }
- String description = descBuf.toString();
-
- String ticketLink = "Unknown Ticket";
- if (ticket != null && ticket.length() > 0) {
- boolean isCldr = false;
- ticket = ticket.toLowerCase(Locale.ENGLISH);
- if (ticket.startsWith(CLDR_TICKET_PREFIX)) {
- isCldr = true;
- ticket = ticket.substring(CLDR_TICKET_PREFIX.length());
- }
- ticketLink = (isCldr ? CLDR_TRAC_URL : ICU_TRAC_URL) + ticket;
- }
-
- if (getParams().knownIssues == null) {
- getParams().knownIssues = new TreeMap<String, List<String>>();
- }
- List<String> lines = getParams().knownIssues.get(ticketLink);
- if (lines == null) {
- lines = new ArrayList<String>();
- getParams().knownIssues.put(ticketLink, lines);
- }
- if (!lines.contains(description)) {
- lines.add(description);
- }
-
+ getParams().knownIssues.logKnownIssue(path, ticket, comment);
return true;
}
private SecurityManager testSecurityManager;
private SecurityManager originalSecurityManager;
- private Map<String, List<String>> knownIssues;
+ private UnicodeKnownIssues knownIssues = null;
private Properties props;
TestParams params = new TestParams();
Properties props = System.getProperties();
params.parseProperties(props);
+ params.knownIssues = new UnicodeKnownIssues(params.getBooleanProperty("allKnownIssues", false));
return params;
}
--- /dev/null
+// © 2021 and later: Unicode, Inc. and others.
+// License & terms of use: https://www.unicode.org/copyright.html
+
+package com.ibm.icu.dev.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * “Known issues” manager.
+ * Intended to be shared between ICU, CLDR, &c.
+ * Test frameworks can create an instance of this to manage known issues
+ */
+public class UnicodeKnownIssues {
+ /**
+ * From Java 1.8
+ */
+ public interface Consumer<T> { void accept(T t); }
+
+ private Map<String, List<String>> knownIssues = new TreeMap<>();
+ /**
+ * Max number of lines to show by default (including the "more")
+ * unless -allKnownIssues is given. Must be at least 2.
+ */
+ public static final int KNOWN_ISSUES_CURTAILMENT = 2;
+
+ /**
+ * true if all issues should be shown, false if they should
+ * be curtailed.
+ */
+ private boolean allKnownIssues;
+
+ /**
+ * Construct a known issue manager
+ * @param allKnownIssues true if all known issues should be printed,
+ * not curtailed
+ */
+ public UnicodeKnownIssues(boolean allKnownIssues) {
+ this.allKnownIssues = allKnownIssues;
+ }
+
+ /**
+ * Base URL for browsing Unicode JIRA
+ */
+ public static final String UNICODE_JIRA_BROWSE = "https://unicode-org.atlassian.net/browse/";
+
+ static final Pattern ICU_TICKET_PATTERN = Pattern.compile(
+ "(?i)(?:icu-)?(\\d+)"
+ );
+ static final Pattern CLDR_TICKET_PATTERN = Pattern.compile(
+ "(?i)cldr(?:bug:)?(?:-)?(\\d+)"
+ );
+
+ /**
+ * Match all linkable ticket patterns
+ * @see {org.unicode.cldr.util.CLDRURLS#CLDR_TICKET_BROWSE}
+ */
+ static final Pattern UNICODE_JIRA_PATTERN = Pattern.compile(
+ "(CLDR|ICU)-(\\d+)"
+ );
+
+ /**
+ * Log the known issue.
+ * Call this from the test framework when logKnownIssue() is called.
+ *
+ * @param path Path to the error, will be returned in the
+ * known issue list
+ * @param ticket A ticket number string. For an ICU ticket, use "ICU-10245".
+ * For a CLDR ticket, use "CLDR-12345".
+ * For compatibility, "1234" -> ICU-1234 and "cldrbug:456" -> CLDR-456
+ * @param comment Additional comment, or null
+ *
+ */
+ public void logKnownIssue(String path, String ticket, String comment) {
+
+ StringBuilder descBuf = new StringBuilder(path);
+
+ if (comment != null && comment.length() > 0) {
+ descBuf.append(" (" + comment + ")");
+ }
+ String description = descBuf.toString();
+
+ String ticketLink = "Unknown Ticket";
+ if (ticket != null && ticket.length() > 0) {
+ Matcher matcher = ICU_TICKET_PATTERN.matcher(ticket);
+ if (matcher.matches()) {
+ ticketLink = "ICU-" + matcher.group(1);
+ } else {
+ matcher = CLDR_TICKET_PATTERN.matcher(ticket);
+ if (matcher.matches()) {
+ ticketLink = "CLDR-" + matcher.group(1);
+ }
+ }
+ }
+
+ List<String> lines = knownIssues.get(ticketLink);
+ if (lines == null) {
+ lines = new ArrayList<>();
+ knownIssues.put(ticketLink, lines);
+ }
+ if (!lines.contains(description)) {
+ lines.add(description);
+ }
+ }
+
+ /**
+ * Print out all known issues to the logFn.
+ * Usage: printKnownIssues(System.out::println)
+ * @param logFn consumer for Strings (e.g. System.out::println)
+ * @return true if (!allKnownIssues) and we had to curtail
+ */
+ public boolean printKnownIssues(Consumer<String> logFn) {
+ boolean didCurtail = false;
+ if (knownIssues.isEmpty()) {
+ return false;
+ }
+ logFn.accept("\n " + knownIssues.size() + " Known Issues:");
+ for (Entry<String, List<String>> entry : knownIssues.entrySet()) {
+ String ticketLink = entry.getKey();
+ if (UNICODE_JIRA_PATTERN.matcher(ticketLink) != null) {
+ logFn.accept(ticketLink + " <" + UNICODE_JIRA_BROWSE + ticketLink + ">");
+ } else {
+ // Unknown or something else
+ logFn.accept("<" + ticketLink + ">");
+ }
+ List<String> entries = entry.getValue();
+ int issuesToShow = entries.size();
+ if (!allKnownIssues && issuesToShow > KNOWN_ISSUES_CURTAILMENT) {
+ issuesToShow = (KNOWN_ISSUES_CURTAILMENT - 1);
+ }
+ for (int i=0; i<issuesToShow; i++) {
+ logFn.accept(" - " + entries.get(i));
+ }
+ if (entries.size() > issuesToShow) {
+ didCurtail = true;
+ logFn.accept(" ... and " +
+ (entries.size() - issuesToShow) + " more");
+ }
+ }
+ return didCurtail;
+ }
+
+ /**
+ * Reset the known issues
+ */
+ public void reset() {
+ knownIssues.clear();
+ }
+}