1aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/* GENERATED SOURCE. DO NOT MODIFY. */
2f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
3f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
4aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/*
5aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
6aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Copyright (C) 1996-2015, International Business Machines Corporation and    *
7aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * others. All Rights Reserved.                                                *
8aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin *******************************************************************************
9aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
10aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinpackage android.icu.dev.test;
11aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
12f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.lang.reflect.Constructor;
13aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.lang.reflect.Method;
14f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.lang.reflect.Modifier;
15f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.security.Policy;
16aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.ArrayList;
17aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Arrays;
18aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.List;
19aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Locale;
20aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Map;
21f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport java.util.Properties;
22aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.Random;
23aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport java.util.TreeMap;
24aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
25f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.After;
26f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.Assert;
27f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertimport org.junit.Before;
28f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
29aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.TimeZone;
30aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffinimport android.icu.util.ULocale;
31aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
32aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin/**
33aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * TestFmwk is a base class for tests that can be run conveniently from the
34aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * command line as well as under the Java test harness.
35aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * <p>
36aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * Sub-classes implement a set of methods named Test <something>. Each of these
37aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * methods performs some test. Test methods should indicate errors by calling
38aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * either err or errln. This will increment the errorCount field and may
39aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * optionally print a message to the log. Debugging information may also be
40aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * added to the log via the log and logln methods. These methods will add their
41aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin * arguments to the log only if the test is being run in verbose mode.
42aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin */
43f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubertabstract public class TestFmwk extends AbstractTestLog {
44aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
45f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * The default time zone for all of our tests. Used in @Before
46aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
47aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private final static TimeZone defaultTimeZone = TimeZone.getTimeZone("America/Los_Angeles");
48aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
49aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
50f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * The default locale used for all of our tests. Used in @Before
51aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
52aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private final static Locale defaultLocale = Locale.US;
53aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
54f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String EXHAUSTIVENESS = "ICU.exhaustive";
55f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final int DEFAULT_EXHAUSTIVENESS = 0;
56f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final int MAX_EXHAUSTIVENESS = 10;
57aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
58f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String LOGGING_LEVEL = "ICU.logging";
59f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final int DEFAULT_LOGGING_LEVEL = 0;
60f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final int MAX_LOGGING_LEVEL = 3;
61aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
62f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static final int LOGGING_NONE = 0;
63f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static final int LOGGING_WARN = 1;
64f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static final int LOGGING_INFO = 2;
65f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static final int LOGGING_DEBUG = 3;
66aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
67f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String SEED = "ICU.seed";
68f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String SECURITY_POLICY = "ICU.securitypolicy";
69aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
70f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final TestParams testParams;
71f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    static {
72f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        testParams = TestParams.create();
73aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
74aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
75aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    protected TestFmwk() {
76aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
77aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
78f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @Before
79f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testInitialize() {
80f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Locale.setDefault(defaultLocale);
81f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        TimeZone.setDefault(defaultTimeZone);
82aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
83f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (getParams().testSecurityManager != null) {
84f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            System.setSecurityManager(getParams().testSecurityManager);
85aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
86aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
87aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
88f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    @After
89f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public void testTeardown() {
90f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (getParams().testSecurityManager != null) {
91f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            System.setSecurityManager(getParams().originalSecurityManager);
92aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
93aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
94aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
95f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static TestParams getParams() {
96f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        //return paramsReference.get();
97f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return testParams;
98aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
99aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
100f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean isVerbose() {
101f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getLoggingLevel() >= LOGGING_INFO;
102aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
103aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
104aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
105aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * 0 = fewest tests, 5 is normal build, 10 is most tests
106aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
107f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int getExhaustiveness() {
108f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().inclusion;
109aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
110aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
111f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean isQuick() {
112f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getInclusion() == 0;
113aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
114aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
115f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    // use this instead of new random so we get a consistent seed
116f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    // for our tests
117f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected Random createRandom() {
118f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return new Random(getParams().getSeed());
119aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
120aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
12105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert    /**
12205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert     * Integer Random number generator, produces positive int values.
12305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert     * Similar to C++ std::minstd_rand, with the same algorithm & constants.
12405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert     * Provided for compatibility with ICU4C.
12505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert     * Get & set of the seed allows for reproducible monkey tests.
12605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert     */
12705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert    protected class ICU_Rand {
12805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        private int fLast;
12905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
13005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        public ICU_Rand(int seed) {
13105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            seed(seed);
13205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        }
13305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
13405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        public int next() {
13505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            fLast = (int)((fLast * 48271L) % 2147483647L);
13605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            return fLast;
13705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        }
13805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
13905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        public void seed(int seed) {
14005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            if (seed <= 0) {
14105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert                seed = 1;
14205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            }
14305fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            seed %= 2147483647;   // = 0x7FFFFFFF
14405fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            fLast = seed > 0 ? seed : 1;
14505fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        }
14605fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
14705fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        public int getSeed() {
14805fa7802d0874812c234a29745586677ee5837eaFredrik Roubert            return fLast;
14905fa7802d0874812c234a29745586677ee5837eaFredrik Roubert        }
15005fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
15105fa7802d0874812c234a29745586677ee5837eaFredrik Roubert    }
15205fa7802d0874812c234a29745586677ee5837eaFredrik Roubert
153aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    static final String ICU_TRAC_URL = "http://bugs.icu-project.org/trac/ticket/";
154aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    static final String CLDR_TRAC_URL = "http://unicode.org/cldr/trac/ticket/";
155aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    static final String CLDR_TICKET_PREFIX = "cldrbug:";
156aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
157aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
158aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Log the known issue.
159aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * This method returns true unless -prop:logKnownIssue=no is specified
160aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * in the argument list.
161f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     *
162aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param ticket A ticket number string. For an ICU ticket, use numeric characters only,
163aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * such as "10245". For a CLDR ticket, use prefix "cldrbug:" followed by ticket number,
164aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * such as "cldrbug:5013".
165aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param comment Additional comment, or null
166aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @return true unless -prop:logKnownIssue=no is specified in the test command line argument.
167aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
168f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean logKnownIssue(String ticket, String comment) {
169aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!getBooleanProperty("logKnownIssue", true)) {
170aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return false;
171aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
172aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
173aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer descBuf = new StringBuffer();
174f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // TODO(junit) : what to do about this?
175f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        //getParams().stack.appendPath(descBuf);
176aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (comment != null && comment.length() > 0) {
177aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            descBuf.append(" (" + comment + ")");
178aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
179aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String description = descBuf.toString();
180aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
181aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String ticketLink = "Unknown Ticket";
182aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (ticket != null && ticket.length() > 0) {
183aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean isCldr = false;
184aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ticket = ticket.toLowerCase(Locale.ENGLISH);
185aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (ticket.startsWith(CLDR_TICKET_PREFIX)) {
186aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                isCldr = true;
187aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ticket = ticket.substring(CLDR_TICKET_PREFIX.length());
188aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
189aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ticketLink = (isCldr ? CLDR_TRAC_URL : ICU_TRAC_URL) + ticket;
190aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
191aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
192f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (getParams().knownIssues == null) {
193f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            getParams().knownIssues = new TreeMap<String, List<String>>();
194aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
195f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        List<String> lines = getParams().knownIssues.get(ticketLink);
196aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (lines == null) {
197aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            lines = new ArrayList<String>();
198f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            getParams().knownIssues.put(ticketLink, lines);
199aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
200aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!lines.contains(description)) {
201aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            lines.add(description);
202aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
203aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
204aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return true;
205aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
206aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
207f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String getProperty(String key) {
208f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getProperty(key);
209aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
210aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
211f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean getBooleanProperty(String key) {
212f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getBooleanProperty(key);
213aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
214aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
215f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean getBooleanProperty(String key, boolean defVal) {
216f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getBooleanProperty(key, defVal);
217aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
218aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
219f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int getIntProperty(String key, int defVal) {
220f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getIntProperty(key, defVal);
221f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
222f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
223f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int getIntProperty(String key, int defVal, int maxVal) {
224f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return getParams().getIntProperty(key, defVal, maxVal);
225f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
226f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
227f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static TimeZone safeGetTimeZone(String id) {
228aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        TimeZone tz = TimeZone.getTimeZone(id);
229aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (tz == null) {
230aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // should never happen
231aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("FAIL: TimeZone.getTimeZone(" + id + ") => null");
232aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
233aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!tz.getID().equals(id)) {
234aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            warnln("FAIL: TimeZone.getTimeZone(" + id + ") => " + tz.getID());
235aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
236aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return tz;
237aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
238aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
239aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
240f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    // Utility Methods
241f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
242f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String hex(char[] s){
243aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer result = new StringBuffer();
244aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < s.length; ++i) {
245aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (i != 0) result.append(',');
246aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            result.append(hex(s[i]));
247aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
248aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result.toString();
249aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
250f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
251f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String hex(byte[] s){
252aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer result = new StringBuffer();
253aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < s.length; ++i) {
254aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (i != 0) result.append(',');
255aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            result.append(hex(s[i]));
256aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
257aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result.toString();
258aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
259f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
260f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String hex(char ch) {
261aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer result = new StringBuffer();
262aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String foo = Integer.toString(ch, 16).toUpperCase();
263aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = foo.length(); i < 4; ++i) {
264aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            result.append('0');
265aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
266aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result + foo;
267aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
268aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
269f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String hex(int ch) {
270aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer result = new StringBuffer();
271aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String foo = Integer.toString(ch, 16).toUpperCase();
272aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = foo.length(); i < 4; ++i) {
273aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            result.append('0');
274aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
275aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result + foo;
276aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
277aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
278f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String hex(CharSequence s) {
279aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuilder result = new StringBuilder();
280aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < s.length(); ++i) {
281aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (i != 0)
282aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append(',');
283aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            result.append(hex(s.charAt(i)));
284aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
285aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result.toString();
286aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
287aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
288f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String prettify(CharSequence s) {
289aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuilder result = new StringBuilder();
290aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int ch;
291aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (int i = 0; i < s.length(); i += Character.charCount(ch)) {
292aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            ch = Character.codePointAt(s, i);
293aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (ch > 0xfffff) {
294aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append("\\U00");
295aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append(hex(ch));
296aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else if (ch > 0xffff) {
297aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append("\\U000");
298aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append(hex(ch));
299aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else if (ch < 0x20 || 0x7e < ch) {
300aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append("\\u");
301aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append(hex(ch));
302aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else {
303aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                result.append((char) ch);
304aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
305aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
306aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
307aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result.toString();
308aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
309aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
310aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    private static java.util.GregorianCalendar cal;
311aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
312aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
313aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Return a Date given a year, month, and day of month. This is similar to
314aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * new Date(y-1900, m, d). It uses the default time zone at the time this
315aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * method is first called.
316aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *
317aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param year
318aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            use 2000 for 2000, unlike new Date()
319aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param month
320aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            use Calendar.JANUARY etc.
321aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param dom
322aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            day of month, 1-based
323aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @return a Date object for the given y/m/d
324aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
325aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    protected static synchronized java.util.Date getDate(int year, int month,
326aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            int dom) {
327aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (cal == null) {
328aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            cal = new java.util.GregorianCalendar();
329aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
330aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        cal.clear();
331aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        cal.set(year, month, dom);
332aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return cal.getTime();
333aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
334aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
335f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static class TestParams {
336aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
337f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private int inclusion;
338f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private long seed;
339f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private int loggingLevel;
340aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
341f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private String policyFileName;
342f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private SecurityManager testSecurityManager;
343f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private SecurityManager originalSecurityManager;
344aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
345aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        private Map<String, List<String>> knownIssues;
346aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
347f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private Properties props;
348aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
349aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
350f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private TestParams() {
351aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
352aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
353f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        static TestParams create() {
354aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            TestParams params = new TestParams();
355f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            Properties props = System.getProperties();
356f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            params.parseProperties(props);
357aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return params;
358aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
359aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
360f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        private void parseProperties(Properties props) {
361f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            this.props = props;
362aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
363f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            inclusion = getIntProperty(EXHAUSTIVENESS, DEFAULT_EXHAUSTIVENESS, MAX_EXHAUSTIVENESS);
364f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            seed = getLongProperty(SEED, System.currentTimeMillis());
365f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            loggingLevel = getIntProperty(LOGGING_LEVEL, DEFAULT_LOGGING_LEVEL, MAX_LOGGING_LEVEL);
366aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
367f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            policyFileName = getProperty(SECURITY_POLICY);
368f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (policyFileName != null) {
369f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                String originalPolicyFileName = System.getProperty("java.security.policy");
370f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                originalSecurityManager = System.getSecurityManager();
371f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                System.setProperty("java.security.policy", policyFileName);
372f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                Policy.getPolicy().refresh();
373f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                testSecurityManager = new SecurityManager();
374f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                System.setProperty("java.security.policy", originalPolicyFileName==null ? "" : originalPolicyFileName);
375aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
376aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
377aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
378f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public String getProperty(String key) {
379f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            String val = null;
380f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (key != null && key.length() > 0) {
381f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                val = props.getProperty(key);
382aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
383f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return val;
384aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
385aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
386f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public boolean getBooleanProperty(String key) {
387f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return getBooleanProperty(key, false);
388aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
389aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
390f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public boolean getBooleanProperty(String key, boolean defVal) {
391f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            String s = getProperty(key);
392f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (s == null) {
393f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return defVal;
394aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
395f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("true") || s.equals("1")) {
396f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return true;
397aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
398f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return false;
399aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
400aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
401f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public int getIntProperty(String key, int defVal) {
402f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return getIntProperty(key, defVal, -1);
403aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
404aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
405f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public int getIntProperty(String key, int defVal, int maxVal) {
406f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            String s = getProperty(key);
407f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (s == null) {
408f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return defVal;
409aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
410f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return (maxVal == -1) ? Integer.valueOf(s) : Math.max(Integer.valueOf(s), maxVal);
411aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
412aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
413f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public long getLongProperty(String key, long defVal) {
414f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            String s = getProperty(key);
415f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            if (s == null) {
416f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                return defVal;
417aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
418f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return Long.valueOf(s);
419aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
420aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
421f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public int getInclusion() {
422f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return inclusion;
423aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
424aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
425f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public long getSeed() {
426f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return seed;
427aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
428aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
429f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        public int getLoggingLevel() {
430f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            return loggingLevel;
431aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
432aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
433aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
434aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
435aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Check the given array to see that all the strings in the expected array
436aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * are present.
437aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *
438aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param msg
439aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            string message, for log output
440aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param array
441aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of strings to check
442aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param expected
443aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of strings we expect to see, or null
444aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @return the length of 'array', or -1 on error
445aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
446f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int checkArray(String msg, String array[], String expected[]) {
447aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int explen = (expected != null) ? expected.length : 0;
448aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!(explen >= 0 && explen < 31)) { // [sic] 31 not 32
449aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            errln("Internal error");
450aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return -1;
451aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
452aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int i = 0;
453aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        StringBuffer buf = new StringBuffer();
454aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        int seenMask = 0;
455aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (; i < array.length; ++i) {
456aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String s = array[i];
457aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (i != 0)
458aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                buf.append(", ");
459aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            buf.append(s);
460aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            // check expected list
461aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int j = 0, bit = 1; j < explen; ++j, bit <<= 1) {
462aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if ((seenMask & bit) == 0) {
463aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    if (s.equals(expected[j])) {
464aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        seenMask |= bit;
465aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        logln("Ok: \"" + s + "\" seen");
466aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    }
467aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
468aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
469aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
470aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        logln(msg + " = [" + buf + "] (" + i + ")");
471aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // did we see all expected strings?
472aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (((1 << explen) - 1) != seenMask) {
473aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            for (int j = 0, bit = 1; j < expected.length; ++j, bit <<= 1) {
474aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                if ((seenMask & bit) == 0) {
475aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    errln("\"" + expected[j] + "\" not seen");
476aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
477aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
478aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
479aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return array.length;
480aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
481aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
482aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
483aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Check the given array to see that all the locales in the expected array
484aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * are present.
485aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *
486aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param msg
487aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            string message, for log output
488aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param array
489aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of locales to check
490aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param expected
491aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of locales names we expect to see, or null
492aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @return the length of 'array'
493aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
494f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int checkArray(String msg, Locale array[], String expected[]) {
495aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String strs[] = new String[array.length];
496f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (int i = 0; i < array.length; ++i) {
497aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            strs[i] = array[i].toString();
498f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
499aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return checkArray(msg, strs, expected);
500aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
501aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
502aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    /**
503aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * Check the given array to see that all the locales in the expected array
504aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * are present.
505aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *
506aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param msg
507aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            string message, for log output
508aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param array
509aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of locales to check
510aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @param expected
511aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     *            array of locales names we expect to see, or null
512aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     * @return the length of 'array'
513aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin     */
514f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static int checkArray(String msg, ULocale array[], String expected[]) {
515aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String strs[] = new String[array.length];
516f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        for (int i = 0; i < array.length; ++i) {
517aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            strs[i] = array[i].toString();
518f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
519aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return checkArray(msg, strs, expected);
520aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
521aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
522aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    // JUnit-like assertions.
523aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
524f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertTrue(String message, boolean condition) {
525aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(condition, message, "true", null);
526aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
527aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
528f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertFalse(String message, boolean condition) {
529aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(!condition, message, "false", null);
530aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
531aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
532f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertEquals(String message, boolean expected,
533aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            boolean actual) {
534aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(expected == actual, message, String
535aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .valueOf(expected), String.valueOf(actual));
536aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
537aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
538f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertEquals(String message, long expected, long actual) {
539aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(expected == actual, message, String
540aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .valueOf(expected), String.valueOf(actual));
541aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
542aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
543aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    // do NaN and range calculations to precision of float, don't rely on
544aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    // promotion to double
545f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertEquals(String message, float expected,
546aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            float actual, double error) {
547aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        boolean result = Float.isInfinite(expected)
548aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ? expected == actual
549aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                : !(Math.abs(expected - actual) > error); // handles NaN
550aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(result, message, String.valueOf(expected)
551aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                + (error == 0 ? "" : " (within " + error + ")"), String
552aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .valueOf(actual));
553aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
554aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
555f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertEquals(String message, double expected,
556aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            double actual, double error) {
557aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        boolean result = Double.isInfinite(expected)
558aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                ? expected == actual
559aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                : !(Math.abs(expected - actual) > error); // handles NaN
560aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(result, message, String.valueOf(expected)
561aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                + (error == 0 ? "" : " (within " + error + ")"), String
562aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .valueOf(actual));
563aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
564aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
565f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static <T> boolean assertEquals(String message, T[] expected, T[] actual) {
566aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Use toString on a List to get useful, readable messages
567aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String expectedString = expected == null ? "null" : Arrays.asList(expected).toString();
568aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        String actualString = actual == null ? "null" : Arrays.asList(actual).toString();
569aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return assertEquals(message, expectedString, actualString);
570aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
571aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
572f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertEquals(String message, Object expected,
573aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Object actual) {
574aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        boolean result = expected == null ? actual == null : expected
575aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .equals(actual);
576aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(result, message, stringFor(expected),
577aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                stringFor(actual));
578aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
579aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
580f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertNotEquals(String message, Object expected,
581aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Object actual) {
582aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        boolean result = !(expected == null ? actual == null : expected
583aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                .equals(actual));
584aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(result, message, stringFor(expected),
585aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                stringFor(actual), "not equal to", true);
586aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
587aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
588aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    protected boolean assertSame(String message, Object expected, Object actual) {
589aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(expected == actual, message, stringFor(expected),
590aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                stringFor(actual), "==", false);
591aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
592aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
593f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertNotSame(String message, Object expected,
594aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Object actual) {
595aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(expected != actual, message, stringFor(expected),
596aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                stringFor(actual), "!=", true);
597aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
598aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
599f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertNull(String message, Object actual) {
600aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(actual == null, message, null, stringFor(actual));
601aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
602aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
603f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean assertNotNull(String message, Object actual) {
604aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(actual != null, message, null, stringFor(actual),
605aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                "!=", true);
606aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
607aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
608f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static void fail() {
609aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        fail("");
610aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
611aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
612f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static void fail(String message) {
613aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (message == null) {
614f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            message = "";
615aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
616aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!message.equals("")) {
617aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            message = ": " + message;
618aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
619aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        errln(sourceLocation() + message);
620aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
621aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
622f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static boolean handleAssert(boolean result, String message,
623aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String expected, String actual) {
624aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return handleAssert(result, message, expected, actual, null, false);
625aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
626aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
627f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    public static boolean handleAssert(boolean result, String message,
628aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            Object expected, Object actual, String relation, boolean flip) {
629aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (!result || isVerbose()) {
630aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (message == null) {
631aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                message = "";
632aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
633aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (!message.equals("")) {
634aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                message = ": " + message;
635aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
636aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            relation = relation == null ? ", got " : " " + relation + " ";
637aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (result) {
638aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                logln("OK " + message + ": "
639aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        + (flip ? expected + relation + actual : expected));
640aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            } else {
641aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // assert must assume errors are true errors and not just warnings
642aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                // so cannot warnln here
643aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                errln(  message
644aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        + ": expected"
645aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                        + (flip ? relation + expected : " " + expected
646aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                                + (actual != null ? relation + actual : "")));
647aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
648aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
649aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return result;
650aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
651aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
652f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    private static final String stringFor(Object obj) {
653aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (obj == null) {
654aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return "null";
655aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
656aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        if (obj instanceof String) {
657aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            return "\"" + obj + '"';
658aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
659aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        return obj.getClass().getName() + "<" + obj + ">";
660aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
661aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
662aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    // Return the source code location of the caller located callDepth frames up the stack.
663f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String sourceLocation() {
664aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        // Walk up the stack to the first call site outside this file
665aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        for (StackTraceElement st : new Throwable().getStackTrace()) {
666aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            String source = st.getFileName();
667aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            if (source != null && !source.equals("TestFmwk.java") && !source.equals("AbstractTestLog.java")) {
668aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                String methodName = st.getMethodName();
669f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert                if (methodName != null &&
670aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                       (methodName.startsWith("Test") || methodName.startsWith("test") || methodName.equals("main"))) {
671aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                    return "(" + source + ":" + st.getLineNumber() + ") ";
672aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin                }
673aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin            }
674aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        }
675aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin        throw new InternalError();
676aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
677aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
678f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean checkDefaultPrivateConstructor(String fullyQualifiedClassName) throws Exception {
679f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return checkDefaultPrivateConstructor(Class.forName(fullyQualifiedClassName));
680f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
681aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
682f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static boolean checkDefaultPrivateConstructor(Class<?> classToBeTested) throws Exception {
683f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Constructor<?> constructor = classToBeTested.getDeclaredConstructor();
684f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
685f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // Check that the constructor is private.
686f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        boolean isPrivate = Modifier.isPrivate(constructor.getModifiers());
687f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
688f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // Call the constructor for coverage.
689f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        constructor.setAccessible(true);
690f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        constructor.newInstance();
691f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
692f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (!isPrivate) {
693f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            errln("Default private constructor for class: " + classToBeTested.getName() + " is not private.");
694f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
695f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return isPrivate;
696f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
697f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert
698f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /**
699f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Tests the toString method on a private or hard-to-reach class.  Assumes constructor of the class does not
700f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * take any arguments.
701f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param fullyQualifiedClassName
702f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @return The output of the toString method.
703f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @throws Exception
704f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
705f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String invokeToString(String fullyQualifiedClassName) throws Exception {
706f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return invokeToString(fullyQualifiedClassName, new Class<?>[]{}, new Object[]{});
707f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
708aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
709f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /**
710f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Tests the toString method on a private or hard-to-reach class.  Assumes constructor of the class does not
711f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * take any arguments.
712f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param classToBeTested
713f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @return The output of the toString method.
714f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @throws Exception
715f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
716f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String invokeToString(Class<?> classToBeTested) throws Exception {
717f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return invokeToString(classToBeTested, new Class<?>[]{}, new Object[]{});
718f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
719aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
720f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /**
721f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Tests the toString method on a private or hard-to-reach class.  Allows you to specify the argument types for
722f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * the constructor.
723f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param fullyQualifiedClassName
724f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @return The output of the toString method.
725f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @throws Exception
726f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
727f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String invokeToString(String fullyQualifiedClassName,
728f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            Class<?>[] constructorParamTypes, Object[] constructorParams) throws Exception {
729f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return invokeToString(Class.forName(fullyQualifiedClassName), constructorParamTypes, constructorParams);
730aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
731aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
732f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /**
733f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * Tests the toString method on a private or hard-to-reach class.  Allows you to specify the argument types for
734f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * the constructor.
735f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @param classToBeTested
736f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @return The output of the toString method.
737f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @throws Exception
738f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
739f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static String invokeToString(Class<?> classToBeTested,
740f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            Class<?>[] constructorParamTypes, Object[] constructorParams) throws Exception {
741f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Constructor<?> constructor = classToBeTested.getDeclaredConstructor(constructorParamTypes);
742f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        constructor.setAccessible(true);
743f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Object obj = constructor.newInstance(constructorParams);
744f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        Method toStringMethod = classToBeTested.getDeclaredMethod("toString");
745f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        toStringMethod.setAccessible(true);
746f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        return (String) toStringMethod.invoke(obj);
747aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin    }
748aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
749aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
750f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    // End JUnit-like assertions
751aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
752f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    // TODO (sgill): added to keep errors away
753f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    /* (non-Javadoc)
754f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     * @see android.icu.dev.test.TestLog#msg(java.lang.String, int, boolean, boolean)
755f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert     */
756f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    //@Override
757f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    protected static void msg(String message, int level, boolean incCount, boolean newln) {
758f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        if (level == TestLog.WARN || level == TestLog.ERR) {
759f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert            Assert.fail(message);
760f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        }
761f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert        // TODO(stuartg): turned off - causing OOM running under ant
762f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//        while (level > 0) {
763f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//            System.out.print(" ");
764f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//            level--;
765f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//        }
766f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//        System.out.print(message);
767f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//        if (newln) {
768f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//            System.out.println();
769f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert//        }
770f86f25d102340da66b9c7cb6b2d5ecdc0de43ecfFredrik Roubert    }
771aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin
772aefe4d1f8f1773ead1a52f7a5d2c9e0009353600Paul Duffin}
773