1 package org.unicode.cldr.unittest; 2 3 import com.google.common.collect.ImmutableList; 4 import com.google.common.collect.ImmutableMap; 5 import java.util.ArrayList; 6 import java.util.Arrays; 7 import java.util.Collections; 8 import java.util.HashMap; 9 import java.util.List; 10 import java.util.Map; 11 import java.util.Map.Entry; 12 import java.util.Set; 13 import java.util.TreeSet; 14 import org.unicode.cldr.test.CheckCLDR.CheckStatus; 15 import org.unicode.cldr.test.CheckCLDR.Options; 16 import org.unicode.cldr.test.CheckDisplayCollisions; 17 import org.unicode.cldr.util.CLDRConfig; 18 import org.unicode.cldr.util.CLDRFile; 19 import org.unicode.cldr.util.SimpleXMLSource; 20 import org.unicode.cldr.util.XMLSource; 21 22 public class TestCheckDisplayCollisions extends TestFmwkPlus { 23 private static final String ukRegion = 24 "//ldml/localeDisplayNames/territories/territory[@type=\"GB\"]"; 25 private static final String englandSubdivision = 26 "//ldml/localeDisplayNames/subdivisions/subdivision[@type=\"gbeng\"]"; 27 28 private static final String scorpioEmoji = 29 "//ldml/annotations/annotation[@cp=\"♏\"][@type=\"tts\"]"; 30 private static final String scorpionEmoji = 31 "//ldml/annotations/annotation[@cp=\"\"][@type=\"tts\"]"; 32 33 private static final String japanRegion = 34 "//ldml/localeDisplayNames/territories/territory[@type=\"JP\"]"; 35 private static final String japanMap = 36 "//ldml/annotations/annotation[@cp=\"\"][@type=\"tts\"]"; 37 38 private static final String milli = 39 "//ldml/units/unitLength[@type=\"short\"]/compoundUnit[@type=\"10p-3\"]/unitPrefixPattern"; 40 private static final String mega = 41 "//ldml/units/unitLength[@type=\"short\"]/compoundUnit[@type=\"10p6\"]/unitPrefixPattern"; 42 43 private static final String deciLong = 44 "//ldml/units/unitLength[@type=\"long\"]/compoundUnit[@type=\"10p-1\"]/unitPrefixPattern"; 45 private static final String deciNarrow = 46 "//ldml/units/unitLength[@type=\"narrow\"]/compoundUnit[@type=\"10p-1\"]/unitPrefixPattern"; 47 private static final String deciShort = 48 "//ldml/units/unitLength[@type=\"short\"]/compoundUnit[@type=\"10p-1\"]/unitPrefixPattern"; 49 main(String[] args)50 public static void main(String[] args) { 51 new TestCheckDisplayCollisions().run(args); 52 } 53 testInheritance()54 public void testInheritance() { 55 XMLSource rootSource = new SimpleXMLSource("root"); 56 CLDRFile root = new CLDRFile(rootSource); 57 58 XMLSource enSource = new SimpleXMLSource("en"); 59 CLDRFile en = new CLDRFile(enSource); 60 61 XMLSource frSource = new SimpleXMLSource("fr"); 62 frSource.putValueAtPath(scorpionEmoji, "scorpion"); 63 frSource.putValueAtPath(scorpioEmoji, "scorpion zodiac"); 64 frSource.putValueAtPath(englandSubdivision, "Angleterre"); 65 frSource.putValueAtPath(ukRegion, "Royaume-Uni"); 66 frSource.putValueAtDPath(japanRegion, "Japon"); 67 frSource.putValueAtDPath(japanMap, "carte du Japon"); 68 frSource.putValueAtDPath(milli, "m{0}"); 69 frSource.putValueAtDPath(mega, "M{0}"); 70 71 frSource.putValueAtDPath(deciLong, "d{0}"); 72 frSource.putValueAtDPath(deciNarrow, "d{0}"); 73 frSource.putValueAtDPath(deciShort, "d{0}"); 74 75 CLDRFile fr = new CLDRFile(frSource); 76 77 XMLSource frCaSource = new SimpleXMLSource("fr_CA"); 78 frCaSource.putValueAtPath(scorpioEmoji, "scorpion"); 79 frCaSource.putValueAtPath(ukRegion, "Angleterre"); 80 frCaSource.putValueAtDPath(japanMap, "Japon"); 81 CLDRFile frCA = new CLDRFile(frCaSource); 82 83 TestFactory factory = new TestFactory(); 84 factory.addFile(root); 85 factory.addFile(en); 86 factory.addFile(fr); 87 factory.addFile(frCA); 88 89 CheckDisplayCollisions cdc = new CheckDisplayCollisions(factory); 90 cdc.setEnglishFile(CLDRConfig.getInstance().getEnglish()); 91 92 CLDRFile frResolved = factory.make("fr", true); 93 checkFile(cdc, fr, frResolved); 94 95 CLDRFile frCaResolved = factory.make("fr_CA", true); 96 checkFile(cdc, frCA, frCaResolved, scorpioEmoji, ukRegion); 97 } 98 testUnitPatternCollisions()99 public void testUnitPatternCollisions() { 100 final String unitPattern1 = 101 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-dot\"]/unitPattern[@count=\"one\"]"; 102 /** different count as # 1. MUST NOT COLLIDE WITH #1 */ 103 final String unitPattern2 = 104 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-dot\"]/unitPattern[@count=\"other\"]"; 105 /** different unit as # 1. MUST COLLIDE WITH #1 */ 106 final String unitPattern3 = 107 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-point\"]/unitPattern[@count=\"one\"]"; 108 /** 109 * #4 and #5 must NOT collide; case="nominative" and case="accusative" when paths are 110 * otherwise identical and have the same value 111 */ 112 final String unitPattern4 = 113 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"volume-dram\"]/unitPattern[@count=\"other\"][@case=\"nominative\"]"; 114 final String unitPattern5 = 115 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"volume-dram\"]/unitPattern[@count=\"other\"][@case=\"accusative\"]"; 116 117 mustCollide(false, unitPattern1, unitPattern2); 118 mustCollide(true, unitPattern1, unitPattern3); 119 mustCollide(false, unitPattern4, unitPattern5); 120 } 121 mustCollide( boolean expectCollisionErrors, String unitPatternA, String unitPatternB)122 private void mustCollide( 123 boolean expectCollisionErrors, String unitPatternA, String unitPatternB) { 124 final String testLocale = "pt"; 125 final String duplicatedValue = "{0}pontos"; 126 127 final XMLSource rootSource = new SimpleXMLSource("root"); 128 final CLDRFile root = new CLDRFile(rootSource); 129 130 final XMLSource enSource = new SimpleXMLSource("en"); 131 final CLDRFile en = new CLDRFile(enSource); 132 133 final XMLSource source = new SimpleXMLSource(testLocale); 134 135 source.putValueAtPath(unitPatternA, duplicatedValue); 136 source.putValueAtPath(unitPatternB, duplicatedValue); 137 138 CLDRFile file = new CLDRFile(source); 139 140 TestFactory factory = new TestFactory(); 141 factory.addFile(root); 142 factory.addFile(en); 143 factory.addFile(file); 144 145 CheckDisplayCollisions cdc = new CheckDisplayCollisions(factory); 146 cdc.setEnglishFile(CLDRConfig.getInstance().getEnglish()); 147 148 CLDRFile ptResolved = factory.make(testLocale, true); 149 if (expectCollisionErrors) { 150 checkFile(cdc, file, ptResolved, unitPatternA, unitPatternB); 151 } else { 152 checkFile(cdc, file, ptResolved); 153 } 154 } 155 checkFile( CheckDisplayCollisions cdc, CLDRFile cldrFile, CLDRFile cldrFileResolved, String... expectedErrors)156 private void checkFile( 157 CheckDisplayCollisions cdc, 158 CLDRFile cldrFile, 159 CLDRFile cldrFileResolved, 160 String... expectedErrors) { 161 List<CheckStatus> possibleErrors = new ArrayList<>(); 162 Options options = new Options(); 163 cdc.setCldrFileToCheck(cldrFile, options, possibleErrors); 164 if (!possibleErrors.isEmpty()) { 165 errln("init: " + possibleErrors); 166 possibleErrors.clear(); 167 } 168 Map<String, List<CheckStatus>> found = new HashMap<>(); 169 for (String path : cldrFileResolved) { 170 String value = cldrFileResolved.getStringValue(path); 171 // System.out.println(path + "\t" + value); 172 if (path.equals(deciLong)) { 173 int debug = 0; 174 } 175 cdc.check(path, path, value, options, possibleErrors); 176 if (!possibleErrors.isEmpty()) { 177 found.put(path, ImmutableList.copyOf(possibleErrors)); 178 possibleErrors.clear(); 179 logln("Found error " + cldrFile.getLocaleID() + ":\t" + path + ", " + value); 180 } else { 181 logln("No error " + cldrFile.getLocaleID() + ":\t" + path + ", " + value); 182 } 183 } 184 Set<String> expected = new TreeSet<>(Arrays.asList(expectedErrors)); 185 for (Entry<String, List<CheckStatus>> entry : found.entrySet()) { 186 String path = entry.getKey(); 187 if (expected.contains(path)) { 188 expected.remove(path); 189 } else { 190 errln( 191 cldrFile.getLocaleID() 192 + " unexpected error: " 193 + path 194 + " : " 195 + entry.getValue()); 196 } 197 checkUnknown(path, entry); 198 } 199 assertEquals( 200 cldrFile.getLocaleID() + " expected to be errors: ", 201 Collections.emptySet(), 202 expected); 203 } 204 205 /** 206 * Report an error if the CheckStatus parameters contain the word "Unknown", which can be a 207 * symptom of errors such as removal of required "count" attribute. "Unknown" may not always be 208 * an error, but for the data used in this test we don't expect it. 209 * 210 * @param path 211 * @param entry 212 */ checkUnknown(String path, Entry<String, List<CheckStatus>> entry)213 private void checkUnknown(String path, Entry<String, List<CheckStatus>> entry) { 214 CheckStatus cs = entry.getValue().get(0); 215 String s = cs.getParameters()[0].toString(); 216 if (s.contains("Unknown")) { 217 errln("Found Unknown in : " + path + ":\n" + s); 218 } 219 } 220 TestDotPixel14031()221 public void TestDotPixel14031() { 222 Map<String, String> pathValuePairs = 223 ImmutableMap.of( 224 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-dot\"]/displayName", 225 "Punkt", 226 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-pixel\"]/displayName", 227 "Punkt", 228 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-pixel-per-centimeter\"]/displayName", 229 "Punkt pro Zentimeter", 230 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-dot-per-centimeter\"]/displayName", 231 "Punkt pro Zentimeter"); 232 TestFactory factory = makeFakeCldrFile("de", pathValuePairs); 233 checkDisplayCollisions("de", pathValuePairs, factory); 234 } 235 checkDisplayCollisions( String locale, Map<String, String> pathValuePairs, TestFactory factory)236 public void checkDisplayCollisions( 237 String locale, Map<String, String> pathValuePairs, TestFactory factory) { 238 CheckDisplayCollisions cdc = new CheckDisplayCollisions(factory); 239 cdc.setEnglishFile(CLDRConfig.getInstance().getEnglish()); 240 241 List<CheckStatus> possibleErrors = new ArrayList<>(); 242 cdc.setCldrFileToCheck( 243 factory.make(locale, true), new Options(ImmutableMap.of()), possibleErrors); 244 for (Entry<String, String> entry : pathValuePairs.entrySet()) { 245 cdc.check( 246 entry.getKey(), 247 entry.getKey(), 248 entry.getValue(), 249 new Options(ImmutableMap.of()), 250 possibleErrors); 251 assertEquals(entry.toString(), Collections.emptyList(), possibleErrors); 252 } 253 } 254 makeFakeCldrFile(String locale, Map<String, String> pathValuePairs)255 public TestFactory makeFakeCldrFile(String locale, Map<String, String> pathValuePairs) { 256 TestFactory factory = new TestFactory(); 257 XMLSource rootSource = new SimpleXMLSource("root"); 258 factory.addFile(new CLDRFile(rootSource)); 259 260 XMLSource localeSource = new SimpleXMLSource(locale); 261 for (Entry<String, String> entry : pathValuePairs.entrySet()) { 262 localeSource.putValueAtPath(entry.getKey(), entry.getValue()); 263 } 264 factory.addFile(new CLDRFile(localeSource)); 265 return factory; 266 } 267 TestDurationPersonVariants()268 public void TestDurationPersonVariants() { 269 Map<String, String> pathValuePairs = 270 ImmutableMap.of( 271 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"duration-day-person\"]/unitPattern[@count=\"other\"]", 272 "Punkt", 273 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"duration-day\"]/unitPattern[@count=\"other\"]", 274 "Punkt", 275 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-pixel\"]/displayName", 276 "Punkt", 277 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-pixel-per-centimeter\"]/displayName", 278 "Punkt pro Zentimeter", 279 "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"graphics-dot-per-centimeter\"]/displayName", 280 "Punkt pro Zentimeter"); 281 TestFactory factory = makeFakeCldrFile("de", pathValuePairs); 282 checkDisplayCollisions("de", pathValuePairs, factory); 283 } 284 } 285