1. /* ===========================================================
  2. * JFreeChart : a free chart library for the Java(tm) platform
  3. * ===========================================================
  4. *
  5. * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
  6. *
  7. * Project Info: http://www.jfree.org/jfreechart/index.html
  8. *
  9. * This library is free software; you can redistribute it and/or modify it under the terms
  10. * of the GNU Lesser General Public License as published by the Free Software Foundation;
  11. * either version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  14. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License along with this
  18. * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  22. * in the United States and other countries.]
  23. *
  24. * ----------------------------
  25. * SegmentedTimelineTests.java
  26. * ----------------------------
  27. * (C) Copyright 2003-2005, by Bill Kelemen and Contributors.
  28. *
  29. * Original Author: Bill Kelemen;
  30. * Contributor(s): ;
  31. *
  32. * $Id: SegmentedTimelineTests.java,v 1.5 2005/01/11 23:27:58 mungady Exp $
  33. *
  34. * Changes
  35. * -------
  36. * 24-May-2003 : Version 1 (BK);
  37. * 07-Jan-2005 : Added test for hashCode() method (DG);
  38. *
  39. */
  40. package org.jfree.chart.axis.junit;
  41. import java.io.ByteArrayInputStream;
  42. import java.io.ByteArrayOutputStream;
  43. import java.io.ObjectInput;
  44. import java.io.ObjectInputStream;
  45. import java.io.ObjectOutput;
  46. import java.io.ObjectOutputStream;
  47. import java.text.Format;
  48. import java.text.NumberFormat;
  49. import java.text.ParseException;
  50. import java.text.SimpleDateFormat;
  51. import java.util.ArrayList;
  52. import java.util.Calendar;
  53. import java.util.GregorianCalendar;
  54. import java.util.Iterator;
  55. import junit.framework.Test;
  56. import junit.framework.TestCase;
  57. import junit.framework.TestSuite;
  58. import org.jfree.chart.axis.SegmentedTimeline;
  59. /**
  60. * JUnit Tests for the {@link SegmentedTimeline} class.
  61. *
  62. * @author Bill Kelemen
  63. */
  64. public class SegmentedTimelineTests extends TestCase {
  65. /** These constants control test cycles in the validateXXXX methods. */
  66. private static final int TEST_CYCLE_START = 0;
  67. /** These constants control test cycles in the validateXXXX methods. */
  68. private static final int TEST_CYCLE_END = 1000;
  69. /** These constants control test cycles in the validateXXXX methods. */
  70. private static final int TEST_CYCLE_INC = 55;
  71. /** Number of ms in five years */
  72. private static final long FIVE_YEARS = 5 * 365 * SegmentedTimeline.DAY_SEGMENT_SIZE;
  73. /** Number format object for ms tests. */
  74. private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance();
  75. /** Date format object for Monday through Friday tests. */
  76. private static final SimpleDateFormat DATE_FORMAT;
  77. /** Date format object 9:00 AM to 4:00 PM tests. */
  78. private static final SimpleDateFormat DATE_TIME_FORMAT;
  79. /** Some ms exceptions for ms testing. */
  80. private static final String[] MS_EXCEPTIONS =
  81. {"0", "2", "4", "10", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24",
  82. "47", "58", "100", "101"};
  83. /** Some ms4 exceptions for ms testing. */
  84. private static final String[] MS2_BASE_TIMELINE_EXCEPTIONS =
  85. {"0", "8", "16", "24", "32", "40", "48", "56", "64", "72", "80", "88", "96", "104",
  86. "112", "120", "128", "136"};
  87. /** US non-trading dates in 2000 through 2002 to test exceptions. */
  88. private static final String[] US_HOLIDAYS =
  89. {"2000-01-17", "2000-02-21", "2000-04-21", "2000-05-29", "2000-07-04",
  90. "2000-09-04", "2000-11-23", "2000-12-25", "2001-01-01", "2001-01-15",
  91. "2001-02-19", "2001-04-13", "2001-05-28", "2001-07-04", "2001-09-03",
  92. "2001-09-11", "2001-09-12", "2001-09-13", "2001-09-14", "2001-11-22",
  93. "2001-12-25", "2002-01-01", "2002-01-21", "2002-02-18", "2002-03-29",
  94. "2002-05-27", "2002-07-04", "2002-09-02", "2002-11-28", "2002-12-25"};
  95. /** Some test exceptions for the fifteen min timeline. */
  96. private static final String[] FIFTEEN_MIN_EXCEPTIONS =
  97. {"2000-01-10 09:00:00", "2000-01-10 09:15:00", "2000-01-10 09:30:00",
  98. "2000-01-10 09:45:00", "2000-01-10 10:00:00", "2000-01-10 10:15:00",
  99. "2000-02-15 09:00:00", "2000-02-15 09:15:00", "2000-02-15 09:30:00",
  100. "2000-02-15 09:45:00", "2000-02-15 10:00:00", "2000-02-15 10:15:00",
  101. "2000-02-16 11:00:00", "2000-02-16 11:15:00", "2000-02-16 11:30:00",
  102. "2000-02-16 11:45:00", "2000-02-16 12:00:00", "2000-02-16 12:15:00",
  103. "2000-02-16 12:30:00", "2000-02-16 12:45:00", "2000-02-16 01:00:00",
  104. "2000-02-16 01:15:00", "2000-02-16 01:30:00", "2000-02-16 01:45:00",
  105. "2000-05-17 11:45:00", "2000-05-17 12:00:00", "2000-05-17 12:15:00",
  106. "2000-05-17 12:30:00", "2000-05-17 12:45:00", "2000-05-17 01:00:00",
  107. "2000-05-17 01:15:00", "2000-05-17 01:30:00", "2000-05-17 01:45:00",
  108. "2000-05-17 02:00:00", "2000-05-17 02:15:00", "2000-05-17 02:30:00",
  109. "2000-05-17 02:45:00", "2000-05-17 03:00:00", "2000-05-17 03:15:00",
  110. "2000-05-17 03:30:00", "2000-05-17 03:45:00", "2000-05-17 04:00:00"};
  111. /** Our 1-ms test timeline using 5 included and 2 excluded segments. */
  112. private SegmentedTimeline msTimeline;
  113. /** Our 1-ms test timeline (with baseTimeline) using 2 included and 2 excluded segments. */
  114. private SegmentedTimeline ms2Timeline;
  115. /** Our 4-ms test base timeline for ms2Timeline using 1 included and 1 excluded segments */
  116. private SegmentedTimeline ms2BaseTimeline;
  117. /** Our test Monday through Friday test timeline. */
  118. private SegmentedTimeline mondayFridayTimeline;
  119. /** Our 9:00 AM to 4:00 PM fifteen minute timeline. */
  120. private SegmentedTimeline fifteenMinTimeline;
  121. /** ms from 1970-01-01 to first monday after 2001-01-01. */
  122. private Calendar monday;
  123. /** ms from 1970-01-01 to 9 am first monday after 2001-01-01. */
  124. private Calendar monday9am;
  125. /** Static initialization block. */
  126. static {
  127. DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
  128. DATE_FORMAT.setTimeZone(SegmentedTimeline.NO_DST_TIME_ZONE);
  129. DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  130. DATE_TIME_FORMAT.setTimeZone(SegmentedTimeline.NO_DST_TIME_ZONE);
  131. }
  132. /**
  133. * Returns the tests as a test suite.
  134. *
  135. * @return The test suite.
  136. */
  137. public static Test suite() {
  138. return new TestSuite(SegmentedTimelineTests.class);
  139. }
  140. /**
  141. * Constructs a new set of tests.
  142. *
  143. * @param name the name of the tests.
  144. */
  145. public SegmentedTimelineTests(String name) {
  146. super(name);
  147. }
  148. /**
  149. * Sets up the fixture, for example, open a network connection.
  150. * This method is called before a test is executed.
  151. *
  152. * @throws Exception if there is a problem.
  153. */
  154. protected void setUp() throws Exception {
  155. // setup our test timelines
  156. //
  157. // Legend for comments below:
  158. // <spaces> = Segments included in the final timeline
  159. // EE = Excluded segments via timeline rules
  160. // xx = Exception segments inherited from base timeline exclusions
  161. // 1-ms test timeline using 5 included and 2 excluded segments.
  162. //
  163. // timeline start time = 0
  164. // |
  165. // v
  166. // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...
  167. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  168. // | | | | | |EE|EE| | | | | |EE|EE| | | | | | |EE|EE| <-- msTimeline
  169. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  170. // \_________ ________/ \_/
  171. // \/ |
  172. // segment group segment size = 1 ms
  173. //
  174. this.msTimeline = new SegmentedTimeline(1, 5, 2);
  175. this.msTimeline.setStartTime(0);
  176. // 4-ms test base timeline for ms2Timeline using 1 included and 1 excluded segments
  177. //
  178. // timeline start time = 0
  179. // |
  180. // v
  181. // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...
  182. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  183. // | | | | |EE|EE|EE|EE| | | | |EE|EE|EE|EE| | | | | <-- ms2BaseTimeline
  184. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  185. // \__________ _________/ \____ _____/
  186. // \/ \/
  187. // segment group segment size = 4 ms
  188. //
  189. this.ms2BaseTimeline = new SegmentedTimeline(4, 1, 1);
  190. this.ms2BaseTimeline.setStartTime(0);
  191. // 1-ms test timeline (with a baseTimeline) using 2 included and 2 excluded segments
  192. // centered inside each base segment
  193. //
  194. // The ms2Timeline without a base would look like this:
  195. //
  196. // timeline start time = 1
  197. // |
  198. // v
  199. // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...
  200. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  201. // |EE| | |EE|EE| | |EE|EE| | |EE|EE| | |EE|EE| | |EE| <-- ms2Timeline
  202. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  203. // \____ _____/ \_/
  204. // \/ |
  205. // segment group segment size = 1 ms
  206. //
  207. // With the base timeline some originally included segments are now removed (see "xx"
  208. // below):
  209. //
  210. // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...
  211. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  212. // |EE| | |EE|EE|xx|xx|EE|EE| | |EE|EE|xx|xx|EE|EE| | |EE| <-- ms2Timeline
  213. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  214. // | | | | |EE|EE|EE|EE| | | | |EE|EE|EE|EE| | | | | <-- ms2BaseTimeline
  215. // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+...
  216. //
  217. this.ms2Timeline = new SegmentedTimeline(1, 2, 2);
  218. this.ms2Timeline.setStartTime(1);
  219. this.ms2Timeline.setBaseTimeline(this.ms2BaseTimeline);
  220. // test monday though friday timeline
  221. this.mondayFridayTimeline = SegmentedTimeline.newMondayThroughFridayTimeline();
  222. // test 9am-4pm Monday through Friday timeline
  223. this.fifteenMinTimeline = SegmentedTimeline.newFifteenMinuteTimeline();
  224. // find first Monday after 2001-01-01
  225. Calendar cal = new GregorianCalendar(SegmentedTimeline.NO_DST_TIME_ZONE);
  226. cal.set(2001, 0, 1, 0, 0, 0);
  227. cal.set(Calendar.MILLISECOND, 0);
  228. while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
  229. cal.add(Calendar.DATE, 1);
  230. }
  231. this.monday = (Calendar) cal.clone();
  232. // calculate 9am on the first Monday after 2001-01-01
  233. cal.add(Calendar.HOUR, 9);
  234. this.monday9am = (Calendar) cal.clone();
  235. }
  236. /**
  237. * Tears down the fixture, for example, close a network connection.
  238. * This method is called after a test is executed.
  239. *
  240. * @throws Exception if there is a problem.
  241. */
  242. protected void tearDown() throws Exception {
  243. // does nothing
  244. }
  245. //////////////////////////////////////////////////////////////////////////
  246. // test construction process
  247. //////////////////////////////////////////////////////////////////////////
  248. /**
  249. * Tests that the new method that created the msTimeline segmented
  250. * timeline did so correctly.
  251. */
  252. public void testMsSegmentedTimeline() {
  253. // verify attributes set during object construction
  254. assertEquals(1, this.msTimeline.getSegmentSize());
  255. assertEquals(0, this.msTimeline.getStartTime());
  256. assertEquals(5, this.msTimeline.getSegmentsIncluded());
  257. assertEquals(2, this.msTimeline.getSegmentsExcluded());
  258. }
  259. /**
  260. * Tests that the new method that created the ms2Timeline segmented
  261. * timeline did so correctly.
  262. */
  263. public void testMs2SegmentedTimeline() {
  264. // verify attributes set during object construction
  265. assertEquals(1, this.ms2Timeline.getSegmentSize());
  266. assertEquals(1, this.ms2Timeline.getStartTime());
  267. assertEquals(2, this.ms2Timeline.getSegmentsIncluded());
  268. assertEquals(2, this.ms2Timeline.getSegmentsExcluded());
  269. assertEquals(this.ms2BaseTimeline, this.ms2Timeline.getBaseTimeline());
  270. }
  271. /**
  272. * Tests that the factory method that creates Monday through Friday segmented
  273. * timeline does so correctly.
  274. */
  275. public void testMondayThroughFridaySegmentedTimeline() {
  276. // verify attributes set during object construction
  277. assertEquals(
  278. SegmentedTimeline.DAY_SEGMENT_SIZE, this.mondayFridayTimeline.getSegmentSize()
  279. );
  280. assertEquals(
  281. SegmentedTimeline.FIRST_MONDAY_AFTER_1900, this.mondayFridayTimeline.getStartTime()
  282. );
  283. assertEquals(5, this.mondayFridayTimeline.getSegmentsIncluded());
  284. assertEquals(2, this.mondayFridayTimeline.getSegmentsExcluded());
  285. }
  286. /**
  287. * Tests that the factory method that creates a 15-min 9:00 AM 4:00 PM
  288. * segmented axis does so correctly.
  289. */
  290. public void testFifteenMinSegmentedTimeline() {
  291. assertEquals(SegmentedTimeline.FIFTEEN_MINUTE_SEGMENT_SIZE,
  292. this.fifteenMinTimeline.getSegmentSize());
  293. assertEquals(SegmentedTimeline.FIRST_MONDAY_AFTER_1900 + 36
  294. * this.fifteenMinTimeline.getSegmentSize(),
  295. this.fifteenMinTimeline.getStartTime());
  296. assertEquals(28, this.fifteenMinTimeline.getSegmentsIncluded());
  297. assertEquals(68, this.fifteenMinTimeline.getSegmentsExcluded());
  298. }
  299. //////////////////////////////////////////////////////////////////////////
  300. // test one-segment and adjacent segments
  301. //////////////////////////////////////////////////////////////////////////
  302. /**
  303. * Tests one segment of the ms timeline. Internal indices
  304. * inside one segment as well as adjacent segments are verified.
  305. */
  306. public void testMsSegment() {
  307. verifyOneSegment(this.msTimeline);
  308. }
  309. /**
  310. * Tests one segment of the ms timeline. Internal indices
  311. * inside one segment as well as adjacent segments are verified.
  312. */
  313. public void testMs2Segment() {
  314. verifyOneSegment(this.ms2Timeline);
  315. }
  316. /**
  317. * Tests one segment of the Monday through Friday timeline. Internal indices
  318. * inside one segment as well as adjacent segments are verified.
  319. */
  320. public void testMondayThroughFridaySegment() {
  321. verifyOneSegment(this.mondayFridayTimeline);
  322. }
  323. /**
  324. * Tests one segment of the Fifteen timeline. Internal indices
  325. * inside one segment as well as adjacent segments are verified.
  326. */
  327. public void testFifteenMinSegment() {
  328. verifyOneSegment(this.fifteenMinTimeline);
  329. }
  330. /**
  331. * Tests one segment of the Monday through Friday timeline. Internal indices
  332. * inside one segment as well as adjacent segments are verified.
  333. * @param timeline the timeline to use for verifications.
  334. */
  335. public void verifyOneSegment(SegmentedTimeline timeline) {
  336. for (long testCycle = TEST_CYCLE_START; testCycle < TEST_CYCLE_END;
  337. testCycle += TEST_CYCLE_INC) {
  338. // get two consecutive segments for various tests
  339. SegmentedTimeline.Segment segment1 =
  340. timeline.getSegment(this.monday.getTime().getTime() + testCycle);
  341. SegmentedTimeline.Segment segment2 =
  342. timeline.getSegment(segment1.getSegmentEnd() + 1);
  343. // verify segments are consecutive and correct
  344. assertEquals(segment1.getSegmentNumber() + 1, segment2.getSegmentNumber());
  345. assertEquals(segment1.getSegmentEnd() + 1, segment2.getSegmentStart());
  346. assertEquals(segment1.getSegmentStart() + timeline.getSegmentSize() - 1,
  347. segment1.getSegmentEnd());
  348. assertEquals(segment1.getSegmentStart() + timeline.getSegmentSize(),
  349. segment2.getSegmentStart());
  350. assertEquals(segment1.getSegmentEnd() + timeline.getSegmentSize(),
  351. segment2.getSegmentEnd());
  352. // verify various indices inside a segment are the same segment
  353. long delta;
  354. if (timeline.getSegmentSize() > 1000000) {
  355. delta = timeline.getSegmentSize() / 10000;
  356. }
  357. else if (timeline.getSegmentSize() > 100000) {
  358. delta = timeline.getSegmentSize() / 1000;
  359. }
  360. else if (timeline.getSegmentSize() > 10000) {
  361. delta = timeline.getSegmentSize() / 100;
  362. }
  363. else if (timeline.getSegmentSize() > 1000) {
  364. delta = timeline.getSegmentSize() / 10;
  365. }
  366. else if (timeline.getSegmentSize() > 100) {
  367. delta = timeline.getSegmentSize() / 5;
  368. }
  369. else {
  370. delta = 1;
  371. }
  372. long start = segment1.getSegmentStart() + delta;
  373. long end = segment1.getSegmentStart() + timeline.getSegmentSize() - 1;
  374. SegmentedTimeline.Segment lastSeg = timeline.getSegment(segment1.getSegmentStart());
  375. SegmentedTimeline.Segment seg;
  376. for (long i = start; i < end; i += delta) {
  377. seg = timeline.getSegment(i);
  378. assertEquals(lastSeg.getSegmentNumber(), seg.getSegmentNumber());
  379. assertEquals(lastSeg.getSegmentStart(), seg.getSegmentStart());
  380. assertEquals(lastSeg.getSegmentEnd(), seg.getSegmentEnd());
  381. assertTrue(lastSeg.getMillisecond() < seg.getMillisecond());
  382. lastSeg = seg;
  383. }
  384. // try next segment
  385. seg = timeline.getSegment(end + 1);
  386. assertEquals(segment2.getSegmentNumber(), seg.getSegmentNumber());
  387. assertEquals(segment2.getSegmentStart(), seg.getSegmentStart());
  388. assertEquals(segment2.getSegmentEnd(), seg.getSegmentEnd());
  389. }
  390. }
  391. //////////////////////////////////////////////////////////////////////////
  392. // test inc methods
  393. //////////////////////////////////////////////////////////////////////////
  394. /**
  395. * Tests the inc methods on the msTimeline.
  396. */
  397. public void testMsInc() {
  398. verifyInc(this.msTimeline);
  399. }
  400. /**
  401. * Tests the inc methods on the msTimeline.
  402. */
  403. public void testMs2Inc() {
  404. verifyInc(this.ms2Timeline);
  405. }
  406. /**
  407. * Tests the inc methods on the Monday through Friday timeline.
  408. */
  409. public void testMondayThroughFridayInc() {
  410. verifyInc(this.mondayFridayTimeline);
  411. }
  412. /**
  413. * Tests the inc methods on the Fifteen minute timeline.
  414. */
  415. public void testFifteenMinInc() {
  416. verifyInc(this.fifteenMinTimeline);
  417. }
  418. /**
  419. * Tests the inc methods.
  420. * @param timeline the timeline to use for verifications.
  421. */
  422. public void verifyInc(SegmentedTimeline timeline) {
  423. for (long testCycle = TEST_CYCLE_START; testCycle < TEST_CYCLE_END;
  424. testCycle += TEST_CYCLE_INC) {
  425. long m = timeline.getSegmentSize();
  426. SegmentedTimeline.Segment segment = timeline.getSegment(testCycle);
  427. SegmentedTimeline.Segment seg1 = segment.copy();
  428. for (int i = 0; i < 1000; i++) {
  429. // test inc() method
  430. SegmentedTimeline.Segment seg2 = seg1.copy();
  431. seg2.inc();
  432. if ((seg1.getSegmentEnd() + 1) != seg2.getSegmentStart()) {
  433. // logically consecutive segments non-physically consecutive
  434. // (with non-contained time in between)
  435. assertTrue(!timeline.containsDomainRange(seg1.getSegmentEnd() + 1,
  436. seg2.getSegmentStart() - 1));
  437. assertEquals(0, (seg2.getSegmentStart() - seg1.getSegmentStart()) % m);
  438. assertEquals(0, (seg2.getSegmentEnd() - seg1.getSegmentEnd()) % m);
  439. assertEquals(0, (seg2.getMillisecond() - seg1.getMillisecond()) % m);
  440. }
  441. else {
  442. // physically consecutive
  443. assertEquals(seg1.getSegmentStart() + m,
  444. seg2.getSegmentStart());
  445. assertEquals(seg1.getSegmentEnd() + m, seg2.getSegmentEnd());
  446. assertEquals(seg1.getMillisecond() + m, seg2.getMillisecond());
  447. }
  448. // test inc(n) method
  449. SegmentedTimeline.Segment seg3 = seg1.copy();
  450. SegmentedTimeline.Segment seg4 = seg1.copy();
  451. for (int j = 0; j < i; j++) {
  452. seg3.inc();
  453. }
  454. seg4.inc(i);
  455. assertEquals(seg3.getSegmentStart(), seg4.getSegmentStart());
  456. assertEquals(seg3.getSegmentEnd(), seg4.getSegmentEnd());
  457. assertEquals(seg3.getMillisecond(), seg4.getMillisecond());
  458. // go to another segment to continue test
  459. seg1.inc();
  460. }
  461. }
  462. }
  463. //////////////////////////////////////////////////////////////////////////
  464. // main include and excluded segments
  465. //////////////////////////////////////////////////////////////////////////
  466. /**
  467. * Tests that the msTimeline's included and excluded
  468. * segments are being calculated correctly.
  469. */
  470. public void testMsIncludedAndExcludedSegments() {
  471. verifyIncludedAndExcludedSegments(this.msTimeline, 0);
  472. }
  473. /**
  474. * Tests that the ms2Timeline's included and excluded
  475. * segments are being calculated correctly.
  476. */
  477. public void testMs2IncludedAndExcludedSegments() {
  478. verifyIncludedAndExcludedSegments(this.ms2Timeline, 1);
  479. }
  480. /**
  481. * Tests that the Monday through Friday timeline's included and excluded
  482. * segments are being calculated correctly. The test is performed starting
  483. * on the first monday after 1/1/2000 and for five years.
  484. */
  485. public void testMondayThroughFridayIncludedAndExcludedSegments() {
  486. verifyIncludedAndExcludedSegments(
  487. this.mondayFridayTimeline, this.monday.getTime().getTime()
  488. );
  489. }
  490. /**
  491. * Tests that the Fifteen-Min timeline's included and excluded
  492. * segments are being calculated correctly. The test is performed starting
  493. * on the first monday after 1/1/2000 and for five years.
  494. */
  495. public void testFifteenMinIncludedAndExcludedSegments() {
  496. verifyIncludedAndExcludedSegments(
  497. this.fifteenMinTimeline, this.monday9am.getTime().getTime()
  498. );
  499. }
  500. /**
  501. * Tests that a timeline's included and excluded segments are being calculated
  502. * correctly.
  503. * @param timeline the timeline to verify
  504. * @param n the first segment number to start verifying
  505. */
  506. public void verifyIncludedAndExcludedSegments(SegmentedTimeline timeline, long n) {
  507. // clear any exceptions in this timeline
  508. timeline.setExceptionSegments(new java.util.ArrayList());
  509. // test some included and excluded segments
  510. SegmentedTimeline.Segment segment = timeline.getSegment(n);
  511. for (int i = 0; i < 1000; i++) {
  512. int d = (i % timeline.getGroupSegmentCount());
  513. if (d < timeline.getSegmentsIncluded()) {
  514. // should be an included segment
  515. assertTrue(segment.inIncludeSegments());
  516. assertTrue(!segment.inExcludeSegments());
  517. assertTrue(!segment.inExceptionSegments());
  518. }
  519. else {
  520. // should be an excluded segment
  521. assertTrue(!segment.inIncludeSegments());
  522. assertTrue(segment.inExcludeSegments());
  523. assertTrue(!segment.inExceptionSegments());
  524. }
  525. segment.inc();
  526. }
  527. }
  528. //////////////////////////////////////////////////////////////////////////
  529. // test exception segments
  530. //////////////////////////////////////////////////////////////////////////
  531. /**
  532. * Tests methods related to exceptions methods in the msTimeline.
  533. *
  534. * @throws ParseException if there is a parsing error.
  535. */
  536. public void testMsExceptionSegments() throws ParseException {
  537. verifyExceptionSegments(this.msTimeline, MS_EXCEPTIONS, NUMBER_FORMAT);
  538. }
  539. /**
  540. * Tests methods related to exceptions methods in the ms2BaseTimeline.
  541. *
  542. * @throws ParseException if there is a parsing error.
  543. */
  544. public void testMs2BaseTimelineExceptionSegments() throws ParseException {
  545. verifyExceptionSegments(this.ms2BaseTimeline, MS2_BASE_TIMELINE_EXCEPTIONS, NUMBER_FORMAT);
  546. }
  547. /**
  548. * Tests methods related to exceptions methods in the mondayFridayTimeline.
  549. *
  550. * @throws ParseException if there is a parsing error.
  551. */
  552. public void testMondayThoughFridayExceptionSegments() throws ParseException {
  553. verifyExceptionSegments(this.mondayFridayTimeline, US_HOLIDAYS, DATE_FORMAT);
  554. }
  555. /**
  556. * Tests methods related to exceptions methods in the fifteenMinTimeline.
  557. *
  558. * @throws ParseException if there is a parsing error.
  559. */
  560. public void testFifteenMinExceptionSegments() throws ParseException {
  561. verifyExceptionSegments(this.fifteenMinTimeline, FIFTEEN_MIN_EXCEPTIONS, DATE_TIME_FORMAT);
  562. }
  563. /**
  564. * Tests methods related to adding exceptions.
  565. *
  566. * @param timeline the timeline to verify
  567. * @param exceptionString array of Strings that represent the exceptions
  568. * @param fmt Format object that can parse the exceptionString strings
  569. *
  570. * @throws ParseException if there is a parsing error.
  571. */
  572. public void verifyExceptionSegments(SegmentedTimeline timeline,
  573. String[] exceptionString,
  574. Format fmt)
  575. throws ParseException {
  576. // fill in the exceptions
  577. long[] exception = verifyFillInExceptions(timeline, exceptionString, fmt);
  578. int m = exception.length;
  579. // verify list of exceptions
  580. assertEquals(exception.length, timeline.getExceptionSegments().size());
  581. SegmentedTimeline.Segment lastSegment = timeline.getSegment(exception[m - 1]);
  582. for (int i = 0; i < m; i++) {
  583. SegmentedTimeline.Segment segment = timeline.getSegment(exception[i]);
  584. assertTrue(segment.inExceptionSegments());
  585. // include current exception and last one
  586. assertEquals(m - i, timeline.getExceptionSegmentCount(
  587. segment.getSegmentStart(), lastSegment.getSegmentEnd()));
  588. // exclude current exception and last one
  589. assertEquals(Math.max(0, m - i - 2), timeline.getExceptionSegmentCount(
  590. exception[i] + 1, exception[m - 1] - 1));
  591. }
  592. }
  593. //////////////////////////////////////////////////////////////////////////
  594. // test timeline translations
  595. //////////////////////////////////////////////////////////////////////////
  596. /**
  597. * Tests translations for 1-ms timeline
  598. *
  599. * @throws ParseException if there is a parsing error.
  600. */
  601. public void testMsTranslations() throws ParseException {
  602. verifyFillInExceptions(this.msTimeline, MS_EXCEPTIONS, NUMBER_FORMAT);
  603. verifyTranslations(this.msTimeline, 0);
  604. }
  605. /**
  606. * Tests translations for the base timeline used for the ms2Timeline
  607. *
  608. * @throws ParseException if there is a parsing error.
  609. */
  610. public void testMs2BaseTimelineTranslations() throws ParseException {
  611. verifyFillInExceptions(this.ms2BaseTimeline, MS2_BASE_TIMELINE_EXCEPTIONS, NUMBER_FORMAT);
  612. verifyTranslations(this.ms2BaseTimeline, 0);
  613. }
  614. /**
  615. * Tests translations for the Monday through Friday timeline
  616. *
  617. * @throws ParseException if there is a parsing error.
  618. */
  619. public void testMs2Translations() throws ParseException {
  620. fillInBaseTimelineExceptions(this.ms2Timeline, MS2_BASE_TIMELINE_EXCEPTIONS, NUMBER_FORMAT);
  621. fillInBaseTimelineExclusionsAsExceptions(this.ms2Timeline, 0, 5000);
  622. verifyTranslations(this.ms2Timeline, 1);
  623. }
  624. /**
  625. * Tests translations for the Monday through Friday timeline
  626. *
  627. * @throws ParseException if there is a parsing error.
  628. */
  629. public void testMondayThroughFridayTranslations() throws ParseException {
  630. verifyFillInExceptions(this.mondayFridayTimeline, US_HOLIDAYS, DATE_FORMAT);
  631. verifyTranslations(this.mondayFridayTimeline, this.monday.getTime().getTime());
  632. }
  633. /**
  634. * Tests translations for the Fifteen Min timeline
  635. *
  636. * @throws ParseException if there is a parsing error.
  637. */
  638. public void testFifteenMinTranslations() throws ParseException {
  639. verifyFillInExceptions(this.fifteenMinTimeline, FIFTEEN_MIN_EXCEPTIONS, DATE_TIME_FORMAT);
  640. fillInBaseTimelineExceptions(this.fifteenMinTimeline, US_HOLIDAYS, DATE_FORMAT);
  641. fillInBaseTimelineExclusionsAsExceptions(
  642. this.fifteenMinTimeline,
  643. this.monday9am.getTime().getTime(),
  644. this.monday9am.getTime().getTime() + FIVE_YEARS
  645. );
  646. verifyTranslations(this.fifteenMinTimeline, this.monday9am.getTime().getTime());
  647. }
  648. /**
  649. * Tests translations between timelines.
  650. *
  651. * @param timeline the timeline to use for verifications.
  652. * @param startTest ??.
  653. */
  654. public void verifyTranslations(SegmentedTimeline timeline, long startTest) {
  655. for (long testCycle = TEST_CYCLE_START; testCycle < TEST_CYCLE_END;
  656. testCycle += TEST_CYCLE_INC) {
  657. long millisecond = startTest + testCycle * timeline.getSegmentSize();
  658. SegmentedTimeline.Segment segment = timeline.getSegment(millisecond);
  659. for (int i = 0; i < 1000; i++) {
  660. long translatedValue = timeline.toTimelineValue(segment.getMillisecond());
  661. long newValue = timeline.toMillisecond(translatedValue);
  662. if (segment.inExcludeSegments() || segment.inExceptionSegments()) {
  663. // the reverse transformed value will be in the start of the
  664. // next non-excluded and non-exception segment
  665. SegmentedTimeline.Segment tempSegment = segment.copy();
  666. tempSegment.moveIndexToStart();
  667. do {
  668. tempSegment.inc();
  669. }
  670. while (!tempSegment.inIncludeSegments());
  671. assertEquals(tempSegment.getMillisecond(), newValue);
  672. }
  673. else {
  674. assertEquals(segment.getMillisecond(), newValue);
  675. }
  676. segment.inc();
  677. }
  678. }
  679. }
  680. //////////////////////////////////////////////////////////////////////////
  681. // test serialization
  682. //////////////////////////////////////////////////////////////////////////
  683. /**
  684. * Serialize an instance, restore it, and check for equality.
  685. */
  686. public void testSerialization() {
  687. verifySerialization(this.msTimeline);
  688. verifySerialization(this.ms2Timeline);
  689. verifySerialization(this.ms2BaseTimeline);
  690. verifySerialization(SegmentedTimeline.newMondayThroughFridayTimeline());
  691. verifySerialization(SegmentedTimeline.newFifteenMinuteTimeline());
  692. }
  693. /**
  694. * Tests serialization of an instance.
  695. * @param a1 The timeline to verify the serialization
  696. */
  697. private void verifySerialization(SegmentedTimeline a1) {
  698. SegmentedTimeline a2 = null;
  699. try {
  700. ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  701. ObjectOutput out = new ObjectOutputStream(buffer);
  702. out.writeObject(a1);
  703. out.close();
  704. ObjectInput in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
  705. a2 = (SegmentedTimeline) in.readObject();
  706. in.close();
  707. }
  708. catch (Exception e) {
  709. System.out.println(e.toString());
  710. }
  711. assertEquals(a1, a2);
  712. }
  713. /**
  714. * Adds an array of exceptions to the timeline. The timeline exception list
  715. * is first cleared.
  716. * @param timeline The timeline where the exceptions will be stored
  717. * @param exceptionString The exceptions to load
  718. * @param fmt The date formatter to use to parse each exceptions[i] value
  719. * @throws ParseException If there is any exception parsing each exceptions[i]
  720. * value.
  721. * @return An array of Dates[] containing each exception date.
  722. */
  723. private long[] verifyFillInExceptions(SegmentedTimeline timeline,
  724. String[] exceptionString,
  725. Format fmt) throws ParseException {
  726. // make sure there are no exceptions
  727. timeline.setExceptionSegments(new java.util.ArrayList());
  728. assertEquals(0, timeline.getExceptionSegments().size());
  729. // add our exceptions and store locally in ArrayList of Longs
  730. ArrayList exceptionList = new ArrayList();
  731. for (int i = 0; i < exceptionString.length; i++) {
  732. long e;
  733. if (fmt instanceof NumberFormat) {
  734. e = ((NumberFormat) fmt).parse(exceptionString[i]).longValue();
  735. }
  736. else {
  737. e = timeline.getTime(((SimpleDateFormat) fmt).parse(exceptionString[i]));
  738. }
  739. // only add an exception if it is currently an included segment
  740. SegmentedTimeline.Segment segment = timeline.getSegment(e);
  741. if (segment.inIncludeSegments()) {
  742. timeline.addException(e);
  743. exceptionList.add(new Long(e));
  744. assertEquals(exceptionList.size(), timeline.getExceptionSegments().size());
  745. assertTrue(segment.inExceptionSegments());
  746. }
  747. }
  748. // make array of exceptions
  749. long[] exception = new long[exceptionList.size()];
  750. int i = 0;
  751. for (Iterator iter = exceptionList.iterator(); iter.hasNext();) {
  752. Long l = (Long) iter.next();
  753. exception[i++] = l.longValue();
  754. }
  755. return (exception);
  756. }
  757. /**
  758. * Adds an array of exceptions relative to the base timeline.
  759. *
  760. * @param timeline The timeline where the exceptions will be stored
  761. * @param exceptionString The exceptions to load
  762. * @param fmt The date formatter to use to parse each exceptions[i] value
  763. * @throws ParseException If there is any exception parsing each exceptions[i]
  764. * value.
  765. */
  766. private void fillInBaseTimelineExceptions(SegmentedTimeline timeline,
  767. String[] exceptionString,
  768. Format fmt) throws ParseException {
  769. SegmentedTimeline baseTimeline = timeline.getBaseTimeline();
  770. for (int i = 0; i < exceptionString.length; i++) {
  771. long e;
  772. if (fmt instanceof NumberFormat) {
  773. e = ((NumberFormat) fmt).parse(exceptionString[i]).longValue();
  774. }
  775. else {
  776. e = timeline.getTime(((SimpleDateFormat) fmt).parse(exceptionString[i]));
  777. }
  778. timeline.addBaseTimelineException(e);
  779. // verify all timeline segments included in the baseTimeline.segment are now exceptions
  780. SegmentedTimeline.Segment segment1 = baseTimeline.getSegment(e);
  781. for (SegmentedTimeline.Segment segment2
  782. = timeline.getSegment(segment1.getSegmentStart());
  783. segment2.getSegmentStart() <= segment1.getSegmentEnd();
  784. segment2.inc()) {
  785. if (!segment2.inExcludeSegments()) {
  786. assertTrue(segment2.inExceptionSegments());
  787. }
  788. }
  789. }
  790. }
  791. /**
  792. * Adds new exceptions to a timeline. The exceptions are the excluded segments from its
  793. * base timeline.
  794. *
  795. * @param timeline the timeline.
  796. * @param from the start.
  797. * @param to the end.
  798. */
  799. private void fillInBaseTimelineExclusionsAsExceptions(SegmentedTimeline timeline,
  800. long from, long to) {
  801. // add the base timeline exclusions as timeline's esceptions
  802. timeline.addBaseTimelineExclusions(from, to);
  803. // validate base timeline exclusions added as timeline's esceptions
  804. for (SegmentedTimeline.Segment segment1 = timeline.getBaseTimeline().getSegment(from);
  805. segment1.getSegmentStart() <= to;
  806. segment1.inc()) {
  807. if (segment1.inExcludeSegments()) {
  808. // verify all timeline segments included in the baseTimeline.segment are now
  809. // exceptions
  810. for (SegmentedTimeline.Segment segment2
  811. = timeline.getSegment(segment1.getSegmentStart());
  812. segment2.getSegmentStart() <= segment1.getSegmentEnd();
  813. segment2.inc()) {
  814. if (!segment2.inExcludeSegments()) {
  815. assertTrue(segment2.inExceptionSegments());
  816. }
  817. }
  818. }
  819. }
  820. }
  821. /**
  822. * Confirm that cloning works.
  823. */
  824. public void testCloning() {
  825. SegmentedTimeline l1 = new SegmentedTimeline(1000, 5, 2);
  826. SegmentedTimeline l2 = null;
  827. try {
  828. l2 = (SegmentedTimeline) l1.clone();
  829. }
  830. catch (CloneNotSupportedException e) {
  831. System.err.println("SegmentedTimelineTests2.testCloning: failed to clone.");
  832. }
  833. assertTrue(l1 != l2);
  834. assertTrue(l1.getClass() == l2.getClass());
  835. assertTrue(l1.equals(l2));
  836. }
  837. /**
  838. * Confirm that the equals method can distinguish all the required fields.
  839. */
  840. public void testEquals() {
  841. SegmentedTimeline l1 = new SegmentedTimeline(1000, 5, 2);
  842. SegmentedTimeline l2 = new SegmentedTimeline(1000, 5, 2);
  843. assertTrue(l1.equals(l2));
  844. l1 = new SegmentedTimeline(1000, 5, 2);
  845. l2 = new SegmentedTimeline(1001, 5, 2);
  846. assertFalse(l1.equals(l2));
  847. l1 = new SegmentedTimeline(1000, 5, 2);
  848. l2 = new SegmentedTimeline(1000, 4, 2);
  849. assertFalse(l1.equals(l2));
  850. l1 = new SegmentedTimeline(1000, 5, 2);
  851. l2 = new SegmentedTimeline(1000, 5, 1);
  852. assertFalse(l1.equals(l2));
  853. l1 = new SegmentedTimeline(1000, 5, 2);
  854. l2 = new SegmentedTimeline(1000, 5, 2);
  855. // start time...
  856. l1.setStartTime(1234L);
  857. assertFalse(l1.equals(l2));
  858. l2.setStartTime(1234L);
  859. assertTrue(l1.equals(l2));
  860. }
  861. /**
  862. * Two objects that are equal are required to return the same hashCode.
  863. */
  864. public void testHashCode() {
  865. SegmentedTimeline l1 = new SegmentedTimeline(1000, 5, 2);
  866. SegmentedTimeline l2 = new SegmentedTimeline(1000, 5, 2);
  867. assertTrue(l1.equals(l2));
  868. int h1 = l1.hashCode();
  869. int h2 = l2.hashCode();
  870. assertEquals(h1, h2);
  871. }
  872. /**
  873. * Serialize an instance, restore it, and check for equality.
  874. */
  875. public void testSerialization2() {
  876. SegmentedTimeline l1 = new SegmentedTimeline(1000, 5, 2);
  877. SegmentedTimeline l2 = null;
  878. try {
  879. ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  880. ObjectOutput out = new ObjectOutputStream(buffer);
  881. out.writeObject(l1);
  882. out.close();
  883. ObjectInput in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray()));
  884. l2 = (SegmentedTimeline) in.readObject();
  885. in.close();
  886. }
  887. catch (Exception e) {
  888. System.out.println(e.toString());
  889. }
  890. boolean b = l1.equals(l2);
  891. assertTrue(b);
  892. }
  893. //////////////////////////////////////////////////////////////////////////
  894. // utility methods
  895. //////////////////////////////////////////////////////////////////////////
  896. /**
  897. * Formats a Calendar object avoiding converting into a Date so the local
  898. * TimeZone is not used to convert the output. The Calendar object used as
  899. * parameter is assumed to use the SegmentedTimeline.TIME_ZONE time zone.
  900. *
  901. * @param cal Calendar object to format
  902. * @return
  903. */
  904. /*
  905. private String calToString(Calendar cal) {
  906. DecimalFormat fmt2 = new DecimalFormat("00");
  907. DecimalFormat fmt4 = new DecimalFormat("0000");
  908. return (getDayOfWeekString(cal)+" "+
  909. fmt2.format(cal.get(Calendar.MONTH)+1)+"/"+
  910. fmt2.format(cal.get(Calendar.DATE))+"/"+
  911. fmt4.format(cal.get(Calendar.YEAR))+" "+
  912. fmt2.format(cal.get(Calendar.HOUR_OF_DAY))+":"+
  913. fmt2.format(cal.get(Calendar.MINUTE))+":"+
  914. fmt2.format(cal.get(Calendar.SECOND))+":"+
  915. fmt4.format(cal.get(Calendar.MILLISECOND)));
  916. }
  917. */
  918. /**
  919. * Formats time avoiding converting into a Date so the local
  920. * TimeZone is not used to convert the output. The time used as
  921. * parameter is assumed to be relative to SegmentedTimeline.TIME_ZONE time zone.
  922. *
  923. * @param time time to format
  924. * @return
  925. */
  926. /*
  927. private String calToString(long time) {
  928. Calendar cal = new GregorianCalendar(SegmentedTimeline.NO_DST_TIME_ZONE);
  929. cal.setTimeInMillis(time);
  930. return (calToString(cal));
  931. }
  932. */
  933. /**
  934. * Returns a three letter day of the week string for Calendar formatting.
  935. * @param cal Calendar to check
  936. * @return
  937. */
  938. /*
  939. private String getDayOfWeekString(Calendar cal) {
  940. switch (cal.get(Calendar.DAY_OF_WEEK)) {
  941. case Calendar.SUNDAY: return ("Sun");
  942. case Calendar.MONDAY: return ("Mon");
  943. case Calendar.TUESDAY: return ("Tue");
  944. case Calendar.WEDNESDAY: return ("Wed");
  945. case Calendar.THURSDAY: return ("Thu");
  946. case Calendar.FRIDAY: return ("Fri");
  947. case Calendar.SATURDAY: return ("Sat");
  948. default: return ("???");
  949. }
  950. }
  951. */
  952. /**
  953. * Tests a basic segmented timeline.
  954. */
  955. public void testBasicSegmentedTimeline() {
  956. SegmentedTimeline stl = new SegmentedTimeline(10, 2, 3);
  957. stl.setStartTime(946684800000L); // 1-Jan-2000
  958. assertFalse(stl.containsDomainValue(946684799999L));
  959. assertTrue(stl.containsDomainValue(946684800000L));
  960. assertTrue(stl.containsDomainValue(946684800019L));
  961. assertFalse(stl.containsDomainValue(946684800020L));
  962. assertFalse(stl.containsDomainValue(946684800049L));
  963. assertTrue(stl.containsDomainValue(946684800050L));
  964. assertTrue(stl.containsDomainValue(946684800069L));
  965. assertFalse(stl.containsDomainValue(946684800070L));
  966. assertFalse(stl.containsDomainValue(946684800099L));
  967. assertTrue(stl.containsDomainValue(946684800100L));
  968. assertEquals(0, stl.toTimelineValue(946684800000L));
  969. assertEquals(19, stl.toTimelineValue(946684800019L));
  970. assertEquals(20, stl.toTimelineValue(946684800020L));
  971. assertEquals(20, stl.toTimelineValue(946684800049L));
  972. assertEquals(20, stl.toTimelineValue(946684800050L));
  973. assertEquals(39, stl.toTimelineValue(946684800069L));
  974. assertEquals(40, stl.toTimelineValue(946684800070L));
  975. assertEquals(40, stl.toTimelineValue(946684800099L));
  976. assertEquals(40, stl.toTimelineValue(946684800100L));
  977. assertEquals(946684800000L, stl.toMillisecond(0));
  978. assertEquals(946684800019L, stl.toMillisecond(19));
  979. assertEquals(946684800050L, stl.toMillisecond(20));
  980. assertEquals(946684800069L, stl.toMillisecond(39));
  981. assertEquals(946684800100L, stl.toMillisecond(40));
  982. }
  983. /**
  984. * Tests a basic time line with one exception.
  985. */
  986. public void testSegmentedTimelineWithException1() {
  987. SegmentedTimeline stl = new SegmentedTimeline(10, 2, 3);
  988. stl.setStartTime(946684800000L); // 1-Jan-2000
  989. stl.addException(946684800050L);
  990. assertFalse(stl.containsDomainValue(946684799999L));
  991. assertTrue(stl.containsDomainValue(946684800000L));
  992. assertTrue(stl.containsDomainValue(946684800019L));
  993. assertFalse(stl.containsDomainValue(946684800020L));
  994. assertFalse(stl.containsDomainValue(946684800049L));
  995. assertFalse(stl.containsDomainValue(946684800050L));
  996. assertFalse(stl.containsDomainValue(946684800059L));
  997. assertTrue(stl.containsDomainValue(946684800060L));
  998. assertTrue(stl.containsDomainValue(946684800069L));
  999. assertFalse(stl.containsDomainValue(946684800070L));
  1000. assertFalse(stl.containsDomainValue(946684800099L));
  1001. assertTrue(stl.containsDomainValue(946684800100L));
  1002. //long v = stl.toTimelineValue(946684800020L);
  1003. assertEquals(0, stl.toTimelineValue(946684800000L));
  1004. assertEquals(19, stl.toTimelineValue(946684800019L));
  1005. assertEquals(20, stl.toTimelineValue(946684800020L));
  1006. assertEquals(20, stl.toTimelineValue(946684800049L));
  1007. assertEquals(20, stl.toTimelineValue(946684800050L));
  1008. assertEquals(29, stl.toTimelineValue(946684800069L));
  1009. assertEquals(30, stl.toTimelineValue(946684800070L));
  1010. assertEquals(30, stl.toTimelineValue(946684800099L));
  1011. assertEquals(30, stl.toTimelineValue(946684800100L));
  1012. assertEquals(946684800000L, stl.toMillisecond(0));
  1013. assertEquals(946684800019L, stl.toMillisecond(19));
  1014. assertEquals(946684800060L, stl.toMillisecond(20));
  1015. assertEquals(946684800069L, stl.toMillisecond(29));
  1016. assertEquals(946684800100L, stl.toMillisecond(30));
  1017. }
  1018. //////////////////////////////////////////////////////////////////////////
  1019. // main method only for debug
  1020. //////////////////////////////////////////////////////////////////////////
  1021. /**
  1022. * Only use to debug JUnit suite.
  1023. *
  1024. * @param args ignored.
  1025. *
  1026. * @throws Exception if there is some problem.
  1027. */
  1028. public static void main(String[] args) throws Exception {
  1029. SegmentedTimelineTests test = new SegmentedTimelineTests("Test");
  1030. test.setUp();
  1031. test.testMondayThoughFridayExceptionSegments();
  1032. test.tearDown();
  1033. }
  1034. }