• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2021 and later: Unicode, Inc. and others.
2 // License & terms of use: https://www.unicode.org/copyright.html
3 
4 package com.ibm.icu.dev.test;
5 
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Map.Entry;
10 import java.util.TreeMap;
11 import java.util.regex.Matcher;
12 import java.util.regex.Pattern;
13 
14 /**
15  * “Known issues” manager.
16  * Intended to be shared between ICU, CLDR, &c.
17  * Test frameworks can create an instance of this to manage known issues
18  */
19 public class UnicodeKnownIssues {
20     /**
21      * From Java 1.8
22      */
accept(T t)23     public interface Consumer<T> { void accept(T t); }
24 
25     private Map<String, List<String>> knownIssues = new TreeMap<>();
26     /**
27      * Max number of lines to show by default (including the "more")
28      * unless -allKnownIssues is given. Must be at least 2.
29      */
30     public static final int KNOWN_ISSUES_CURTAILMENT = 2;
31 
32     /**
33      * true if all issues should be shown, false if they should
34      * be curtailed.
35      */
36     private boolean allKnownIssues;
37 
38     /**
39      * Construct a known issue manager
40      * @param allKnownIssues true if all known issues should be printed,
41      * not curtailed
42      */
UnicodeKnownIssues(boolean allKnownIssues)43     public UnicodeKnownIssues(boolean allKnownIssues) {
44         this.allKnownIssues = allKnownIssues;
45     }
46 
47     /**
48      * Base URL for browsing Unicode JIRA
49      */
50     public static final String UNICODE_JIRA_BROWSE = "https://unicode-org.atlassian.net/browse/";
51 
52     static final Pattern ICU_TICKET_PATTERN = Pattern.compile(
53         "(?i)(?:icu-)?(\\d+)"
54     );
55     static final Pattern CLDR_TICKET_PATTERN = Pattern.compile(
56         "(?i)cldr(?:bug:)?(?:-)?(\\d+)"
57     );
58 
59     /**
60      * Match all linkable ticket patterns
61      * @see {org.unicode.cldr.util.CLDRURLS#CLDR_TICKET_BROWSE}
62      */
63     static final Pattern UNICODE_JIRA_PATTERN = Pattern.compile(
64         "(CLDR|ICU)-(\\d+)"
65     );
66 
67     /**
68      * Log the known issue.
69      * Call this from the test framework when logKnownIssue() is called.
70      *
71      * @param path Path to the error, will be returned in the
72      * known issue list
73      * @param ticket A ticket number string. For an ICU ticket, use "ICU-10245".
74      * For a CLDR ticket, use "CLDR-12345".
75      * For compatibility, "1234" -> ICU-1234 and "cldrbug:456" -> CLDR-456
76      * @param comment Additional comment, or null
77      *
78      */
logKnownIssue(String path, String ticket, String comment)79     public void logKnownIssue(String path, String ticket, String comment) {
80 
81         StringBuilder descBuf = new StringBuilder(path);
82 
83         if (comment != null && comment.length() > 0) {
84             descBuf.append(" (" + comment + ")");
85         }
86         String description = descBuf.toString();
87 
88         String ticketLink = "Unknown Ticket";
89         if (ticket != null && ticket.length() > 0) {
90             Matcher matcher = ICU_TICKET_PATTERN.matcher(ticket);
91             if (matcher.matches()) {
92                 ticketLink = "ICU-" + matcher.group(1);
93             } else {
94                 matcher = CLDR_TICKET_PATTERN.matcher(ticket);
95                 if (matcher.matches()) {
96                     ticketLink = "CLDR-" + matcher.group(1);
97                 }
98             }
99         }
100 
101         List<String> lines = knownIssues.get(ticketLink);
102         if (lines == null) {
103             lines = new ArrayList<>();
104             knownIssues.put(ticketLink, lines);
105         }
106         if (!lines.contains(description)) {
107             lines.add(description);
108         }
109     }
110 
111     /**
112      * Print out all known issues to the logFn.
113      * Usage:  printKnownIssues(System.out::println)
114      * @param logFn consumer for Strings (e.g. System.out::println)
115      * @return true if (!allKnownIssues) and we had to curtail
116      */
printKnownIssues(Consumer<String> logFn)117     public boolean printKnownIssues(Consumer<String> logFn) {
118         boolean didCurtail = false;
119         if (knownIssues.isEmpty()) {
120             return false;
121         }
122         logFn.accept("\n " + knownIssues.size() + " Known Issues:");
123         for (Entry<String, List<String>> entry : knownIssues.entrySet()) {
124             String ticketLink = entry.getKey();
125             if (UNICODE_JIRA_PATTERN.matcher(ticketLink) != null) {
126                 logFn.accept(ticketLink + " <" + UNICODE_JIRA_BROWSE + ticketLink + ">");
127             } else {
128                 // Unknown or something else
129                 logFn.accept("<" + ticketLink + ">");
130             }
131             List<String> entries = entry.getValue();
132             int issuesToShow = entries.size();
133             if (!allKnownIssues && issuesToShow > KNOWN_ISSUES_CURTAILMENT) {
134                 issuesToShow = (KNOWN_ISSUES_CURTAILMENT - 1);
135             }
136             for (int i=0; i<issuesToShow; i++) {
137                 logFn.accept("  - " + entries.get(i));
138             }
139             if (entries.size() > issuesToShow) {
140                 didCurtail = true;
141                 logFn.accept("  ... and " +
142                     (entries.size() - issuesToShow) + " more");
143             }
144         }
145         return didCurtail;
146     }
147 
148     /**
149      * Reset the known issues
150      */
reset()151     public void reset() {
152         knownIssues.clear();
153     }
154 }
155