blob: ddf8b05e627fe754d43570ff448287d8b25b954a [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 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;
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.*;
import org.unicode.cldr.util.PathHeader.PageId;
import org.unicode.cldr.util.SupplementalDataInfo.PluralInfo.Count;
import org.unicode.cldr.util.VettingViewer.MissingStatus;
import org.unicode.cldr.util.VoteResolver.Level;
import org.unicode.cldr.util.VoteResolver.Status;
import org.unicode.cldr.util.VoteResolver.VoteStatus;
import org.unicode.cldr.util.VoteResolver.VoterInfo;
import org.unicode.cldr.util.props.ICUPropertyFactory;
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.unaffiliated);
final int TWO_VETTER_BAR = VoteResolver.LOWER_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 {
private final Random r = new Random();
private final 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 */
public enum TestUser {
unaffiliatedS(801, Organization.unaffiliated, Level.guest),
gnomeS(701, Organization.gnome, Level.guest),
gnomeV(702, Organization.gnome, Level.vetter),
googleV(404, Organization.google, Level.vetter),
googleS(411, Organization.google, Level.guest),
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.guest),
microsoftV(134, Organization.microsoft, Level.vetter),
ibmE(114, Organization.ibm, Level.manager),
ibmT(129, Organization.ibm, Level.tc),
unaffiliatedS2(802, Organization.unaffiliated, Level.guest);
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;
}
/** Public to use from other tests */
public static VoterInfoList getTestVoterInfoList() {
return new VoterInfoList().setVoterToInfo(testdata);
}
public void TestTrunkStatus() {
VoteResolver<String> resolver = new VoteResolver<>(getTestVoterInfoList());
resolver.setLocale(CLDRLocale.getInstance("de"), null);
resolver.setBaileyValue("bailey");
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.setBaileyValue("bailey");
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("", VoteResolver.VoteStatus.ok, voteStatus);
voteStatus = resolver.getStatusForOrganization(Organization.apple);
assertEquals("", VoteResolver.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("", VoteResolver.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);
resolver.setBaileyValue("bailey");
VoteStatus status = resolver.getStatusForOrganization(Organization.openoffice_org);
assertEquals("", VoteResolver.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("", VoteResolver.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("", VoteResolver.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.getResolvedVoteCountsIncludingIntraOrgDisputes();
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.getResolvedVoteCountsIncludingIntraOrgDisputes();
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.getResolvedVoteCountsIncludingIntraOrgDisputes();
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",
"zh_Hant_HK",
"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 + guest = 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 guest 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 type for " + loc,
type,
SpecialLocales.getType(CLDRLocale.getInstance(loc)));
}
public void TestSpecialLocales() {
assertSpecialLocale("sr", null);
assertSpecialLocale("ha_NE", SpecialLocales.Type.algorithmic);
assertSpecialLocale("sr_Latn", SpecialLocales.Type.algorithmic);
assertSpecialLocale("sr_Latn_BA", SpecialLocales.Type.algorithmic);
assertSpecialLocale("yue_Hans", null); // not readonly, because it is not policy DISCARD
assertSpecialLocale("en", SpecialLocales.Type.readonly);
assertSpecialLocale("en_ZZ_PROGRAMMERESE", null); // not defined
assertSpecialLocale(LocaleNames.UND, null);
assertSpecialLocale(LocaleNames.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 unaffiliated 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, unaffiliated]",
"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 -- should get INHERITANCE_MARKER now that we have "dropped hard inheritance"
*/
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);
if (VoteResolver.DROP_HARD_INHERITANCE) {
assertEquals(
"Simple case, all = bailey",
CldrUtility.INHERITANCE_MARKER,
resolver.getWinningValue());
} else {
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 lose even if it has MORE votes than INHERITANCE_MARKER, now that we
* have "dropped hard inheritance"
*/
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);
if (VoteResolver.DROP_HARD_INHERITANCE) {
assertEquals(
"Bailey never beats INHERITANCE_MARKER",
CldrUtility.INHERITANCE_MARKER,
resolver.getWinningValue());
} else {
assertEquals(
"Bailey can beat INHERITANCE_MARKER if not dropped",
"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
*
* <p>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()
*
* <p>Compare org.unicode.cldr.unittest.web.TestUserRegistry.TestCanSetUserLevel()
*/
public void TestCanCreateOrSetLevelTo() {
if (Level.vetter.canCreateOrSetLevelTo(Level.guest)
|| Level.anonymous.canCreateOrSetLevelTo(Level.guest)
|| Level.guest.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");
}
}
}