/** * Test the functions getXxxMinimum() and getXxxMaximum() by marching a test calendar 'cal' * through 'numberOfDays' sequential days starting with 'startDate'. For each date, read a field * value along with its reported actual minimum and actual maximum. These values are checked * against one another as well as against getMinimum(), getGreatestMinimum(), getLeastMaximum(), * and getMaximum(). We expect to see: * * <p>1. minimum <= actualMinimum <= greatestMinimum <= leastMaximum <= actualMaximum <= maximum * * <p>2. actualMinimum <= value <= actualMaximum * * <p>Note: In addition to outright failures, this test reports some results as warnings. These * are not generally of concern, but they should be evaluated by a human. To see these, run this * test in verbose mode. * * @param cal the calendar to be tested * @param fieldsToTest an array of field values to be tested, e.g., new int[] { Calendar.MONTH, * Calendar.DAY_OF_MONTH }. It only makes sense to test the day fields; the time fields are * not tested by this method. If null, then test all standard fields. * @param startDate the first date to test * @param testDuration if positive, the number of days to be tested. If negative, the number of * seconds to run the test. */ public void doLimitsTest(Calendar cal, int[] fieldsToTest, Date startDate, int testDuration) { GregorianCalendar greg = new GregorianCalendar(); greg.setTime(startDate); logln("Start: " + startDate); if (fieldsToTest == null) { fieldsToTest = new int[] { Calendar.ERA, Calendar.YEAR, Calendar.MONTH, Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH, Calendar.DAY_OF_MONTH, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH, Calendar.YEAR_WOY, Calendar.EXTENDED_YEAR }; } // Keep a record of minima and maxima that we actually see. // These are kept in an array of arrays of hashes. Map[][] limits = new Map[fieldsToTest.length][2]; Object nub = new Object(); // Meaningless placeholder // This test can run for a long time; show progress. long millis = System.currentTimeMillis(); long mark = millis + 5000; // 5 sec millis -= testDuration * 1000; // stop time if testDuration<0 for (int i = 0; testDuration > 0 ? i < testDuration : System.currentTimeMillis() < millis; ++i) { if (System.currentTimeMillis() >= mark) { logln("(" + i + " days)"); mark += 5000; // 5 sec } cal.setTimeInMillis(greg.getTimeInMillis()); for (int j = 0; j < fieldsToTest.length; ++j) { int f = fieldsToTest[j]; int v = cal.get(f); int minActual = cal.getActualMinimum(f); int maxActual = cal.getActualMaximum(f); int minLow = cal.getMinimum(f); int minHigh = cal.getGreatestMinimum(f); int maxLow = cal.getLeastMaximum(f); int maxHigh = cal.getMaximum(f); // Fetch the hash for this field and keep track of the // minima and maxima. Map[] h = limits[j]; if (h[0] == null) { h[0] = new HashMap(); h[1] = new HashMap(); } h[0].put(new Integer(minActual), nub); h[1].put(new Integer(maxActual), nub); if (minActual < minLow || minActual > minHigh) { errln( "Fail: " + ymdToString(cal) + " Range for min of " + FIELD_NAME[f] + "(" + f + ")=" + minLow + ".." + minHigh + ", actual_min=" + minActual); } if (maxActual < maxLow || maxActual > maxHigh) { errln( "Fail: " + ymdToString(cal) + " Range for max of " + FIELD_NAME[f] + "(" + f + ")=" + maxLow + ".." + maxHigh + ", actual_max=" + maxActual); } if (v < minActual || v > maxActual) { errln( "Fail: " + ymdToString(cal) + " " + FIELD_NAME[f] + "(" + f + ")=" + v + ", actual range=" + minActual + ".." + maxActual + ", allowed=(" + minLow + ".." + minHigh + ")..(" + maxLow + ".." + maxHigh + ")"); } } greg.add(Calendar.DAY_OF_YEAR, 1); } // Check actual maxima and minima seen against ranges returned // by API. StringBuffer buf = new StringBuffer(); for (int j = 0; j < fieldsToTest.length; ++j) { int f = fieldsToTest[j]; buf.setLength(0); buf.append(FIELD_NAME[f]); Map[] h = limits[j]; boolean fullRangeSeen = true; for (int k = 0; k < 2; ++k) { int rangeLow = (k == 0) ? cal.getMinimum(f) : cal.getLeastMaximum(f); int rangeHigh = (k == 0) ? cal.getGreatestMinimum(f) : cal.getMaximum(f); // If either the top of the range or the bottom was never // seen, then there may be a problem. if (h[k].get(new Integer(rangeLow)) == null || h[k].get(new Integer(rangeHigh)) == null) { fullRangeSeen = false; } buf.append(k == 0 ? " minima seen=(" : "; maxima seen=("); for (Object v : h[k].keySet()) { buf.append(" " + v); } buf.append(") range=" + rangeLow + ".." + rangeHigh); } if (fullRangeSeen) { logln("OK: " + buf.toString()); } else { // This may or may not be an error -- if the range of dates // we scan over doesn't happen to contain a minimum or // maximum, it doesn't mean some other range won't. logln("Warning: " + buf.toString()); } } logln("End: " + greg.getTime()); }