blob: c964443cdd28c6c39ba842498e16659488373b2a [file] [log] [blame]
package org.unicode.cldr.unittest;
/*
* TODO: rename this file and class to avoid confusion with org.unicode.cldr.util TestUtilities.java
* When Eclipse console shows an error such as
* Error: (TestUtilities.java:1154) : 8 value: expected "old-value", got null
* the link wrongly opens the wrong file named TestUtilities.java. The two files are:
* cldr/tools/cldr-code/src/main/java/org/unicode/cldr/util/TestUtilities.java
* cldr/tools/cldr-code/src/test/java/org/unicode/cldr/unittest/TestUtilities.java
*/
import java.io.StringWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import org.unicode.cldr.test.SubmissionLocales;
import org.unicode.cldr.tool.ConvertLanguageData.InverseComparator;
import org.unicode.cldr.util.CLDRConfig;
import org.unicode.cldr.util.CLDRFile;
import org.unicode.cldr.util.CLDRLocale;
import org.unicode.cldr.util.CLDRURLS;
import org.unicode.cldr.util.CldrUtility;
import org.unicode.cldr.util.Counter;
import org.unicode.cldr.util.DelegatingIterator;
import org.unicode.cldr.util.EscapingUtilities;
import org.unicode.cldr.util.Factory;
import org.unicode.cldr.util.NotificationCategory;
import org.unicode.cldr.util.Organization;
import org.unicode.cldr.util.PathHeader;
import org.unicode.cldr.util.PathHeader.PageId;
import org.unicode.cldr.util.PatternCache;
import org.unicode.cldr.util.PluralSamples;
import org.unicode.cldr.util.SpecialLocales;
import org.unicode.cldr.util.StringId;
import org.unicode.cldr.util.SupplementalDataInfo;
import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo.Count;
import org.unicode.cldr.util.VettingViewer;
import org.unicode.cldr.util.VettingViewer.MissingStatus;
import org.unicode.cldr.util.VettingViewer.VoteStatus;
import org.unicode.cldr.util.VoteResolver;
import org.unicode.cldr.util.VoteResolver.Level;
import org.unicode.cldr.util.VoteResolver.Status;
import org.unicode.cldr.util.VoteResolver.VoterInfo;
import org.unicode.cldr.util.VoterInfoList;
import org.unicode.cldr.util.XMLUploader;
import org.unicode.cldr.util.props.ICUPropertyFactory;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Ordering;
import com.ibm.icu.dev.util.UnicodeMap;
import com.ibm.icu.impl.Relation;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.lang.UProperty;
import com.ibm.icu.text.Collator;
import com.ibm.icu.text.UnicodeSet;
import com.ibm.icu.util.ULocale;
public class TestUtilities extends TestFmwkPlus {
public static boolean DEBUG = true;
private static final UnicodeSet DIGITS = new UnicodeSet("[0-9]");
static CLDRConfig testInfo = CLDRConfig.getInstance();
private static final SupplementalDataInfo SUPPLEMENTAL_DATA_INFO = testInfo
.getSupplementalDataInfo();
private static final int STRING_ID_TEST_COUNT = 1024 * 16;
final int ONE_VETTER_BAR = Level.vetter.getVotes(Organization.guest);
final int TWO_VETTER_BAR = 2 * ONE_VETTER_BAR;
public static void main(String[] args) {
new TestUtilities().run(args);
}
public void TestPluralSamples() {
checkPluralSamples("en");
checkPluralSamples("cs");
checkPluralSamples("ar");
}
private void checkPluralSamples(String locale) {
PluralSamples pluralSamples = PluralSamples.getInstance(locale);
Set<Count> counts = SUPPLEMENTAL_DATA_INFO.getPlurals(locale)
.getCounts();
for (int i = 1; i < 5; ++i) {
Map<Count, Double> samplesForDigits = pluralSamples.getSamples(i);
if (!counts.containsAll(samplesForDigits.keySet())) {
errln(locale + ": mismatch in samples, expected " + counts
+ ", got: " + samplesForDigits);
} else if (samplesForDigits.size() == 0) {
errln(locale + ": no sample for digit " + i);
} else {
logln(locale + " plural samples: " + samplesForDigits);
}
}
}
public static class StringIdException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
public class StringIdThread extends Thread {
final private Random r = new Random();
final private int id;
StringIdThread(int i) {
super("Demo Thread");
id = i;
}
@Override
public void run() {
logln("Starting thread: " + this);
for (int i = 0; i < STRING_ID_TEST_COUNT; ++i) {
String s = String.valueOf(r.nextInt());
long l = StringId.getId(s);
String s2 = StringId.getStringFromId(l);
if (!s.equals(s2)) {
throw new StringIdException();
}
}
logln("Ending thread: " + this);
}
@Override
public String toString() {
return "StringIdThread " + id;
}
}
public void TestStringId() {
ArrayList<StringIdThread> threads = new ArrayList<>();
for (int i = 0; i < 8; i++) {
StringIdThread thread = new StringIdThread(i);
threads.add(thread);
thread.start();
}
for (StringIdThread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
errln(e.toString());
}
}
}
public void TestUrlEscape() {
Matcher byte1 = PatternCache.get("%[A-Za-z0-9]{2}").matcher("");
Matcher byte2 = PatternCache.get("%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}")
.matcher("");
Matcher byte3 = PatternCache.get(
"%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}").matcher("");
Matcher byte4 = PatternCache.get(
"%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}%[A-Za-z0-9]{2}")
.matcher("");
for (int i = 1; i <= 0x10FFFF; i = i * 3 / 2 + 1) {
String escaped = EscapingUtilities.urlEscape(new StringBuilder()
.appendCodePoint(i).toString());
logln(Integer.toHexString(i) + " => " + escaped);
if (EscapingUtilities.OK_TO_NOT_QUOTE.contains(i)) {
assertTrue("Should be unquoted", escaped.length() == 1);
} else if (i < 0x80) {
assertTrue("Should be %xx", byte1.reset(escaped).matches());
} else if (i < 0x800) {
assertTrue("Should be %xx%xx", byte2.reset(escaped).matches());
} else if (i < 0x10000) {
assertTrue("Should be %xx%xx%xx", byte3.reset(escaped)
.matches());
} else {
assertTrue("Should be %xx%xx%xx%xx", byte4.reset(escaped)
.matches());
}
}
}
public void TestDelegatingIterator() {
Set<String> s = new TreeSet<>(Arrays.asList(new String[] { "a",
"b", "c" }));
Set<String> t = new LinkedHashSet<>(Arrays.asList(new String[] {
"f", "d", "e" }));
StringBuilder result = new StringBuilder();
for (String u : DelegatingIterator.iterable(s, t)) {
result.append(u);
}
assertEquals("Iterator", "abcfde", result.toString());
result.setLength(0);
for (String u : DelegatingIterator.array("s", "t", "u")) {
result.append(u);
}
assertEquals("Iterator", "stu", result.toString());
int count = 0;
result.setLength(0);
for (int u : DelegatingIterator.array(1, 3, 5)) {
count += u;
}
assertEquals("Iterator", 9, count);
result.setLength(0);
for (Object u : DelegatingIterator.array(1, "t", "u", new UnicodeSet(
"[a-z]"))) {
result.append(u);
}
assertEquals("Iterator", "1tu[a-z]", result.toString());
}
public void TestUntimedCounter() {
// simulates how Counter is used in VettingViewer
Counter<NotificationCategory> problemCounter = new Counter<>();
problemCounter.increment(NotificationCategory.error);
problemCounter.increment(NotificationCategory.error);
problemCounter.increment(NotificationCategory.warning);
assertEquals("problemCounter error", 2, problemCounter.get(NotificationCategory.error));
assertEquals("problemCounter warning", 1, problemCounter.get(NotificationCategory.warning));
assertEquals("problemCounter weLost", 0, problemCounter.get(NotificationCategory.weLost));
Counter<NotificationCategory> otherCounter = new Counter<>();
otherCounter.addAll(problemCounter);
otherCounter.increment(NotificationCategory.error);
assertEquals("otherCounter error", 3, otherCounter.get(NotificationCategory.error));
assertEquals("otherCounter warning", 1, otherCounter.get(NotificationCategory.warning));
assertEquals("otherCounter weLost", 0, otherCounter.get(NotificationCategory.weLost));
}
public void TestCounter() {
Counter<String> counter = new Counter<>(true);
Comparator<String> uca = new Comparator<>() {
Collator col = Collator.getInstance(ULocale.ENGLISH);
@Override
public int compare(String o1, String o2) {
return col.compare(o1, o2);
}
};
InverseComparator ucaDown = new InverseComparator(uca);
counter.add("c", 95);
counter.add("b", 50);
counter.add("b", 101);
counter.add("a", 100);
counter.add("a", -5);
counter.add("d", -3);
assertEquals("getCount(b)", counter.getCount("b"), 151);
assertEquals("getCount(a)", counter.getCount("a"), 95);
assertEquals("getCount(a)", counter.getTotal(), 338);
assertEquals("getItemCount", counter.getItemCount(), 4);
assertEquals("getMap", "{a=95, b=151, c=95, d=-3}", counter.toString());
assertEquals("getKeysetSortedByKey", Arrays.asList("a", "b", "c", "d"),
new ArrayList<>(counter.getKeysetSortedByKey()));
assertEquals(
"getKeysetSortedByCount(true, ucaDown)",
Arrays.asList("d", "c", "a", "b"),
new ArrayList<String>(counter.getKeysetSortedByCount(true,
ucaDown)));
assertEquals("getKeysetSortedByCount(true, null), value",
Arrays.asList("d", "a", "c", "b"), new ArrayList<>(
counter.getKeysetSortedByCount(true, uca)));
assertEquals("getKeysetSortedByCount(false, ucaDown), descending",
Arrays.asList("b", "c", "a", "d"), new ArrayList<String>(
counter.getKeysetSortedByCount(false, ucaDown)));
assertEquals("getKeysetSortedByCount(false, null), descending, value",
Arrays.asList("b", "a", "c", "d"), new ArrayList<>(
counter.getKeysetSortedByCount(false, uca)));
}
public void TestOrganizationOrder() {
Map<String, Organization> stringToOrg = new TreeMap<>();
for (Organization org : Organization.values()) {
stringToOrg.put(org.toString(), org);
}
List<Organization> reordered = new ArrayList<>(
stringToOrg.values());
List<Organization> plain = Arrays.asList(Organization.values());
for (int i = 0; i < reordered.size(); ++i) {
assertEquals("Items not in alphabetical order", reordered.get(i),
plain.get(i));
}
}
public void TestOrganizationNames() {
UnicodeSet uppercase = new UnicodeSet("[:uppercase:]");
for (Organization org : Organization.values()) {
if (!uppercase.contains(org.getDisplayName().codePointAt(0))) {
errln("Organization name isn't titlecased: " + org + ", "
+ org.getDisplayName());
}
assertEquals("Organization from enum name", org,
Organization.fromString(org.toString()));
assertEquals("Organization from display name", org,
Organization.fromString(org.getDisplayName()));
}
}
static final boolean SHOW_DETAILS = CldrUtility.getProperty("showdetails",
false);
private static final CharSequence DEBUG_COMMENT = "set up a case of conflict within organization";
static class PathValueInfo {
private static Map<Integer, String> voteInfo;
private CLDRFile file;
public PathValueInfo(Factory factory, String locale) {
this.file = factory.make(locale, false);
}
public String getRealValue(int id) {
return file.getStringValue(getRealPath(id));
}
public String getRealPath(int id) {
return voteInfo.get(id);
}
}
/** Test user data. Restructured to be easier to read, more typesafe */
enum TestUser {
guestS(801, Organization.guest, Level.street),
gnomeS(701, Organization.gnome, Level.street),
gnomeV(702, Organization.gnome, Level.vetter),
googleV(404, Organization.google, Level.vetter),
googleS(411, Organization.google, Level.street),
googleV2(424, Organization.google, Level.vetter),
appleV(304, Organization.apple, Level.vetter),
adobeE(204, Organization.adobe, Level.manager),
adobeV(209, Organization.adobe, Level.vetter),
ibmS(101, Organization.ibm, Level.street),
microsoftV(134, Organization.microsoft, Level.vetter),
ibmE(114, Organization.ibm, Level.manager),
ibmT(129, Organization.ibm, Level.tc),
guestS2(802, Organization.guest, Level.street);
public static final Map<Integer, VoterInfo> TEST_USERS;
public final Integer voterId;
public final VoterInfo voterInfo;
TestUser(int intVoterId, Organization organization, Level level) {
voterId = intVoterId;
voterInfo = new VoterInfo(organization, level, name());
}
static {
ImmutableMap.Builder<Integer, VoterInfo> temp = ImmutableMap.builder();
for (TestUser testUser : values()) {
temp.put(testUser.voterId, testUser.voterInfo);
}
TEST_USERS = temp.build();
}
}
public static final Map<Integer, VoterInfo> testdata = TestUser.TEST_USERS;
private int toVoterId(String s) {
return TestUser.valueOf(s).voterId;
}
private VoterInfoList getTestVoterInfoList() {
return new VoterInfoList().setVoterToInfo(testdata);
}
public void TestTrunkStatus() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("new-item", Status.approved);
assertEquals("", "new-item", resolver.getWinningValue());
/*
* Formerly last-release would win over trunk in a 2nd scenario here, due to
* the difference in status. Now last-release plays no role, that test is obsolete.
* Reference: https://unicode.org/cldr/trac/ticket/11916
*/
}
public void TestVoteResolverNgombaTrunkStatus() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
resolver.setLocale(CLDRLocale.getInstance("jgo"), null);
final String jgo22trunk = "\uA78C"; // "[a á â ǎ b c d ɛ {ɛ́} {ɛ̂} {ɛ̌} {ɛ̀} {ɛ̄} f ɡ h i í î ǐ j k l m ḿ {m̀} {m̄} n ń ǹ {n̄} ŋ {ŋ́} {ŋ̀} {ŋ̄} ɔ {ɔ́} {ɔ̂} {ɔ̌} p {pf} s {sh} t {ts} u ú û ǔ ʉ {ʉ́} {ʉ̂} {ʉ̌} {ʉ̈} v w ẅ y z ꞌ]";
resolver.setBaseline(jgo22trunk, Status.approved); // seed/jgo.xml from 22
// trunk
logln("SVN: " + jgo22trunk);
logln(resolver.toString());
assertEquals("Winning Value", jgo22trunk, resolver.getWinningValue());
}
public void TestVoteStatus() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("fii", toVoterId("adobeE"));
resolver.add("fii", toVoterId("appleV"));
VoteStatus voteStatus;
voteStatus = resolver.getStatusForOrganization(Organization.google);
assertEquals("", VoteStatus.ok, voteStatus);
voteStatus = resolver.getStatusForOrganization(Organization.apple);
assertEquals("", VoteStatus.ok, voteStatus);
// make non-equal foo
String s1 = "foo";
String s2 = new StringBuilder("fo").append("o").toString();
if (s1 == s2) {
errln("Test problem");
}
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setBaseline(s1, Status.approved);
resolver.add(s2, toVoterId("appleV"));
voteStatus = resolver.getStatusForOrganization(Organization.apple);
assertEquals("", VoteStatus.ok, voteStatus);
}
public void TestLosingStatus() {
// af
// losing? {baseline: {BQ, missing}, trunk: {null, null},
// {orgToVotes: , totals: {}, conflicted: []},
// sameVotes: [BQ], O: null, N: null, totals: {}, winning: {BQ,
// missing}}
// XPath: //ldml/localeDisplayNames/territories/territory[@type="BQ"]
// gcvs.openoffice_org.example.com
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
resolver.setLocale(CLDRLocale.getInstance("af"), null);
resolver.setBaseline("BQ", Status.missing);
VoteStatus status = resolver
.getStatusForOrganization(Organization.openoffice_org);
assertEquals("", VoteStatus.provisionalOrWorse, status);
// {lastRelease: {{0}: {1}, missing}, trunk: {null, null}, {orgToVotes:
// pakistan={{0}: {1}=8}, totals: {{0}:
// {1}=8}, conflicted: []}, sameVotes: [{0}: {1}], O: {0}: {1}, N: null,
// totals: {{0}: {1}=8}, winning: {{0}:
// {1}, approved}}
resolver.clear();
resolver.setBaileyValue("bailey");
// resolver.setLastRelease("{0}: {1}", Status.missing);
resolver.add("{0}: {1}", toVoterId("adobeE"));
status = resolver.getStatusForOrganization(Organization.openoffice_org);
assertEquals("", VoteStatus.ok, status);
// {lastRelease: {Arabisch, approved}, trunk: {Arabisch, approved},
// {orgToVotes: , totals: {}, conflicted: []},
// sameVotes: [Arabisch], O: null, N: null, totals: {}, winning:
// {Arabisch, approved}}
resolver.clear();
resolver.setBaileyValue("bailey");
// resolver.setLastRelease("Arabisch", Status.approved);
resolver.setBaseline("Arabisch", Status.approved);
status = resolver.getStatusForOrganization(Organization.openoffice_org);
assertEquals("", VoteStatus.ok_novotes, status);
}
public void TestTotalVotesStatus() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
Status oldStatus = Status.unconfirmed;
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("zebra", toVoterId("googleV"));
resolver.add("apple", toVoterId("appleV"));
// check that alphabetical wins when votes are equal
String winner = resolver.getWinningValue();
Status winningStatus = resolver.getWinningStatus();
assertEquals("", "apple", winner);
assertEquals("", Status.provisional, winningStatus);
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("zebra", toVoterId("googleV"));
resolver.add("zebra", toVoterId("googleS"));
resolver.add("apple", toVoterId("appleV"));
// check that total votes over alphabetical
winner = resolver.getWinningValue();
winningStatus = resolver.getWinningStatus();
assertEquals("", "zebra", winner);
assertEquals("", Status.provisional, winningStatus);
}
public void TestVoteDowngrade() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
Status oldStatus = Status.unconfirmed;
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("mt"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("aardvark", toVoterId("adobeE"));
resolver.add("zebra", toVoterId("ibmT"));
assertEquals("", "zebra", resolver.getWinningValue()); // TC vote of 20
// beats
// expert's 8
assertEquals("", Status.approved, resolver.getWinningStatus());
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("mt"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("aardvark", toVoterId("adobeE"));
resolver.add("zebra", toVoterId("ibmT"));
resolver.add("aardvark", toVoterId("ibmE"));
assertEquals("", "zebra", resolver.getWinningValue()); // TC vote of 20
// beats
// manager's 4
// and its own
// manager's 4
assertEquals("", Status.approved, resolver.getWinningStatus());
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("mt"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("aardvark", toVoterId("adobeE"));
resolver.add("zebra", toVoterId("ibmT"), Level.vetter.getVotes(Organization.ibm)); // NOTE:
// reduced
// votes:
// as
// vetter.
resolver.add("aardvark", toVoterId("ibmE"));
assertEquals("", "aardvark", resolver.getWinningValue()); // Now
// aardvark
// wins -
// managers
// win out as provisional
assertEquals("", Status.provisional, resolver.getWinningStatus());
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("mt"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("aardvark", toVoterId("adobeE"));
resolver.add("zebra", toVoterId("ibmT"), Level.vetter.getVotes(Organization.ibm)); // NOTE:
// reduced
// votes:
// as
// vetter.
assertEquals("", "aardvark", resolver.getWinningValue()); // Now
// aardvark
// wins -
// managers
// win out.
assertEquals("", Status.provisional, resolver.getWinningStatus());
}
public void TestResolvedVoteCounts() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
Status oldStatus = Status.unconfirmed;
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("foo", oldStatus);
resolver.add("zebra", toVoterId("googleV"));
resolver.add("apple", toVoterId("appleV"));
// check that alphabetical wins when votes are equal
Map<String, Long> counts = resolver.getResolvedVoteCounts();
logln(counts.toString());
assertEquals("", "foo", new ArrayList<>(counts.keySet()).get(2));
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("foo", Status.approved);
resolver.add("zebra", toVoterId("googleV"));
resolver.add("apple", toVoterId("appleV"));
counts = resolver.getResolvedVoteCounts();
logln(counts.toString());
assertEquals("", "foo", new ArrayList<>(counts.keySet()).get(0));
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaseline("foo", Status.approved);
resolver.add("zebra", toVoterId("googleS"));
counts = resolver.getResolvedVoteCounts();
logln(counts.toString());
assertEquals("", "foo", new ArrayList<>(counts.keySet()).get(0));
}
private void verifyRequiredVotes(VoteResolver<String> resolver, String locale,
String xpath, Status baselineStatus, int required) {
StringBuilder sb = new StringBuilder();
sb.append("Locale: " + locale);
resolver.clear();
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", baselineStatus);
PathHeader ph = null;
if (xpath != null) {
sb.append(" XPath: " + xpath);
ph = PathHeader.getFactory(testInfo.getEnglish())
.fromPath(xpath);
}
resolver.setLocale(CLDRLocale.getInstance(locale), ph);
if (!assertEquals(locale + " verifyRequiredVotes: " + ph.toString(), required, resolver.getRequiredVotes())) {
int debug = 0;
}
}
public void TestRequiredVotes() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
verifyRequiredVotes(resolver, "mt",
"//ldml/localeDisplayNames/languages/language[@type=\"fr_CA\"]",
Status.missing, ONE_VETTER_BAR);
verifyRequiredVotes(resolver, "fr",
"//ldml/localeDisplayNames/languages/language[@type=\"fr_CA\"]",
Status.provisional, TWO_VETTER_BAR);
verifyRequiredVotes(resolver, "es",
"//ldml/numbers/symbols[@numberSystem=\"latn\"]/group",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "es",
"//ldml/numbers/symbols[@numberSystem=\"latn\"]/decimal",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "hi",
"//ldml/numbers/symbols[@numberSystem=\"deva\"]/decimal",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "hi",
"//ldml/numbers/symbols[@numberSystem=\"deva\"]/group",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "ast",
"//ldml/numbers/symbols[@numberSystem=\"latn\"]/decimal",
Status.approved, ONE_VETTER_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters[@type=\"auxiliary\"]",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters[@type=\"numbers\"]",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters[@type=\"punctuation\"]",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "mt",
"//ldml/characters/exemplarCharacters[@type=\"index\"]",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "es",
"//ldml/dates/calendars/calendar[@type=\"gregorian\"]/days/dayContext[@type=\"format\"]/dayWidth[@type=\"wide\"]/day[@type=\"sun\"]",
Status.approved, VoteResolver.HIGH_BAR);
verifyRequiredVotes(resolver, "ast",
"//ldml/dates/calendars/calendar[@type=\"gregorian\"]/days/dayContext[@type=\"format\"]/dayWidth[@type=\"wide\"]/day[@type=\"sun\"]",
Status.approved, ONE_VETTER_BAR);
verifyRequiredVotes(resolver, "es",
"//ldml/dates/calendars/calendar[@type=\"gregorian\"]/months/monthContext[@type=\"format\"]/monthWidth[@type=\"wide\"]/month[@type=\"1\"]",
Status.provisional, VoteResolver.LOWER_BAR);
verifyRequiredVotes(resolver, "ast",
"//ldml/dates/calendars/calendar[@type=\"gregorian\"]/months/monthContext[@type=\"format\"]/monthWidth[@type=\"wide\"]/month[@type=\"1\"]",
Status.approved, ONE_VETTER_BAR);
}
/**
* In sublocales, for a typical path, the required votes should be 4, except for
* a few specified locales.
*/
public void TestSublocaleRequiredVotes() {
final Set<String> eightVoteSublocales = new HashSet<>(Arrays.asList("pt_PT", "zh_Hant", "en_AU", "en_GB", "es_MX", "fr_CA", "es_419"));
final VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
final String path = "//ldml/annotations/annotation[@cp=\"🌏\"][@type=\"tts\"]";
for (String locale : SubmissionLocales.CLDR_OR_HIGH_LEVEL_LOCALES) {
if (locale.contains("_")) {
int expectedRequiredVotes = eightVoteSublocales.contains(locale) ? TWO_VETTER_BAR : ONE_VETTER_BAR;
verifyRequiredVotes(resolver, locale, path, Status.approved, expectedRequiredVotes);
}
}
}
public void TestVoteResolver() {
// to make it easier to debug failures, the first digit is an org,
// second is the individual in that org, and
// third is the voting weight.
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
String[] tests = {
"bailey=BAILEY",
"comment=regression case from John Emmons",
"locale=wae",
"oldValue=2802",
"oldStatus=approved",
"304=208027", // Apple vetter
// expected values
"value=208027",
"status=approved",
"sameVotes=208027",
"conflicts=[]",
"check",
// first test
"oldValue=old-value",
"oldStatus=provisional",
"comment=Check that identical values get the top overall vote, and that org is maxed (eg vetter + street = vetter)",
"404=next",
"411=next",
"304=best",
// expected values
"value=next",
"sameVotes=next,best",
"conflicts=[]",
"status=provisional",
"check",
"comment=now give next a slight edge (5 to 4) with a different organization",
"404=next",
"304=best",
"801=next",
// expected values
"value=next",
"sameVotes=next",
"status=approved",
"check",
"comment=set up a case of conflict within organization",
"404=next",
"424=best",
// expected values
"value=best", // alphabetical
"sameVotes=best",
"conflicts=[google]",
"status=approved",
"check",
"comment=now cross-organizational conflict, also check for max value in same organization (4, 1) => 4 not 5",
"404=next",
"424=best",
"411=best",
"304=best",
// expected values
"conflicts=[google]",
"value=best",
"sameVotes=best",
"status=approved",
"check",
"comment=now clear winner 8 over 4",
"404=next",
// "424=best",
"411=best",
"304=best",
"204=primo",
"114=primo",
// expected values
"conflicts=[]",
"value=primo",
"sameVotes=primo",
"status=approved",
"check",
"comment=now not so clear, throw in a street value. So it is 8 to 5. (used to be provisional)",
"404=next",
// "424=best",
"411=best",
"304=best",
"204=primo",
"114=primo",
"101=best",
// expected values
"conflicts=[]",
"value=primo",
"status=approved",
"check",
"comment=set up vote of 4 in established locale, with old provisional value",
"locale=fr",
"404=best",
"oldStatus=provisional",
// expected values
"value=best",
"sameVotes=best",
"status=contributed",
"conflicts=[]",
"check",
"comment=now set up vote of 4 in established locale, but with old contributed value",
"oldStatus=contributed",
// expected values
"value=old-value",
"sameVotes=old-value",
"status=contributed",
"conflicts=[]",
"check",
"comment=now set up vote of 1 + 1 in established locale, and with old contributed value",
"411=best", "101=best", "oldStatus=contributed",
// expected values
"value=best", "sameVotes=best", "status=contributed",
"conflicts=[]", "check", };
String expectedValue = null;
String expectedConflicts = null;
Status expectedStatus = null;
String oldValue = null;
Status oldStatus = null;
String baileyValue = null;
List<String> sameVotes = null;
String locale = null;
Map<Integer, String> values = new TreeMap<>();
int counter = -1;
for (String test : tests) {
String[] item = test.split("=");
String name = item[0];
String value = item.length < 2 ? null : item[1];
if (name.equalsIgnoreCase("comment")) {
logln("#\t" + value);
//System.out.println("#\t" + value);
if (DEBUG_COMMENT != null && value.contains(DEBUG_COMMENT)) {
int x = 0;
}
} else if (name.equalsIgnoreCase("locale")) {
locale = value;
} else if (name.equalsIgnoreCase("bailey")) {
baileyValue = value;
} else if (name.equalsIgnoreCase("oldValue")) {
oldValue = value;
} else if (name.equalsIgnoreCase("oldStatus")) {
oldStatus = Status.valueOf(value);
} else if (name.equalsIgnoreCase("value")) {
expectedValue = value;
} else if (name.equalsIgnoreCase("sameVotes")) {
sameVotes = value == null ? new ArrayList<>(0) : Arrays
.asList(value.split(",\\s*"));
} else if (name.equalsIgnoreCase("status")) {
expectedStatus = Status.valueOf(value);
} else if (name.equalsIgnoreCase("conflicts")) {
expectedConflicts = value;
} else if (DIGITS.containsAll(name)) {
final int voter = Integer.parseInt(name);
if (value == null || value.equals("null")) {
values.remove(voter);
} else {
values.put(voter, value);
}
} else if (name.equalsIgnoreCase("check")) {
counter++;
// load the resolver
resolver.setBaileyValue(baileyValue);
resolver.setLocale(CLDRLocale.getInstance(locale), null);
resolver.setBaseline(oldValue, oldStatus);
for (int voter : values.keySet()) {
resolver.add(values.get(voter), voter);
}
// print the contents
logln(counter + "\t" + values);
logln(resolver.toString());
// now print the values
assertEquals(counter + " value", expectedValue,
resolver.getWinningValue());
assertEquals(counter + " sameVotes", sameVotes.toString(),
resolver.getValuesWithSameVotes().toString());
assertEquals(counter + " status", expectedStatus,
resolver.getWinningStatus());
assertEquals(counter + " conflicts", expectedConflicts,
resolver.getConflictedOrganizations().toString());
resolver.clear();
resolver.setBaileyValue("bailey");
values.clear();
} else {
errln("unknown command:\t" + test);
}
}
}
void assertSpecialLocale(String loc, SpecialLocales.Type type) {
assertEquals("SpecialLocales.txt for " + loc, type,
SpecialLocales.getType(CLDRLocale.getInstance(loc)));
}
public void TestSpecialLocales() {
assertSpecialLocale("sr", null);
assertSpecialLocale("ha_NE", SpecialLocales.Type.readonly);
assertSpecialLocale("sr_Latn", SpecialLocales.Type.readonly);
assertSpecialLocale("sr_Latn_BA", SpecialLocales.Type.readonly);
assertSpecialLocale("yue_Hans", null); // not readonly, because it is not policy DISCARD
assertSpecialLocale("en", SpecialLocales.Type.readonly);
assertSpecialLocale("en_ZZ", SpecialLocales.Type.readonly);
assertSpecialLocale("en_ZZ_PROGRAMMERESE", null); // not defined
assertSpecialLocale("und", null);
assertSpecialLocale("mul", SpecialLocales.Type.scratch);
assertSpecialLocale("mul_ZZ", SpecialLocales.Type.scratch);
assertSpecialLocale("und_001", null); // not defined
CLDRLocale sr_Latn = CLDRLocale.getInstance("sr_Latn");
CLDRLocale sr_Latn_BA = CLDRLocale.getInstance("sr_Latn_BA");
logln("sr_Latn raw comment = " + SpecialLocales.getCommentRaw(sr_Latn));
assertTrue("sr_Latn raw contains @ sign",
SpecialLocales.getCommentRaw(sr_Latn).contains("@"));
logln("sr_Latn comment = " + SpecialLocales.getComment(sr_Latn));
assertTrue("sr_Latn comment does NOT contain @ sign", !SpecialLocales
.getComment(sr_Latn).contains("@"));
logln("sr_Latn_BA raw comment = "
+ SpecialLocales.getCommentRaw(sr_Latn_BA));
assertTrue("sr_Latn_BA raw contains '@sr_Latn_BA'", SpecialLocales
.getCommentRaw(sr_Latn_BA).contains("@sr_Latn_BA"));
}
public void TestCLDRURLS() {
final String KOREAN_LANGUAGE = "//ldml/localeDisplayNames/languages/language[@type=\"ko\"]";
final String KOREAN_LANGUAGE_STRID = "821c2a2fc5c206d";
final CLDRLocale maltese = CLDRLocale.getInstance("mt");
assertEquals("base", "https://st.unicode.org/cldr-apps", CLDRConfig
.getInstance().urls().base());
assertEquals(
"locales list",
"https://st.unicode.org/cldr-apps/v#locales///",
CLDRConfig.getInstance().urls()
.forSpecial(CLDRURLS.Special.Locales));
assertEquals("maltese", "https://st.unicode.org/cldr-apps/v#/mt//",
CLDRConfig.getInstance().urls().forLocale(maltese));
assertEquals("korean in maltese",
"https://st.unicode.org/cldr-apps/v#/mt//"
+ KOREAN_LANGUAGE_STRID,
CLDRConfig.getInstance()
.urls().forXpath(maltese, KOREAN_LANGUAGE));
assertEquals("korean in maltese via stringid",
"https://st.unicode.org/cldr-apps/v#/mt//"
+ KOREAN_LANGUAGE_STRID,
CLDRConfig.getInstance()
.urls().forXpathHexId(maltese, KOREAN_LANGUAGE_STRID));
assertEquals("south east asia in maltese",
"https://st.unicode.org/cldr-apps/v#/mt/C_SEAsia/", CLDRConfig
.getInstance().urls().forPage(maltese, PageId.C_SEAsia));
try {
String ret = CLDRConfig.getInstance().urls()
.forXpathHexId(maltese, KOREAN_LANGUAGE);
errln("Error- expected forXpathHexId to choke on an xpath but got "
+ ret);
} catch (IllegalArgumentException iae) {
logln("GOOD: forXpathHexId Caught expected " + iae);
}
try {
String ret = CLDRConfig.getInstance().urls()
.forXpath(maltese, KOREAN_LANGUAGE_STRID);
errln("Error- expected forXpath to choke on a hexid but got "
+ ret);
} catch (IllegalArgumentException iae) {
logln("GOOD: forXpath Caught expected " + iae);
}
assertEquals("korean in maltese - absoluteUrl",
"https://st.unicode.org/cldr-apps/v#/mt//"
+ KOREAN_LANGUAGE_STRID,
CLDRConfig.getInstance()
.absoluteUrls().forXpath(maltese, KOREAN_LANGUAGE));
}
static final UnicodeMap<String> SCRIPTS = ICUPropertyFactory.make().getProperty("script").getUnicodeMap_internal();
static final UnicodeMap<String> GC = ICUPropertyFactory.make().getProperty("general_category").getUnicodeMap_internal();
public void TestUnicodeMapCompose() {
logln("Getting Scripts");
UnicodeMap.Composer<String> composer = new UnicodeMap.Composer<>() {
@Override
public String compose(int codepoint, String string, String a, String b) {
return a.toString() + "_" + b.toString();
}
};
logln("Trying Compose");
UnicodeMap<String> composed = ((UnicodeMap) SCRIPTS.cloneAsThawed()).composeWith(GC, composer);
String last = "";
for (int i = 0; i < 0x10FFFF; ++i) {
String comp = composed.getValue(i);
String gc = GC.getValue(i);
String sc = SCRIPTS.getValue(i);
if (!comp.equals(composer.compose(i, null, sc, gc))) {
errln("Failed compose at: " + i);
break;
}
if (!last.equals(comp)) {
logln(Utility.hex(i) + "\t" + comp);
last = comp;
}
}
}
private static final int SET_LIMIT = 0x10FFFF;
private static final int CHECK_LIMIT = 0xFFFF;
private static final NumberFormat pf = NumberFormat.getPercentInstance();
private static final NumberFormat nf = NumberFormat.getInstance();
public void TestUnicodeMapTime() {
boolean shortTest = getInclusion() < 10;
double hashTime, umTime, icuTime, treeTime;
int warmup = shortTest ? 1 : 20;
umTime = checkUnicodeMapSetTime(warmup, 0);
hashTime = checkUnicodeMapSetTime(warmup, 1);
logln("Percentage: " + pf.format(hashTime / umTime));
treeTime = checkUnicodeMapSetTime(warmup, 3);
logln("Percentage: " + pf.format(treeTime / umTime));
if (shortTest) {
return;
}
umTime = checkUnicodeMapGetTime(1000, 0);
hashTime = checkUnicodeMapGetTime(1000, 1);
logln("Percentage: " + pf.format(hashTime / umTime));
icuTime = checkUnicodeMapGetTime(1000, 2);
logln("Percentage: " + pf.format(icuTime / umTime));
treeTime = checkUnicodeMapGetTime(1000, 3);
logln("Percentage: " + pf.format(treeTime / umTime));
}
private static final int propEnum = UProperty.GENERAL_CATEGORY;
private double checkUnicodeMapSetTime(int iterations, int type) {
_checkUnicodeMapSetTime(1, type);
double result = _checkUnicodeMapSetTime(iterations, type);
logln((type == 0 ? "UnicodeMap" : type == 1 ? "HashMap" : type == 2 ? "ICU" : "TreeMap") + "\t" + nf.format(result));
return result;
}
private double _checkUnicodeMapSetTime(int iterations, int type) {
UnicodeMap<String> map1 = SCRIPTS;
Map<Integer, String> map2 = map1.putAllCodepointsInto(new HashMap<Integer, String>());
Map<Integer, String> map3 = new TreeMap<>(map2);
System.gc();
double start = System.currentTimeMillis();
for (int j = 0; j < iterations; ++j)
for (int cp = 0; cp <= SET_LIMIT; ++cp) {
int enumValue = UCharacter.getIntPropertyValue(cp, propEnum);
if (enumValue <= 0) continue; // for smaller set
String value = UCharacter.getPropertyValueName(propEnum, enumValue, UProperty.NameChoice.LONG);
switch (type) {
case 0:
map1.put(cp, value);
break;
case 1:
map2.put(cp, value);
break;
case 3:
map3.put(cp, value);
break;
}
}
double end = System.currentTimeMillis();
return (end - start) / 1000 / iterations;
}
private double checkUnicodeMapGetTime(int iterations, int type) {
UnicodeMap<String> map1 = new UnicodeMap<>();
Map<Integer, String> map2 = map1.putAllCodepointsInto(new HashMap<Integer, String>());
Map<Integer, String> map3 = new TreeMap<>();
_checkUnicodeMapGetTime(map1, map2, map3, 1, type); // warmup
double result = _checkUnicodeMapGetTime(map1, map2, map3, iterations, type);
logln((type == 0 ? "UnicodeMap" : type == 1 ? "HashMap" : type == 2 ? "ICU" : "TreeMap") + "\t" + nf.format(result));
return result;
}
private double _checkUnicodeMapGetTime(UnicodeMap<String> map1, Map<Integer, String> map2, Map<Integer, String> map3, int iterations, int type) {
System.gc();
double start = System.currentTimeMillis();
for (int j = 0; j < iterations; ++j)
for (int cp = 0; cp < CHECK_LIMIT; ++cp) {
switch (type) {
case 0:
map1.getValue(cp);
break;
case 1:
map2.get(cp);
break;
case 2:
int enumValue = UCharacter.getIntPropertyValue(cp, propEnum);
UCharacter.getPropertyValueName(propEnum, enumValue, UProperty.NameChoice.LONG);
break;
case 3:
map3.get(cp);
break;
}
}
double end = System.currentTimeMillis();
return (end - start) / 1000 / iterations;
}
public void TestStevenTest() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
String tests[] = {
"bailey=BAILEY",
"comment=Steven Loomis test case tweaked by Parthinator",
"locale=wae",
"oldValue=_",
"oldStatus=approved",
"304=test", // Apple vetter
// expected values
"value=test",
"status=approved",
"sameVotes=test",
"conflicts=[]",
"check",
//test1
"comment=timestamp case1",
"locale=de",
"oldValue=old-value",
"oldStatus=provisional",
"404=Foo",
"424=Bar",
//expected
"value=Bar",
"status=provisional",
"sameVotes=Bar, test",
"conflicts=[google]",
"check",
//test2
"comment=timestamp case2",
"locale=de",
"oldValue=Bar",
"oldStatus=provisional",
"424=Foo",
"404=Bar",
// expected values
"value=Bar",
"status=provisional",
"sameVotes=Bar, test",
"conflicts=[google]",
"check",
//test 3
"comment=timestamp guest case",
"locale=de",
"oldValue=_",
"oldStatus=unconfirmed",
//# // G vetter A
//timestamp=1
"801=Foo",
//timestamp=2
"802=Bar",
// expected values
"value=Bar",
"status=contributed",
"sameVotes=Bar",
"conflicts=[google, guest]",
"check",
};
String expectedValue = null;
String expectedConflicts = null;
Status expectedStatus = null;
String oldValue = null;
Status oldStatus = null;
String baileyValue = null;
List<String> sameVotes = null;
String locale = null;
int voteEntries = 0;
Map<Integer, String> values = new TreeMap<>();
Map<Integer, VoteEntries> valuesMap = new TreeMap<>();
int counter = -1;
for (String test : tests) {
String[] item = test.split("=");
String name = item[0];
String value = item.length < 2 ? null : item[1];
if (name.equalsIgnoreCase("comment")) {
logln("#\t" + value);
//System.out.println("#\t" + value);
if (DEBUG_COMMENT != null && value.contains(DEBUG_COMMENT)) {
int x = 0;
}
} else if (name.equalsIgnoreCase("locale")) {
locale = value;
} else if (name.equalsIgnoreCase("oldValue")) {
oldValue = value;
} else if (name.equalsIgnoreCase("oldStatus")) {
oldStatus = Status.valueOf(value);
} else if (name.equalsIgnoreCase("value")) {
expectedValue = value;
} else if (name.equalsIgnoreCase("bailey")) {
baileyValue = value;
} else if (name.equalsIgnoreCase("sameVotes")) {
sameVotes = value == null ? new ArrayList<>(0) : Arrays
.asList(value.split(",\\s*"));
} else if (name.equalsIgnoreCase("status")) {
expectedStatus = Status.valueOf(value);
} else if (name.equalsIgnoreCase("conflicts")) {
expectedConflicts = value;
} else if (DIGITS.containsAll(name)) {
final int voter = Integer.parseInt(name);
if (value == null || value.equals("null")) {
values.remove(voter);
for (Map.Entry<Integer, VoteEntries> entry : valuesMap.entrySet()) {
if (entry.getValue().getVoter() == voter) {
valuesMap.remove(entry.getKey());
}
}
} else {
values.put(voter, value);
valuesMap.put(++voteEntries, new VoteEntries(voter, value));
}
} else if (name.equalsIgnoreCase("check")) {
counter++;
// load the resolver
resolver.setBaileyValue(baileyValue);
resolver.setLocale(CLDRLocale.getInstance(locale), null);
resolver.setBaseline(oldValue, oldStatus);
for (int voteEntry : valuesMap.keySet()) {
resolver.add(valuesMap.get(voteEntry).getValue(), valuesMap.get(voteEntry).getVoter());
}
// print the contents
logln(counter + "\t" + values);
logln(resolver.toString());
// now print the values
assertEquals(counter + " value", expectedValue,
resolver.getWinningValue());
assertEquals(counter + " sameVotes", sameVotes.toString(),
resolver.getValuesWithSameVotes().toString());
assertEquals(counter + " status", expectedStatus,
resolver.getWinningStatus());
assertEquals(counter + " conflicts", expectedConflicts,
resolver.getConflictedOrganizations().toString());
resolver.clear();
values.clear();
} else {
errln("unknown command:\t" + test);
}
}
}
public void testBaileyVotes() {
VoterInfoList vil = new VoterInfoList().setVoterToInfo(TestUser.TEST_USERS);
VoteResolver<String> resolver = new VoteResolver<>(vil);
CLDRLocale locale = CLDRLocale.getInstance("de");
PathHeader path = null;
/*
* Simple case, all = bailey
*/
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("bailey", TestUser.appleV.voterId);
resolver.add("bailey", TestUser.microsoftV.voterId);
resolver.add("bailey", TestUser.googleV.voterId);
assertEquals("Simple case, all = bailey", "bailey", resolver.getWinningValue());
/*
* Another simple case, all = INHERITANCE_MARKER
* Added per https://unicode.org/cldr/trac/ticket/11299
*/
resolver.clear();
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.appleV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.microsoftV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.googleV.voterId);
assertEquals("Another simple case, all = INHERITANCE_MARKER", CldrUtility.INHERITANCE_MARKER, resolver.getWinningValue());
/*
* INHERITANCE_MARKER should win here, having more votes than bailey.
* Changed per https://unicode.org/cldr/trac/ticket/11299
*/
resolver.clear();
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("bailey", TestUser.appleV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.microsoftV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.googleV.voterId);
assertEquals("The bailey value and explicit value combine to win", CldrUtility.INHERITANCE_MARKER, resolver.getWinningValue());
/*
* INHERITANCE_MARKER should win here, having equal number of votes with bailey;
* first they combine to win over other-vote.
* Changed per https://unicode.org/cldr/trac/ticket/11299
*/
resolver.clear();
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("bailey", TestUser.appleV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.microsoftV.voterId);
resolver.add("other-vote", TestUser.googleV.voterId);
assertEquals("The bailey value and explicit value combine to win again", CldrUtility.INHERITANCE_MARKER, resolver.getWinningValue());
/*
* Split vote, no action
*/
resolver.clear();
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("bailey", TestUser.appleV.voterId);
resolver.add("not-bailey", TestUser.microsoftV.voterId);
resolver.add("other-vote", TestUser.googleV.voterId);
assertEquals("Split vote, no action", "foo", resolver.getWinningValue());
/*
* Bailey should win if it has MORE votes than INHERITANCE_MARKER, helped
* by the presence of INHERITANCE_MARKER to win over other-vote.
* Changed per https://unicode.org/cldr/trac/ticket/11299
* Previously, "the only case where CldrUtility.INHERITANCE_MARKER wins is where they all are";
* now we already have several tests above where INHERITANCE_MARKER wins.
*/
resolver.clear();
resolver.setLocale(locale, path);
resolver.setBaileyValue("bailey");
resolver.setBaseline("foo", Status.approved);
resolver.add("bailey", TestUser.googleV.voterId);
resolver.add("bailey", TestUser.appleV.voterId);
resolver.add(CldrUtility.INHERITANCE_MARKER, TestUser.microsoftV.voterId);
resolver.add("other-vote", TestUser.adobeV.voterId);
resolver.add("other-vote", TestUser.gnomeV.voterId);
assertEquals("Bailey wins with help of INHERITANCE_MARKER", "bailey", resolver.getWinningValue());
}
/**
* Test XMLUploader.writeBulkInfoHtml
*/
public void TestBulkUploadHtml() {
StringWriter out = new StringWriter();
final String bulkStage = "submit";
try {
XMLUploader.writeBulkInfoHtml(bulkStage, out);
} catch (Exception e) {
errln("Exception for writeBulkInfoHtml in TestBulkUploadHtml: " + e);
}
final String expected = "<div class='bulkNextInfo'>\n<ul>\n<li class='header'>Bulk Upload:</li>\n" +
"<li class='inactive'>\n<h1>1. upload</h1>\n<h2>Upload XML file</h2>\n</li>\n" +
"<li class='inactive'>\n<h1>2. check</h1>\n<h2>Verify valid XML</h2>\n</li>\n" +
"<li class='inactive'>\n<h1>3. test</h1>\n<h2>Test for CLDR errors</h2>\n</li>\n" +
"<li class='active'>\n<h1>4. submit</h1>\n<h2>Data submitted into SurveyTool</h2>\n</li>\n" +
"</ul>\n</div>\n";
assertEquals("writeBulkInfoHtml", expected, out.toString());
}
/**
* Verify that VettingViewer.getMissingStatus returns MissingStatus.PRESENT
* for a typical path in a well-populated locale
*
* Ideally we should also test for MissingStatus.DISPUTED, etc.; that's more difficult
*/
public void TestMissingStatus() {
final String path = "//ldml/units/unitLength[@type=\"short\"]/unit[@type=\"volume-cup\"]/displayName";
final String locale = "fr";
final CLDRFile cldrFile = testInfo.getCLDRFile(locale, true);
final MissingStatus expected = MissingStatus.PRESENT;
// Note: VettingViewer.getMissingStatus reports PRESENT for items with ↑↑↑ and absent if the item
// is removed to inherit from root, even though the value obtained is the same in either case;
// so for path pick an item that does not have ↑↑↑, otherwise when that item is stripped for
// production data the test will fail.
final MissingStatus status = VettingViewer.getMissingStatus(cldrFile, path, true /* latin */);
if (status != expected) {
errln("Got getMissingStatus = " + status.toString() + "; expected " + expected.toString());
}
}
/**
* Check that expected paths are Aliased, and have debugging code
*/
public void TestMissingGrammar() {
// https://cldr-smoke.unicode.org/cldr-apps/v#/hu/Length/a4915bf505ffb49
final String path = "//ldml/units/unitLength[@type=\"long\"]/unit[@type=\"length-meter\"]/unitPattern[@count=\"one\"][@case=\"accusative\"]";
checkGrammarCoverage("hr", path, MissingStatus.PRESENT, DEBUG, 1, 0, 0, 0, 0); // this isn't a very good test, since we have to adjust each time. Should create fake cldr data instead
checkGrammarCoverage("kw", path, MissingStatus.ABSENT, false, 0, 0, 1, 1, 0);
checkGrammarCoverage("en_NZ", path, MissingStatus.ALIASED, DEBUG, 1, 0, 0, 0, 0);
}
/**
* Check the getMissingStatus and getStatus. Note that the values may need to be adjusted in successive versions. The sizes are expected sizes.
* @param locale
* @param path
* @param statusExpected
* @param debug TODO
*/
public void checkGrammarCoverage(final String locale, final String path, MissingStatus statusExpected, boolean debug, int... sizes) {
final CLDRFile cldrFile = testInfo.getCLDRFile(locale, true);
final MissingStatus expected = statusExpected;
final MissingStatus status = VettingViewer.getMissingStatus(cldrFile, path, true /* latin */);
if (status != expected) {
errln(locale + " got getMissingStatus = " + status.toString() + "; expected " + expected.toString());
}
Iterable<String> pathsToTest = Collections.singleton(path);
Counter<org.unicode.cldr.util.Level> foundCounter = new Counter<>();
Counter<org.unicode.cldr.util.Level> unconfirmedCounter = new Counter<>();
Counter<org.unicode.cldr.util.Level> missingCounter = new Counter<>();
Relation<MissingStatus, String> missingPaths = new Relation(new TreeMap<MissingStatus,String>(), TreeSet.class, Ordering.natural());
Set<String> unconfirmedPaths = new TreeSet<>();
VettingViewer.getStatus(pathsToTest, cldrFile, PathHeader.getFactory(),
foundCounter, unconfirmedCounter, missingCounter, missingPaths, unconfirmedPaths);
assertEquals(locale + " foundCounter (0)", sizes[0], foundCounter.getTotal());
assertEquals(locale + " unconfirmedCounter (1)", sizes[1], unconfirmedCounter.getTotal());
assertEquals(locale + " missingCounter (2)", sizes[2], missingCounter.getTotal());
assertEquals(locale + " missingPaths (3)", sizes[3], missingPaths.size());
assertEquals(locale + " unconfirmedPaths (4)", sizes[4], unconfirmedPaths.size());
showStatusResults(locale, foundCounter, unconfirmedCounter, missingCounter, missingPaths, unconfirmedPaths);
if (debug) {
foundCounter.clear();
unconfirmedCounter.clear();
missingCounter.clear();
missingPaths.clear();
unconfirmedPaths.clear();
pathsToTest = cldrFile.fullIterable();
VettingViewer.getStatus(pathsToTest, cldrFile, PathHeader.getFactory(),
foundCounter, unconfirmedCounter, missingCounter, missingPaths, unconfirmedPaths);
showStatusResults(locale, foundCounter, unconfirmedCounter, missingCounter, missingPaths, unconfirmedPaths);
}
}
public void showStatusResults(final String locale, Counter<org.unicode.cldr.util.Level> foundCounter,
Counter<org.unicode.cldr.util.Level> unconfirmedCounter, Counter<org.unicode.cldr.util.Level> missingCounter,
Relation<MissingStatus, String> missingPaths, Set<String> unconfirmedPaths) {
warnln("\n" + locale + " foundCounter:\t" + foundCounter
+ "\n" + locale + " unconfirmedCounter:\t" + unconfirmedCounter
+ "\n" + locale + " missingCounter:\t" + missingCounter
+ "\n" + locale + " unconfirmedPaths:\t" + unconfirmedPaths
+ "\n" + locale + " missing paths (modern):"
);
int count = 0;
for (Entry<MissingStatus, String> entry : missingPaths.entrySet()) {
final MissingStatus missingStatus = entry.getKey();
final String missingPath = entry.getValue();
warnln(++count
+ "\t" + locale
+ "\t" + missingStatus
+ "\t" + missingPath
+ "\t" + SUPPLEMENTAL_DATA_INFO.getCoverageLevel(missingPath, locale));
}
}
/**
* Test the function VoteResolver.Level.canCreateOrSetLevelTo()
*
* Compare org.unicode.cldr.unittest.web.TestUserRegistry.TestCanSetUserLevel()
*/
public void TestCanCreateOrSetLevelTo() {
if (Level.vetter.canCreateOrSetLevelTo(Level.street)
|| Level.anonymous.canCreateOrSetLevelTo(Level.street)
|| Level.street.canCreateOrSetLevelTo(Level.locked)
|| Level.locked.canCreateOrSetLevelTo(Level.locked)
) {
errln("Only managers and above can change levels at all");
}
if (Level.manager.canCreateOrSetLevelTo(Level.tc)
|| Level.manager.canCreateOrSetLevelTo(Level.admin)
|| Level.tc.canCreateOrSetLevelTo(Level.admin)
) {
errln("Can’t change anyone to a more privileged level than you");
}
}
}