| package org.unicode.cldr.unittest; |
| |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.HashSet; |
| import java.util.LinkedHashSet; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.unicode.cldr.util.DiscreteComparator; |
| import org.unicode.cldr.util.DiscreteComparator.Builder; |
| import org.unicode.cldr.util.DiscreteComparator.CycleException; |
| import org.unicode.cldr.util.DiscreteComparator.MissingItemException; |
| import org.unicode.cldr.util.DiscreteComparator.Ordering; |
| import org.unicode.cldr.util.DtdType; |
| import org.unicode.cldr.util.ElementAttributeInfo; |
| |
| import com.ibm.icu.dev.test.TestFmwk; |
| import com.ibm.icu.impl.Relation; |
| import com.ibm.icu.impl.Row; |
| import com.ibm.icu.impl.Row.R2; |
| |
| /** |
| * Tests the ordering of DTD elements and attributes within the dtd files. |
| */ |
| public class TestComparisonBuilder extends TestFmwk { |
| public static void main(String[] args) { |
| new TestComparisonBuilder().run(args); |
| } |
| |
| private void verifyOrdering(DiscreteComparator<String> comp, |
| Set<String> children) { |
| String last = null; |
| for (String child : children) { |
| if (last != null) { |
| int compare = comp.compare(last, child); |
| if (compare != -1) { |
| errln("Elements not ordered:\t" + last + ", " + child |
| + "; in " + children); |
| break; |
| } |
| } |
| last = child; |
| } |
| } |
| |
| private void dtdAttributes() { |
| // NOTE: This method was originally TestDtdAttributes. It's been |
| // disabled |
| // because DTD attributes aren't managed |
| // by FindDtdOrder, which leads to a lot of ordering cycles being found. |
| // There's no point in reordering the dtd contents to make this test |
| // pass |
| // unless FindDtdOrder also checks attributes. |
| Builder<String> builder = new Builder<String>(Ordering.NATURAL); |
| for (DtdType dtd : DtdType.values()) { |
| Relation<String, String> eaInfo = ElementAttributeInfo.getInstance( |
| dtd).getElement2Attributes(); |
| for (String element : eaInfo.keySet()) { |
| Set<String> attributes = eaInfo.getAll(element); |
| if (attributes.size() == 0) |
| continue; |
| // logln(dtd + ": " + element + ": " + attributes); |
| builder.add(attributes); |
| } |
| |
| } |
| DiscreteComparator<String> comp; |
| try { |
| comp = builder.get(); |
| } catch (CycleException e) { |
| errln(e.getMessage() + ",\t" + builder.getCycle()); |
| throw e; |
| } |
| |
| logln("Attribute Ordering:\t" + comp.getOrdering().toString()); |
| for (DtdType dtd : DtdType.values()) { |
| // check that the ordering is right |
| Relation<String, String> eaInfo = ElementAttributeInfo.getInstance( |
| dtd).getElement2Attributes(); |
| for (String element : eaInfo.keySet()) { |
| Set<String> children = eaInfo.getAll(element); |
| verifyOrdering(comp, children); |
| } |
| } |
| } |
| |
| public void TestDtdElements() { |
| Set<String> specials = new HashSet<String>(Arrays.asList(new String[] { |
| "EMPTY", "PCDATA", "ANY" })); |
| Builder<String> builder = new Builder<String>(Ordering.NATURAL); |
| for (DtdType dtd : DtdType.values()) { |
| if (dtd.rootType != dtd) { |
| continue; |
| } |
| builder.add(dtd.toString()); |
| Relation<String, String> eaInfo = ElementAttributeInfo.getInstance( |
| dtd).getElement2Children(); |
| for (String element : eaInfo.keySet()) { |
| Set<String> children = new LinkedHashSet<String>( |
| eaInfo.getAll(element)); |
| children.removeAll(specials); |
| if (children.size() == 0) |
| continue; |
| // logln(dtd + ": " + element + ": " + children); |
| builder.add(children); |
| } |
| } |
| DiscreteComparator<String> comp = builder.get(); |
| logln("Element Ordering: " + comp.getOrdering().toString()); |
| for (DtdType dtd : DtdType.values()) { |
| if (dtd.rootType != dtd) { |
| continue; |
| } |
| Relation<String, String> eaInfo = ElementAttributeInfo.getInstance( |
| dtd).getElement2Children(); |
| // check that the ordering is right |
| for (String element : eaInfo.keySet()) { |
| Set<String> elements = eaInfo.getAll(element); |
| Set<String> children = new LinkedHashSet<String>(elements); |
| children.removeAll(specials); |
| verifyOrdering(comp, children); |
| } |
| // check that all can be ordered |
| try { |
| Set<String> items = new TreeSet<String>(comp); |
| items.addAll(eaInfo.keySet()); // we'll get exception if it |
| // fails |
| } catch (Exception e) { |
| Set<String> missing = new LinkedHashSet<String>(eaInfo.keySet()); |
| missing.removeAll(comp.getOrdering()); |
| errln(dtd + "\t" + e.getClass().getName() + "\t" |
| + e.getMessage() + ";\tMissing: " + missing); |
| } |
| } |
| } |
| |
| public void TestMonkey() { |
| Random random = new Random(1); |
| Set<R2<Integer, Integer>> soFar = new HashSet<R2<Integer, Integer>>(); |
| for (int j = 0; j < 100; ++j) { |
| int itemCount = 50; |
| int linkCount = 1000; |
| buildNodes(random, soFar, random.nextInt(itemCount - 1) + 1, |
| random.nextInt(linkCount)); |
| |
| for (Ordering order : Ordering.values()) { |
| Builder<Integer> builder = new Builder<Integer>(order); |
| for (R2<Integer, Integer> pair : soFar) { |
| builder.add(pair.get0(), pair.get1()); |
| } |
| logln(builder.toString()); |
| DiscreteComparator<Integer> comp = builder.get(); |
| logln("\t" + comp); |
| |
| for (R2<Integer, Integer> pair : soFar) { |
| int value = comp.compare(pair.get0(), pair.get1()); |
| if (value >= 0) { |
| errln("Failure with " + pair); |
| } |
| } |
| } |
| } |
| } |
| |
| private void buildNodes(Random random, Set<R2<Integer, Integer>> soFar, |
| int items, int links) { |
| soFar.clear(); |
| for (int i = 0; i < links; ++i) { |
| Integer start = random.nextInt(items); |
| Integer end = random.nextInt(10); |
| if (start.intValue() <= end.intValue()) |
| continue; |
| soFar.add(Row.of(start, end)); |
| } |
| } |
| |
| public void TestCycle3() { |
| for (Ordering order : Ordering.values()) { |
| Builder<String> builder = new Builder<String>(order); |
| builder.add("c", "a"); |
| builder.add("a", "b"); |
| builder.add("b", "c"); |
| mustHaveException(builder); |
| } |
| } |
| |
| public void TestCycle7() { |
| for (Ordering order : Ordering.values()) { |
| Builder<String> builder = new Builder<String>(order); |
| builder.add("f", "a"); |
| builder.add("a", "b"); |
| builder.add("b", "c"); |
| builder.add("b", "q"); |
| builder.add("c", "d"); |
| builder.add("d", "e"); |
| builder.add("e", "f"); |
| mustHaveException(builder); |
| } |
| } |
| |
| public void TestCycle2() { |
| for (Ordering order : Ordering.values()) { |
| Builder<String> builder = new Builder<String>(order); |
| try { |
| builder.add("c", "d"); |
| builder.add("d", "e"); |
| builder.add("e", "f"); |
| builder.add("b", "b"); |
| DiscreteComparator<String> comp = builder.get(); |
| } catch (CycleException e) { |
| logln("Expected cycle and got one at:\t" + e.getMessage() |
| + ", " + builder.getCycle()); |
| return; |
| } |
| throw new IllegalArgumentException( |
| "Failed to generate CycleException"); |
| } |
| } |
| |
| public void TestFallback() { |
| for (Ordering order : Ordering.values()) { |
| DiscreteComparator<String> comp = new Builder<String>(order) |
| .add("a", "b", "c", "d").add("a", "m", "n").get(); |
| logln("Ordering " + comp.getOrdering()); |
| expectException(comp, "a", "a1"); |
| expectException(comp, "a1", "b"); |
| expectException(comp, "a1", "a2"); |
| } |
| } |
| |
| private void expectException(DiscreteComparator<String> comp, String a, |
| String b) { |
| try { |
| comp.compare(a, b); |
| } catch (MissingItemException e) { |
| logln("Expected missing item and got one at:\t" + e.getMessage()); |
| return; |
| } |
| throw new IllegalArgumentException("Failed to generate CycleException"); |
| } |
| |
| public void TestFallback2() { |
| for (Ordering order : Ordering.values()) { |
| Builder<String> builder = new Builder<String>(order); |
| builder.setFallbackComparator(new Comparator<String>() { |
| public int compare(String o1, String o2) { |
| return o1.compareTo(o2); |
| } |
| }); |
| builder.add("a", "b"); |
| builder.add("b", "c"); |
| builder.add("b", "d"); |
| DiscreteComparator<String> comp = builder.get(); |
| int result = comp.compare("a", "a1"); |
| if (result != -1) |
| errln("a >= a1"); |
| result = comp.compare("b", "a1"); |
| if (result != -1) |
| errln("a1 >= b"); |
| result = comp.compare("a1", "a2"); |
| if (result != -1) |
| errln("a1 >= a2"); |
| } |
| } |
| |
| private <T> void mustHaveException(Builder<T> builder) { |
| try { |
| logln(builder.toString()); |
| DiscreteComparator<T> comp = builder.get(); |
| } catch (CycleException e) { |
| logln("Expected cycle and got one at:\t" + e.getMessage() + ",\t" |
| + builder.getCycle()); |
| return; |
| } |
| throw new IllegalArgumentException("Failed to generate CycleException"); |
| } |
| } |