1 package org.unicode.cldr.unittest.web;
2 
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.LinkedHashSet;
7 import java.util.Set;
8 
9 import org.unicode.cldr.unittest.web.TestAll.WebTestInfo;
10 import org.unicode.cldr.util.VoteResolver;
11 
12 import com.ibm.icu.dev.test.TestFmwk;
13 
14 public class TestAnnotationVotes extends TestFmwk {
15 
16     TestAll.WebTestInfo testInfo = WebTestInfo.getInstance();
17 
18     VoteResolver<String> r = new VoteResolver<>();
19     Set<String> sortedValuesI = null, sortedValuesO = null; // input and output
20     HashMap<String, Long> voteCountI = null; // input
21 
main(String[] args)22     public static void main(String[] args) {
23         new TestAnnotationVotes().run(args);
24     }
25 
26     /**
27      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
28      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
29      */
TestAV00()30     public void TestAV00() {
31         String test = "adjustAnnotationVoteCounts(null, null) should return quietly";
32         try {
33             r.adjustAnnotationVoteCounts(null, null);
34         } catch (Exception e) {
35             errln("❌ " + test + ". Unexpected exception: " + e.toString() + " - " + e.getMessage());
36             return;
37         }
38         // TODO: logln instead of System.out.println -- but how to make it display in log? Set "level" or "verbose" somewhere?
39         System.out.println("✅ " + test);
40     }
41 
42     /**
43      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
44      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
45      */
TestAV01()46     public void TestAV01() {
47         String test = "adjustAnnotationVoteCounts for a=100, b=99, c=98 should return unchanged";
48         String[] valI = {"a", "b", "c"}; // input
49         long[] votesI = {100,  99,  98}; // input vote counts
50         String[] valO = {"a", "b", "c"}; // expected/desired output
51         runTest(test, valI, votesI, valO);
52      }
53 
54     /**
55      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
56      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
57      */
TestAV02()58     public void TestAV02() {
59         String test = "adjustAnnotationVoteCounts for a|b=1, c|d=2, e|f=3 should reverse order";
60         String[] valI = {"a|b", "c|d", "e|f"}; // input
61         long[] votesI = {1,      2,     3   }; // input vote counts
62         String[] valO = {"e|f", "c|d", "a|b"}; // expected/desired output
63         runTest(test, valI, votesI, valO);
64     }
65 
66     /**
67      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
68      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
69      */
TestAV03()70     public void TestAV03() {
71         String test = "adjustAnnotationVoteCounts for a=2, b=2, b|c=1 should make b, a, b|c";
72         String[] valI = {"a", "b", "b|c"}; // input
73         long[] votesI = { 2,   2,   1   }; // input vote counts
74         String[] valO = {"b", "a", "b|c"}; // expected/desired output
75         runTest(test, valI, votesI, valO);
76     }
77 
78     /**
79      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
80      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
81      */
TestAV04()82     public void TestAV04() {
83         String test = "adjustAnnotationVoteCounts for a|b|c|f=8, a|b|e=6, a|e=4 should make a|b|e, a|e, a|b|c|f";
84         String[] valI = {"a|b|c|f", "a|b|e", "a|e"}; // input
85         long[] votesI = {8,          6,       4   }; // input vote counts
86         String[] valO = {"a|b|e", "a|e", "a|b|c|f"}; // expected/desired output
87         runTest(test, valI, votesI, valO);
88     }
89 
90     /**
91      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
92      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
93      */
TestAV05()94     public void TestAV05() {
95         /* An older version of this test ("a=3, b|c=2, b|c|d=2 should make b|c, b|c|d, a") would now
96          * fail due to rounding double (float) to long (integer) when calculating the geometric mean.
97          * Most actual votes are multiples of 4, and this test passes with the new vote counts
98          * simply being the old vote counts multiplied by 4.
99          */
100         String test = "adjustAnnotationVoteCounts for a=12, b|c=8, b|c|d=8 should make b|c, b|c|d, a";
101         String[] valI = {"a", "b|c", "b|c|d"}; // input
102         long[] votesI = {12  , 8,     8     }; // input vote counts
103         String[] valO = {"b|c", "b|c|d", "a"}; // expected/desired output
104         runTest(test, valI, votesI, valO);
105     }
106 
107     /**
108      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
109      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
110      */
TestAV06()111     public void TestAV06() {
112         String test = "adjustAnnotationVoteCounts for a|b|c=8, a|b|d=6, a|d=4 should make a|b|d, a|d, a|b|c";
113         String[] valI = {"a|b|c", "a|b|d", "a|d"}; // input
114         long[] votesI = {8,        6,       4   }; // input vote counts
115         String[] valO = {"a|b|d", "a|d", "a|b|c"}; // expected/desired output
116         runTest(test, valI, votesI, valO);
117     }
118 
119     /**
120      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
121      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
122      */
TestAV07()123     public void TestAV07() {
124         String test = "adjustAnnotationVoteCounts for a=24, b|c=20, b|c|d=20 should make b|c, b|c|d, a";
125         String[] valI = {"a", "b|c", "b|c|d"}; // input
126         long[] votesI = {24,   20,    20    }; // input vote counts
127         String[] valO = {"b|c", "b|c|d", "a"}; // expected/desired output
128         runTest(test, valI, votesI, valO);
129     }
130 
131     /**
132      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
133      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
134      */
TestAV08()135     public void TestAV08() {
136         // References:
137         //  https://unicode.org/cldr/trac/ticket/11165
138         //  https://unicode.org/cldr/trac/ticket/10973
139         String test = "adjustAnnotationVoteCounts for hmyz | malárie | moskyt | štípnutí | virus, dengue | hmyz | malárie | moskyt | štípnutí | virus ...";
140         String[] valI = {"hmyz | malárie | moskyt | štípnutí | virus", "dengue | hmyz | malárie | moskyt | štípnutí | virus"}; // input
141         long[] votesI = {4,                                             8                                                   }; // input vote counts
142         String[] valO = {"dengue | hmyz | malárie | moskyt | štípnutí | virus", "hmyz | malárie | moskyt | štípnutí | virus"}; // expected/desired output
143         runTest(test, valI, votesI, valO);
144     }
145 
146     /**
147      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
148      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
149      */
TestAV09()150     public void TestAV09() {
151         // same as TestAV08 except one-letter names
152         String test = "adjustAnnotationVoteCounts for b|c|d|e|f=4, a|b|c|d|e|f=8 should make a|b|c|d|e|f, b|c|d|e|f";
153         String[] valI = {"b|c|d|e|f", "a|b|c|d|e|f"}; // input
154         long[] votesI = {4,            8           }; // input vote counts
155         String[] valO = {"a|b|c|d|e|f", "b|c|d|e|f"}; // expected/desired output
156         runTest(test, valI, votesI, valO);
157     }
158 
159     /**
160      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
161      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
162      */
TestAV10()163     public void TestAV10() {
164         // same input and output as TestAV09, different vote counts
165         String test = "adjustAnnotationVoteCounts for b|c|d|e|f=4, a|b|c|d|e|f=6 should make a|b|c|d|e|f, b|c|d|e|f";
166         String[] valI = {"b|c|d|e|f", "a|b|c|d|e|f"}; // input
167         long[] votesI = {4,            6           }; // input vote counts
168         String[] valO = {"a|b|c|d|e|f", "b|c|d|e|f"}; // expected/desired output
169         runTest(test, valI, votesI, valO);
170     }
171 
172     /**
173      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
174      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
175      */
TestAV11()176     public void TestAV11() {
177         // same input as TestAV09, different vote counts and output
178         String test = "adjustAnnotationVoteCounts for b|c|d|e|f=4, a|b|c|d|e|f=5 should make b|c|d|e|f, a|b|c|d|e|f";
179         String[] valI = {"b|c|d|e|f", "a|b|c|d|e|f"}; // input
180         long[] votesI = {4,            5           }; // input vote counts
181         String[] valO = {"b|c|d|e|f", "a|b|c|d|e|f"}; // expected/desired output
182         runTest(test, valI, votesI, valO);
183     }
184 
185     /**
186      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
187      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
188      */
TestAV12()189     public void TestAV12() {
190         // test superior supersets with alphabetical fallback: a|b|c before a|b|d
191         String test = "adjustAnnotationVoteCounts for a|b=4, a|b|d=8, a|b|c=8 should make a|b|c, a|b|d, a|b";
192         String[] valI = {"a|b", "a|b|d", "a|b|c"}; // input
193         long[] votesI = {4,      8,       8     }; // input vote counts
194         String[] valO = {"a|b|c", "a|b|d", "a|b"}; // expected/desired output
195         runTest(test, valI, votesI, valO);
196     }
197 
198     /**
199      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
200      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
201      */
TestAV13()202     public void TestAV13() {
203         String test = "adjustAnnotationVoteCounts for a|b=4, a|b|d=8, a|b|c=7 should make a|b|d, a|b|c, a|b";
204         String[] valI = {"a|b", "a|b|d", "a|b|c"}; // input
205         long[] votesI = {4,      8,       7     }; // input vote counts
206         String[] valO = {"a|b|d", "a|b|c", "a|b"}; // expected/desired output
207         runTest(test, valI, votesI, valO);
208     }
209 
210     /**
211      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
212      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
213      */
TestAV14()214     public void TestAV14() {
215         String test = "adjustAnnotationVoteCounts for a|b=8, a=8 should make a, a|b";
216         String[] valI = {"a|b", "a"}; // input
217         long[] votesI = {8,      8 }; // input vote counts
218         String[] valO = {"a", "a|b"}; // expected/desired output
219         runTest(test, valI, votesI, valO);
220     }
221 
222     /**
223      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
224      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
225      */
TestAV15()226     public void TestAV15() {
227         String test = "adjustAnnotationVoteCounts for a|b=8, a=4 should make a|b, a";
228         String[] valI = {"a|b", "a"}; // input
229         long[] votesI = {8,      4 }; // input vote counts
230         String[] valO = {"a|b", "a"}; // expected/desired output
231         runTest(test, valI, votesI, valO);
232     }
233 
234     /**
235      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
236      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
237      */
TestAV16()238     public void TestAV16() {
239         String test = "adjustAnnotationVoteCounts for a|b=4, a|b|d=8, a|b|c=7 should make a|b|d, a|b|c, a|b";
240         String[] valI = {"a|b", "a|b|d", "a|b|c"}; // input
241         long[] votesI = {4,      8,       7     }; // input vote counts
242         String[] valO = {"a|b|d", "a|b|c", "a|b"}; // expected/desired output
243         runTest(test, valI, votesI, valO);
244     }
245 
246     /**
247      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
248      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
249      */
TestAV17()250     public void TestAV17() {
251         // test superior supersets with shorter-set fallback: a|b|e before a|b|c|d
252         String test = "adjustAnnotationVoteCounts for a|b=4, a|b|c|d=8, a|b|e=8 should make a|b|e, a|b|c|d, a|b";
253         String[] valI = {"a|b", "a|b|c|d", "a|b|e"}; // input
254         long[] votesI = {4,      8,         8     }; // input vote counts
255         String[] valO = {"a|b|e", "a|b|c|d", "a|b"}; // expected/desired output
256         runTest(test, valI, votesI, valO);
257     }
258 
259     /**
260      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
261      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
262      */
TestAV18()263     public void TestAV18() {
264         // test shorter-set fallback: a|b|e before a|b|c|d
265         String test = "adjustAnnotationVoteCounts for a|b|c|d=8, a|b|e=8 should make a|b|e, a|b|c|d";
266         String[] valI = {"a|b|c|d", "a|b|e"}; // input
267         long[] votesI = {8,          8     }; // input vote counts
268         String[] valO = {"a|b|e", "a|b|c|d"}; // expected/desired output
269         runTest(test, valI, votesI, valO);
270     }
271 
272     /**
273      * Test features related to adjustAnnotationVoteCounts in VoteResolver.java.
274      * Note: the name of each function must begin with "Test", or it will be ignored! See TestFmwk.java.
275      */
TestAV19()276     public void TestAV19() {
277         // Superior supersets can't have more than 7 = CheckWidths.MAX_COMPONENTS_PER_ANNOTATION.
278         String test = "adjustAnnotationVoteCounts for a|b=4, a|b|c|d|e|f|g|h=9, a|b|c|x|y=8 should make a|b|c|x|y, a|b, a|b|c|d|e|f|g|h";
279         String[] valI = {"a|b", "a|b|c|d|e|f|g|h", "a|b|c|x|y"}; // input
280         long[] votesI = {4,      9,                 8         }; // input vote counts
281         String[] valO = {"a|b|c|d|e|f|g|h", "a|b|c|x|y", "a|b"}; // expected/desired output
282         runTest(test, valI, votesI, valO);
283     }
284 
285     /**
286      * Run adjustAnnotationVoteCounts with the given input and expected output.
287      * Test whether the actual output matches the expected output.
288      *
289      * @param test the string describing what should happen
290      * @param valI the array of input values
291      * @param votesI the array of vote counts corresponding to valI
292      * @param valO the array of expected output values
293      *
294      * Note: there is no array of expected output vote counts. Treat the test as passing
295      * or failing based only on the order of output values, not on the exact output vote counts.
296      */
runTest(String test, String[] valI, long[] votesI, String[] valO)297    private void runTest(String test, String[] valI, long[] votesI, String[] valO) {
298         setupTestIO(valI, votesI, valO);
299         String input = sortedValuesI.toString() + " " + voteCountI.toString(); // before adjusting
300         try {
301             r.adjustAnnotationVoteCounts(sortedValuesI, voteCountI);
302         } catch (Exception e) {
303             errln("❌ " + test + ". Unexpected exception: " + e.toString() + " - " + e.getMessage());
304             return;
305         }
306         // Convert sets to strings for comparison, otherwise the set.equals() function ignores differences in order.
307         // Also, strings can be displayed more conveniently with errln.
308         String expected = sortedValuesO.toString();
309         String actually = sortedValuesI.toString();
310         if (!actually.equals(expected)) {
311             String msg = test + "."
312                 + "\n\tInput:   \t" + input
313                 + "\n\tExpected:\t" + expected
314                 + "\n\tActually:\t" + actually + " " + voteCountI.toString();
315             errln("❌ " + msg);
316             return;
317         }
318         System.out.println("✅ " + test);
319     }
320 
321     /**
322      * Set up test inputs and outputs.
323      *
324      * @param valI the array of input values
325      * @param votesI the array of vote counts corresponding to valI
326      * @param valO the array of expected output values
327      */
setupTestIO(String[] valI, long[] votesI, String[] valO)328     private void setupTestIO(String[] valI, long[] votesI, String[] valO) {
329         sortedValuesI = new LinkedHashSet<>(new ArrayList<>(Arrays.asList(valI)));
330         sortedValuesO = new LinkedHashSet<>(new ArrayList<>(Arrays.asList(valO)));
331         voteCountI = new HashMap<>();
332         int i = 0;
333         for (String value : valI) {
334             voteCountI.put(value, votesI[i++]);
335         }
336     }
337 }
338